<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Refactor Life like code.</title>
    <link>https://sinam7.tistory.com/</link>
    <description>개발하는 사람입니다. 하고 싶은 것들 사이에서 매번 선택하는 삶을 살고 있습니다.</description>
    <language>ko</language>
    <pubDate>Wed, 29 Jul 2026 06:48:24 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>시남</managingEditor>
    <image>
      <title>Refactor Life like code.</title>
      <url>https://tistory1.daumcdn.net/tistory/1419940/attach/b2f4d58725f246e0bcbf9791d36a1cec</url>
      <link>https://sinam7.tistory.com</link>
    </image>
    <item>
      <title>[Codex 튜토리얼] (1) Codex 설치하기</title>
      <link>https://sinam7.tistory.com/32</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFqBWj/dJMcacJR0iV/QAmKwb44vDN6qVRWHqKCc1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFqBWj/dJMcacJR0iV/QAmKwb44vDN6qVRWHqKCc1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFqBWj/dJMcacJR0iV/QAmKwb44vDN6qVRWHqKCc1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFqBWj%2FdJMcacJR0iV%2FQAmKwb44vDN6qVRWHqKCc1%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;256&quot; height=&quot;256&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;0. 들어가며 - 어쩌다 Codex를?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 몇 달 간 Claude Code를 잘 사용하고 있었지만, 최근 가용 세션 한도가 너무 빠르게 소진되는 것이 느껴졌다. 관련 소식들을 찾아보니 나만 겪던 문제는 아닌 것 같았다. 그 와중 자주 보이던 단어가 있었는데, 그게 바로 Codex였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 Codex에 대해 약간 부정적인 견해를 가지고 있었다. 과거 Claude Code가 처음 등장했을 시점에 OpenAI에서 공개한 &lt;code&gt;openai-cli&lt;/code&gt;의 성능은 단순 ChatGPT를 CLI 환경에 옮겨놓은 수준이라 비교가 불가능했던 데다, 이후 Codex CLI가 출시된 직후에 사용했을 때에도 Claude Code에 비해 그리 똑똑하지 않았고 주먹구구식 저품질 코드를 쏟아냈던 기억이 있었기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 현재로 돌아와, Claude를 사용하며 겪는 토큰 부족 이슈의 불쾌감이 누적되는 와중 Codex를 향한 좋은 평가들이 자주 눈에 띄었다. 옛날보다 훨씬 코드 품질도 좋아졌다는 평가가 많았던데다 Claude Code보다 더 좋은 퍼포먼스를 낸다는 후기도 여럿 보였다. 이 정도면 다시 써볼만 하지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 지난달 말 $20 수준 플랜인 ChatGPT Plus 플랜의 Codex CLI 사용 한도가 늘어났다는 소식을 들었다. Claude의 사용 한도에 불만을 가졌던 내겐 더없이 반가운 소식이었다. 이정도면 더 고민할 이유가 없다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 결제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;26년 초부터 &lt;b&gt;Free 플랜에도 Codex CLI 사용 권한이 열렸다&lt;/b&gt;곤 하나, &lt;b&gt;세션당(5시간마다) 10건 내외의 메시지만 전송 가능&lt;/b&gt;하다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이정도면 마트 시식코너에서 판촉 중인 만두 하나 찍어먹는 수준 아닌가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Free 플랜 다음인 &lt;b&gt;Go 플랜&lt;/b&gt;도 알아보았다. &lt;b&gt;$8 플랜&lt;/b&gt;이며, Free와 Plus 플랜 사이에 들어가는 저가형 요금제다.&lt;br /&gt;&lt;b&gt;월 13000원 정도&lt;/b&gt; 플랜이며, Free 사용량의 10배이나 &lt;b&gt;서비스 이용시 답변 하단에 광고가 달린다&lt;/b&gt;고 한다.&lt;br /&gt;Plus의 반값 이하 수준인데, 둘을 비교해보자:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;height: 134px;&quot; width=&quot;555&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;th style=&quot;height: 20px;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;height: 20px;&quot;&gt;ChatGPT Go&lt;/th&gt;
&lt;th style=&quot;height: 20px;&quot;&gt;ChatGPT Plus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;월 요금&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;$8&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;$20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;주요 모델&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;GPT-5.3 Instant&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;GPT-5.5 Thinking (추론 모델)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;메시지 한도&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;3시간당 약 160회 (Instant 모델)&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;3시간당 160회 + 높은 추론 모델 한도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;광고 여부&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;일부 지역 광고 포함&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;광고 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;전문 도구&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;제한된 Codex 및 이미지 생성&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;Deep Research, Agent 모드 외 다수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;b&gt;사용자층&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;b&gt;라이트 유저, 학생&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;b&gt;전문가, 개발자, 파워 유저&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(by Gemini)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Codex를 사용하려는 내 입장에서 바라보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추론 모델을 사용하기 어려운 Go 모델은 간단한 개인용 워크플로 정도만 개발이 가능하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 옆집처럼 개발 도구로 사용하려면 최소 $20 수준은 들어가야겠더라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Plus 결제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Codex CLI 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 Codex는 App과 CLI로 사용 가능하다. 지금 시점에는 CLI가 App보다 '조금' 더 많은 것을 할 수 있는 수준이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 요약하면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 로컬에서 여러 레포를 건너다니며 작업하는 경우에는 App이,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SSH가 필요하거나 굳이 GUI가 필요없거나 저사양 환경에서는 CLI가 우세하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용성 측면에선 앱이 더 유리하지만 (가독성, 코드 리뷰 작업, `AGENTS.md` 수정, 스킬 설치 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tmux를 사용하거나 원격 작업이 필요한 경우에는 CLI가 필요한 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 그것과는 별개로 Claude Code CLI에 익숙한 나에겐 앱보단 CLI 환경이 익숙하므로 우선 이쪽으로 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자신이 터미널 환경에 익숙하지 않다면&lt;/b&gt;&lt;b&gt;&amp;nbsp;App 사용을 강하게 권장한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그러나 본인이 개발자를 지망한다면 CLI 사용을 강하게 권장한다.&lt;/b&gt; 조금이라도 CLI에 익숙해져야 한다. 뭐든 직접 부딪히면서 배워야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 CLI 설치 방법이고, App 설치는 &lt;a href=&quot;https://openai.com/ko-KR/codex/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;여기&lt;/b&gt;&lt;/a&gt;에서 진행한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1778493022219&quot; class=&quot;coffeescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;npm i -g @openai/codex
codex

# Upgrade
npm i -g @openai/codex@latest&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;homebrew&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1778493098183&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install codex
codex

# Upgrade
brew upgrade codex&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Windows 환경에선 Windows sandbox에서 PowerShell을 이용하거나 WSL2를 사용하는 것을 권장한다.&lt;br /&gt;npm으로 설치 시 Node.js 22+ 버전을 권장한다. 가능하면 최신 LTS를 사용하도록 하자.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EASY!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 `codex` 명령을 입력하면 아래와 같은 창이 나타난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1bu8G/dJMcagMgGBm/2VKXktGIGgIrjhSeYaDQlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1bu8G/dJMcagMgGBm/2VKXktGIGgIrjhSeYaDQlK/img.png&quot; data-alt=&quot;돌아가는 아스키아트는 언제 봐도 아름다운 것&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1bu8G/dJMcagMgGBm/2VKXktGIGgIrjhSeYaDQlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1bu8G%2FdJMcagMgGBm%2F2VKXktGIGgIrjhSeYaDQlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;555&quot; height=&quot;598&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;돌아가는 아스키아트는 언제 봐도 아름다운 것&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 경우에는 그대로 1번을 선택해 엔터를 눌러주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번은 공용 PC에서 사용하면 되고, 3번은 API 키를 통해 사용량 기반 결제하는 경우 선택하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IW5to/dJMcagFvm6h/WkRnuS0NrDG8GmHkRdU0W1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IW5to/dJMcagFvm6h/WkRnuS0NrDG8GmHkRdU0W1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IW5to/dJMcagFvm6h/WkRnuS0NrDG8GmHkRdU0W1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIW5to%2FdJMcagFvm6h%2FWkRnuS0NrDG8GmHkRdU0W1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;555&quot; height=&quot;141&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1658&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이런 식의 안내가 나오고, 그와 동시에 새 탭으로 ChatGPT 로그인 페이지가 나타난다. 로그인하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 나타나는 사용 전 유의사항을 넘기고 디렉토리 신뢰 여부 응답을 하고 나면, 축하한다! 이제 Codex CLI를 사용할 준비가 되었다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kK9QY/dJMcacC51l1/K46lT5Vw6FV4WVh78zg6Y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kK9QY/dJMcacC51l1/K46lT5Vw6FV4WVh78zg6Y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kK9QY/dJMcacC51l1/K46lT5Vw6FV4WVh78zg6Y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkK9QY%2FdJMcacC51l1%2FK46lT5Vw6FV4WVh78zg6Y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;555&quot; height=&quot;161&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 Codex를 &quot;잘&quot; 사용하기 위한 OpenAI의 공식 가이드를 알아보겠다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.openai.com/codex/cli&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developers.openai.com/codex/cli&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 기술/Codex</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/32</guid>
      <comments>https://sinam7.tistory.com/32#entry32comment</comments>
      <pubDate>Mon, 11 May 2026 19:19:42 +0900</pubDate>
    </item>
    <item>
      <title>이중 NAT 환경에서 라즈베리파이 3 홈서버 구축 및 통합 가이드</title>
      <link>https://sinam7.tistory.com/31</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vwvZI/dJMcag6rTvG/lgq6DEFKgxrWQJEpPfi8C0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vwvZI/dJMcag6rTvG/lgq6DEFKgxrWQJEpPfi8C0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vwvZI/dJMcag6rTvG/lgq6DEFKgxrWQJEpPfi8C0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvwvZI%2FdJMcag6rTvG%2Flgq6DEFKgxrWQJEpPfi8C0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;269&quot; height=&quot;340&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 RaspberryPi 3 Model B를 활용하여 24/7 구동되는 홈서버를 구축하는 과정을 다룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 다음 상황에서 작성되었습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이중 NAT 환경&lt;/b&gt;: WAN - 건물 모뎀 - 집 공유기 - 라즈베리파이
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;건물 모뎀에 접근할 수 없어 모뎀 - 공유기 간 포트포워딩이 불가능한 상황입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Raspberry Pi 3 Model B&lt;/b&gt; 를 사용합니다. 라즈베리파이 버전과 모델은 달라도 상관없으나, 각 모델마다 설정이 다를 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Oracle Cloud Infrastructure (OCI)&lt;/b&gt; 내 인스턴스를 실행하고 있습니다. 상기 이중 NAT 구조를 우회하기 위한 방법으로 사용했으며, AWS, GCP 등 다른 클라우드 서비스도 적용 가능합니다. 어디에서나 접근할 수 있는 서버가 있으면 해당 서버를 사용하시고, 외부에서 집 공유기로 바로 접속 가능하면 굳이 필요하지 않습니다.&lt;/li&gt;
&lt;li&gt;공유기 설정 및 라즈베리파이 설치는 &lt;b&gt;Windows 10&lt;/b&gt; 데스크탑에서 진행했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1단계: OS 선택 및 초기 설정 (Raspberry Pi Imager)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라즈베리파이 3의 한정된 자원(RAM 1GB)에서 최적의 성능과 안정성을 확보하기 위한 기초 단계입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.raspberrypi.com/software/&quot;&gt;https://www.raspberrypi.com/software/&lt;/a&gt; 에서 라즈베리파이 이미저(Raspberry Pi Imager)를 다운로드받아 진행합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;OS 선택:&lt;/b&gt; Raspberry Pi OS Lite (64-bit)를 선택합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GUI가 없는 Lite 버전은 유휴 RAM 사용량이 약 120MB로 매우 적어 서버 가용 자원을 극대화할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용자 지정 설정 (톱니바퀴 아이콘 클릭):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;호스트 이름:&lt;/b&gt; [HOSTNAME] // 예: homeserver, raspberrypi 등 네트워크 식별용 이름 설정.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용자 및 비밀번호:&lt;/b&gt; [USER_ID] // 주로 pi를 사용하나, 강력한 비밀번호를 설정하길 권장합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;원격 접근:&lt;/b&gt; SSH 활성화에 체크하고 비밀번호 인증 사용을 선택합니다. 비밀번호 인증 사용 시 직전에 입력한 내용을 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로컬화:&lt;/b&gt; 시간대를 Asia/Seoul로 설정하여 서버 로그 및 자동화 시간을 동기화합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;라즈베리파이 커넥트:&lt;/b&gt; 리소스 낭비 방지를 위해 &lt;b&gt;비활성화&lt;/b&gt;를 권장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2단계: 하드웨어 배치 및 물리 구성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;24/7 안정적인 구동을 위해 발열과 먼지를 관리하고 물리적 연결을 완료합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3B2H0/dJMcadhz8Aw/4Du4QQYcSLwDvxLFcqXf0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3B2H0/dJMcadhz8Aw/4Du4QQYcSLwDvxLFcqXf0K/img.png&quot; data-alt=&quot;이미지 출처: https://robotscience.kr/goods/view?no=18963&amp;amp;amp;srsltid=AfmBOorfmZ3G2B-vxKuQ3nH5n9llxjfZXuV9xPl2iS3PBi4LlCvjCmtA2f4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3B2H0/dJMcadhz8Aw/4Du4QQYcSLwDvxLFcqXf0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3B2H0%2FdJMcadhz8Aw%2F4Du4QQYcSLwDvxLFcqXf0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;361&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지 출처: https://robotscience.kr/goods/view?no=18963&amp;amp;srsltid=AfmBOorfmZ3G2B-vxKuQ3nH5n9llxjfZXuV9xPl2iS3PBi4LlCvjCmtA2f4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;네트워크 연결:&lt;/b&gt; 반드시 &lt;b&gt;유선 랜(Ethernet)&lt;/b&gt; 사용을 강력히 권장합니다. 이는 외부 접속 안정성을 확보하고 블루투스 사용 시 Wi-Fi 간섭을 방지하기 위함입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Raspberry Pi 3 Model B는 Wi-Fi와 블루투스가 동일 장치/안테나를 공유하므로 유선랜을 권장합니다. 다른 모델을 사용하시는 경우 해당 이슈가 있는지를 확인해 판단하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전원 공급:&lt;/b&gt; 정격 어댑터(&lt;b&gt;5V 3A 이상&lt;/b&gt; 추천) 사용 여부를 확인하세요. 전원 공급이 부족한 경우 부팅에 실패하거나 성능 하락, 각종 불안정 현상이 발생할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방열 및 케이스:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주요 칩셋에 방열판을 부착합니다. 라즈베리파이 정품 구매 시 칩셋용 방열판도 같이 배송받았을 겁니다.&lt;/li&gt;
&lt;li&gt;적절한 공간이 있으면 좋지만 마땅히 둘 공간이 없을 수 있습니다. 그럴 땐 먼지 방지를 위해 라즈베리파이 케이스에 수납하되, 뚜껑을 완전히 닫기보다 어느 정도의 &lt;b&gt;유격&lt;/b&gt;을 주거나 공기 순환로를 확보하는 것을 추천합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;배치:&lt;/b&gt; 책장 위 등에 설치할 경우 벽면에서 &lt;b&gt;3~5cm 이격&lt;/b&gt;하여 공기 흐름을 확보합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3단계: 초기 접속 및 인터페이스 최적화&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/busBx7/dJMcai4cu73/FZSZi2wCP2sPle2sWWs8ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/busBx7/dJMcai4cu73/FZSZi2wCP2sPle2sWWs8ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/busBx7/dJMcai4cu73/FZSZi2wCP2sPle2sWWs8ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbusBx7%2FdJMcai4cu73%2FFZSZi2wCP2sPle2sWWs8ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;262&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장비의 전원을 켠 후 터미널을 통해 초기 최적화를 진행합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SSH 접속:&lt;/b&gt; 제어용 PC(Windows)에서 PowerShell을 열고 접속합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssh [USER_ID]@[IP_ADDRESS]&lt;/code&gt; // 예: &lt;code&gt;ssh pi@192.168.0.100&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;ssh pi@raspberrypi.local&lt;/code&gt; 로도 접속 가능합니다.&lt;br /&gt;불가능한 경우 arp 테이블을 초기화하거나 로컬 네트워크를 점검해 보세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무선 인터페이스 비활성화:&lt;/b&gt; 유선 랜을 사용 중이라면 블루투스 안정성을 위해 Wi-Fi를 차단합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;방법 1 (커널 수준 차단 - rfkill):&lt;/b&gt; 하드웨어 라디오를 직접 제어합니다.&lt;br /&gt;&lt;code&gt;sudo rfkill block wifi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방법 2 (네트워크 매니저 차단 - nmcli):&lt;/b&gt; 소프트웨어 인터페이스 충돌을 방지합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sudo nmcli device disconnect wlan0 sudo nmcli radio wifi off&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;참고:&lt;/b&gt; rfkill은 하드웨어 자원 간섭 차단에 효과적이며, nmcli는 인터페이스 관리에 유용하므로 두 방법 모두 수행하는 것이 가장 확실합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4단계: [선택] 네트워크 장애 트러블슈팅&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QUXkZ/dJMcadu24Vq/KvA0RXV0BQgdVJQhJiKpA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QUXkZ/dJMcadu24Vq/KvA0RXV0BQgdVJQhJiKpA1/img.png&quot; data-alt=&quot;(C) Cloudflare&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QUXkZ/dJMcadu24Vq/KvA0RXV0BQgdVJQhJiKpA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQUXkZ%2FdJMcadu24Vq%2FKvA0RXV0BQgdVJQhJiKpA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;270&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(C) Cloudflare&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;만약 IP 할당이 되지 않거나, 핑(Ping) 타임아웃이 발생하거나, 부팅할 때마다 MAC 주소가 변한다면 이 단계를 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4.1. MAC 주소 고정 (MAC Randomization 해제)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 OS의 보안 기능을 해제하여 공유기에서 설정한 IP 바인딩이 무효화되지 않도록 합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;설정 파일 생성:&lt;/b&gt;&lt;code&gt;sudo nano /etc/NetworkManager/conf.d/10-ignore-mac-randomization.conf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;아래 내용 입력:&lt;/b&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[device] 
wifi.scan-rand-mac-address=no 
[connection] 
ethernet.cloned-mac-address=preserve 
wifi.cloned-mac-address=preserve&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서비스 재시작:&lt;/b&gt; &lt;code&gt;sudo systemctl restart NetworkManager&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4.2. 커널 매개변수를 통한 MAC 강제 할당 (보조 방법)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방법으로도 MAC 주소가 변한다면 부팅 단계에서 하드웨어 주소를 고정합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;설정 수정:&lt;/b&gt; &lt;code&gt;sudo nano /boot/firmware/cmdline.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기존 내용 끝에 한 칸 띄우고 추가:&lt;/b&gt; &lt;code&gt;smsc95xx.macaddr=[HW_MAC]&lt;/code&gt; // 예: &lt;code&gt;2C:F0:5D:96:24:66&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;재부팅:&lt;/b&gt; &lt;code&gt;sudo reboot&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4.3. ARP 캐시 초기화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공유기와 PC에 남아있는 잘못된 MAC-IP 매칭 정보를 지웁니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;공유기:&lt;/b&gt; 관리 페이지 접속 &amp;rarr; DHCP 고정 할당 목록에서 기존 라즈베리파이 항목 삭제 &amp;rarr; 랜선 재연결.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Windows PC:&lt;/b&gt; PowerShell(관리자 권한)에서 실행.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arp -d * ping [IP_ADDRESS]&lt;/code&gt; // 예: &lt;code&gt;ping 192.168.0.100&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5단계: [선택] 이중 NAT 환경 대응 (건물 모뎀 + 개인 공유기)&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TUqQh/dJMcagSU6qv/kKcEjKLCskSb8IEnVsskK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TUqQh/dJMcagSU6qv/kKcEjKLCskSb8IEnVsskK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TUqQh/dJMcagSU6qv/kKcEjKLCskSb8IEnVsskK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTUqQh%2FdJMcagSU6qv%2FkKcEjKLCskSb8IEnVsskK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;262&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중 NAT 환경이 아닌 경우 생략합니다.&lt;br /&gt;PC와 라즈베리파이가 같은 공유기에 있음에도 대역폭 불일치로 서로 보이지 않을 때 수행합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;DNS 서버 강제 지정:&lt;/b&gt; 인터넷 연결은 되나 도메인(tailscale.com 등) 접속이 안 될 때 수정합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sudo nano /etc/resolv.conf&lt;/code&gt; # 기존 내용 삭제 후 아래 추가nano의 경우 작성 후 Ctrl+O, Enter, Ctrl+X 로 저장 후 종료합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nameserver 8.8.8.8
nameserver 8.8.4.4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PC IP 대역 수동 설정 (Windows):&lt;/b&gt; PC가 상위 모뎀(예: 192.168.55.x)의 주소를 받아올 경우, 하위 공유기 대역(예: 192.168.0.x)으로 강제 고정합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설정 &amp;rarr; 네트워크 &amp;rarr; 이더넷 &amp;rarr; 수동(IPv4)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IP 주소:&lt;/b&gt; [PC_STATIC_IP] // 예: 192.168.0.110 (공유기 범위 내)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서브넷 접두사:&lt;/b&gt; 24 // 서브넷 마스크인 경우: 255.255.255.0&lt;/li&gt;
&lt;li&gt;&lt;b&gt;게이트웨이:&lt;/b&gt; [GATEWAY] // 예: 192.168.0.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6단계:&lt;/b&gt; &lt;b&gt;외부 접속(Tailscale) 및 OCI 서버 연동&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OwcXA/dJMcabjNELc/fnLtuts8PkpVwy4skfZHuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OwcXA/dJMcabjNELc/fnLtuts8PkpVwy4skfZHuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OwcXA/dJMcabjNELc/fnLtuts8PkpVwy4skfZHuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOwcXA%2FdJMcabjNELc%2FfnLtuts8PkpVwy4skfZHuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;154&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트포워딩 없이 외부에서도 내 서버에 안전하게 접속할 수 있도록 VPN 환경을 구축합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;라즈베리파이 설치:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;화면에 나타나는 URL로 브라우저에서 로그인하여 인증합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up&lt;/code&gt; 을 입력합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OCI 서버 연동:&lt;/b&gt; OCI 인스턴스에도 위와 동일한 과정을 수행하여 라즈베리파이와 OCI를 같은 가상망으로 묶습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인증 유지:&lt;/b&gt; Tailscale 대시보드에서 라즈베리파이 장비의 Disable Key Expiry 옵션을 활성화합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적으로 Tailscale에선 6개월마다 디바이스 인증 정보를 초기화합니다. 이를 방지하기 위한 옵션입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;curl&lt;/code&gt;로 tailscale 다운로드 시 타임아웃 에러가 발생하는 경우, 5단계: 이중 NAT 환경 대응에서 네임서버 추가 작업을 진행하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7단계: SSH 접속 최적화 (Config 및 무암호 로그인)&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lbI7L/dJMcaaLWqnL/fNhIQsNCtv1hf3ErWnAXIK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lbI7L/dJMcaaLWqnL/fNhIQsNCtv1hf3ErWnAXIK/img.jpg&quot; data-alt=&quot;(C) IPXO&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lbI7L/dJMcaaLWqnL/fNhIQsNCtv1hf3ErWnAXIK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlbI7L%2FdJMcaaLWqnL%2FfNhIQsNCtv1hf3ErWnAXIK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;269&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;359&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(C) IPXO&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별칭(Alias)으로 즉시 접속하고 비밀번호 입력을 생략하는 환경을 만듭니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SSH Config 작성:&lt;/b&gt; PC의 ~/.ssh/config에 저장합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HostName \[TAILSCALE\_IP\] // 예: 100.x.y.z User \[USER\_ID\] // 예: pi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무암호 로그인 (키 전송):&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# Windows PowerShell에서 실행 
cat $HOME\.ssh\id_rsa.pub | ssh [ALIAS] &quot;mkdir -p ~/.ssh &amp;amp;&amp;amp; cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최종 확인:&lt;/b&gt; 이제 &lt;code&gt;ssh [ALIAS]&lt;/code&gt;만 입력하면 즉시 로그인이 완료됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;8단계: 시스템 모니터링 및 유지보수&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;24/7 안정성을 위해 온도를 주기적으로 확인합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;실시간 온도 확인:&lt;/b&gt; &lt;code&gt;watch -n 5 vcgencmd measure_temp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정상 범위:&lt;/b&gt; 50&amp;deg;C ~ 60&amp;deg;C.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주의:&lt;/b&gt; 75&amp;deg;C 이상 지속 시 냉각 솔루션 보강 및 알림 스크립트 추가를 권장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>IT 기술</category>
      <category>OCI</category>
      <category>RaspberryPi</category>
      <category>tailscale</category>
      <category>라즈베리파이</category>
      <category>이중NAT</category>
      <category>홈서버</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/31</guid>
      <comments>https://sinam7.tistory.com/31#entry31comment</comments>
      <pubDate>Sun, 3 May 2026 20:56:10 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] 특정 프로세스 오디오 출력 디바이스 변경 스크립트, 트러블슈팅</title>
      <link>https://sinam7.tistory.com/30</link>
      <description>&lt;h1&gt;[Windows] 특정 프로세스 오디오 출력 디바이스 변경 스크립트, 트러블슈팅&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Firefox 사운드를 블루투스 스피커로 보내기 위해 PowerShell 스크립트를 만들면서&lt;br /&gt;겪은 삽질들을 정리해두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성한 PowerShell 스크립트는 아래에서 확인 가능합니다. Star 한 번씩 부탁드립니다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gist.github.com/sinam7/703412ff6ab17e653141670c4054567f&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://gist.github.com/sinam7/703412ff6ab17e653141670c4054567f&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하고 싶은 건 단순했다. Firefox 에서 틀어놓은 유튜브 소리를 블루투스 스피커로 보내고,&lt;br /&gt;필요하면 다시 기본 출력으로 돌리는 것. 이런 일은 Claude에게 맡기기에 딱이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows는 프로세스별 오디오 라우팅 API를 공식으로 제공하지 않아서,&lt;br /&gt;NirSoft의 &lt;code&gt;SoundVolumeView&lt;/code&gt; / &lt;code&gt;svcl&lt;/code&gt;을 써야 한다.&lt;br /&gt;그 과정에서 여러 가지 문제를 겪었는데, 그 기록을 남겨본다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;0. 준비물&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nirsoft.net/utils/sound_volume_view.html&quot;&gt;SoundVolumeView&lt;/a&gt; (GUI 버전, 디바이스 목록 확인용)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nirsoft.net/utils/sound_volume_command_line.html&quot;&gt;svcl.exe&lt;/a&gt; (콘솔 버전, 스크립트 실행용)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 파일을 같은 폴더에 넣어두면 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. &lt;code&gt;&amp;amp;&lt;/code&gt; 연산자로 exe 실행이 안 됨&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;&amp;amp; : 'C:\...\soundvolumeview-x64' 용어가 cmdlet, 함수, 스크립트 파일 또는
실행할 수 있는 프로그램 이름으로 인식되지 않습니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경로에 &lt;code&gt;.exe&lt;/code&gt;가 없거나, 경로에 공백이 포함된 경우 따옴표 처리가 안 된 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;tex&quot;&gt;&lt;code&gt;# 실행 파일 확장자 포함, 경로 전체를 따옴표로 감쌀 것 (아래 경로는 예시)
$svcl = &quot;C:\Users\User\Desktop\Tools\soundvolumeview-x64\svcl.exe&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. &lt;code&gt;param&lt;/code&gt; 블록 위치 오류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;대입 식이 잘못되었습니다. 대입 연산자의 입력은 변수 또는 속성과 같이
대입을 허용할 수 있는 개체여야 합니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;param&lt;/code&gt; 블록 앞에 관리자 권한 상승 코드를 먼저 배치하면 파싱 오류가 발생한다.&lt;br /&gt;PowerShell에서 &lt;code&gt;param&lt;/code&gt;은 반드시 스크립트 최상단에 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# 맨 위에 param 먼저. 디바이스 이름과 프로세스명은 필요에 맞게 수정할 것
param(
    [string]$Device  = &quot;Philips S2108 Stereo&quot;,
    [string]$Default = &quot;Realtek High Definition Audio&quot;,
    [string]$Process = &quot;firefox&quot;
)

# 그 다음 관리자 권한 상승. svcl 사용을 위해선 관리자 권한이 필요
if (-not ([Security.Principal.WindowsPrincipal]...)) {
    Start-Process powershell -ArgumentList &quot;... -Device `&quot;$Device`&quot; ...&quot; -Verb RunAs
    exit
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자 권한으로 재실행 시 파라미터도 명시적으로 넘겨줘야 기본값이 유지된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 한글 깨짐&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔 출력에서 한글이 &lt;code&gt;??&lt;/code&gt; 또는 알 수 없는 문자로 표시됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크립트 상단에 아래 두 줄 추가.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
chcp 65001 | Out-Null&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 깨진다면 스크립트 파일 자체의 인코딩을 확인하자.&lt;br /&gt;VS Code 기준으로 우측 하단에서 &lt;code&gt;UTF-8 with BOM&lt;/code&gt;으로 저장하면 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. &lt;code&gt;/RemoveAppDefault&lt;/code&gt;가 동작하지 않음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 기본 출력으로 복원하기 위해 &lt;code&gt;/RemoveAppDefault&lt;/code&gt; 명령어를 썼더니&lt;br /&gt;SoundVolumeView GUI가 그냥 열리거나, 아무 반응이 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/RemoveAppDefault&lt;/code&gt;는 SoundVolumeView 공식 문서에 없는 명령어다.&lt;br /&gt;환각 문제는 역시 완벽하게 해결될 수 없는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복원할 때도 &lt;code&gt;/SetAppDefault&lt;/code&gt;를 쓰되, 시스템 기본 디바이스 이름을 직접 지정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 Firefox 오디오 라우팅 상태 확인:&lt;/p&gt;
&lt;pre class=&quot;powershell&quot;&gt;&lt;code&gt;&amp;amp; $svcl /scomma &quot;$env:TEMP\app_check.csv&quot; | Out-Null
Get-Content &quot;$env:TEMP\app_check.csv&quot; -Encoding UTF8 | Select-String &quot;firefox&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 결과에서 &lt;code&gt;Active&lt;/code&gt; 항목의 Device Name이 현재 라우팅된 디바이스,&lt;br /&gt;&lt;code&gt;Inactive&lt;/code&gt; 항목이 시스템 기본 디바이스다.&lt;/p&gt;
&lt;pre class=&quot;autohotkey&quot;&gt;&lt;code&gt;Firefox,Application,Render,Philips S2108 Stereo,,,,Active,...
Firefox,Application,Render,Realtek High Definition Audio,,,,Inactive,...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 복원 명령은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;&amp;amp; $svcl /SetAppDefault &quot;Realtek High Definition Audio&quot; all &quot;firefox.exe&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 명령어 실행 시 GUI가 열림&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;svcl 명령어 실행 시 터미널 출력 없이 GUI 창으로 열림.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PowerShell에서 슬래시(&lt;code&gt;/&lt;/code&gt;)가 나누기 연산자로 파싱되는 경우가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Start-Process&lt;/code&gt;로 교체하면 안정적으로 동작한다.&lt;/p&gt;
&lt;pre class=&quot;autohotkey&quot;&gt;&lt;code&gt;Start-Process -FilePath $svcl `
    -ArgumentList &quot;/SetAppDefault `&quot;$Device`&quot; all `&quot;$Process.exe`&quot;&quot; `
    -Wait -WindowStyle Hidden&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;-WindowStyle Hidden&lt;/code&gt;으로 창이 뜨는 것도 막을 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;맺으며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows에서 프로세스별 오디오 라우팅은 공식 API가 없다 보니,&lt;br /&gt;제3자 툴에 의존할 수밖에 없고 그 과정에서 문서화가 덜 된 부분들이 꽤 있다.&lt;br /&gt;Windows 11에서는 좀 나아졌으려나 모르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/RemoveAppDefault&lt;/code&gt;처럼 없는 명령어를 추측으로 쓰다가 삽질한 게 가장 아팠다. (Claude가.)&lt;br /&gt;결국 실제 디바이스 목록을 csv로 뽑아서 확인하고 나서야 해결됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 안 된다 싶으면 추측보다 먼저 상태를 확인하는 게 맞다.&lt;/p&gt;
&lt;pre class=&quot;powershell&quot;&gt;&lt;code&gt;# 현재 오디오 라우팅 상태 확인 (항상 여기서 시작)
&amp;amp; $svcl /scomma &quot;$env:TEMP\check.csv&quot; | Out-Null
Get-Content &quot;$env:TEMP\check.csv&quot; -Encoding UTF8 | Select-String &quot;firefox&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h6&gt;&amp;nbsp;&lt;/h6&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이 글은 Claude를 통해 스크립트를 작성한 뒤, Troubleshooting을 이전 글 문체로 작성시킨 뒤 최소한의 퇴고만 거쳐 게시되었습니다.&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>IT 기술</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/30</guid>
      <comments>https://sinam7.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 30 Mar 2026 23:57:01 +0900</pubDate>
    </item>
    <item>
      <title>OpenAI 무료 토큰(Complimentary Daily Tokens)이 사용되지 않는 이유</title>
      <link>https://sinam7.tistory.com/29</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;OpenAI_Icon_0.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfgxNa/dJMcafZNnYQ/1N8mSeiuFWJBRtQ1ok2CZ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfgxNa/dJMcafZNnYQ/1N8mSeiuFWJBRtQ1ok2CZ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfgxNa/dJMcafZNnYQ/1N8mSeiuFWJBRtQ1ok2CZ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfgxNa%2FdJMcafZNnYQ%2F1N8mSeiuFWJBRtQ1ok2CZ0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;200&quot; height=&quot;200&quot; data-filename=&quot;OpenAI_Icon_0.jpeg&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;OpenAI 무료 토큰(Complimentary Daily Tokens)이 사용되지 않는 이유&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(insufficient quota detected.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 배경&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI API에 Data Sharing 옵트인을 하면 매일 무료 토큰을 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tier 3-5 기준으로 대형 모델(gpt-5, gpt-4.1, gpt-4o, o1, o3 등) 1M 토큰,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소형 모델(gpt-5-mini, gpt-4o-mini, o3-mini 등) 10M 토큰. Tier 1-2는 각각 250K, 2.5M입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 페이지에 &quot;You're enrolled for complimentary daily tokens&quot;도 잘 떠 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 API를 호출하면 이게 나옵니다.&lt;/p&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;Error code: 429 - You exceeded your current quota,
please check your plan and billing details.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 무료 토큰 범위 안인데 429가 뜹니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 원인: 잔고가 0 이하&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한참 찾았는데 원인은 단순했습니다. &lt;b&gt;계정 잔고(Balance)가 양수여야&lt;/b&gt; 무료 토큰이 작동합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0balance.png&quot; data-origin-width=&quot;923&quot; data-origin-height=&quot;108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Adt92/dJMcaf6zWtN/kdBH5N0asl3uoMroEKcNSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Adt92/dJMcaf6zWtN/kdBH5N0asl3uoMroEKcNSk/img.png&quot; data-alt=&quot;잔고가 $0가 되면 API 요청 전부가 막히는 듯 합니다. 킬 스위치 같네요.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Adt92/dJMcaf6zWtN/kdBH5N0asl3uoMroEKcNSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAdt92%2FdJMcaf6zWtN%2FkdBH5N0asl3uoMroEKcNSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;923&quot; height=&quot;108&quot; data-filename=&quot;0balance.png&quot; data-origin-width=&quot;923&quot; data-origin-height=&quot;108&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;잔고가 $0가 되면 API 요청 전부가 막히는 듯 합니다. 킬 스위치 같네요.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;무료&quot;라면서 잔고가 있어야 된다는 건 좀 이상하긴 한데, 그렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크레딧을 다 써서 잔고가 0 이하로 내려가면, 무료 토큰까지 같이 막힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커뮤니티에서도 Tier 5인데 -$0.25 잔고 때문에 안 됐다는 사례가 있었습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;balance.png&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2v19q/dJMcaaqFMQG/W2jjUPjUxC5skRbxQO4ihk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2v19q/dJMcaaqFMQG/W2jjUPjUxC5skRbxQO4ihk/img.png&quot; data-alt=&quot;부가세는 별도로 청구될 수 있습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2v19q/dJMcaaqFMQG/W2jjUPjUxC5skRbxQO4ihk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2v19q%2FdJMcaaqFMQG%2FW2jjUPjUxC5skRbxQO4ihk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;284&quot; height=&quot;160&quot; data-filename=&quot;balance.png&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;부가세는 별도로 청구될 수 있습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://platform.openai.com/settings/organization/billing/overview&quot;&gt;Billing Overview&lt;/a&gt;에서 &quot;Add to balance&quot;로 크레딧을 충전하면 됩니다. 최소 $5.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;충전 후 시스템 반영에 몇 분 걸릴 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 그래도 안 되면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잔고를 충전했는데도 안 된다면 확인할 게 몇 가지 더 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-1. Data Sharing 옵트인&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;datasharing.png&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bja4fw/dJMcac9NT9N/hWpIaswDE6snv2KKkgeWS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bja4fw/dJMcac9NT9N/hWpIaswDE6snv2KKkgeWS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bja4fw/dJMcac9NT9N/hWpIaswDE6snv2KKkgeWS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbja4fw%2FdJMcac9NT9N%2FhWpIaswDE6snv2KKkgeWS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;713&quot; height=&quot;280&quot; data-filename=&quot;datasharing.png&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://platform.openai.com/settings/organization/data-controls/sharing&quot;&gt;Data Controls &amp;gt; Sharing&lt;/a&gt; 페이지에 가서, &quot;You're enrolled for complimentary daily tokens&quot; 문구가 보이는지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안 보이면 옵트인이 안 된 겁니다. 옵트인은 Organization Owner만 할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-2. API 키가 옵트인된 프로젝트의 키인지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Data Sharing을 특정 프로젝트에만 활성화했다면, 해당 프로젝트의 API 키로 호출해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 프로젝트 키로 쏘면 무료 토큰이 적용 안 됩니다. &quot;Enable for all projects&quot;로 했으면 상관없습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-3. 일일 한도 초과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무료 토큰에도 일일 한도가 있고, 매일 00:00 UTC에 초기화됩니다. 한도를 넘긴 요청부터는 정상 요금으로 부과됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-4. 미지원 모델&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fine-tuned 모델, Fine-tuning training, Evals, Tool use는 무료 토큰 대상이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지원 모델 목록은 &lt;a href=&quot;https://help.openai.com/en/articles/10306912-sharing-feedback-evaluation-and-fine-tuning-data-and-api-inputs-and-outputs-with-openai&quot;&gt;공식 문서&lt;/a&gt; 혹은 &lt;a href=&quot;https://platform.openai.com/settings/organization/data-controls/sharing&quot;&gt;옵트인 설정 페이지&lt;/a&gt;에서 확인하세요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 카드 등록 시 $5 결제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 결제 수단을 등록하면 $5가 바로 빠집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 결제가 아니라 임시 인증용 홀드(Temporary Authorization Hold)입니다. 7일 이내에 자동 환불됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://help.openai.com/en/articles/7438062-after-updating-my-api-payment-method-i-noticed-a-5-charge-is-this-a-temporary-hold&quot;&gt;OpenAI 공식 안내 - $5 Temporary Hold&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 참고&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://help.openai.com/en/articles/10306912-sharing-feedback-evaluation-and-fine-tuning-data-and-api-inputs-and-outputs-with-openai&quot;&gt;OpenAI 공식 - Data Sharing &amp;amp; Complimentary Tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://help.openai.com/en/articles/7438062-after-updating-my-api-payment-method-i-noticed-a-5-charge-is-this-a-temporary-hold&quot;&gt;OpenAI 공식 - $5 Temporary Hold&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://community.openai.com/t/api-data-sharing-free-credits-not-working/1250558/5&quot;&gt;OpenAI Community - API Data Sharing Free Credits Not Working&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://community.openai.com/t/issue-understanding-free-tier-token-usage-and-billing-in-openai-dashboard/1153697&quot;&gt;OpenAI Community - Issue Understanding Free Tier Token Usage and Billing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT 기술</category>
      <category>429에러</category>
      <category>API</category>
      <category>API빌링</category>
      <category>Billing</category>
      <category>Complimentary Tokens</category>
      <category>Data Sharing</category>
      <category>OpenAI</category>
      <category>무료토큰</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/29</guid>
      <comments>https://sinam7.tistory.com/29#entry29comment</comments>
      <pubDate>Tue, 10 Feb 2026 16:36:43 +0900</pubDate>
    </item>
    <item>
      <title>n8n 공부 방법 완벽 가이드: 초보자도 7일 만에 자동화 전문가 되는 법</title>
      <link>https://sinam7.tistory.com/28</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wHfSz/dJMcaaRBV92/TKSX3K5GzcLUZ9BpktlAJ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wHfSz/dJMcaaRBV92/TKSX3K5GzcLUZ9BpktlAJ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wHfSz/dJMcaaRBV92/TKSX3K5GzcLUZ9BpktlAJ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwHfSz%2FdJMcaaRBV92%2FTKSX3K5GzcLUZ9BpktlAJ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;426&quot; height=&quot;426&quot; data-filename=&quot;0.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;&lt;b&gt;n8n 공부 방법 완벽 가이드: 초보자도 7일 만에 자동화 전문가 되는 법&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동화, AI, 그리고 노코드 시대. 이제 코딩을 몰라도 누구나 업무 자동화와 AI 연동을 할 수 있습니다. 하지만 n8n 공부 방법을 처음 접하는 분들은 어디서부터 시작해야 할지 막막하죠. &quot;실습 중심으로 빠르게 배우고 싶다&quot;, &quot;실무에 바로 적용하고 싶다&quot;, &quot;비용과 수익화까지 궁금하다&quot;는 분들을 위해, 이 글에서는 n8n 공부 방법의 모든 것을 7일 만에 마스터할 수 있는 로드맵으로 정리했습니다. 초보자도 따라할 수 있는 실전 예제와 인프런 n8n 강의, 커뮤니티 활용법까지, 지금 바로 자동화 전문가로 성장해보세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6ZipL/dJMcahiTUcC/QqQQgVcKde4RDFvnBD0gok/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6ZipL/dJMcahiTUcC/QqQQgVcKde4RDFvnBD0gok/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6ZipL/dJMcahiTUcC/QqQQgVcKde4RDFvnBD0gok/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6ZipL%2FdJMcahiTUcC%2FQqQQgVcKde4RDFvnBD0gok%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1384&quot; height=&quot;752&quot; data-filename=&quot;1.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;n8n 공부 방법 시작하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법을 제대로 익히려면, 먼저 n8n이 무엇인지, 왜 배워야 하는지부터 이해해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;n8n이란? 자동화 도구의 기본 개념&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n은 다양한 앱과 서비스를 연결해 반복 업무를 자동화하는 오픈소스 노코드 플랫폼입니다. 복잡한 코딩 없이도 워크플로우를 시각적으로 설계할 수 있어, 초보자도 쉽게 접근할 수 있습니다. 예를 들어, 이메일을 자동 분류하거나, 유튜브 영상을 요약해 텔레그램으로 보내는 등, 실무에 바로 쓸 수 있는 자동화가 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;n8n을 공부해야 하는 이유&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법을 익히면, 단순 반복 업무를 줄이고, AI와 연동해 창의적인 자동화 시스템을 구축할 수 있습니다. 특히, ChatGPT, Notion, Google Sheets 등 다양한 서비스와 연동이 쉬워, 실무 생산성을 극대화할 수 있습니다. 개발자가 아니어도, 누구나 자동화 전문가로 성장할 수 있는 시대입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d27pGp/dJMcadncPF2/oUDkNpG9ChHEHtj32bEyDK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d27pGp/dJMcadncPF2/oUDkNpG9ChHEHtj32bEyDK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d27pGp/dJMcadncPF2/oUDkNpG9ChHEHtj32bEyDK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd27pGp%2FdJMcadncPF2%2FoUDkNpG9ChHEHtj32bEyDK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1384&quot; height=&quot;752&quot; data-filename=&quot;2.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인프런 n8n 강의로 기초 다지기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법의 첫걸음은 체계적인 강의와 실습입니다. 인프런 n8n 강의는 초보자도 쉽게 따라할 수 있도록 구성되어 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인프런 n8n 강의 추천 및 수강 후기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프런에 포함된 여러 강의는 실무에 바로 적용 가능한 예제와 워크플로우를 제공합니다. 수강생들은 &quot;코딩을 몰라도 따라할 수 있다&quot;, &quot;실습 중심이라 바로 적용 가능하다&quot;는 후기를 남기고 있습니다. 실제로 2,000명 이상의 수강생이 높은 만족도를 보이고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;무료 vs 유료 강의 비교&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무료 강의는 기초 개념과 간단한 예제 위주로, 입문자에게 적합합니다. 반면, 유료 강의는 실무 중심의 고급 예제, AI 연동, 수익화 전략까지 다루며, 워크플로우 템플릿과 프롬프트 자료도 제공합니다. n8n 공부 방법을 체계적으로 익히고 싶다면 유료 강의가 확실히 효율적입니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;무료 강의&lt;/th&gt;
&lt;th&gt;유료 강의 (인프런)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;난이도&lt;/td&gt;
&lt;td&gt;입문&lt;/td&gt;
&lt;td&gt;입문~고급&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실습&lt;/td&gt;
&lt;td&gt;간단 예제&lt;/td&gt;
&lt;td&gt;실무 중심, 다양한 자동화 예제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;자료&lt;/td&gt;
&lt;td&gt;제한적&lt;/td&gt;
&lt;td&gt;워크플로우, 프롬프트, 노트 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비용&lt;/td&gt;
&lt;td&gt;무료&lt;/td&gt;
&lt;td&gt;5~10만원대(할인 가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;수익화&lt;/td&gt;
&lt;td&gt;미포함&lt;/td&gt;
&lt;td&gt;수익화 전략, 실전 사례 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCsROX/dJMcahDaZTX/TxUjQlU0wuakUSHZN0GrW1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCsROX/dJMcahDaZTX/TxUjQlU0wuakUSHZN0GrW1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCsROX/dJMcahDaZTX/TxUjQlU0wuakUSHZN0GrW1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCsROX%2FdJMcahDaZTX%2FTxUjQlU0wuakUSHZN0GrW1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1384&quot; height=&quot;752&quot; data-filename=&quot;3.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;n8n 실습: 따라하며 배우는 첫 자동화&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 n8n 공부 방법의 핵심, 직접 실습을 통해 첫 자동화를 만들어봅시다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;설치 및 환경 설정 방법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n은 클라우드(웹)와 자체 호스팅(로컬) 두 가지 방식으로 사용할 수 있습니다. 초보자는 웹에서 계정만 만들면 바로 시작할 수 있고, Docker를 활용하면 로컬에서도 쉽게 설치할 수 있습니다. 공식 문서와 인프런 강의에서 설치 과정을 단계별로 안내하니, 그대로 따라하면 어렵지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;첫 번째 워크플로우 만들기 실습&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법의 첫 실습으로, 이메일 자동 분류 워크플로우를 만들어보세요. 트리거(이메일 수신) &amp;rarr; 조건(스팸/일반 분류) &amp;rarr; 액션(폴더 이동) 순서로 노드를 연결하면, 반복적인 메일 분류 업무가 자동화됩니다. 실습을 통해 n8n의 시각적 인터페이스와 노드 연결 방식을 자연스럽게 익힐 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;4.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/upm66/dJMcabprRuk/fuNMkstALLJkGkePpdESqk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/upm66/dJMcabprRuk/fuNMkstALLJkGkePpdESqk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/upm66/dJMcabprRuk/fuNMkstALLJkGkePpdESqk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fupm66%2FdJMcabprRuk%2FfuNMkstALLJkGkePpdESqk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1384&quot; height=&quot;752&quot; data-filename=&quot;4.jpg&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;n8n 자동화 예제 모음&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에 바로 적용 가능한 n8n 자동화 예제를 익히면, n8n 공부 방법이 훨씬 재미있어집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실무에 바로 적용 가능한 자동화 예제 3가지&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;유튜브 영상 요약 및 텔레그램 전송&lt;/b&gt;&lt;br /&gt;RSS 트리거 &amp;rarr; 유튜브 트랜스크립트 추출 &amp;rarr; AI 요약 &amp;rarr; 텔레그램 메시지 전송&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구글 시트 자동 데이터 입력&lt;/b&gt;&lt;br /&gt;웹훅 트리거 &amp;rarr; 데이터 파싱 &amp;rarr; 구글 시트에 자동 기록&lt;/li&gt;
&lt;li&gt;&lt;b&gt;뉴스 요약 및 이메일 발송&lt;/b&gt;&lt;br /&gt;뉴스 API &amp;rarr; AI 요약 &amp;rarr; 이메일 자동 발송&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;AI와 연동한 n8n 활용법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법의 진정한 강점은 AI와의 연동입니다. OpenAI, Claude, Gemini 등 다양한 AI 모델을 API 키만 입력하면 바로 연결할 수 있습니다. 예를 들어, 사용자의 질문을 받아 위키백과에서 정보를 찾아 요약해주는 AI 에이전트를 만들 수 있습니다. 프롬프트 엔지니어링과 메모리 노드를 활용하면, 대화형 AI 챗봇도 손쉽게 구현 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;5.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUoZsy/dJMcabiGBkK/DRkYrTfAYnx1qY3olWQWd0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUoZsy/dJMcabiGBkK/DRkYrTfAYnx1qY3olWQWd0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUoZsy/dJMcabiGBkK/DRkYrTfAYnx1qY3olWQWd0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUoZsy%2FdJMcabiGBkK%2FDRkYrTfAYnx1qY3olWQWd0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;559&quot; data-filename=&quot;5.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7일 만에 마스터하는 n8n 공부 플랜&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짧은 시간에 n8n 공부 방법을 마스터하려면, 체계적인 학습 로드맵이 필요합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;하루별 학습 로드맵 제안&lt;/b&gt;&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;요일&lt;/th&gt;
&lt;th&gt;학습 내용&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1일차&lt;/td&gt;
&lt;td&gt;n8n 개념 이해, 설치 및 환경 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2일차&lt;/td&gt;
&lt;td&gt;기본 인터페이스, 첫 워크플로우 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3일차&lt;/td&gt;
&lt;td&gt;조건, 반복, 데이터 변환 등 핵심 노드 익히기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4일차&lt;/td&gt;
&lt;td&gt;외부 서비스 연동(구글, 텔레그램 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5일차&lt;/td&gt;
&lt;td&gt;AI 연동, 프롬프트 엔지니어링 실습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6일차&lt;/td&gt;
&lt;td&gt;실무 자동화 예제 2~3개 직접 구현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7일차&lt;/td&gt;
&lt;td&gt;수익화 전략, 커뮤니티 자료 탐색&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실습 중심의 학습법 팁&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;따라하기&lt;/b&gt;: 강의와 공식 튜토리얼을 그대로 따라하며 손에 익히세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;작은 성공 경험&lt;/b&gt;: 간단한 워크플로우부터 시작해 점차 난이도를 높이세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제 해결&lt;/b&gt;: 오류가 나면 커뮤니티나 공식 문서에서 해결법을 찾아보세요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;템플릿 활용&lt;/b&gt;: 인프런 강의나 공식 사이트에서 제공하는 워크플로우 템플릿을 적극 활용하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1091&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uimBw/dJMcahDaZU3/Fr0QFEPi0bjrF5H9cWbesk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uimBw/dJMcahDaZU3/Fr0QFEPi0bjrF5H9cWbesk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uimBw/dJMcahDaZU3/Fr0QFEPi0bjrF5H9cWbesk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuimBw%2FdJMcahDaZU3%2FFr0QFEPi0bjrF5H9cWbesk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2000&quot; height=&quot;1091&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1091&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;n8n 활용 비용과 수익화 전략&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법을 익히면, 실제 비용과 수익화 전략도 궁금해집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;n8n 무료/유료 플랜 비교&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n은 오픈소스라 자체 호스팅 시 무료로 사용할 수 있습니다. 클라우드 플랜은 월 20~50달러 수준으로, 관리와 보안이 강화된 환경을 제공합니다. 대부분의 실습과 소규모 프로젝트는 무료로 충분하며, 대규모 서비스나 팀 단위 협업이 필요할 때 유료 플랜을 고려하면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;n8n으로 수익화하는 방법&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;업무 자동화 컨설팅&lt;/b&gt;: 기업이나 프리랜서를 대상으로 자동화 솔루션을 제공&lt;/li&gt;
&lt;li&gt;&lt;b&gt;워크플로우 템플릿 판매&lt;/b&gt;: 실무에 특화된 워크플로우를 템플릿으로 제작해 판매&lt;/li&gt;
&lt;li&gt;&lt;b&gt;교육 및 강의&lt;/b&gt;: n8n 공부 방법을 강의나 워크샵 형태로 제공&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사이드 프로젝트&lt;/b&gt;: 블로그, 유튜브, 뉴스레터 등 콘텐츠 자동화로 부수입 창출&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEFRSv/dJMcahwqYR3/IP7P1SfVijIZYcXGDkmp21/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEFRSv/dJMcahwqYR3/IP7P1SfVijIZYcXGDkmp21/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEFRSv/dJMcahwqYR3/IP7P1SfVijIZYcXGDkmp21/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEFRSv%2FdJMcahwqYR3%2FIP7P1SfVijIZYcXGDkmp21%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;559&quot; data-filename=&quot;7.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;자주 묻는 질문과 커뮤니티 활용법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로, n8n 공부 방법을 익히는 과정에서 자주 나오는 질문과 커뮤니티 활용법을 정리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;초보자가 자주 하는 질문 정리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Q: 코딩을 몰라도 n8n을 쓸 수 있나요?&lt;/b&gt;&lt;br /&gt;A: 네, 대부분의 기능은 노코드로 구현 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Q: AI 연동은 어렵지 않나요?&lt;/b&gt;&lt;br /&gt;A: API 키만 입력하면 쉽게 연동할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Q: 실습 중 오류가 나면 어떻게 하나요?&lt;/b&gt;&lt;br /&gt;A: 공식 문서, 인프런 Q&amp;amp;A, Reddit, GPTers 등 커뮤니티에서 해결법을 찾을 수 있습니다. 이 포스트 아래 덧글로도 물어보세요!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;n8n 커뮤니티 및 자료 추천&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;공식 문서 한글판&lt;/b&gt;: &lt;a href=&quot;https://n8n-docs.infograb.net/learning-path/&quot;&gt;https://n8n-docs.infograb.net/learning-path/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인프런 n8n 강의&lt;/b&gt;: &lt;a href=&quot;https://www.inflearn.com/course/ai-%EC%9E%90%EB%8F%99%ED%99%94-n8n&quot;&gt;https://www.inflearn.com/course/ai-자동화-n8n&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reddit n8n 커뮤니티&lt;/b&gt;: &lt;a href=&quot;https://www.reddit.com/r/n8n/&quot;&gt;https://www.reddit.com/r/n8n/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GPTers 실전 예제&lt;/b&gt;: &lt;a href=&quot;https://www.gpters.org/nocode/&quot;&gt;https://www.gpters.org/nocode/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유튜브 채널, 블로그&lt;/b&gt;: 실습 영상과 템플릿 자료 다수&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n 공부 방법, 이제 어렵지 않습니다. 오늘부터 7일만 투자해 자동화 전문가로 성장해보세요. 궁금한 점은 언제든 아래 댓글로 남겨주세요. 여러분의 자동화 여정을 응원합니다!&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고자료&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/n8n/comments/1j988ab/whats_the_best_way_to_master_n8n_from_scratch/?tl=ko&quot;&gt;Reddit - The heart of the internet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://apidog.com/kr/blog/getting-started-with-n8n-kr/&quot;&gt;n8n 튜토리얼: 초보자를 위한 n8n 시작 가이드&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ai-%EC%9E%90%EB%8F%99%ED%99%94-n8n?srsltid=AfmBOooEfnLdmcXgoiV0DCBhRuJOtVmNPzXK7bCSXOCVC_U-8F_9mD3p&quot;&gt;[인프런어워드 베스트셀러] 코딩 없이 AI 자동화 전문가가 되는 법, n8n 완벽 가이드 강의 | 남박사 - 인프런&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gpters.org/nocode/post/insaeng-ceos-n8n-gyeongheomgi-buje-ceos-mannameun-neomu-eoryeoweo-536vfOHYOBEI6Qc&quot;&gt;인생 첫 n8n 경험기 (부제: 첫 만남은 너무 어려워)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://n8n-docs.infograb.net/learning-path/&quot;&gt;학습 경로 | n8n 공식 기술 문서 한글판&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT 기술/n8n</category>
      <category>n8n공부방법</category>
      <category>n8n실습</category>
      <category>n8n자동화예제</category>
      <category>노코드자동화</category>
      <category>인프런n8n</category>
      <category>자동화공부</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/28</guid>
      <comments>https://sinam7.tistory.com/28#entry28comment</comments>
      <pubDate>Wed, 21 Jan 2026 20:23:09 +0900</pubDate>
    </item>
    <item>
      <title>[n8n] Cloud 환경에서 Threads 스크래핑하기 - 삽질 기록</title>
      <link>https://sinam7.tistory.com/27</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 배경&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텔레그램 봇을 만들고 있었습니다. 링크를 보내면 AI가 내용을 요약해주는 그런 거요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 Threads 링크가 문제였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Threads는 JavaScript로 콘텐츠를 렌더링합니다. 단순 HTTP Request로는 빈 페이지만 옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 자동화(Puppeteer 같은 거)가 필요하다는 뜻이죠. n8n에서 어떻게든 해봅시다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 시도 1: Puppeteer 노드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n에 Puppeteer 커뮤니티 노드가 있다는 걸 알았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치하려고 했더니... &lt;b&gt;n8n Cloud는 커뮤니티 노드 설치가 안 된답니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Self-hosted면 가능한데, Cloud는 보안 문제로 막혀있습니다. 그럼 Code 노드에서 직접?&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;const puppeteer = require('puppeteer');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;역시 안 됩니다.&lt;/b&gt; Cloud 환경에 Puppeteer가 설치되어 있을 리가 없죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 방향을 틀었습니다. n8n 내부에서 해결하는 건 포기.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 시도 2: 외부 서비스 검토&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 자동화를 외부에서 돌리고, n8n에서 API로 호출하는 방식을 찾아봤습니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;서비스&lt;/th&gt;
&lt;th&gt;장점&lt;/th&gt;
&lt;th&gt;단점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Browserless&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Puppeteer 직접 실행&lt;/td&gt;
&lt;td&gt;무료 티어 제한적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;ScrapingBee&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;간단한 API&lt;/td&gt;
&lt;td&gt;JS 렌더링 품질 불확실&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Apify&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;커스텀 Actor 가능, 무료 크레딧&lt;/td&gt;
&lt;td&gt;러닝커브&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apify를 선택했습니다. 월 $5 무료 크레딧이 있고, Puppeteer로 원하는 대로 코드를 짤 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 해결: Apify Actor 만들기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-1. Actor 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apify Console에서 새 Actor를 만듭니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Template: &lt;b&gt;JS + Puppeteer + Chrome&lt;/b&gt; 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-2. 코드 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;src/main.js&lt;/code&gt;를 아래처럼 작성합니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { Actor } from 'apify';
import { PuppeteerCrawler } from 'crawlee';

await Actor.init();

const input = await Actor.getInput();

const crawler = new PuppeteerCrawler({
    async requestHandler({ page, request }) {
        await page.goto(request.url, { waitUntil: 'networkidle0' });
        await new Promise(resolve =&amp;gt; setTimeout(resolve, 3000));

        const results = await page.evaluate(() =&amp;gt; {
            const posts = [];
            let originalAuthor = null;

            document.querySelectorAll('div[data-pressable-container=&quot;true&quot;]').forEach((el, index) =&amp;gt; {
                const authorLink = el.querySelector('a[href^=&quot;/@&quot;]');
                const authorId = authorLink?.getAttribute('href') || null;
                const authorName = authorLink?.innerText || null;

                // 첫 번째 게시물 작성자를 원본 작성자로 저장
                if (index === 0 &amp;amp;&amp;amp; authorId) {
                    originalAuthor = authorId;
                }

                const contentSpans = el.querySelectorAll('span[dir=&quot;auto&quot;]');
                const content = [];
                contentSpans.forEach(span =&amp;gt; {
                    const text = span.innerText?.trim();
                    if (text &amp;amp;&amp;amp; text !== authorName &amp;amp;&amp;amp; text !== &quot;더 보기&quot; &amp;amp;&amp;amp; text.length &amp;gt; 2) {
                        content.push(text);
                    }
                });

                const timeEl = el.querySelector('time');
                const timestamp = timeEl?.getAttribute('datetime') || null;

                // 이미지: 프로필 썸네일 제외
                const images = [];
                el.querySelectorAll('img').forEach(img =&amp;gt; {
                    const src = img.getAttribute('src');
                    if (src &amp;amp;&amp;amp; !src.includes('s150x150') &amp;amp;&amp;amp; !src.includes('s42x42')) {
                        images.push(src);
                    }
                });

                const postLinkEl = el.querySelector('a[href*=&quot;/post/&quot;]');
                const postUrl = postLinkEl ? `https://www.threads.net${postLinkEl.getAttribute('href')}` : null;

                posts.push({
                    authorId,
                    authorName,
                    content: content.join('\n'),
                    timestamp,
                    images,
                    postUrl,
                    isOriginalAuthor: authorId === originalAuthor
                });
            });

            // 원본 작성자 게시물 또는 관련 댓글만 필터링
            const originalPostPattern = originalAuthor ? originalAuthor.replace('/@', '') : null;

            return posts.filter(post =&amp;gt; {
                if (post.authorId === originalAuthor) return true;
                if (originalPostPattern &amp;amp;&amp;amp; post.postUrl?.includes(originalPostPattern)) return true;
                return false;
            });
        });

        await Actor.pushData(results);
    },
});

await crawler.run([input.url]);

await Actor.exit();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-3. Input Schema 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;.actor/input_schema.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
    &quot;title&quot;: &quot;Threads Scraper&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;schemaVersion&quot;: 1,
    &quot;properties&quot;: {
        &quot;url&quot;: {
            &quot;title&quot;: &quot;Threads Post URL&quot;,
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;스크래핑할 Threads 게시물 URL&quot;,
            &quot;editor&quot;: &quot;textfield&quot;
        }
    },
    &quot;required&quot;: [&quot;url&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-4. 삽질 포인트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 몇 가지 삽질이 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) &lt;code&gt;page.waitForTimeout&lt;/code&gt; 안 됨&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 Puppeteer에서 deprecated 되었다고 하더군요.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// ❌ 안 됨
await page.waitForTimeout(3000);

// ✅ 이렇게
await new Promise(resolve =&amp;gt; setTimeout(resolve, 3000));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) DOM 선택자&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Threads는 React Native 웹 빌드라서 클래스명이 &lt;code&gt;x1lliihq&lt;/code&gt; 같은 난독화된 형태입니다. 클래스명으로 잡으면 언제 바뀔지 모릅니다. 그래서 상대적으로 안정적으로 보이는 속성을 선택했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;div[data-pressable-container=&quot;true&quot;]&lt;/code&gt; - 게시물 컨테이너&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a[href^=&quot;/@&quot;]&lt;/code&gt; - 작성자 링크&lt;/li&gt;
&lt;li&gt;&lt;code&gt;time&lt;/code&gt; - 타임스탬프&lt;/li&gt;
&lt;li&gt;&lt;code&gt;span[dir=&quot;auto&quot;]&lt;/code&gt; - 본문 텍스트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 프로필 이미지 필터링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 &lt;code&gt;profile_pic&lt;/code&gt; 문자열로 필터링하려 했는데, CDN URL에 그런 패턴이 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 썸네일 사이즈로 구분했습니다: &lt;code&gt;s150x150&lt;/code&gt;, &lt;code&gt;s42x42&lt;/code&gt;가 포함된 URL은 프로필 이미지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4) 피드 추천 게시물 섞임&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Threads가 관련 없는 추천 게시물도 같이 보여줍니다. 원본 작성자 게시물이거나, 원본 게시물에 대한 댓글만 필터링하는 로직을 추가했습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. n8n 연동&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Actor를 직접 Tool로 붙이면 문제가 있습니다. Actor 실행 API는 메타데이터만 반환하고, 실제 데이터는 Dataset에 따로 저장됩니다. API를 2번 호출해야 하는 셈이죠:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Actor 실행 &amp;rarr; &lt;code&gt;defaultDatasetId&lt;/code&gt; 획득&lt;/li&gt;
&lt;li&gt;Dataset 조회 &amp;rarr; 실제 데이터 획득&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI Agent에 Tool로 붙이려면 이걸 하나로 묶어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 Actor Tool과 HTTP Request Tool을 같이 써도 되지만, 이러면 별도의 프롬프팅이 더 필요합니다. 실패할 수도 있고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 저는 실패했습니다. 그래서,&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Sub-workflow로 해결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;새 Workflow 생성&lt;/b&gt;: &lt;code&gt;Threads Scraper&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;노드 1: When Executed by Another Workflow&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input data mode: &lt;code&gt;Define using fields below&lt;/code&gt;.&lt;br /&gt;Add field 누르고,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Name: &lt;code&gt;url&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Type: &lt;code&gt;String&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;노드 2: Apify : Run an Actor&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OAuth로 로그인해주시고,&lt;/li&gt;
&lt;li&gt;Resource: &lt;code&gt;Actor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Operation: &lt;code&gt;Run an Actor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Actor Source: &lt;code&gt;Apify Store Actors&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Actor: From list - &lt;code&gt;Thread Post Parser (sinam7/thread-post-parser)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Input JSON: (&lt;u&gt;Expression&lt;/u&gt; 모드)
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{ &quot;url&quot;: &quot;{{ $json.url }}&quot; }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Wait for Finish 활성화&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;노드 3: HTTP Request (Dataset 조회)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Method: &lt;code&gt;GET&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;URL: &lt;code&gt;https://api.apify.com/v2/datasets/{{ $json.defaultDatasetId }}/items&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Authentication: 동일&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 메인 Workflow의 AI Agent에 &lt;b&gt;Call n8n Workflow Tool&lt;/b&gt;로 연결하면 끝입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 마무리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최종 구조&lt;/h3&gt;
&lt;pre class=&quot;mathematica&quot;&gt;&lt;code&gt;Telegram Trigger 
  &amp;rarr; URL 파싱 
  &amp;rarr; Threads Scraper (Sub-workflow)
    &amp;rarr; Actor 실행
    &amp;rarr; Dataset 조회
  &amp;rarr; AI 요약 
  &amp;rarr; Telegram 응답&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 됩니다.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Threads 게시물 URL을 보내면 본문 + 댓글까지 긁어서 AI가 요약해줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Threads DOM 구조는 언제든 바뀔 수 있습니다. 선택자 업데이트가 필요할 수 있어요.&lt;/li&gt;
&lt;li&gt;Apify 무료 티어는 월 $5 크레딧입니다. 가벼운 용도로는 충분합니다.&lt;/li&gt;
&lt;li&gt;Self-hosted n8n이면 그냥 Puppeteer 노드 쓰면 됩니다. Cloud의 한계죠.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>IT 기술/n8n</category>
      <category>Apify</category>
      <category>n8n</category>
      <category>Threads</category>
      <category>스크래핑</category>
      <category>쓰레드</category>
      <category>워크플로</category>
      <category>자동화</category>
      <category>크롤링</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/27</guid>
      <comments>https://sinam7.tistory.com/27#entry27comment</comments>
      <pubDate>Thu, 27 Nov 2025 22:12:50 +0900</pubDate>
    </item>
    <item>
      <title>[Claude Code] 마켓플레이스 플러그인 설치 실패 (Permission denied) 오류 해결</title>
      <link>https://sinam7.tistory.com/26</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-20 오후 8.48.54.png&quot; data-origin-width=&quot;1936&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CfYCf/dJMcadNTQ7d/XrSonTagaBI7Cf7ZoqEYP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CfYCf/dJMcadNTQ7d/XrSonTagaBI7Cf7ZoqEYP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CfYCf/dJMcadNTQ7d/XrSonTagaBI7Cf7ZoqEYP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCfYCf%2FdJMcadNTQ7d%2FXrSonTagaBI7Cf7ZoqEYP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1936&quot; height=&quot;136&quot; data-filename=&quot;스크린샷 2025-11-20 오후 8.48.54.png&quot; data-origin-width=&quot;1936&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code에 새 Skill을 등록하기 위해 &lt;code&gt;/plugin marketplace install&lt;/code&gt; 명령어를 사용했는데, 어라?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플러그인 설치에 실패했습니다. 아무래도 문제가 생기긴 했나봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 이런 문제가 터지면 기계엔 잘못이 없고, 제 문제일 가능성이 1.0 정도 되겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자, 바로 해결해보도록 합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사진 속 &lt;b&gt;Permission denied (publickey) 문제는 ssh 키 관련 문제&lt;/b&gt;로, git@github.com에 연결된 ssh key가 잘못되었거나 없기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. SSH key 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH 키가 없어서 생긴 문제라면, &lt;b&gt;SSH 키를 만들면 되겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763640021394&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ssh-keygen -t rsa -C &amp;ldquo;메모&amp;rdquo;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH key를 RSA 방식으로 만들겠다는 뜻이고, 뒤에 -C로 시작하는 파라미터는 메모용이니 생략하셔도 됩니다. 깃허브 이메일을 적어도 괜찮겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 명령어를 입력하면 대략 아래의 흐름으로 진행됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1763640263513&quot; class=&quot;gherkin&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Generating public/private rsa key pair.
Enter file in which to save the key (~/.ssh/id_rsa): 
Enter passphrase for &quot;~/.ssh/id_rsa&quot; (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ~/.ssh/id_rsa
Your public key has been saved in ~/.ssh/id_rsa.pub
The key fingerprint is:
(무언가 긴 문자열)
The key's randomart image is:
+---[RSA 3072]----+
|(무언가 그림이 그려짐)|
|                 |
|                 |
|                 |
|       ^_^       |
|                 |
|                 |
|                 |
|                 |
+----[SHA256]-----+&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;그냥 엔터 3번 치시면 됩니다.&lt;/b&gt; 그럼 맥북 기준으로&amp;nbsp;&lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt;에 공개키가 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1763640484440&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat ~/.ssh/id_rsa.pub&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어 아웃풋을 복사합시다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Github 설정 들어가기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github - Settings - SSH and GPG Keys 로 들어갑니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.09.33.png&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwk1Bd/dJMcagjBKBD/UmoO0EkN7dPCDKzbH2KP2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwk1Bd/dJMcagjBKBD/UmoO0EkN7dPCDKzbH2KP2k/img.png&quot; data-alt=&quot;이 탭을 못찾으셨다면, 좌측의 Access 섹션을 찾아보세요.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwk1Bd/dJMcagjBKBD/UmoO0EkN7dPCDKzbH2KP2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwk1Bd%2FdJMcagjBKBD%2FUmoO0EkN7dPCDKzbH2KP2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1930&quot; height=&quot;338&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.09.33.png&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이 탭을 못찾으셨다면, 좌측의 Access 섹션을 찾아보세요.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;New SSH Key&lt;/b&gt; 를 눌러줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.10.32.png&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;996&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ced4Ho/dJMcaaKsv37/07mpDtpRfhybYkKWoIW7Pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ced4Ho/dJMcaaKsv37/07mpDtpRfhybYkKWoIW7Pk/img.png&quot; data-alt=&quot;Key type은 굳이 건들지 않습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ced4Ho/dJMcaaKsv37/07mpDtpRfhybYkKWoIW7Pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fced4Ho%2FdJMcaaKsv37%2F07mpDtpRfhybYkKWoIW7Pk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1916&quot; height=&quot;996&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.10.32.png&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;996&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Key type은 굳이 건들지 않습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Key에 이전에 복사해 둔 문자열을 그대로 넣습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Title은 마음대로 정하시면 됩니다. 사용중인 디바이스 이름이라던가, RSA 키 만들 때 붙인 메모도 좋습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.12.02.png&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWMPf/dJMcadNTRic/K4GicdY3KcpkqVp9kDXkY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWMPf/dJMcadNTRic/K4GicdY3KcpkqVp9kDXkY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWMPf/dJMcadNTRic/K4GicdY3KcpkqVp9kDXkY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWMPf%2FdJMcadNTRic%2FK4GicdY3KcpkqVp9kDXkY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1894&quot; height=&quot;598&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.12.02.png&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 이렇게 SSH Key가 잘 등록됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 확인&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.13.12.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buCcBL/dJMcabWT5lf/43k2LAet8eTRHiyfslE6y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buCcBL/dJMcabWT5lf/43k2LAet8eTRHiyfslE6y0/img.png&quot; data-alt=&quot;Woo-hoo!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buCcBL/dJMcabWT5lf/43k2LAet8eTRHiyfslE6y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuCcBL%2FdJMcabWT5lf%2F43k2LAet8eTRHiyfslE6y0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1372&quot; height=&quot;412&quot; data-filename=&quot;스크린샷 2025-11-20 오후 9.13.12.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Woo-hoo!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 잘 되네요. 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굿&lt;/p&gt;</description>
      <category>IT 기술/Claude</category>
      <category>claude marketplace</category>
      <category>claudecode</category>
      <category>git@github.com</category>
      <category>permission denied</category>
      <category>Publickey</category>
      <category>ssh-keygen</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/26</guid>
      <comments>https://sinam7.tistory.com/26#entry26comment</comments>
      <pubDate>Thu, 20 Nov 2025 21:18:53 +0900</pubDate>
    </item>
    <item>
      <title>Docker 빌드 503 Service Unavailable 에러 해결 (Registry Mirror 설정)</title>
      <link>https://sinam7.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 도커 빌드 중 아래 문제가 발생하는 경우 해결 방법입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;failed to authorize: failed to fetch anonymous token: unexpected status from GET request to &lt;a href=&quot;https://auth.docker.io/token:&quot;&gt;https://auth.docker.io/token:&lt;/a&gt; 503 Service Unavailable&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(수정: 이번 문제는 AWS에서 발생한 Outage 이슈로, AWS를 사용 중인 Docker 등 여러 서비스에 영향이 전파된 것으로 보입니다.)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 원인 분석&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러 로그에서 auth.docker.io가 503 Service Unavailable 응답을 준 것을 확인할 수 있습니다. 원인은 크게 두 가지로 추측했습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker Hub 일시적 장애&lt;/b&gt;: Docker Hub 인증 서비스에 순간적인 장애가 발생했을 가능성입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rate Limiting&lt;/b&gt;: Docker Hub는 익명 사용자에 대해 6시간당 100회의 이미지 pull 제한을 둡니다. 프로덕션 서버에서 이 제한에 도달했을 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 경우 모두 프로덕션 배포가 Docker Hub라는 외부 서비스에 강하게 의존하고 있어 발생하는 문제, 즉 SPOF(Single Point of Failure)가 될 수 있는 상황이었습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결 방법: Docker Registry Mirror 설정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일시적 장애라면 재시도(Retry)로 해결될 수 있고, Rate Limit 문제라면 docker login을 통한 인증으로 해결할 수 있습니다. 하지만 저는 두 가지 문제를 모두 우회하고 향후 더 안정적인 운영을 위해 &lt;b&gt;레지스트리 미러(Registry Mirror)&lt;/b&gt;를 설정하는 방법을 선택했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미러 설정은 Docker Hub 대신 지리적으로 가깝거나 안정적인 미러 서버에서 이미지를 받아오도록 Docker 데몬 설정을 변경하는 것입니다. 저는 Google Container Registry(GCR)에서 제공하는 미러를 사용하기로 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 방법은 간단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. /etc/docker/daemon.json 파일 생성 및 수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;daemon.json 파일에 registry-mirrors 항목을 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ sudo nano /etc/docker/daemon.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 내용은 다음과 같이 작성합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;{
    &quot;registry-mirrors&quot;: [&quot;https://mirror.gcr.io&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Docker 데몬 재시작&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 파일을 저장한 후, Docker 데몬을 재시작하여 변경 사항을 적용합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo systemctl restart docker&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 빌드 재시도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 배포 명령을 실행합니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo docker compose up -d --build&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 조치한 결과, Docker Hub가 아닌 mirror.gcr.io를 통해 이미지를 정상적으로 PULL하며 빌드 및 배포가 성공적으로 완료되었습니다.&lt;/p&gt;</description>
      <category>IT 기술/AWS</category>
      <category>docker</category>
      <category>개발</category>
      <category>도커</category>
      <category>도커 503</category>
      <category>도커 미러</category>
      <category>도커 토큰 503</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/25</guid>
      <comments>https://sinam7.tistory.com/25#entry25comment</comments>
      <pubDate>Mon, 20 Oct 2025 17:53:29 +0900</pubDate>
    </item>
    <item>
      <title>[EC2] AWS EC2에 네트워크 트래픽 스파이크와 CPU 크레딧소모로 인한 서버 다운 해결 방법</title>
      <link>https://sinam7.tistory.com/24</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2에 t2.micro 인스턴스를 올려놓고 스테이징용 백엔드 서버로 쓰고 있었다. 그런데 어느 순간 보니 서버가 죽어 있는 것 아닌가? 인스턴스 모니터링을 보니, 네트워크 패킷 입력 그래프에 뾰족한 것이 보였다. 지금 서비스가 돌아가고 있는 서버도 아닌데, 아이고...&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;0. 자세한 상황&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 패킷 입력에 스파이크 나타남&lt;/li&gt;
&lt;li&gt;같은 시간대에 CPU 사용률 100% 달성&lt;/li&gt;
&lt;li&gt;이후 CPU 크레딧이 0을 향해 달려감&lt;/li&gt;
&lt;li&gt;서버 다운되어 접근 불가능해짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-08-28 오후 9.15.33.png&quot; data-origin-width=&quot;2796&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdd1UJ/btsQcZoWbys/vShpp65yQR9jNwr8CzdHaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdd1UJ/btsQcZoWbys/vShpp65yQR9jNwr8CzdHaK/img.png&quot; data-alt=&quot;아... 다시 봐도 머리가 아프다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdd1UJ/btsQcZoWbys/vShpp65yQR9jNwr8CzdHaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcdd1UJ%2FbtsQcZoWbys%2FvShpp65yQR9jNwr8CzdHaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;530&quot; height=&quot;153&quot; data-filename=&quot;스크린샷 2025-08-28 오후 9.15.33.png&quot; data-origin-width=&quot;2796&quot; data-origin-height=&quot;808&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아... 다시 봐도 머리가 아프다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 예상 원인 분석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DDoS인가?&lt;/b&gt;&lt;br /&gt;보통 필자가 겪은 가장 흔한 원인은 SecurityGroup(보안 그룹) 설정이 미흡해 랜덤 DDOS에 치이는 경우다. 그런데 본인은 이미 이를 몇 번 당해봐서 이 문제는 절대 아님을 확신할 수 있었다. 혹시 몰라 더블 체크를 했으나 당연히 문제는 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그럼 코드 탓인가?&lt;/b&gt;&lt;br /&gt;그게 아니라면 인스턴스에 올라간 애플리케이션 내부 무한루프 내지는 메모리 누수가 있을 수 있다. 하지만 네트워크 패킷에 스파이크가 찍히기 전까진 고요했으니 이것도 원인이라고 할 수는 없겠다. 당장 인스턴스에 올라간 건 REST API 서버 정도였으니, 무한루프가 터지기가 더 어렵지 않을까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 이리저리 분석하다 발견한 원인은 다른 무언가였으니...&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 실제 원인 분석 과정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 내가 놓치고 있는 무언가가 있는지, 혹시 몰라 열린 경로를 찾아보았다.&lt;br /&gt;이 글을 읽고 계신 분들 중, SecurityGroup 설정이 미흡(0.0.0.0/0으로 열어둔다던가...)한 경우 아래 명령어로 잡히는 리스닝 소켓들을 막거나, SecurityGroup 부분을 제대로 설정하면 DDoS 공격을 막을 수 있을 것이다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;$ ss -tulpn | grep 0.0.0.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 다른 경우였으니 다음으로 넘어가자.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;$ free -h
               total        used        free      shared  buff/cache   available
Mem:           957Mi       827Mi        67Mi       1.1Mi       219Mi       130Mi
Swap:             0B          0B          0B&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벌써 느낌이 온다. 인스턴스를 재부팅했는데도 저렇게 메모리 압박이 다가온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 CPU가 터져나간 이유는 아마도 메모리가 먼저 터졌기 때문이리라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 무슨 일이 일어났는지는 페이징과 스레싱에 대해 따로 찾아보도록 하자. CS 만세.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대략 인스턴스의 사망 원인은 알아냈다. 그런데 메모리가 왜 터져나갔을까? 네트워크 트래픽은 왜 솟구쳤는가? 여기에 대한 문제가 해결되지 않았다. 네트워크 트래픽이 몰린 시간대를 보고 관련 네트워크 로그를 딸 수 있는 것들을 찾아봤다.&lt;/p&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt;$ sudo journalctl --since &quot;2 days ago&quot; | grep -i &quot;network\|traffic\|ddos\|attack&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아웃풋은 지극히 정상적인 Docker 활동이었다. 다음.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;$ sudo docker-compose logs app --since 24h | head -100&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 로그. 여기도 깨끗하다. 다음.&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;$ cat /proc/net/dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 인터페이스 로그...는 봐도 잘 모르겠다. 다음.&lt;/p&gt;
&lt;pre class=&quot;dsconfig&quot;&gt;&lt;code&gt;# 네트워크 트래픽이 몰린 06:20~06:30 시간대 모든 로그
sudo journalctl --since &quot;2025-08-28 06:20:00&quot; --until &quot;2025-08-28 06:30:00&quot;

# Docker 컨테이너 로그 (해당 시간대)
sudo docker-compose logs --since &quot;2025-08-28T06:20:00&quot; --until &quot;2025-08-28T06:30:00&quot;

# 시스템 리소스 관련 로그
sudo journalctl --since &quot;2025-08-28 06:20:00&quot; --until &quot;2025-08-28 06:30:00&quot; | grep -i &quot;cpu\|memory\|oom\|kill&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 단서를 잡을 수 있었다. 로그를 정리해보자면 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;cron-daily 작업 시작&lt;/li&gt;
&lt;li&gt;apt-daily-upgrade 작업 시작&lt;/li&gt;
&lt;li&gt;PackageKit 데몬 시작&lt;/li&gt;
&lt;li&gt;fwupd 서비스 재시작 (155.1M 메모리 사용)&lt;/li&gt;
&lt;li&gt;메모리 압박으로 캐시 플러시&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하자면 데일리 시스템 업데이트가 크론잡으로 돌았고, 이때 여러 시스템 서비스가 동시에 돌면서 메모리가 터진 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후는 직전에 언급한대로...&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 해결 - 업데이트 비활성화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리 오래 쓸 인스턴스도 아니고, 프라이빗하게 사용하는 인스턴스인데 굳이 무언가 몸을 비틀 필요는 없다고 생각했다.&lt;br /&gt;자동 업데이트를 꺼버리면 해결되는 것 아닌가?&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 자동 업데이트 비활성화
sudo systemctl disable apt-daily-upgrade.service

# 타이머도 비활성화
sudo systemctl disable apt-daily-upgrade.timer
sudo systemctl stop apt-daily-upgrade.timer

# apt-daily 관련 모든 서비스/타이머 비활성화
sudo systemctl disable apt-daily.timer
sudo systemctl stop apt-daily.timer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 별개로 t2.micro의 메모리 할당량에 대한 기억을 되찾았으니, 바로 Swap space까지 걸어주도록 하자.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Swap space 설정하기&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 128M * 16 = 2GB
sudo dd if=/dev/zero of=/swapfile bs=128M count=16

sudo chmod 600 /swapfile

sudo mkswap /swapfile

sudo swapon /swapfile

sudo swapon -s&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Swap space 설정이 끝났다.&lt;br /&gt;Swapfile용 파일을 만들고, 권한 잡고, 적용하고, 활성화했다. 마지막은 잘 되었는지 로그 확인용이다. 지금은 2GB로 설정했으며, 필요에 따라 수정하면 된다. 인스턴스 재부팅 이후에도 계속 Swap space를 적용하려면 아래 작업을 진행하자.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;sudo vi /etc/fstab&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령어 입력 후 나타난 vi에&amp;nbsp;&amp;nbsp;&lt;code&gt;/swapfile swap swap defaults&lt;/code&gt; 를 작성하고 저장하자.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;free&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어로 Swap space가 잘 적용되었는지 확인하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;맺으며&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3420&quot; data-origin-height=&quot;2214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oLDE3/btsQb8fCFCh/hkLIGk2G5p6DVLHCzm1z4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oLDE3/btsQb8fCFCh/hkLIGk2G5p6DVLHCzm1z4k/img.png&quot; data-alt=&quot;https://www.youtube.com/watch?v=n3-oeEJWgc0&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oLDE3/btsQb8fCFCh/hkLIGk2G5p6DVLHCzm1z4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoLDE3%2FbtsQb8fCFCh%2FhkLIGk2G5p6DVLHCzm1z4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;530&quot; height=&quot;343&quot; data-origin-width=&quot;3420&quot; data-origin-height=&quot;2214&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.youtube.com/watch?v=n3-oeEJWgc0&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;어째 AWS, 특히 t2.micro는 매번 쓸 때마다 별 일이 다 생기는 기분이다. 언제쯤 되어야 이런 일들을 겪지 않을 수 있을지...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Reference&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://diary-developer.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://diary-developer.tistory.com/32&lt;/a&gt; - Swapfile 생성 및 Swap Space 설정&lt;/p&gt;</description>
      <category>IT 기술/AWS</category>
      <category>APT</category>
      <category>AWS</category>
      <category>cpu 크레딧</category>
      <category>ec2</category>
      <category>swapfile</category>
      <category>t2.micro</category>
      <category>인스턴스</category>
      <category>자동업데이트</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/24</guid>
      <comments>https://sinam7.tistory.com/24#entry24comment</comments>
      <pubDate>Thu, 28 Aug 2025 22:04:57 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] ngrok 기반 리버스 SSH 터널을 통한 원격 접속 방법</title>
      <link>https://sinam7.tistory.com/23</link>
      <description>&lt;h1&gt;들어가며&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS 등 방화벽 뒤에 있는 내부 서버에 접근할 일이 많은데, 밖에서 접속할 땐 허용된 IP가 아니라 접속이 불가능한 이슈가 생긴다. 그때그때 보안 그룹을 수정해 준다면 가능하지만, 그럴 권한이 없을 수도 있고 작업을 마친 뒤 보안그룹을 다시 되돌려야 하는 귀찮은 일도 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럴 때는 방화벽에서 허용된 IP를 통해 접속하면 이를 우회할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;환경&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 게시글은 아래 환경 기반에서 작성했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이중 NAT 환경 - 집 PC의 공인 IP로 직접 접속 불가능한 환경.&lt;/li&gt;
&lt;li&gt;집 PC - Windows 10 (방화벽 뒤 내부 서버에 접근하기 위한 터널 PC)&lt;/li&gt;
&lt;li&gt;외부 PC - MacOS Sequoia 15.5 (카페같은 외부 환경에서 접속할 PC)&lt;/li&gt;
&lt;li&gt;ngrok - 무료 플랜&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그런데, 왜 이렇게 했나?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상기 언급했듯, 이중 NAT 환경이 발목을 잡았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 DDNS 혹은 포트포워딩을 통해 직접 SSH 연결을 하면 해결되는 단순한 문제지만, 이중 NAT에선 이야기가 좀 달라진다.&lt;br /&gt;이중 NAT 환경에선 포트포워딩 작업을 건물 모뎀과 집 공유기 모두에서 해 주어야 한다. 건물 모뎀에선 공인 IP를 집 공유기로, 집 공유기에선 건물 모뎀으로부터 들어온 트래픽을 작업 PC에 포워딩하는 방식으로 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 건물 모뎀은 건물주가 직접 관리해 접근할 수가 없어, 부득이하게 리버스 터널링으로 방향을 잡았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;작업&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5번 작업까진 모두 집 PC에서 진행한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 절전 모드 비활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집 밖에서 쓰려는데 터널링 PC가 절전으로 꺼져버리면 곤란해진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. OpenSSH Server 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows 10/11 이상에선 기본적으로 OpenSSH Client는 설치되어 있지만, 서버는 선택 설치 사항이다. 직접 설치하자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Windows 설정 - 앱 - 선택적 기능 - OpenSSH 서버
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시작 버튼 누르고 선택적 기능 쳐도 적당히 나온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 서비스가 켜져있는지 확인하면 된다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Get-Service sshd&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꺼져있다면 아래 명령어로 실행하자.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 방화벽 설정 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH 포트인 22번 포트가 열려 있어야 한다.&lt;br /&gt;직접 방화벽을 손봐도 되지만, 명령어로 깔끔하게 하자. 안 된다면 관리자 권한으로 Powershell을 열었는지 확인하자.&lt;/p&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;New-NetFirewallRule -Name sshd -DisplayName &quot;OpenSSH Server (sshd)&quot; -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 아래 명령어로 포트가 잘 열려있는지 확인한다.&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;netstat -an | findstr :22&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트 상태가 LISTEN이 아니라면 뭔가 문제가 생긴 것이다. GPT나 퍼플렉시티 등에게 물어보도록 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. SSH 키 준비&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4-1. SSH 키 생성&lt;/h4&gt;
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;ssh-keygen -t ed25519 -C &quot;설명이나 이름&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;-C&quot; 옵션은 키를 구분할 주석(PC명, 이메일 등)을 붙이는 것으로, 설명이나 이름은 알아서 적도록 하자.&lt;br /&gt;명령어 입력 시 저장 경로와 패스프레이즈를 입력하라고 한다. 저장 경로를 물을 때 경로 없이 엔터치면 기본 경로(&lt;code&gt;~/.ssh/&lt;/code&gt;)로 간다.&lt;br /&gt;ED25519 대신 RSA(4096비트)를 원한다면, 아래 명령어로 진행하면 된다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C &quot;설명&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 PublicKey 에러로 튕겨나가는 걸 막기 위한 SSH 키 권한을 잡아보자.&lt;br /&gt;일반적으로는 &lt;code&gt;chmod 700 ~/ssh&lt;/code&gt;로 해결 가능하지만, 여긴 윈도우라 그런게 없다. 아래 명령으로 해결하자.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;$sshFolder = &quot;$env:USERPROFILE\.ssh&quot;
icacls.exe $sshFolder /inheritance:r
icacls.exe $sshFolder /grant:r &quot;$($env:USERNAME):(F)&quot;
icacls.exe $sshFolder /remove &quot;Users&quot; &quot;Everyone&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 문제가 생긴 듯 하다면, 관리자 권한으로 Powershell을 켰는지 확인하자.&lt;br /&gt;여기까지 마쳤다면, 외부 PC(노트북)의 &lt;code&gt;~/.ssh&lt;/code&gt;에 지금 만든 key를 저장하기 위해 개인 Discord나 카카오톡 나에게 보내기 등을 활용해 미리 준비하는 게 좋겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4-2. 공개키 등록&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 공개키 내용을 집 PC (연결할 대상)의 &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;에 등록해야 한다.&lt;/p&gt;
&lt;pre class=&quot;arcade&quot;&gt;&lt;code&gt;cat ~/.ssh/id_ed25519.pub &amp;gt;&amp;gt; ~/.ssh/authorized_keys&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 &lt;code&gt;authorized_keys&lt;/code&gt; 파일에도 권한을 설정해야 한다.&lt;br /&gt;역시나 &lt;code&gt;chmod 600 ~/.ssh/authorized_keys&lt;/code&gt;로 해결할 수 있겠지만, 여긴 윈도우다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;$authKeys = &quot;$env:USERPROFILE\.ssh\authorized_keys&quot;
icacls.exe $authKeys /inheritance:r
icacls.exe $authKeys /grant:r &quot;$($env:USERNAME):(R,W)&quot;
icacls.exe $authKeys /remove &quot;Users&quot; &quot;Everyone&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PowerShell에서 환경 변수 $env:USERPROFILE은 사용자 홈 디렉토리를 가리킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. ngrok&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5-1. ngrok 설치&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ngrok.com&quot;&gt;https://ngrok.com&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 환경에서 각자에게 맞는 ngrok을 설치한다. 이 글에서는 Windows 10 x64가 되겠다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5-1-1. ngrok 가입 (Optional)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ngrok 가입 후 Authtoken 설정을 안 하면 세션 연결이 8시간 뒤에 끊긴다고 하더라.&lt;br /&gt;굳이 상관 없다면 이 단락은 넘기고 5.2로 가자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요하다면 가입한 후, Authtoken을 찾아 집 PC에 등록하자.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ngrok config add-authtoken $YOUR_AUTHTOKEN&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 입력하면, 어떤 경로에 설정 정보가 저장되었다고 나온다. (ex: &lt;code&gt;C:\Users\[USERPROFILE]\AppData\Local/ngrok/ngrok.yml&lt;/code&gt;) 근데 본인은 저 위치에 저장된 파일이 없어서 굉장히 이상하지만, 아무튼 잘 되니까 넘어가도록 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;관련 설정 파일은 &lt;code&gt;ngrok config check&lt;/code&gt;, &lt;code&gt;ngrok config edit&lt;/code&gt; 등 활용 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련 내용은 &lt;a href=&quot;https://ngrok.com/docs/agent/config/&quot;&gt;공식 페이지&lt;/a&gt;를 참고하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5-2. ngrok 실행&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ngrok tcp 22&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH를 여는 게 목표니, tcp 22로 열자. 웹서버나 기타 포트 관련 방법은 다루지 않고 넘어간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;245&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l66xm/btsP8EswZDO/Wkvn0BxMBC6WQvra3tqpRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l66xm/btsP8EswZDO/Wkvn0BxMBC6WQvra3tqpRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l66xm/btsP8EswZDO/Wkvn0BxMBC6WQvra3tqpRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl66xm%2FbtsP8EswZDO%2FWkvn0BxMBC6WQvra3tqpRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;837&quot; height=&quot;245&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;245&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하면 대략 저런 모습으로 나온다. 저기에서 우리가 필요한 정보는 &lt;b&gt;Forwarding&lt;/b&gt;의 Host와 Port만 알면 된다.&lt;br /&gt;여기에선 Host: &lt;code&gt;0.tcp.jp.ngrok.io&lt;/code&gt;, Port: &lt;code&gt;16704&lt;/code&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 무료 플랜에서 ngrok을 껐다 키면 포트가 변경된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 외부 PC 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 외부 PC에서 작업할 차례다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6-1. SSH Key 저장&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4-1 단계에서 생성한 SSH Key를 &lt;code&gt;~/.ssh&lt;/code&gt;에 저장하자. 이름은 딱히 상관 없으니 필요하다면 변경하자.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6-2. SSH 연결&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 잘 따라왔다면, &lt;code&gt;ssh -p [PORT] [USERNAME]@[HOST] -i [SSH 키 경로]&lt;/code&gt;로 접속 가능하다.&lt;br /&gt;PORT와 HOST는 직전에 언급했고, USERNAME을 모른다면 집 PC에서 cmd를 열어보자. (관리자 권한 X)&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;C:\Users\[USERNAME]&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 나타날텐데, 저 USERNAME이 집 PC에서 지금 사용하는 사용자 이름이다.&lt;br /&gt;SSH 키 경로는 &lt;code&gt;~/.ssh&lt;/code&gt;에 저장한 키 파일 경로다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;publicKey 문제가 발생한 경우, 여기에선 마음 편히 &lt;code&gt;chmod 600&lt;/code&gt;으로 해결하면 되겠다.&lt;br /&gt;디렉토리에 설정하는 경우엔 &lt;code&gt;chmod 700&lt;/code&gt;으로 하면 된다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa          # 개인키
chmod 600 ~/.ssh/authorized_keys # 서버측 공개키 리스트 파일&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고하도록 하자.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6-1-1. SSH config 설정 (Optional)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 저 긴 ssh 명령어 를 입력하는 건 조금 번거롭다. &lt;code&gt;~/.ssh&lt;/code&gt;에 config 파일을 만들자. (&lt;code&gt;~/.ssh/config&lt;/code&gt;)&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Host ngrok-home
    HostName [HOST]
    User [USERNAME]
    IdentityFile [SSH 키 경로]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 값을 적절히 수정해 저장하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트까지 고정하려면 HostName, User 등과 같은 들여쓰기 레벨에서 &lt;code&gt;Port ????&lt;/code&gt; 로 지정하면 되나, 우리는 포트가 항상 바뀔 것을 염두해야 하므로 생략한다. &lt;code&gt;ngrok-home&lt;/code&gt; 대신 다른 이름을 사용해도 되나, 아래 명령어 사용 시 그 이름으로 바꾸어 입력하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 기존의 그 긴 명령어를 치는 대신, 아래 명령어로 간략하게 보낼 수 있다.&lt;/p&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;ssh ngrok-home -p [PORT]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TroubleShooting&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Permission denied (publickey)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 PC의 권한 문제다. &lt;code&gt;chmod 600 [ssh key path]&lt;/code&gt;로 해결하자.&lt;br /&gt;그래도 안 된다면, 집 PC의 &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;에 있는지 점검하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 관리자 권한으로 집 PC에서 OpenSSH를 열어서 디버그 모드로 확인하자.&lt;/p&gt;
&lt;pre class=&quot;taggerscript&quot;&gt;&lt;code&gt;C:\Windows\System32\OpenSSH\sshd.exe&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디버그 모드인 경우에는 기존 &lt;code&gt;authorized_keys&lt;/code&gt; 파일 대신 &lt;code&gt;__PROGRAMDATA__/ssh/administrators_authorized_keys&lt;/code&gt;에 접근하는 경우가 있는데, 관련 문제는 GPT나 퍼플렉시티, 혹은 검색으로 해결하자. 필자는 이 문제가 발생했으나 그냥 서비스로 돌려 실행하니 해결되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 연결 시도 즉시 연결 끊김&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집 PC(호스트)의 SSH 서버가 꺼져 있다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Get-Service sshd&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령어로 실행 여부를 확인하자. 꺼져있다면 아래 명령으로 시작하자.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별도로 SSH 서버가 예기치 않게 종료되어도 자동으로 재시작할 수 있는 방법이 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;sc.exe failure sshd reset= 86400 actions= restart/5000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;[SC] ChangeServiceConfig2 성공&lt;/code&gt; 이 나오면 정상적으로 된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정이 제대로 적용되었는지 확인은 아래 명령으로 한다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;sc.exe qfailure sshd&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;[SC] QueryServiceConfig2 성공

SERVICE_NAME: sshd
        RESET_PERIOD (in seconds)    : 86400
        REBOOT_MESSAGE               :
        COMMAND_LINE                 :
        FAILURE_ACTIONS              : 다시 시작 -- 지연 = 5000밀리초.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대략 이런 식의 출력이 보이면 잘 설정되었다.&lt;/p&gt;
&lt;h1&gt;References&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jybaek.tistory.com/798&quot;&gt;https://jybaek.tistory.com/798&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://innerjoin.tistory.com/25#Ngork%20Authtoken%20%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0-1&quot;&gt;https://innerjoin.tistory.com/25#Ngork%20Authtoken%20%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0-1&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://ngrok.com/docs/agent/config/&quot;&gt;https://ngrok.com/docs/agent/config/&lt;/a&gt;&lt;/p&gt;</description>
      <category>IT 기술/AWS</category>
      <category>ngrok</category>
      <category>openssh</category>
      <category>reverse tunnel</category>
      <category>ssh</category>
      <category>리버스 터널링</category>
      <category>방화벽</category>
      <category>터널링</category>
      <author>시남</author>
      <guid isPermaLink="true">https://sinam7.tistory.com/23</guid>
      <comments>https://sinam7.tistory.com/23#entry23comment</comments>
      <pubDate>Wed, 27 Aug 2025 15:18:10 +0900</pubDate>
    </item>
  </channel>
</rss>