<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>G 스토리</title>
    <link>https://jiione.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 9 May 2026 11:31:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Jiione</managingEditor>
    <image>
      <title>G 스토리</title>
      <url>https://tistory1.daumcdn.net/tistory/5547306/attach/f77717607d7c4523bd958182feecb209</url>
      <link>https://jiione.tistory.com</link>
    </image>
    <item>
      <title>[Side Project] 단일 AI의 한계를 넘어: LangGraph와 Streamlit으로 구축한 나만의 다중 에이전트 시스템(MAS) 개발기</title>
      <link>https://jiione.tistory.com/36</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며 ...&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;왜 다중 에이전트(Multi-Agent)인가?&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;426&quot;&gt;&lt;span data-start-index=&quot;426&quot;&gt;&quot;AI에게 코드를 짜달라고 하고, 그 코드를 스스로 검증하라고 하면 왜 자꾸 같은 실수를 반복할까?&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;482&quot;&gt;&lt;span data-start-index=&quot;482&quot;&gt;이번 사이드 프로젝트는 이 단순한 질문에서 시작되었습니다. 사람이 무언가를 기획하고 스스로 검토할 때 확증 편향에 빠져 자신의 실수를 발견하지 못하는 것처럼, 단일 AI 모델 역시 자신이 생성한 결과물에 대해 비판적인 시각을 유지하기 어렵습니다. 하나의 프롬프트 안에서 계획, 실행, 검증을 모두 수행하려다 보면 역할 간의 경계가 모호해지고 결과물의 품질이 저하됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;482&quot;&gt;&lt;span data-start-index=&quot;482&quot;&gt;저는 최근 AI 엔지니어링에 관심을 가지며 얻게된 호기심 충족과 제 업무와 취미를 보조할 좀 더&lt;b&gt; 완전한 AI&lt;/b&gt;를 만들어보고자&lt;br /&gt;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;&lt;b&gt;'다중 에이전트 시스템(Multi-Agent System, MAS)'&lt;/b&gt;을 설계했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;span data-start-index=&quot;482&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;이 글에서는 LangGraph 프레임워크를 기반으로 AI-native 검색 엔진인 Tavily, 그리고 Streamlit 웹 인터페이스를 결합하여 어떻게 이 시스템을 밑바닥부터 구축했는지 상세한 과정을 공유하고자 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;시스템 아키텍처 및 핵심 도구&lt;/span&gt;&lt;/h2&gt;
&lt;div data-start-index=&quot;1074&quot;&gt;&lt;span data-start-index=&quot;1074&quot;&gt;제가 구축한 시스템은 크게 4가지 역할을 가진 에이전트와 최종 결정권자인 사람(Human)으로 구성됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #303030; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start-index=&quot;1133&quot;&gt;&lt;b data-start-index=&quot;1133&quot;&gt;Planner (계획 수립자)&lt;/b&gt;&lt;span data-start-index=&quot;1149&quot;&gt;: 사용자의 요청을 분석하고 구체적인 실행 계획을 세웁니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1182&quot;&gt;&lt;b data-start-index=&quot;1182&quot;&gt;Executor (실행자)&lt;/b&gt;&lt;span data-start-index=&quot;1196&quot;&gt;: 계획을 바탕으로 실제 코드 작성, 파일 시스템 접근, 검색 등의 도구를 사용해 작업을 수행합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1252&quot;&gt;&lt;b data-start-index=&quot;1252&quot;&gt;Skeptic (회의론자)&lt;/b&gt;&lt;span data-start-index=&quot;1266&quot;&gt;: Executor와 병렬로 실행되며, Executor의 결과물이 아닌 Planner의 계획 자체를 보고 독립적인 위협 모델과 검토 기준을 세웁니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1349&quot;&gt;&lt;b data-start-index=&quot;1349&quot;&gt;Executive (관리자)&lt;/b&gt;&lt;span data-start-index=&quot;1364&quot;&gt;: 실행 로그와 리뷰 코멘트를 취합하여 최종 판단(승인, 수정, 거절)을 내립니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1410&quot;&gt;&lt;b data-start-index=&quot;1410&quot;&gt;Human-in-the-Loop (사람)&lt;/b&gt;&lt;span data-start-index=&quot;1432&quot;&gt;: 최종 실행 전 개입하여 승인하거나 수정 지시를 내립니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-start-index=&quot;1465&quot;&gt;&lt;span data-start-index=&quot;1465&quot;&gt;이 아키텍처를 구현하기 위해 다음과 같은 핵심 기술 스택을 채택했습니다.&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #303030; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start-index=&quot;1505&quot;&gt;&lt;b data-start-index=&quot;1505&quot;&gt;오케스트레이션&lt;/b&gt;&lt;span data-start-index=&quot;1512&quot;&gt;: &lt;/span&gt;LangGraph&lt;span data-start-index=&quot;1523&quot;&gt; (에이전트 간의 상태와 흐름 제어)&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1543&quot;&gt;&lt;b data-start-index=&quot;1543&quot;&gt;웹 인터페이스&lt;/b&gt;&lt;span data-start-index=&quot;1550&quot;&gt;: &lt;/span&gt;Streamlit&lt;span data-start-index=&quot;1561&quot;&gt; (기존 디스코드 봇의 메시지 제한 한계를 극복하기 위한 세련된 UI)&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1600&quot;&gt;&lt;b data-start-index=&quot;1600&quot;&gt;검색 엔진&lt;/b&gt;&lt;span data-start-index=&quot;1605&quot;&gt;: &lt;/span&gt;Tavily API&lt;span data-start-index=&quot;1617&quot;&gt; (AI 에이전트에 최적화된 정보 검색 및 추출)&lt;/span&gt;&lt;/li&gt;
&lt;li data-start-index=&quot;1644&quot;&gt;&lt;b data-start-index=&quot;1644&quot;&gt;코딩 보조 및 자동화&lt;/b&gt;&lt;span data-start-index=&quot;1655&quot;&gt;: &lt;/span&gt;Claude Code CLI&lt;span data-start-index=&quot;1672&quot;&gt; (터미널 기반의 에이전틱 코딩 도구로 전체 스캐폴딩 및 테스트 자동화 수행)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;단계별 구축 프로세스 및 핵심 구현 로직&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1822&quot;&gt;프로젝트는 복잡한 시스템을 한 번에 뭉뚱그려 짜는 대신, 총 9개의 페이즈(Phase)로 나누어 점증적으로 구축하고 검증하는 방식을 택했습니다&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1901&quot;&gt;&lt;br /&gt;&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;size18&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;Phase 1 &amp;amp; 2: 기초 스캐폴딩과 상태(State) 설계&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;1940&quot;&gt;&lt;span data-start-index=&quot;1940&quot;&gt;가장 먼저 &lt;/span&gt;uv&lt;span data-start-index=&quot;1948&quot;&gt;를 사용해 가상환경을 초기화하고, &lt;/span&gt;LangGraph&lt;span data-start-index=&quot;1976&quot;&gt;, &lt;/span&gt;LangChain&lt;span data-start-index=&quot;1987&quot;&gt;, &lt;/span&gt;Pydantic&lt;span data-start-index=&quot;1997&quot;&gt; 등의 필수 패키지를 설치했습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;2015&quot;&gt;. 모든 과정은 터미널에서 Claude Code CLI를 통해 자연어로 지시하여 자동화했습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;2067&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;1940&quot;&gt;&lt;span data-start-index=&quot;2067&quot;&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;759&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5nTmo/dJMcabDWRLF/218H2gzrcZH3mmUM9tINrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5nTmo/dJMcabDWRLF/218H2gzrcZH3mmUM9tINrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5nTmo/dJMcabDWRLF/218H2gzrcZH3mmUM9tINrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5nTmo%2FdJMcabDWRLF%2F218H2gzrcZH3mmUM9tINrk%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;567&quot; height=&quot;350&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;759&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div data-start-index=&quot;2068&quot;&gt;&lt;span data-start-index=&quot;2068&quot;&gt;다중 에이전트 시스템에서 가장 중요한 것은 에이전트들이 정보를 주고받을 &lt;/span&gt;&lt;b data-start-index=&quot;2108&quot;&gt;'칠판(State)'의 설계&lt;/b&gt;&lt;span data-start-index=&quot;2123&quot;&gt;입니다. 특히 병렬로 실행되는 노드들이 동시에 값을 쓸 때 데이터가 덮어써지는(Overwrite) 문제를 막아야 했습니다.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;2068&quot;&gt;&lt;span data-start-index=&quot;2123&quot;&gt;&lt;/span&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;&lt;code&gt;class AgentState(TypedDict):
    # 누적 필드: 병렬 노드가 동시에 쓰더라도 덮어쓰지 않고 리스트에 추가됨
    messages: Annotated[list[BaseMessage], operator.add]
    review_comments: Annotated[list[str], operator.add]
    execution_logs: Annotated[list[str], operator.add]
    
    # 단일값 필드: 마지막으로 쓴 노드의 값이 최종값
    task: str
    current_agent: str
    executive_verdict: str&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2536&quot;&gt;위 코드처럼 &lt;/span&gt;Annotated[list[str], operator.add]&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2577&quot;&gt;를 사용해 리스트가 안전하게 누적(Append)되도록 설계했습니다&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2613&quot;&gt;. 이 리듀서(Reducer) 기능이 없었다면 Skeptic의 비판적 리뷰가 Executor의 로그에 조용히 덮어써져 사라지는 문제를 겪었을 수도 있습니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2700&quot;&gt;&lt;br /&gt;&lt;/span&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-origin-width=&quot;978&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F7i2H/dJMcaiQy8gp/p4yyW6pBrjVs1METeA1M7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F7i2H/dJMcaiQy8gp/p4yyW6pBrjVs1METeA1M7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F7i2H/dJMcaiQy8gp/p4yyW6pBrjVs1METeA1M7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF7i2H%2FdJMcaiQy8gp%2Fp4yyW6pBrjVs1METeA1M7k%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;585&quot; height=&quot;272&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;455&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;Phase 3 &amp;amp; 4: 병렬 팬아웃(Fan-out) 설계&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-start-index=&quot;2736&quot;&gt;Planner의 계획이 수립된 후, Executor와 Skeptic 노드는 직렬이 아닌 &lt;b&gt;병렬(Parallel)&lt;/b&gt;로 실행되도록 &lt;/span&gt;add_edge&lt;span data-start-index=&quot;2817&quot;&gt;를 구성했습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;2825&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;2826&quot;&gt;&lt;span data-start-index=&quot;2826&quot;&gt;만약 직렬(Executor 완료 후 Skeptic 실행)로 구성했다면, Skeptic은 Executor의 결과물 프레임에 갇혀 수동적인 리뷰어에 머물렀을 것입니다. 두 노드를 병렬로 분기(Fan-out)시켜 동일한 계획을 보게 함으로써, Skeptic이 완전히 독립적인 시각에서 발생할 수 있는 문제점(위협 모델)을 사전에 짚어낼 수 있도록 의도했습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;3023&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;2826&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7Ukvd/dJMcaaLOwVV/5NGSbpwW8tAhRSJMkCXUt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7Ukvd/dJMcaaLOwVV/5NGSbpwW8tAhRSJMkCXUt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7Ukvd/dJMcaaLOwVV/5NGSbpwW8tAhRSJMkCXUt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7Ukvd%2FdJMcaaLOwVV%2F5NGSbpwW8tAhRSJMkCXUt0%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;622&quot; height=&quot;309&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-start-index=&quot;2826&quot;&gt;&lt;span data-start-index=&quot;3023&quot;&gt;&lt;/span&gt;
&lt;p data-start-index=&quot;3024&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start-index=&quot;3024&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span data-start-index=&quot;3024&quot;&gt;Phase 5: 무한 루프 방지와 Executive 피드백 루프&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;3059&quot;&gt;&lt;span data-start-index=&quot;3059&quot;&gt;Executor와 Skeptic의 작업이 끝나면 팬인(Fan-in)되어 Executive 노드로 모입니다. Executive는 두 결과를 분석하여 &lt;/span&gt;approve&lt;span data-start-index=&quot;3148&quot;&gt;, &lt;/span&gt;revise&lt;span data-start-index=&quot;3156&quot;&gt;, &lt;/span&gt;reject&lt;span data-start-index=&quot;3164&quot;&gt; 중 하나를 판정합니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;3176&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;3177&quot;&gt;&lt;span data-start-index=&quot;3177&quot;&gt;여기서 핵심은 자율성 시스템이 가진 '무한 루프'의 위험을 통제하는 것이었습니다.&lt;/span&gt;&lt;/div&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;if has_error:
    if revision_count &amp;gt;= MAX_REVISIONS: # 안전장치: 상한선 도달 시 강제 종료
        verdict = &quot;reject&quot;
    else:
        verdict = &quot;revise&quot;
        revision_count = revision_count + 1
&lt;/code&gt;&lt;/pre&gt;
&lt;div data-start-index=&quot;3407&quot;&gt;&lt;span data-start-index=&quot;3407&quot;&gt;위와 같이 상태(State)에 &lt;/span&gt;revision_count&lt;span data-start-index=&quot;3438&quot;&gt; 필드를 두고 최대 3회까지만 수정을 허용하도록 안전장치를 구현했습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;3477&quot;&gt;. 이 제약이 없으면 Skeptic이 사소한 트집을 잡을 때마다 시스템이 무한히 재작업을 수행하여 엄청난 API 비용이 청구될 수 있습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;3554&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;3407&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1231&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuSZxS/dJMcaaE3ZHD/xEhMWNKhTk2UjgoNLvgEUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuSZxS/dJMcaaE3ZHD/xEhMWNKhTk2UjgoNLvgEUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuSZxS/dJMcaaE3ZHD/xEhMWNKhTk2UjgoNLvgEUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuSZxS%2FdJMcaaE3ZHD%2FxEhMWNKhTk2UjgoNLvgEUk%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;570&quot; height=&quot;324&quot; data-origin-width=&quot;1231&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div data-start-index=&quot;3555&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-start-index=&quot;3555&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start-index=&quot;3555&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span data-start-index=&quot;3555&quot;&gt;Phase 6: Docker 기반의 안전한 코드 실행 샌드박스&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;3589&quot;&gt;&lt;span data-start-index=&quot;3589&quot;&gt;에이전트(Executor)에게 시스템 제어권을 부여하는 것은 매우 위험합니다. LLM이 생성한 코드가 제 로컬 파일 시스템을 망치거나, 보안을 우회할 수 있기 때문입니다. 이를 방지하기 위해 파이썬의 &lt;/span&gt;subprocess&lt;span data-start-index=&quot;3711&quot;&gt;를 활용하여 Docker 컨테이너 내부에서만 코드가 실행되는 샌드박스 툴을 만들었습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;3759&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;3760&quot;&gt;docker run --rm --network=none --memory=512m --cpus=1 python:3.11-slim python -c &quot;실행할코드&quot;&lt;/div&gt;
&lt;div data-start-index=&quot;3848&quot;&gt;&lt;span data-start-index=&quot;3848&quot;&gt;외부 해킹이나 악의적인 API 호출을 막기 위해 &lt;/span&gt;--network=none&lt;span data-start-index=&quot;3889&quot;&gt;으로 네트워크를 원천 차단하고, 메모리 폭탄을 막기 위해 &lt;/span&gt;--memory=512m&lt;span data-start-index=&quot;3934&quot;&gt; 제약을 걸었습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;3944&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;3945&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/em85co/dJMcah5feIK/WLkPDZ9S7jT1ts40QLLkSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/em85co/dJMcah5feIK/WLkPDZ9S7jT1ts40QLLkSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/em85co/dJMcah5feIK/WLkPDZ9S7jT1ts40QLLkSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fem85co%2FdJMcah5feIK%2FWLkPDZ9S7jT1ts40QLLkSk%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;540&quot; height=&quot;498&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-start-index=&quot;3945&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start-index=&quot;3945&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span data-start-index=&quot;3945&quot;&gt;Phase 7: 권한의 물리적 분리와 Tavily 지능형 검색&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;3979&quot;&gt;&lt;span data-start-index=&quot;3979&quot;&gt;에이전트의 역할을 프롬프트(글)로만 나누는 것은 불완전합니다. 따라서 &lt;/span&gt;&lt;b data-start-index=&quot;4018&quot;&gt;'도구(Tool) 바인딩'을 통해 권한을 물리적으로 분리&lt;/b&gt;&lt;span data-start-index=&quot;4049&quot;&gt;했습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;4053&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #303030; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start-index=&quot;4054&quot;&gt;&lt;b data-start-index=&quot;4054&quot;&gt;Executor 툴&lt;/b&gt;&lt;span data-start-index=&quot;4064&quot;&gt;: &lt;/span&gt;read_file&lt;span data-start-index=&quot;4075&quot;&gt;, &lt;/span&gt;write_file&lt;span data-start-index=&quot;4087&quot;&gt;, &lt;/span&gt;run_code_in_sandbox&lt;span data-start-index=&quot;4108&quot;&gt;, &lt;/span&gt;web_search&lt;/li&gt;
&lt;li data-start-index=&quot;4120&quot;&gt;&lt;b data-start-index=&quot;4120&quot;&gt;Skeptic 툴&lt;/b&gt;&lt;span data-start-index=&quot;4129&quot;&gt;: &lt;/span&gt;grep_logs&lt;span data-start-index=&quot;4140&quot;&gt; (읽기 전용), &lt;/span&gt;web_search&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-start-index=&quot;4160&quot;&gt;&lt;span data-start-index=&quot;4160&quot;&gt;Skeptic 에이전트에게는 의도적으로 파일 쓰기나 코드 실행 권한을 주지 않았습니다. 만약 부여했다면 검토자가 코드를 직접 수정해버리는 월권 행위가 발생하여 다중 에이전트의 밸런스가 무너졌을 것입니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;4272&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;4273&quot;&gt;&lt;span data-start-index=&quot;4273&quot;&gt;특히 웹 검색 툴로는 &lt;/span&gt;&lt;b data-start-index=&quot;4285&quot;&gt;Tavily&lt;/b&gt;&lt;span data-start-index=&quot;4291&quot;&gt;를 선택했습니다. 전통적인 검색 API가 정리되지 않은 HTML이나 단순 링크만 반환하여 LLM의 토큰을 낭비하는 반면, Tavily는 에이전트 시스템을 위해 설계되어 복잡한 정보 추출과 정제된 클린 텍스트/마크다운을 제공해주어 RAG 및 에이전트 워크플로우에 최적화되어 있기 때문입니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;4451&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;4273&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;881&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TQs3D/dJMcahxpnTF/Ha78u55Zxiogw6PmQ5ztS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TQs3D/dJMcahxpnTF/Ha78u55Zxiogw6PmQ5ztS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TQs3D/dJMcahxpnTF/Ha78u55Zxiogw6PmQ5ztS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTQs3D%2FdJMcahxpnTF%2FHa78u55Zxiogw6PmQ5ztS0%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;564&quot; height=&quot;368&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;881&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div data-start-index=&quot;4452&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-start-index=&quot;4452&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start-index=&quot;4452&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span data-start-index=&quot;4452&quot;&gt;Phase 8: Streamlit을 활용한 Human-in-the-Loop (인간 개입)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div data-start-index=&quot;4501&quot;&gt;&lt;span data-start-index=&quot;4501&quot;&gt;초기 계획은 디스코드 봇을 연동하는 것이었으나, 긴 코드 스니펫이나 리서치 결과를 2,000자 제한이 있는 메신저로 보는 것은 비효율적이었습니다. 그래서 &lt;/span&gt;&lt;b data-start-index=&quot;4587&quot;&gt;Streamlit&lt;/b&gt;&lt;span data-start-index=&quot;4596&quot;&gt;을 활용해 직관적인 웹 기반 상호작용 UI를 구축했습니다.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;4628&quot;&gt;&lt;span data-start-index=&quot;4628&quot;&gt;가장 중요한 기술적 성취는 LangGraph의 &lt;/span&gt;interrupt_before=[&quot;executive&quot;]&lt;span data-start-index=&quot;4684&quot;&gt; 설정을 통한 &lt;/span&gt;&lt;b data-start-index=&quot;4692&quot;&gt;Human-in-the-Loop(HITL)&lt;/b&gt;&lt;span data-start-index=&quot;4715&quot;&gt; 구현입니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;4721&quot;&gt;.&lt;/span&gt;&lt;span data-start-index=&quot;4722&quot;&gt; &lt;/span&gt;&lt;span data-start-index=&quot;4723&quot;&gt;시스템이 위험하거나 비가역적인 작업을 최종 승인하기 직전, 그래프 실행이 멈추고(Pause) Streamlit 화면에 Executor의 결과와 Skeptic의 비판적 리뷰가 나란히 렌더링됩니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span data-start-index=&quot;4830&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;4831&quot;&gt;&lt;span data-start-index=&quot;4831&quot;&gt;사용자(저)는 이 리뷰를 읽고 UI의 &lt;/span&gt;&lt;b data-start-index=&quot;4852&quot;&gt;[승인]&lt;/b&gt;&lt;span data-start-index=&quot;4856&quot;&gt; 버튼을 누르거나 &lt;/span&gt;&lt;b data-start-index=&quot;4866&quot;&gt;[수정 지시]&lt;/b&gt;&lt;span data-start-index=&quot;4873&quot;&gt; 텍스트를 입력해 에이전트를 다시 루프에 태울 수 있습니다. 사용자의 피드백은 &lt;/span&gt;graph.update_state&lt;span data-start-index=&quot;4935&quot;&gt;를 통해 반영되며, &lt;/span&gt;graph.invoke(None, config)&lt;span data-start-index=&quot;4972&quot;&gt;가 호출되어 멈췄던 지점부터 시스템이 재개(Resume)됩니다.&lt;/span&gt;&lt;/div&gt;
&lt;div data-start-index=&quot;4831&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-start-index=&quot;4831&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;904&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYZVS8/dJMcaiiKWjk/kpr7UAkQN2ClkyGKJVRnG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYZVS8/dJMcaiiKWjk/kpr7UAkQN2ClkyGKJVRnG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYZVS8/dJMcaiiKWjk/kpr7UAkQN2ClkyGKJVRnG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYZVS8%2FdJMcaiiKWjk%2Fkpr7UAkQN2ClkyGKJVRnG0%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;1912&quot; height=&quot;904&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;904&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1899&quot; data-origin-height=&quot;890&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br3vxk/dJMcai34Uob/OtTiSVnHPMvbr6oUVYpA2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br3vxk/dJMcai34Uob/OtTiSVnHPMvbr6oUVYpA2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br3vxk/dJMcai34Uob/OtTiSVnHPMvbr6oUVYpA2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr3vxk%2FdJMcai34Uob%2FOtTiSVnHPMvbr6oUVYpA2K%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;1899&quot; height=&quot;890&quot; data-origin-width=&quot;1899&quot; data-origin-height=&quot;890&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로젝트 회고 및 개선점(희망 사항)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 사람의 개입에서 완전한 A2A 시스템으로&lt;/b&gt;&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;&amp;nbsp;AI의 추론 과정에서 제 의견을 주입하여 방향을 틀 수 있고, 완벽하다면 입력창을 비워 둔채 통과시켜 유연하게 저의 개입을 정하려고 했습니다.&lt;/li&gt;
&lt;li&gt;가장 큰 이유는 &lt;b&gt;Claude API 가격&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이 너무 많이 나올까봐 였습니다...&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; Executor(실행자)와 Skeptic(검토자) 사이에서 무한 루프를 돌며 API 토큰 비용을 기하급수적으로 소모할 수 있기 때문에 제어가 필요하다고 생각했습니다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 저의 기존 목표는 &lt;b&gt;완전 자율형 A2A&lt;/b&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;2. 에이전트 프레임워크 다원화 와 &lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;멀티 모델&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1518&quot;&gt;이번 프로젝트에서는 에이전트 간의 '상태(State)'와 '제어 흐름(Control Flow)'을 명시적인 그래프 구조로 정밀하게 제어하기 위해 &lt;/span&gt;&lt;b data-start-index=&quot;1599&quot;&gt;LangGraph&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1608&quot;&gt;를 채택했고 시스템의 모든 에이전트는 Claude 단일 모델을 사용하였습니다.&amp;nbsp;&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;&lt;span style=&quot;color: #303030;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;그래서 첫 번째로는 정확히 동일한 조건과 목표(과제)를 부여한 상태에서&lt;b&gt; CrewAI&lt;/b&gt;와&lt;b&gt; AutoGen(AG2)&lt;/b&gt; 같은 다른 에이전트 프레임워크를 사용해 시스템을 재구축&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1807&quot;&gt;해&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;LangGraph와 비교했을 때 &lt;b&gt;개발자 경험(DX), 토큰 소모량, 결과물의 품질&lt;/b&gt; 면에서 어떤 차이를 보이는지 직접 벤치마킹 해보고 싶습니다.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&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;&lt;span style=&quot;color: #303030;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1807&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;두 번째는 Gemini 3.1 pro나 다른 오픈소스 모델 등 &lt;b&gt;AI 모델들의 각기 다른 특화된 강점을 살려&lt;/b&gt; &lt;b&gt;멀티 모델 시스템&lt;/b&gt;을 구축할 예정입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&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;&lt;b&gt;&lt;span style=&quot;color: #303030;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1807&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;3. 홈 서버와 결합&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1141&quot;&gt;현재는 로컬 환경에서 가동하여, 집에 있는 데스크탑에서만 사용이 가능하지만, 조금 더 고도화를 한 이후에&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1141&quot;&gt;&amp;nbsp;웹 페이지와 에이전트 시스템 전체를 &lt;/span&gt;&lt;b data-start-index=&quot;1199&quot;&gt;제 홈 서버의 Proxmox VM에 배포하여 상시 가동을 하며, 외부에서도 핸드폰이나 노트북으로 사용&lt;/b&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;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;1807&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;4. &lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;Claude Code와 NotebookLM을 통한 '프롬프트 엔지니어링'의 재발견&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2014&quot;&gt;번 프로젝트의 뼈대를 세우고 문서화하는 과정에서 터미널 기반의 &lt;/span&gt;&lt;b data-start-index=&quot;2050&quot;&gt;Claude Code&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2061&quot;&gt;와 구글의 &lt;/span&gt;&lt;b data-start-index=&quot;2067&quot;&gt;NotebookLM&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2077&quot;&gt;을 처음으로 적극 활용해 보았습니다&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2096&quot;&gt;. 이 도구들이 프로젝트 스캐폴딩과 코드 실행을 자동화해주어 개발 속도가 비약적으로 상승했습니다.&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;또한, &lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2150&quot;&gt;프롬프트의 미세한 차이가 전체 시스템의 결과물에 얼마나 영향을 미치는가 를 느꼈습니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2273&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot; data-start-index=&quot;2274&quot;&gt;단순히 &quot;~ 해 줘&quot;라고 묻는 것을 넘어서 에 &lt;span style=&quot;background-color: #ffffff; color: #303030; text-align: start;&quot;&gt;이전트의 페르소나, 사용 가능한 도구의 제약 조건 등을 어떻게 걸어두냐에 따라서 결과물이 많이 달랐습니다.&lt;/span&gt;&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;이후에도 계속해서 프롬프트 엔지니어링에 대해서 공부하고 제 방향에 맞는 프롬프트를 찾아볼 예정입니다.&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;</description>
      <category>IT 이것저것 요모조모/AI</category>
      <category>Agent</category>
      <category>AI</category>
      <category>claude</category>
      <category>Claude API</category>
      <category>langgraph</category>
      <category>notebooklm</category>
      <category>streamlit</category>
      <category>tavily</category>
      <category>생성형AI</category>
      <category>프롬프트</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/36</guid>
      <comments>https://jiione.tistory.com/36#entry36comment</comments>
      <pubDate>Wed, 22 Apr 2026 23:04:04 +0900</pubDate>
    </item>
    <item>
      <title>[GPU 엔지니어링 #2] GPU 구조와 SIMT</title>
      <link>https://jiione.tistory.com/35</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b data-path-to-node=&quot;6&quot; data-index-in-node=&quot;0&quot;&gt;이슈 배경 및 포스팅 목표&lt;/b&gt;&lt;/h2&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;최근 ChatGPT와 같은 거대 언어 모델(LLM)과 딥러닝이 폭발적으로 성장하면서, GPU는 단순한 그래픽 처리 장치를 넘어 'AI 시대의 심장'이 되었습니다. 하지만 많은 분들이 비싼 GPU 서버를 구축하고도 &quot;왜 기대만큼 연산 속도가 나오지 않을까?&quot; 혹은 &quot;왜 메모리(VRAM)는 마음대로 증설할 수 없을까?&quot;라는 엔지니어링 문제에 부딪히곤 합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;이러한 문제를 근본적으로 해결하려면 단순히 코드를 잘 짜는 것을 넘어, 코드가 실행되는 &lt;b&gt;하드웨어 밑바닥의 작동 원리(아키텍처)&lt;/b&gt;를 이해해야 합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;오늘 글에서는 CPU와 GPU의 설계 철학 차이에서 출발해, GPU의 핵심 실행 모델인 &lt;b data-index-in-node=&quot;137&quot; data-path-to-node=&quot;7&quot;&gt;SIMT&lt;/b&gt;, 성능 저하의 주범인 &lt;b data-index-in-node=&quot;154&quot; data-path-to-node=&quot;7&quot;&gt;분기 발산(Warp Divergence)&lt;/b&gt;, 그리고 &lt;b data-index-in-node=&quot;182&quot; data-path-to-node=&quot;7&quot;&gt;VRAM의 물리적 한계&lt;/b&gt;까지 흩어져 있던 개념들을 하나의 흐름으로 완벽하게 정리해 보겠습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size23&quot;&gt;GPU의 구조: SM, CUDA 코어, Warp&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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 data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;SM (Streaming Multiprocessor) - &quot;독립적인 작업장&quot;:&lt;/b&gt; GPU 칩 내부에는 수십 개에서 최상위 모델의 경우 140여 개 이상의 SM이 탑재되어 있습니다. SM은 단순한 코어의 묶음이 아니라, 그 자체로 명령어를 해석하고 메모리를 공유하며 수백 개의 연산 유닛을 품고 있는 완전한 독립 작업장입니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;CUDA 코어 (ALU) - &quot;단순 반복 작업자&quot;:&lt;/b&gt; SM 내부에 존재하는 실질적인 연산 유닛(ALU)입니다. CPU의 ALU가 복잡한 논리 연산과 상황 대처에 능한 '만능 박사'라면, GPU의 CUDA 코어는 행렬 곱셈이나 덧셈 같은 단순 사칙연산에 극도로 특화된 '단순 반복 숙련공'입니다. 이들은 크기가 매우 작아 하나의 SM 안에 수백 개씩 들어갈 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0&quot;&gt;워프 (Warp) - &quot;32명의 작업 조&quot;:&lt;/b&gt; 아무리 작업자가 많아도 개별적으로 지시를 내리면 통제가 불가능합니다. 그래서 NVIDIA는 하드웨어적으로 &lt;b data-index-in-node=&quot;84&quot; data-path-to-node=&quot;12,2,0&quot;&gt;32개의 스레드(작업자)를 하나의 조(Warp)로 묶어버렸습니다.&lt;/b&gt; 워프에 속한 32개의 스레드는 단 하나의 명령어를 받아 **완벽하게 똑같은 연산(Lock-step)**을 동시에 수행합니다. 다루는 데이터의 위치만 다를 뿐, 움직임은 완전히 일치해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16&quot;&gt;[핵심 원리: Lock-step 실행]&lt;/b&gt; 가장 중요한 작동 원리는 하나의 워프 스케줄러가 &quot;단 1개의 명령어&quot;를 가져오면, 워프에 속한 32개의 스레드가 각자의 CUDA 코어에 매핑되어 &lt;b data-index-in-node=&quot;107&quot; data-path-to-node=&quot;16&quot;&gt;&quot;정확히 똑같은 연산&quot;을 동시에 수행&lt;/b&gt;한다는 것입니다. 다루는 데이터의 위치만 다를 뿐 행동은 완벽히 일치합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size20&quot;&gt;워프와 워프 스케줄러의 심층 이해 (+ SM 파티셔닝)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;이 워프들에게 일감을 던져주는 주체는 누구일까요? 바로 SM 내부에 존재하는 **워프 스케줄러(Warp Scheduler)**입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;워프(Warp) vs 워프 스케줄러(Warp Scheduler)의 차이:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,1,0,0&quot;&gt;워프:&lt;/b&gt; 실행되는 스레드들의 묶음(논리적/물리적 대상)입니다. (예: 공장의 작업 조)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,1,1,0&quot;&gt;워프 스케줄러:&lt;/b&gt; SM 내부에서 대기 중인 수십 개의 워프들 중, &quot;지금 당장 메모리에서 데이터를 가져와 연산할 준비가 끝난 워프&quot;를 찾아내어 명령어를 하달(Dispatch)하는 &lt;b data-index-in-node=&quot;99&quot; data-path-to-node=&quot;15,0,1,1,0&quot;&gt;하드웨어 제어 장치&lt;/b&gt;입니다. (예: 공장의 작업 반장)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;스케줄러의 가장 중요한 역할은 &lt;b&gt;'지연 시간 은닉(Latency Hiding)'&lt;/b&gt;입니다. A 워프가 VRAM에서 데이터를 가져오느라 시간이 걸려 멍하니 서 있다면, 스케줄러는 즉시 계산 준비가 끝난 B 워프를 CUDA 코어에 투입시켜 하드웨어가 1초도 쉬지 않게 만듭니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17&quot;&gt;[심화: SM 파티셔닝 (Sub-core Partitioning) 체제의 도입]&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;GPU 세대가 발전하면서 SM 하나에 들어가는 CUDA 코어의 수가 128개 이상으로 폭발적으로 늘어났습니다. 그러자 스케줄러(반장) 1명이 128명의 작업자에게 제때 명령어를 나눠주지 못하는 병목 현상이 발생했습니다. 이를 해결하기 위해 최신 아키텍처에서는 &lt;b data-index-in-node=&quot;190&quot; data-path-to-node=&quot;17&quot;&gt;거대한 SM 내부를 4개의 구역(Sub-core)으로 쪼개는 파티셔닝(Partitioning) 설계&lt;/b&gt;를 도입했습니다. 각 구역마다 1명의 전담 워프 스케줄러와 전용 레지스터를 독립적으로 배치하여, 4명의 반장이 동시에 명령을 쏟아내도록 만들어 동시 처리량을 극대화한 것입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;18&quot; data-ke-size=&quot;size20&quot;&gt;SIMD에서 SIMT로&lt;/h4&gt;
&lt;p data-path-to-node=&quot;19&quot; data-ke-size=&quot;size16&quot;&gt;이러한 워프 기반의 실행 구조를 바탕으로 NVIDIA는 &lt;b&gt;SIMT(Single Instruction, Multiple Threads)&lt;/b&gt;라는 혁신적인 실행 모델을 정립했습니다. 이를 이해하려면 과거의 SIMD와 비교해 보아야 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;20&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;20,0,0&quot;&gt;SIMD (Single Instruction, Multiple Data):&lt;/b&gt; 하나의 명령어로 여러 데이터를 처리하는 하드웨어 방식입니다. 하지만 이 방식을 쓰려면 개발자가 코드 단에서 직접 &quot;데이터 4개를 1세트로 묶어라&quot;라고 명시하는 복잡한 벡터(Vector) 프로그래밍을 해야만 했습니다. 매우 귀찮고 오류가 나기 쉬운 작업입니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;20,1,0&quot;&gt;SIMT (Single Instruction, Multiple Threads):&lt;/b&gt; 반면 SIMT 모델에서는 개발자가 그냥 &quot;&lt;b&gt;스레드 1개가 데이터 1개를 처리한다&quot;&lt;/b&gt;는 스칼라(Scalar) 코드를 아주 단순하게 작성하기만 하면 됩니다. 코드를 컴파일하고 실행하면, GPU 안의 '워프 스케줄러'가 알아서 스레드 32개를 모아 하드웨어 레벨에서 SIMD 방식으로 묶어서 실행해 줍니다. 개발자의 편의성과 하드웨어의 병렬 처리 성능을 완벽하게 조화시킨 패러다임입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size20&quot;&gt;분기 발산 (Warp Divergence): if문이 초래하는 치명적 병목&lt;/h4&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;SIMT 구조는 32개의 스레드가 무조건 똑같은 명령어를 실행해야 한다는 강력한 전제 조건이 있습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;58&quot; data-path-to-node=&quot;22&quot;&gt;만약, 이 스레드들이 if-else 같은 조건문을 만나 실행 경로가 엇갈리게 되면 큰 병목현상이 발생합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;GPU는 CPU처럼 분기를 예측하거나 두 갈래 길을 동시에 처리할 수 있는 복잡한 회로가 없습니다. 따라서 워프 내에서 경로가 엇갈리면, 하드웨어는 울며 겨자 먹기로 각 경로를&lt;b&gt; 순차적으로 실행(직렬화)해&lt;/b&gt;야만 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1775135925749&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// [문제 상황] 데이터 값에 따라 스레드의 동작이 달라지는 분기문 발생
__global__ void process_data(int *data) {
    int tid = threadIdx.x; // 워프 내 각 스레드의 고유 ID (0~31)

    // 워프 내 32개의 스레드가 이 조건문을 만납니다.
    if (data[tid] &amp;gt; 0) {
        // [경로 A] 16개의 스레드가 이 연산을 수행할 때,
        // 나머지 16개는 유용한 작업을 하지 못하고 마스킹(대기) 상태가 됩니다.
        data[tid] = data[tid] * 2; 
    } else {
        // [경로 B] A 경로가 끝나면, 이번엔 반대로 A 스레드들이 멈추고
        // 나머지 16개 스레드가 순차적으로 이 연산을 수행합니다.
        data[tid] = data[tid] * -1;
    }
}&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;워프 발산(Warp Divergence)&lt;/b&gt;이라고 부릅니다. 이 현상이 발생하면 1번 사이클에 끝날 일이 2번 사이클로 늘어나고, 매 시간마다 연산 유닛(CUDA 코어)의 50%가 아무것도 하지 않고 자원을 낭비하게 됩니다. 조건문이 중첩될수록 효율은 기하급수적으로 떨어지며, 이는 GPU 프로그래밍에서 성능을 갉아먹는 1순위 주범입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;26&quot; data-ke-size=&quot;size20&quot;&gt;VRAM의 물리적 한계: 왜 마음대로 꽂을 수 없을까?&lt;/h4&gt;
&lt;p data-path-to-node=&quot;27&quot; data-ke-size=&quot;size16&quot;&gt;수천 개의 코어가 워프 단위로 엄청난 연산을 쏟아내려면, 그에 걸맞은 속도로 데이터를 공급해 주는 메모리가 필수적입니다. 여기서 일반적인 &lt;b data-index-in-node=&quot;77&quot; data-path-to-node=&quot;27&quot;&gt;시스템 RAM&lt;/b&gt;과 GPU 전용인 &lt;b data-index-in-node=&quot;94&quot; data-path-to-node=&quot;27&quot;&gt;VRAM&lt;/b&gt;의 아키텍처 차이가 명확해집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;28&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;28,0,0&quot;&gt;시스템 RAM (지연 시간 최적화):&lt;/b&gt; CPU가 다양한 상황에 대처하기 위해 필요한 소규모의 데이터를 최대한 빨리(응답 속도 위주) 가져오는 데 특화되어 있습니다. 도로로 치면 좁지만 제한 속도가 무제한인 고속도로입니다. (메모리 버스 폭: 보통 64-bit)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;28,1,0&quot;&gt;VRAM (대역폭 극대화):&lt;/b&gt; GPU의 수많은 코어에 엄청난 양의 데이터를 한 번에 때려 부어야 하므로, 응답 속도보다는 데이터가 지나가는 통로 자체를 무식할 정도로 넓힌 메모리입니다. 도로로 치면 차선이 수천 개인 초대형 고속도로입니다. (메모리 버스 폭: 256-bit ~ 5120-bit 이상)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;29&quot;&gt;Q. 왜 컴퓨터 RAM처럼 슬롯에 꽂아서 추가하지 못할까요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;초당 수백 기가바이트(GB/s)에서 테라바이트(TB/s)의 막대한 데이터를 전송하려면 수백, 수천 가닥의 전기 배선(Pin)이 필요합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;데이터 전송 클럭이 이렇게 극단적으로 높을 때, 칩과 메모리 사이의 거리가 단 몇 밀리미터(mm)라도 멀어지면 찰나의 시간 차이로 인해 전기 신호가 훼손되고 노이즈가 발생합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;따라서 VRAM은 물리적인 슬롯(DIMM) 형태를 거치지 않고, &lt;b data-index-in-node=&quot;245&quot; data-path-to-node=&quot;29&quot;&gt;반드시 GPU 칩셋 바로 옆 기판에 바짝 붙여 납땜(Soldered)해야만 신호 무결성을 유지&lt;/b&gt;할 수 있습니다. 특히 최신 데이터센터용 AI 칩(H100 등)은 이 거리마저도 아깝다고 판단하여, 아예 HBM(High Bandwidth Memory)을 칩 다이(Die) 옆에 2.5D 패키징으로 하나의 덩어리로 만들어버립니다. 이 때문에 사용자는 최초에 구매한 VRAM 용량을 영원히 안고 가야 하는 물리적 한계를 가지게 됩니다.&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;따라서, VRAM은 증설이 힘드니, Out of Memory 에러가 발생하지 않도록 모델의 Batch Size를 세밀하게 튜닝해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/공부기록</category>
      <category>CUDA</category>
      <category>GPU</category>
      <category>SIMT</category>
      <category>SM</category>
      <category>VRAM</category>
      <category>WARP</category>
      <category>분기예측</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/35</guid>
      <comments>https://jiione.tistory.com/35#entry35comment</comments>
      <pubDate>Thu, 2 Apr 2026 22:23:11 +0900</pubDate>
    </item>
    <item>
      <title>[GPU 엔지니어링 #1] CPU vs GPU</title>
      <link>https://jiione.tistory.com/34</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며..&lt;/h2&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;최근 GPU 엔지니어링에 대해 공부한 내용을 블로그에 기록해 보려 합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;이 내용은 지식은 생각보다 쉽게 참고할 만한 레퍼런스가 많지 않더라고요. 그래서 학습 과정에서 여러 기업들의 딥다이브 테크 블로그와 NVIDIA 공식 문서, 그리고 Gemini와의 문답을 적극적으로 활용했습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;오로지 개인적인 핵심 개념 복습과 기록을 목적으로 작성하는 포스팅이다 보니, 글에 다소 두서가 없더라도 양해 부탁드립니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CPU(Central Processing Unit) vs GPU(Graphics Processing Unit)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU와 GPU는 겉보기엔 비슷한 실리콘 칩이지만, 탄생 목적부터 완전히 다른 &quot;이종(Heterogeneous)&quot; 프로세서입니다.&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;CPU:&lt;/b&gt; 소수의 똑똑한 교수님들이 복잡한 문제를 순서대로 빠르게 해결하는 것 (순차 처리)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GPU:&lt;/b&gt; 수천 명의 초등학생들이 쉬운 문제를 동시에 해결하는 것 (병렬 처리 최적화)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Die 면적의 배분&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CPU (Control Unit 중심, ALU 소수):&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설계 철학: &amp;ldquo;어떤 복잡한 명령어가 와도 멈추지 않고 처리한다.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; 전체 면적의 절반 이상을 &lt;b&gt;캐시 메모리(L1/L2/L3)&lt;/b&gt;와 &lt;b&gt;제어 유닛(Control Unit)&lt;/b&gt;이 차지합니다. 실제 연산을 담당하는 &lt;b&gt;ALU(Arithmetic Logic Unit)&lt;/b&gt;의 비중은 상대적으로 작습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이유:&lt;/b&gt; CPU는 운영체제 실행, I/O 인터럽트 처리, 조건 분기 등 예측 불가능하고 순서 의존적인 작업을 처리해야 합니다. 따라서 명령어의 순서를 바꾸어 최적화하는 비순차 실행(Out-of-Order Execution)이나 데이터가 오길 기다리는 시간을 줄이기 위한 거대한 캐시가 필수적입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Latency Oriented (지연 시간 최소화):&lt;/b&gt; 클럭 속도(GHz)를 극단적으로 높이고, 데이터가 메모리에서 오기를 기다리지 않도록 큰 캐시를 사용하여 '한 놈'을 아주 빠르게 처리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GPU (ALU 중심, Control Unit 최소화):&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; &quot;계산할 게 산더미니, 관리자는 줄이고 일꾼을 늘린다.&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구조:&lt;/b&gt; 다이 면적의 대부분을 수천 개의&lt;b&gt; ALU&lt;/b&gt;가 차지합니다. 캐시 메모리는 아주 작고, 제어 유닛은 단순합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이유:&lt;/b&gt; 그래픽 렌더링이나 행렬 연산은 모든 픽셀(데이터)에 똑같은 계산을 반복합니다. 복잡한 흐름 제어보다는 단순히 계산량을 밀어붙이는 것이 중요하므로, 제어 로직을 쳐내고 그 자리에 연산 장치를 꽉 채워 넣었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Throughput Oriented (처리량 최대화) :&lt;/b&gt; 클럭 속도는 CPU보다 낮지만, 수천 개의 스레드를 동시에 돌립니다. 메모리 로딩으로 인해 딜레이가 발생하면, 기다리지 않고 즉시 다른 스레드로 컨텍스트 스위칭하여 유휴 시간을 숨깁니다(&lt;b&gt;Latency Hiding&lt;/b&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 GPU 병렬 처리의 핵심인 SIMT(Single Instruction, Multiple Threads) 구조와 GPU 명령어 집합에 대해 정리할 예정입니다.&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/공부기록</category>
      <category>AI</category>
      <category>CPU</category>
      <category>GPU</category>
      <category>GPU 엔지니어링</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/34</guid>
      <comments>https://jiione.tistory.com/34#entry34comment</comments>
      <pubDate>Mon, 30 Mar 2026 21:16:59 +0900</pubDate>
    </item>
    <item>
      <title>[Side Project] Gemini CLI + Discord를 활용한 ChatOps 구축기</title>
      <link>https://jiione.tistory.com/33</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0. 들어가며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평화로운 주말 혹은 깊은 밤, 갑자기 울리는 알람 소리에 무거운 몸을 이끌고 노트북을 열어 VPN을 연결하고 터미널을 켜는 것은 제게는 매우 번거로웠습니다.&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 data-index-in-node=&quot;11&quot; data-path-to-node=&quot;4&quot;&gt;&quot;알람이 울렸을 때, 그냥 핸드폰으로 대화하듯 상황을 파악하고 조치까지 끝낼 수 없을까?&quot;&lt;/b&gt; 이 단순한 호기심이 Gemini CLI와 MCP, 그리고 Discord를 결합한 저만의 ChatOps 프로젝트를 시작해봤습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 시스템 아키텍처 및 환경 &lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 73.2558%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.8546%;&quot;&gt;구분&lt;/td&gt;
&lt;td style=&quot;width: 57.4012%;&quot;&gt;상세 내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.8546%;&quot;&gt;Node 구성&lt;/td&gt;
&lt;td style=&quot;width: 57.4012%;&quot;&gt;AWS EC2 (t3.medium) /&amp;nbsp; 1 Master, 2 Workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.8546%;&quot;&gt;OS&lt;/td&gt;
&lt;td style=&quot;width: 57.4012%;&quot;&gt;Ubuntu Image / Ubuntu 22.04 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.8546%;&quot;&gt;Runtime&lt;/td&gt;
&lt;td style=&quot;width: 57.4012%;&quot;&gt;Docker / Containerd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15.8546%;&quot;&gt;Network&lt;/td&gt;
&lt;td style=&quot;width: 57.4012%;&quot;&gt;CNI Flannel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;h4 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size20&quot;&gt;소프트웨어 스택&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,0,0&quot;&gt;Monitoring:&lt;/b&gt; kube-prometheus-stack (Prometheus, Grafana, Alertmanager 연동)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,0&quot;&gt;AI Engine:&lt;/b&gt; Gemini CLI (@google/gemini-cli)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,2,0&quot;&gt;AI Interface:&lt;/b&gt; Model Context Protocol (MCP)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 핵심 개념 이해하기: 왜 Gemini CLI와 MCP인가?&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;요즘 LLM(대형 언어 모델) 트렌드는 단순히 '말을 잘하는 것'을 넘어, '도구를 직접 사용하는 에이전트'로 진화하고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;8,0,0&quot; data-index-in-node=&quot;0&quot;&gt;Gemini CLI:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Google의 강력한 모델을 터미널 환경에서 즉시 실행할 수 있게 해주는 도구입니다. 복잡한 API 호출 코드 없이도 쉘 스크립트나 다른 프로그램과 연동이 쉽다는 장점이 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;8,1,0&quot; data-index-in-node=&quot;0&quot;&gt;MCP (Model Context Protocol):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AI 모델이 외부 데이터(파일 시스템, DB, 모니터링 툴 등)에 표준화된 방식으로 접근할 수 있게 해주는 프로토콜입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-path-to-node=&quot;8,1,1&quot;&gt;
&lt;li&gt;이를 통해 Gemini는 단순한 텍스트 생성을 넘어,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b data-path-to-node=&quot;8,1,1,0,0&quot; data-index-in-node=&quot;30&quot;&gt;실제 쿠버네티스 클러스터의 상태를 조회하거나 Alertmanager의 설정을 변경&lt;/b&gt;하는 능력을 갖추게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&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;&lt;b&gt;3. Gemini CLI&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1771234423231&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Python 설치, Node / npm 설치를 위해 필요
$ sudo apt-get install python3

# GCC 및 G++ 설치, Node.js 설치를 위해 필요
$ sudo apt-get install g++-12 gcc-12

# Node.js 및 npm 설치
$ wget https://nodejs.org/dist/latest-v21.x/node-v21.7.3-linux-x64.tar.gz
$ tar -xvf node-v21.7.3-linux-x64.tar.gz
$ sudo cp -r node-v21.7.3-linux-x64/* /usr/local

$ source ~/.bashrc
$ node --version

# Gemini CLI 설치
$ sudo npm install -g @google/gemini-cli

# Gemini CLI 실행
$ gemini&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6q3ue/dJMcabiSAMv/1Bh7nZjYE28nzhMaGJejGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6q3ue/dJMcabiSAMv/1Bh7nZjYE28nzhMaGJejGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6q3ue/dJMcabiSAMv/1Bh7nZjYE28nzhMaGJejGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6q3ue%2FdJMcabiSAMv%2F1Bh7nZjYE28nzhMaGJejGk%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;913&quot; height=&quot;423&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;423&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 모니터링 설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링 툴은 &lt;b&gt;prometheus-stack&lt;/b&gt;(prometheus + grafana + alertmanager) 을 Gemini CLI를 활용하여 설치하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인상 깊었던 점은 설치하다가 막히더라도 본인이 문제를 찾아서 해결하는 것이었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlpE48/dJMcadnoXcm/ylaySggKRiSqgOkElhwbBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlpE48/dJMcadnoXcm/ylaySggKRiSqgOkElhwbBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlpE48/dJMcadnoXcm/ylaySggKRiSqgOkElhwbBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlpE48%2FdJMcadnoXcm%2FylaySggKRiSqgOkElhwbBK%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;1302&quot; height=&quot;644&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;644&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;645&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6Rog2/dJMb99ZFB02/xQV9zMevzM0y6nya9L3MT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6Rog2/dJMb99ZFB02/xQV9zMevzM0y6nya9L3MT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6Rog2/dJMb99ZFB02/xQV9zMevzM0y6nya9L3MT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6Rog2%2FdJMb99ZFB02%2FxQV9zMevzM0y6nya9L3MT0%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;1305&quot; height=&quot;645&quot; data-origin-width=&quot;1305&quot; data-origin-height=&quot;645&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. Alertmanager MCP 서버 등록&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alertmanager MCP는 아래 오픈소스를 활용했습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1771237444467&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - ntk148v/alertmanager-mcp-server: A Model Context Protocol (MCP) server that enables AI assistants to integreate with Pr&quot; data-og-description=&quot;A Model Context Protocol (MCP) server that enables AI assistants to integreate with Prometheus Alertmanager - ntk148v/alertmanager-mcp-server&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ntk148v/alertmanager-mcp-server&quot; data-og-url=&quot;https://github.com/ntk148v/alertmanager-mcp-server&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bPaHex/dJMb9lL7Uxn/bI7uRkrzCNYNz4tCR2gXTK/img.png?width=1200&amp;amp;height=600&amp;amp;face=952_114_1066_239,https://scrap.kakaocdn.net/dn/xFFPA/dJMb9fZrEDW/CEpqiwxL33n4ZimXOEvDg0/img.png?width=1200&amp;amp;height=600&amp;amp;face=952_114_1066_239&quot;&gt;&lt;a href=&quot;https://github.com/ntk148v/alertmanager-mcp-server&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ntk148v/alertmanager-mcp-server&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bPaHex/dJMb9lL7Uxn/bI7uRkrzCNYNz4tCR2gXTK/img.png?width=1200&amp;amp;height=600&amp;amp;face=952_114_1066_239,https://scrap.kakaocdn.net/dn/xFFPA/dJMb9fZrEDW/CEpqiwxL33n4ZimXOEvDg0/img.png?width=1200&amp;amp;height=600&amp;amp;face=952_114_1066_239');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - ntk148v/alertmanager-mcp-server: A Model Context Protocol (MCP) server that enables AI assistants to integreate with Pr&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A Model Context Protocol (MCP) server that enables AI assistants to integreate with Prometheus Alertmanager - ntk148v/alertmanager-mcp-server&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP 등록 설정 파일&lt;/p&gt;
&lt;pre id=&quot;code_1771237546004&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ~/.gemini/settings.json 에 alertmanager mcp 정보 추가
{
  &quot;mcpServers&quot;: {
    &quot;filesystem&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [
        &quot;-y&quot;,
        &quot;@modelcontextprotocol/server-filesystem&quot;,
        &quot;~/Desktop&quot;,
        &quot;~/MyGemini_CLI&quot;
      ]
    },
    &quot;alertmanager&quot;: {
      &quot;command&quot;: &quot;docker&quot;,
      &quot;args&quot;: [
        &quot;run&quot;,
        &quot;--rm&quot;,
        &quot;-i&quot;,
        &quot;-e&quot;, &quot;ALERTMANAGER_URL&quot;,
        &quot;ghcr.io/ntk148v/alertmanager-mcp-server:latest&quot;
      ],
      &quot;env&quot;: {
        &quot;ALERTMANAGER_URL&quot;: &quot;http://172.31.13.45:30093&quot;
      }
    }
  },
  &quot;security&quot;: {
    &quot;auth&quot;: {
      &quot;selectedType&quot;: &quot;oauth-personal&quot;
    }
  },
  &quot;ui&quot;: {
    &quot;theme&quot;: &quot;Default&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. Discord 통합 및 ChatOps 인터페이스 구현&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 언제 어디서나 인프라에 접근할 수 있도록 &lt;b data-index-in-node=&quot;38&quot; data-path-to-node=&quot;17&quot;&gt;Discord&lt;/b&gt;와 연결하겠습니다.&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;18&quot; data-ke-size=&quot;size23&quot;&gt;6-1. 디스코드 앱 설정&lt;/h3&gt;
&lt;p data-path-to-node=&quot;19&quot; data-ke-size=&quot;size16&quot;&gt;Discord Developer Portal에서 봇을 생성하고 필요한 권한을 부여했습니다. ! 특히 메시지를 읽고 답장하기 위해 **'Message Content Intent'**를 활성화하는 것이 중요합니다. !&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1908&quot; data-origin-height=&quot;611&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/edTtV1/dJMcagEur8n/gLIFKk5ffOsx3Bb4qmSx4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/edTtV1/dJMcagEur8n/gLIFKk5ffOsx3Bb4qmSx4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/edTtV1/dJMcagEur8n/gLIFKk5ffOsx3Bb4qmSx4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FedTtV1%2FdJMcagEur8n%2FgLIFKk5ffOsx3Bb4qmSx4K%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;1908&quot; height=&quot;611&quot; data-origin-width=&quot;1908&quot; data-origin-height=&quot;611&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oe52T/dJMcagEur9x/OAZKDJt0M0TsUFZ3f1saBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oe52T/dJMcagEur9x/OAZKDJt0M0TsUFZ3f1saBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oe52T/dJMcagEur9x/OAZKDJt0M0TsUFZ3f1saBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOe52T%2FdJMcagEur9x%2FOAZKDJt0M0TsUFZ3f1saBk%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;1540&quot; height=&quot;449&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;20&quot; data-ke-size=&quot;size23&quot;&gt;6-2. ChatOps 봇 코드 로직&lt;/h3&gt;
&lt;p data-path-to-node=&quot;21&quot; data-ke-size=&quot;size16&quot;&gt;Python의 discord.py 라이브러리와 subprocess 모듈을 사용하여, 사용자가 디스코드에 입력한 명령을 내부의 Gemini CLI로 전달하고 결과를 다시 출력해 주도록 설계했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1771241946700&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 핵심 로직 요약: 디스코드 메시지를 Gemini CLI 명령어로 변환
full_prompt = f&quot;{conversation_history}\n\nUser: {command_text}\nGemini:&quot;.strip()

process = await asyncio.to_thread(
    subprocess.run,
    [GEMINI_CLI_PATH, '-y', full_prompt],
    capture_output=True,
    text=True,
    env=os.environ
)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-path-to-node=&quot;24&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. 트러블 슈팅: 상태가 없어서 이전 대화를 기억을 못함&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 진행 중 가장 큰 난관은 &lt;b data-index-in-node=&quot;19&quot; data-path-to-node=&quot;25&quot;&gt;Gemini CLI의 'Stateless(상태 없음)' 특성&lt;/b&gt;이었습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;26&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,0,0&quot;&gt;문제점:&lt;/b&gt; CLI 방식은 실행할 때마다 새로운 세션으로 인식되어, 이전 대화 맥락을 전혀 기억하지 못했습니다. &quot;현재 알람 보여줘&quot;라고 한 뒤 &quot;그거 해결해줘&quot;라고 하면 &quot;그게 뭔데요?&quot;라는 식으로 직전 대화를 알지 못했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7pekv/dJMcafr04Z3/Qb6y6TWuQ8SnKjN8HEspO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7pekv/dJMcafr04Z3/Qb6y6TWuQ8SnKjN8HEspO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7pekv/dJMcafr04Z3/Qb6y6TWuQ8SnKjN8HEspO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7pekv%2FdJMcafr04Z3%2FQb6y6TWuQ8SnKjN8HEspO0%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;1138&quot; height=&quot;235&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;26&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;26,1,0&quot;&gt;해결책:&lt;/b&gt; 봇 코드 내부에 user_conversations라는 딕셔너리를 만들어 &lt;b data-index-in-node=&quot;45&quot; data-path-to-node=&quot;26,1,0&quot;&gt;사용자별 대화 기록을 직접 관리&lt;/b&gt;하도록 구현했습니다. Gemini CLI를 호출할 때마다 이전 기록을 통째로 '프롬프트'에 포함시켜 넘겨주는 방식입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1771242108885&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; # !gemini-new: 대화 기록 초기화
    if command_name == '!gemini-new':
        if user_id in user_conversations:
            del user_conversations[user_id]
        await message.channel.send(&quot;대화 기록을 초기화하고 새로운 대화를 시작합니다. 무엇을 도와드릴까요?&quot;)
        return

    # !gemini: 대화 계속 또는 시작
    if not command_text:
        await message.channel.send(&quot;명령어를 입력해주세요. 예: `!gemini 현재 폴더에 있는 파일 목록 보여줘`\n대화를 새로 시작하려면 `!gemini-new`를 사용하세요.&quot;)
        return

    # 이전 대화 기록 가져오기
    conversation_history = &quot;&quot;
    if user_id in user_conversations:
        conversation_history = user_conversations[user_id][&quot;history&quot;]

    # Gemini에게 전달할 전체 프롬프트 구성
    full_prompt = f&quot;{conversation_history}\n\nUser: {command_text}\nGemini:&quot;.strip()

    thinking_message = await message.channel.send(f&quot;알겠습니다. Gemini에게 물어볼게요: `{command_text}` (이전 대화 포함)&quot;)

    try:
        process = await asyncio.to_thread(
            subprocess.run,
            [GEMINI_CLI_PATH, '-y', full_prompt],
            capture_output=True,
            text=True,
            timeout=180, # 시간 연장
            env=os.environ
        )&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-path-to-node=&quot;26&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;26,2,0&quot; data-index-in-node=&quot;0&quot;&gt;결과:&lt;/b&gt;&lt;span&gt; &lt;/span&gt;맥락이 유지되는 대화형 운영 시스템이 완성되었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9viGx/dJMcacWlQYF/8FiIEtosD3tiTVSLS93nu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9viGx/dJMcacWlQYF/8FiIEtosD3tiTVSLS93nu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9viGx/dJMcacWlQYF/8FiIEtosD3tiTVSLS93nu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9viGx%2FdJMcacWlQYF%2F8FiIEtosD3tiTVSLS93nu0%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;1168&quot; height=&quot;682&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;682&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; 8. 마치며: 회고와 향후 과제&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트를 통해 AI가 단순한 도구를 넘어 많은 부분에서 편리함을 가져올 수 있다는 것을 느꼈습니다.&lt;/p&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;하지만, 부족한 점도 많이 보였고 실제 운영 환경에 도입하기 위해서는&amp;nbsp; 아직 해결해야 될 과제들도 명확히 보였습니다.&lt;/b&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;h4 data-path-to-node=&quot;36&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;안정성 및 신뢰성 확보 (Reliability)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;37&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;37,0,0&quot;&gt;예외 처리 고도화:&lt;/b&gt; CLI 실행 실패나 네트워크 타임아웃 발생 시 봇이 죽지 않고 재시도(Retry)하거나 사용자에게 명확한 오류 상황을 알리는 로직이 보강되어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;37,1,0&quot;&gt;상태 저장의 견고함:&lt;/b&gt; 현재는 메모리에 대화 이력을 저장하지만, 봇 프로세스가 재시작되면 기억이 사라집니다. 이를 DB나 Redis에 저장하여 데이터의 지속성을 확보할 계획입니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;37,2,0&quot;&gt;모니터링의 모니터링:&lt;/b&gt; 봇 자체가 죽었을 때를 대비해 Health Check 기능을 추가하고, 봇의 상태를 감시하는 시스템이 필수적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;38&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;성능 및 보안 개선&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;39&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;39,0,0&quot;&gt;토큰 최적화:&lt;/b&gt; 대화가 길어질수록 토큰 소모가 커지는 문제를 해결하기 위해 '대화 요약' 기법을 도입하려 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;39,1,0&quot;&gt;보안(RBAC):&lt;/b&gt; 누구나 인프라를 건드릴 수 없도록 특정 사용자 ID만 허용하는 엄격한 권한 체계를 구축할 것입니다.&lt;/li&gt;
&lt;/ul&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;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>alertmanager</category>
      <category>chatops</category>
      <category>discord</category>
      <category>Gemini</category>
      <category>gemini cli</category>
      <category>Grafana</category>
      <category>MCP</category>
      <category>Prometheus</category>
      <category>prometheus-stack</category>
      <category>모니터링</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/33</guid>
      <comments>https://jiione.tistory.com/33#entry33comment</comments>
      <pubDate>Mon, 16 Feb 2026 20:52:47 +0900</pubDate>
    </item>
    <item>
      <title>홈 NAS 만들기 #2: Proxmox 설치부터 TrueNAS 구축까지</title>
      <link>https://jiione.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;1915&quot; data-origin-height=&quot;871&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C6Bq1/dJMcahi5bqu/2GLf3CKGNlm5MaKEvOhbMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C6Bq1/dJMcahi5bqu/2GLf3CKGNlm5MaKEvOhbMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C6Bq1/dJMcahi5bqu/2GLf3CKGNlm5MaKEvOhbMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC6Bq1%2FdJMcahi5bqu%2F2GLf3CKGNlm5MaKEvOhbMk%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;1915&quot; height=&quot;871&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;871&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 포스팅에서 하드웨어 조립을 완료했으니, 이번에는 서버 운영을 위한 소프트웨어 환경을 구축할 차례입니다. 가상화 플랫폼인 &lt;b data-index-in-node=&quot;70&quot; data-path-to-node=&quot;3&quot;&gt;Proxmox&lt;/b&gt;를 설치하고, 그 위에 &lt;b data-index-in-node=&quot;90&quot; data-path-to-node=&quot;3&quot;&gt;TrueNAS CORE&lt;/b&gt;를 올려 NAS 환경을 만드는 과정을 정리했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; 1. 하이퍼바이저로 Proxmox를 선택한 이유&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;자작 서버의 성능(i7-10700 / 48GB RAM)을 효율적으로 사용하기 위해 일반 OS가 아닌 하이퍼바이저를 선택했습니다. 그중에서도 Proxmox를 고른 이유는 크게 두 가지입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;유연한 자원 분배:&lt;/b&gt; NAS 외에도 Docker, 각종 VM, RHCSA 실습 환경 등을 독립적으로 구동하기에 최적화되어 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;스냅샷(Snapshot)을 통한 복구:&lt;/b&gt; 서버 구축 초기에는 설정 실수로 OS가 꼬이는 경우가 많습니다. Proxmox의 스냅샷 기능을 이용하면 문제가 생기기 직전의 상태로 즉시 복구가 가능해, 시행착오가 많은 저에게 큰 장점이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; 2. Proxmox 설치 및 기본 설정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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 data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;ISO 다운로드:&lt;/b&gt; Proxmox 공식 홈페이지에서 최신 버전의 ISO 파일을 내려받습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1771031557252&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Downloads&quot; data-og-description=&quot;Proxmox VE 9.1 ISO Installer Version 9.1-1 File Size 1.83 GB Last Updated November 19, 2025 SHA256SUM 6d8f5afc78c0c66812d7272cde7c8b98be7eb54401ceb045400db05eb5ae6d22&quot; data-og-host=&quot;proxmox.com&quot; data-og-source-url=&quot;https://www.proxmox.com/en/downloads&quot; data-og-url=&quot;https://proxmox.com/en/downloads&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bl5ziq/dJMb81fOOBi/SxKYaf8knNoBrGn2PluHE0/img.png?width=1240&amp;amp;height=698&amp;amp;face=0_0_1240_698,https://scrap.kakaocdn.net/dn/bt96q6/dJMb88644Mr/dEfGPDPM1nx1LmOcqMD9A1/img.png?width=1240&amp;amp;height=698&amp;amp;face=0_0_1240_698&quot;&gt;&lt;a href=&quot;https://www.proxmox.com/en/downloads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.proxmox.com/en/downloads&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bl5ziq/dJMb81fOOBi/SxKYaf8knNoBrGn2PluHE0/img.png?width=1240&amp;amp;height=698&amp;amp;face=0_0_1240_698,https://scrap.kakaocdn.net/dn/bt96q6/dJMb88644Mr/dEfGPDPM1nx1LmOcqMD9A1/img.png?width=1240&amp;amp;height=698&amp;amp;face=0_0_1240_698');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Downloads&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Proxmox VE 9.1 ISO Installer Version 9.1-1 File Size 1.83 GB Last Updated November 19, 2025 SHA256SUM 6d8f5afc78c0c66812d7272cde7c8b98be7eb54401ceb045400db05eb5ae6d22&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;proxmox.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;6,1,0&quot; data-index-in-node=&quot;0&quot;&gt;부팅 USB 제작:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Rufus나 BalenaEtcher 같은 도구를 사용하여 USB 메모리에 ISO 파일을 씁니다(Flash).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biWIfB/dJMcafrZJSr/wWI62yM2DfEih7hEuUrhxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biWIfB/dJMcafrZJSr/wWI62yM2DfEih7hEuUrhxk/img.png&quot; data-alt=&quot;Rufus&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biWIfB/dJMcafrZJSr/wWI62yM2DfEih7hEuUrhxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiWIfB%2FdJMcafrZJSr%2FwWI62yM2DfEih7hEuUrhxk%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;240&quot; height=&quot;351&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Rufus&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;6,2,0&quot; data-index-in-node=&quot;0&quot;&gt;부팅 순서 변경:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;제작된 USB를 서버(i7-10700 본체)에 꽂고, BIOS 설정에서 USB를 부팅 순서 1위로 변경한 뒤 설치 화면으로 진입합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2036&quot; data-origin-height=&quot;1339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekZDrW/dJMcagdoC6M/URXN42Gfx9UFWLEvf3QijK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekZDrW/dJMcagdoC6M/URXN42Gfx9UFWLEvf3QijK/img.png&quot; data-alt=&quot;설치 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekZDrW/dJMcagdoC6M/URXN42Gfx9UFWLEvf3QijK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekZDrW%2FdJMcagdoC6M%2FURXN42Gfx9UFWLEvf3QijK%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;380&quot; height=&quot;250&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2036&quot; data-origin-height=&quot;1339&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;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;접속: 설치 완료 후 웹 브라우저에서 https://[할당된 IP]:8006으로 접속하여 관리 화면에 진입합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1889&quot; data-origin-height=&quot;891&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U1oJL/dJMcagYJZPJ/t28kmdUvOSSv5ccAACrx6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U1oJL/dJMcagYJZPJ/t28kmdUvOSSv5ccAACrx6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U1oJL/dJMcagYJZPJ/t28kmdUvOSSv5ccAACrx6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU1oJL%2FdJMcagYJZPJ%2Ft28kmdUvOSSv5ccAACrx6K%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;782&quot; height=&quot;369&quot; data-origin-width=&quot;1889&quot; data-origin-height=&quot;891&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 저장소 OS의 선택: 왜 TrueNAS SCALE인가?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;다양한 NAS OS가 있지만, 저는 &lt;b data-index-in-node=&quot;20&quot; data-path-to-node=&quot;10&quot;&gt;TrueNAS SCALE&lt;/b&gt;를 선택했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;ZFS 파일 시스템의 신뢰성:&lt;/b&gt; 데이터 무결성을 보장하는 ZFS를 가장 안정적으로 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;오픈소스와 많은 레퍼런스:&lt;/b&gt; 오픈 소스라 무료로 사용 가능하고, 많은 레퍼런스가 있어서 빠르게 구축이 가능하다고 생각했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;Debian Linux 기반:&lt;/b&gt; 익숙한 리눅스 환경이라 터미널 작업과 드라이버 호환성이 뛰어납니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1771033754199&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Download TrueNAS | TrueNAS - Open Enterprise Storage&quot; data-og-description=&quot;Built on OpenZFS and trusted by over a million users, TrueNAS puts you in full control of your data with zero vendor lock-in.Scroll for Install&quot; data-og-host=&quot;www.truenas.com&quot; data-og-source-url=&quot;https://www.truenas.com/download/&quot; data-og-url=&quot;https://www.truenas.com/download/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bpUP7i/dJMb8T9VDM5/6gb9iQjoYpbCUQi8LXgYV0/img.png?width=1350&amp;amp;height=338&amp;amp;face=873_92_1256_227,https://scrap.kakaocdn.net/dn/cUpynd/dJMb8RjX7PR/GlBRIREYZdBAn4o7waVta0/img.png?width=1350&amp;amp;height=338&amp;amp;face=873_92_1256_227&quot;&gt;&lt;a href=&quot;https://www.truenas.com/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.truenas.com/download/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bpUP7i/dJMb8T9VDM5/6gb9iQjoYpbCUQi8LXgYV0/img.png?width=1350&amp;amp;height=338&amp;amp;face=873_92_1256_227,https://scrap.kakaocdn.net/dn/cUpynd/dJMb8RjX7PR/GlBRIREYZdBAn4o7waVta0/img.png?width=1350&amp;amp;height=338&amp;amp;face=873_92_1256_227');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download TrueNAS | TrueNAS - Open Enterprise Storage&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Built on OpenZFS and trusted by over a million users, TrueNAS puts you in full control of your data with zero vendor lock-in.Scroll for Install&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.truenas.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. TrueNAS 가상 머신(VM) 생성 및 설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;이제 Proxmox 관리 화면에서 TrueNAS를 위한 공간을 만듭니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;VM 생성:&lt;/b&gt; 'Create VM'을 누르고 이름을 지정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0&quot;&gt;리소스 할당:&lt;/b&gt; &amp;nbsp;&lt;b data-index-in-node=&quot;10&quot; data-path-to-node=&quot;15,1,0&quot;&gt;CPU:&lt;/b&gt; 4코어 할당 (i7-10700의 8코어 16스레드 자원을 활용)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,1,0,0&quot;&gt;RAM:&lt;/b&gt; &lt;b data-index-in-node=&quot;5&quot; data-path-to-node=&quot;15,1,1,0,0&quot;&gt;16GB (고정 할당)&lt;/b&gt;. ZFS는 램을 캐시(ARC)로 적극 활용하기 때문에, 넉넉한 48GB 램 중 16GB를 TrueNAS에 우선 배정했습니다. 가상화 환경에서는 메모리 벌루닝(Ballooning) 기능을 끄고 고정으로 할당하는 것이 안정적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,0&quot;&gt;OS 설치:&lt;/b&gt; TrueNAS ISO를 마운트하여 부팅한 뒤 지시에 따라 설치를 진행합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLsmsf/dJMcahpPg0Z/9Jzi5ItdAUG0xK1qcJlhEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLsmsf/dJMcahpPg0Z/9Jzi5ItdAUG0xK1qcJlhEk/img.png&quot; data-alt=&quot;TrueNAS 스펙&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLsmsf/dJMcahpPg0Z/9Jzi5ItdAUG0xK1qcJlhEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLsmsf%2FdJMcahpPg0Z%2F9Jzi5ItdAUG0xK1qcJlhEk%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;395&quot; height=&quot;297&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;TrueNAS 스펙&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;14&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 핵심 설정: 하드디스크 패스스루(Passthrough)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;가상화 환경에서 ZFS의 안정성을 온전히 누리려면 Proxmox가 아닌 TrueNAS가 하드디스크를 직접 제어해야 합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;Proxmox 셸(Shell)에서 명령어를 통해 WD RED 4TB 하드 2개를 VM에 연결해 주었습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;ZFS의 안정성을 위해 물리 하드디스크(WD Red Plus 4TB x 2)를 VM이 직접 제어하도록 설정합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;Proxmox Shell에서 by-id 값을 확인한 뒤 아래 명령어로 연결했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1771036287963&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 디스크 1 연결
qm set 100 -scsi1 /dev/disk/by-id/ata-WDC_WD40EFPX-68CxxN0_WD-W52Dxxxxxx

# 디스크 2 연결
qm set 100 -scsi2 /dev/disk/by-id/ata-WDC_WD40EFPX-68CxxN0_WD-WX6xxxxxx&lt;/code&gt;&lt;/pre&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;1080&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2HQmH/dJMcaibc7cC/8tgFySDFdi2VoDDvHmgxTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2HQmH/dJMcaibc7cC/8tgFySDFdi2VoDDvHmgxTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2HQmH/dJMcaibc7cC/8tgFySDFdi2VoDDvHmgxTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2HQmH%2FdJMcaibc7cC%2F8tgFySDFdi2VoDDvHmgxTK%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;1080&quot; height=&quot;117&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;117&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;h3 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 트러블슈팅: 시리얼 번호 중복 에러 해결&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1885&quot; data-origin-height=&quot;885&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2bSgj/dJMcaajWgOv/GDeIuYWTkA4keyTw7NnJk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2bSgj/dJMcaajWgOv/GDeIuYWTkA4keyTw7NnJk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2bSgj/dJMcaajWgOv/GDeIuYWTkA4keyTw7NnJk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2bSgj%2FdJMcaajWgOv%2FGDeIuYWTkA4keyTw7NnJk0%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;481&quot; height=&quot;885&quot; data-origin-width=&quot;1885&quot; data-origin-height=&quot;885&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;디스크 연결 후 TrueNAS에서 풀(Pool)을 생성하려니 &quot;Disks have duplicate serial numbers: None&quot;이라는 에러가 발생하며 진행되지 않았습니다. 가상화 환경에서 디스크의 고유 시리얼 번호를 제대로 넘겨받지 못해 발생하는 문제입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 Proxmox의 VM 설정 파일을 수동으로 수정했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;파일 경로:&lt;/b&gt; /etc/pve/qemu-server/100.conf&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0&quot;&gt;해결 방법:&lt;/b&gt; 각 scsi 설정 끝에 ,serial=1001, ,serial=1002와 같이 고유 시리얼 번호를 강제로 주입합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;이 작업 후 TrueNAS에서 디스크를 고유하게 인식하게 되어 에러가 사라졌습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mx4C0/dJMcah4qB1G/IHKQdfJaW4yJqCfVTuo6k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mx4C0/dJMcah4qB1G/IHKQdfJaW4yJqCfVTuo6k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mx4C0/dJMcah4qB1G/IHKQdfJaW4yJqCfVTuo6k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMx4C0%2FdJMcah4qB1G%2FIHKQdfJaW4yJqCfVTuo6k0%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;547&quot; height=&quot;646&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;646&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. 스토리지 풀 및 데이터셋 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;디스크 인식 문제가 해결되었으니 실제 저장 공간을 구성합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,0,0&quot;&gt;Pool 생성:&lt;/b&gt; 'tank'라는 이름으로 풀을 만들고, 데이터 보호를 위해 &lt;b data-index-in-node=&quot;42&quot; data-path-to-node=&quot;19,0,0&quot;&gt;Mirror(RAID 1)&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-origin-width=&quot;1647&quot; data-origin-height=&quot;827&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d0iJpM/dJMcahi5bp5/9198PlLqIYsQTtg1mczAa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d0iJpM/dJMcahi5bp5/9198PlLqIYsQTtg1mczAa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d0iJpM/dJMcahi5bp5/9198PlLqIYsQTtg1mczAa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd0iJpM%2FdJMcahi5bp5%2F9198PlLqIYsQTtg1mczAa0%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;482&quot; height=&quot;242&quot; data-origin-width=&quot;1647&quot; data-origin-height=&quot;827&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,1,0&quot;&gt;상태 확인:&lt;/b&gt; 3.51 TiB의 가용 용량이 확보되었으며, 'Online' 상태로 정상 가동되는 것을 확인했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,2,0&quot;&gt;Dataset 추가:&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-origin-width=&quot;1912&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg47NY/dJMcaiIZLau/4Qt37CxuoXMXNHWtPTpwHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg47NY/dJMcaiIZLau/4Qt37CxuoXMXNHWtPTpwHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg47NY/dJMcaiIZLau/4Qt37CxuoXMXNHWtPTpwHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg47NY%2FdJMcaiIZLau%2F4Qt37CxuoXMXNHWtPTpwHK%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;521&quot; height=&quot;245&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;898&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>NAS</category>
      <category>proxmox</category>
      <category>TrueNAS</category>
      <category>zfs</category>
      <category>가상화</category>
      <category>패스스루</category>
      <category>홈랩</category>
      <category>홈서버</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/32</guid>
      <comments>https://jiione.tistory.com/32#entry32comment</comments>
      <pubDate>Sat, 14 Feb 2026 11:59:00 +0900</pubDate>
    </item>
    <item>
      <title>홈 서버/NAS 만들기 #1: 부품 드래곤볼부터 누드 테스트까지</title>
      <link>https://jiione.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;집에 개인용 스토리지(NAS)를 구축하기 위해 기성품인 시놀로지를 먼저 살펴보았습니다. 하지만 하드웨어 성능에 비해서 높은 가격대라고 생각이 들었고 고민에 빠졌습니다.&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;자작 서버/NAS&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 하드웨어 선정: 효율성 확장성과 갈림길&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 저전력과 가성비에 초점을 맞춘 &lt;b&gt;N100 ITX&lt;/b&gt; 보드를 생각했습니다. 24시간 구동해야되기 때문에 전력 소모가 걱정되었기 때문입니다. 하지만 케이스로 선택한 &lt;b&gt;Jonsbo N4&lt;/b&gt;를 실제로 보니 생각이 달라졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 케이스가 너무 예뻤고 &lt;b&gt;m-ITX&lt;/b&gt; 메인보드 뿐만 아니라 &lt;b&gt;m-ATX&lt;/b&gt; 메인보드까지 지원하는 확장성을 갖추고 있었기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 N100을 올리기엔 케이스가 너무 아깝다는 생각이 들었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n1fSH/dJMcaajTupL/MClOJMGwIrPk3KlIZdsVSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n1fSH/dJMcaajTupL/MClOJMGwIrPk3KlIZdsVSK/img.png&quot; data-alt=&quot;Jonsbo N4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n1fSH/dJMcaajTupL/MClOJMGwIrPk3KlIZdsVSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn1fSH%2FdJMcaajTupL%2FMClOJMGwIrPk3KlIZdsVSK%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;383&quot; height=&quot;511&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Jonsbo N4&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;결정적으로 제가 이 서버에서 돌릴 &lt;b data-index-in-node=&quot;19&quot; data-path-to-node=&quot;4&quot;&gt;서비스들의 부하&lt;/b&gt;를 계산해 보았습니다. 단순히 파일만 저장하는 NAS 역할만 한다면 N100으로도 충분하겠지만, 제 목표는 그 위에 &lt;b data-index-in-node=&quot;92&quot; data-path-to-node=&quot;4&quot;&gt;Proxmox&lt;/b&gt; 하이퍼바이저를 올리고 &lt;b data-index-in-node=&quot;112&quot; data-path-to-node=&quot;4&quot;&gt;TrueNAS&lt;/b&gt;와 각종 &lt;b data-index-in-node=&quot;124&quot; data-path-to-node=&quot;4&quot;&gt;Docker 컨테이너, 학습용 VM&lt;/b&gt;들을 동시에 구동하는 것이었습니다. 특히 TrueNAS의 ZFS 파일 시스템은 CPU와 RAM 자원을 상당 부분 점유하기 때문에, 다중 서비스를 안정적으로 유지하려면 더 큰 리소스가 필요했습니다.&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;i7-10700(8코어 16스레드)&lt;/b&gt;과 &lt;b data-index-in-node=&quot;37&quot; data-path-to-node=&quot;5&quot;&gt;B460M&lt;/b&gt; 보드로 선회했습니다. 8코어 16스레드라는 넉넉한 자원을 확보함으로써, TrueNAS에 충분한 코어를 할당하고도 남은 리소스로 다른 서버 워크로드를 간섭 없이 처리할 수 있는 환경을 구축하고자 했습니다.&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;&lt;b&gt; 2. 메모리 및 스토리지 구성: 자원 할당의 최적화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;메모리 또한 같은 맥락에서 결정했습니다. 최근 램 가격이 가파르게 오르고 있어 고민이 많았지만, 다행히 중고로 &lt;b data-index-in-node=&quot;62&quot; data-path-to-node=&quot;7&quot;&gt;DDR4 16GB 3개&lt;/b&gt;를 수급하여 총 &lt;b data-index-in-node=&quot;83&quot; data-path-to-node=&quot;7&quot;&gt;48GB&lt;/b&gt;의 풀을 확보했습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 넉넉하게 램을 구성한 이유는 명확합니다. &lt;b data-index-in-node=&quot;27&quot; data-path-to-node=&quot;8&quot;&gt;TrueNAS(ZFS)에 16GB를 고정 할당&lt;/b&gt;하여 스토리지의 안정성과 캐싱 성능을 확보하고, 나머지 &lt;b data-index-in-node=&quot;83&quot; data-path-to-node=&quot;8&quot;&gt;32GB를 서버 서비스용&lt;/b&gt;으로 여유 있게 분배하기 위함입니다. 램이 부족해서 서비스가 죽거나 스와핑(Swapping)이 발생하는 상황을 미연에 방지하고 싶었습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;스토리지의 경우, 데이터 안정성만큼은 타협할 수 없어 &lt;b data-index-in-node=&quot;30&quot; data-path-to-node=&quot;9&quot;&gt;WD RED PLUS NAS HDD 4TB (WD40EFPX) 2개&lt;/b&gt;를 선택했습니다. 하드디스크 가격에 놀라기도 했지만, NAS 전용 라인업이 주는 신뢰성과 백업 환경 구축을 위해 과감히 투자했습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6dExF/dJMb996l0sv/UqRdxUpxU8LEJumus4xMS1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6dExF/dJMb996l0sv/UqRdxUpxU8LEJumus4xMS1/img.jpg&quot; data-alt=&quot;당근으로 산 RAM,,&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6dExF/dJMb996l0sv/UqRdxUpxU8LEJumus4xMS1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6dExF%2FdJMb996l0sv%2FUqRdxUpxU8LEJumus4xMS1%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;228&quot; height=&quot;304&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;당근으로 산 RAM,,&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;9&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주요 부품 리스트&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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 data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;CPU:&lt;/b&gt; Intel Core i7-10700 (8C/16T)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt;Mainboard:&lt;/b&gt; B460M (m-ATX)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,2,0&quot;&gt;RAM:&lt;/b&gt; DDR4 16GB x 3 (총 48GB)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,2,1,0,0&quot;&gt;TrueNAS에 16GB를 고정 할당하고, 나머지 32GB를 서버용으로 분배할 계획입니다.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,3,0&quot;&gt;Storage:&lt;/b&gt; WD RED PLUS NAS HDD 4TB (WD40EFPX) x 2
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10,3,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,3,1,0,0&quot;&gt;데이터 안정성을 위해 NAS 전용 하드를 선택했으며, 하나는 백업용으로 구성할 예정입니다.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,4,0&quot;&gt;PSU:&lt;/b&gt; 마이크로닉스 Compact SFX 450W 80Plus Bronze
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10,4,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,4,1,0,0&quot;&gt;Jonsbo N4 케이스 규격에 맞는 SFX 파워를 선택했습니다.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,5,0&quot;&gt;Case:&lt;/b&gt; Jonsbo N4&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;&lt;b&gt; 3. 신뢰성 확보를 위한 누드 테스트&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;중고 부품 비중이 높기 때문에 케이스에 조립하기 전, 부품의 동작 상태를 확인하는 과정이 필수적이었습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;박스 위에 메인보드를 올리고 쿨러와 파워만 연결한 뒤, 전원 핀을 쇼트시켜 부팅하는 &lt;b data-index-in-node=&quot;47&quot; data-path-to-node=&quot;13&quot;&gt;누드 테스트&lt;/b&gt;를 진행했습니다. 가장 우려했던 램(48GB) 인식 상태와 메인보드의 UEFI(BIOS) 진입 여부를 먼저 확인했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1497&quot; data-origin-height=&quot;1747&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFCx3H/dJMcacvgaoG/RpWZHFWCfzViN5BqybnsW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFCx3H/dJMcacvgaoG/RpWZHFWCfzViN5BqybnsW0/img.png&quot; data-alt=&quot;드라이버로 전원 핀 쇼트를 내서 누드 테스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFCx3H/dJMcacvgaoG/RpWZHFWCfzViN5BqybnsW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFCx3H%2FdJMcacvgaoG%2FRpWZHFWCfzViN5BqybnsW0%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;281&quot; height=&quot;328&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1497&quot; data-origin-height=&quot;1747&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;&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDvCcC/dJMcadnkVqH/em84ChK4iWOXmeAEcKJO11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDvCcC/dJMcadnkVqH/em84ChK4iWOXmeAEcKJO11/img.png&quot; data-alt=&quot;UEFI 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDvCcC/dJMcadnkVqH/em84ChK4iWOXmeAEcKJO11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDvCcC%2FdJMcadnkVqH%2Fem84ChK4iWOXmeAEcKJO11%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;401&quot; height=&quot;260&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1328&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;UEFI 화면&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;&lt;b&gt;&lt;span style=&quot;color: #000000; font-size: 1.44em; letter-spacing: -1px;&quot;&gt;4. 조립 및 마감: Jonsbo N4 빌드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;본격적으로 조립을 시작했습니다. &lt;b data-index-in-node=&quot;18&quot; data-path-to-node=&quot;16&quot;&gt;Jonsbo N4&lt;/b&gt;는 디자인이 수려하고 하드 베이 구성이 좋지만, m-ATX 보드와 SFX 파워를 넣으면 내부가 꽤 빽빽해집니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;공간이 아주 넉넉한 편은 아니라 선정리에 신경을 써야 했지만, 하드 베이와 보드 사이의 간격을 잘 활용하니 큰 문제 없이 마무리할 수 있었습니다. 특히 SATA 케이블과 전원선이 엉키지 않게 배치하는 데 시간을 조금 더 썼는데, 조립을 마치고 보니 뿌듯함이 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ehcgNB/dJMcaiPHpZb/DarhxPW6PnsDUtNgjeaVYk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ehcgNB/dJMcaiPHpZb/DarhxPW6PnsDUtNgjeaVYk/img.jpg&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot; data-is-animation=&quot;false&quot; width=&quot;267&quot; style=&quot;width: 46.3155%; margin-right: 10px;&quot; data-widthpercent=&quot;46.86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ehcgNB/dJMcaiPHpZb/DarhxPW6PnsDUtNgjeaVYk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FehcgNB%2FdJMcaiPHpZb%2FDarhxPW6PnsDUtNgjeaVYk%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;1536&quot; height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9E7ny/dJMcahcd86h/AqKm2IrshcPmrfdFKWwxzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9E7ny/dJMcahcd86h/AqKm2IrshcPmrfdFKWwxzK/img.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1806&quot; data-is-animation=&quot;false&quot; width=&quot;278&quot; data-filename=&quot;blob&quot; style=&quot;width: 52.5217%;&quot; data-widthpercent=&quot;53.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9E7ny/dJMcahcd86h/AqKm2IrshcPmrfdFKWwxzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9E7ny%2FdJMcahcd86h%2FAqKm2IrshcPmrfdFKWwxzK%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;1536&quot; height=&quot;1806&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEemVz/dJMcabwjx85/QqLccCVID8nkp0QWCFM5bk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEemVz/dJMcabwjx85/QqLccCVID8nkp0QWCFM5bk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEemVz/dJMcabwjx85/QqLccCVID8nkp0QWCFM5bk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEemVz%2FdJMcabwjx85%2FQqLccCVID8nkp0QWCFM5bk%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;391&quot; height=&quot;293&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1536&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;h3 data-path-to-node=&quot;19&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 마치며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;20&quot; data-ke-size=&quot;size16&quot;&gt;하드웨어 구성을 모두 마쳤습니다. 기성품 NAS에서는 보기 힘든 묵직한 사양의 서버가 완성되었습니다. 직접 고민해서 부품을 고르고 조립한 만큼, 이 장비가 보여줄 퍼포먼스가 기대됩니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;21&quot; data-ke-size=&quot;size16&quot;&gt;이제 하드웨어라는 그릇은 준비되었습니다. 다음 편에서는 이 리소스들을 효율적으로 나누어 쓸 수 있게 해줄 &lt;b data-index-in-node=&quot;59&quot; data-path-to-node=&quot;21&quot;&gt;Proxmox 설치와 가상화 설정 과정&lt;/b&gt;을 다뤄보겠습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;21&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>i7-10700</category>
      <category>JONSBO</category>
      <category>NAS</category>
      <category>인프라</category>
      <category>자작NAS</category>
      <category>홈랩</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/31</guid>
      <comments>https://jiione.tistory.com/31#entry31comment</comments>
      <pubDate>Sat, 7 Feb 2026 21:58:59 +0900</pubDate>
    </item>
    <item>
      <title>[HomeLab] 놀고 있는 N100 미니 PC로 OPNsense 구축하기 2부 (Zenarmor, WireGuard)</title>
      <link>https://jiione.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지난 1부 포스팅에서는 N100 미니 PC에 OPNsense를 설치하고, 터미널(Console) 환경에서 기본적인 WAN/LAN 인터페이스를 할당하는 과정까지 다뤘습니다.&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;&lt;a href=&quot;https://jiione.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2026.01.04 - [Develop/Infra] - [HomeLab] 놀고 있는 N100 미니 PC로 고성능 방화벽(OPNsense) 구축하기 1부&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767784369029&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[HomeLab] 놀고 있는 N100 미니 PC로 고성능 방화벽(OPNsense) 구축하기 1부&quot; data-og-description=&quot;들어가며얼마 전, 홈랩 확장을 위해 메인 서버를 새로 조립했습니다. 더 강력한 성능이 필요해 서버를 올리고 나니, 기존에 알리익스프레스에서 구매해서 잘 사용하던 N100 미니 PC가 남게 되었습&quot; data-og-host=&quot;jiione.tistory.com&quot; data-og-source-url=&quot;https://jiione.tistory.com/29&quot; data-og-url=&quot;https://jiione.tistory.com/29&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bGd7kP/hyZQI5rRJd/tDJpHvUArZE2pE5tVkPzXk/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/kAcjI/hyZPSIBsAt/ehjoCQZYkoUHSsu72gZJF0/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/bKSlPX/hyZPK4S1lY/fEkVcuCn9LQoQm4O6TgzQK/img.png?width=1804&amp;amp;height=874&amp;amp;face=0_0_1804_874&quot;&gt;&lt;a href=&quot;https://jiione.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jiione.tistory.com/29&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bGd7kP/hyZQI5rRJd/tDJpHvUArZE2pE5tVkPzXk/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/kAcjI/hyZPSIBsAt/ehjoCQZYkoUHSsu72gZJF0/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/bKSlPX/hyZPK4S1lY/fEkVcuCn9LQoQm4O6TgzQK/img.png?width=1804&amp;amp;height=874&amp;amp;face=0_0_1804_874');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[HomeLab] 놀고 있는 N100 미니 PC로 고성능 방화벽(OPNsense) 구축하기 1부&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;들어가며얼마 전, 홈랩 확장을 위해 메인 서버를 새로 조립했습니다. 더 강력한 성능이 필요해 서버를 올리고 나니, 기존에 알리익스프레스에서 구매해서 잘 사용하던 N100 미니 PC가 남게 되었습&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jiione.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 2부에서는 &lt;b data-index-in-node=&quot;99&quot; data-path-to-node=&quot;9&quot;&gt;기본 대시보드 설정&lt;/b&gt;부터, 차세대 방화벽의 꽃인 &lt;b data-index-in-node=&quot;125&quot; data-path-to-node=&quot;9&quot;&gt;Zenarmor&lt;/b&gt;, 그리고 외부 접속을 위한 &lt;b data-index-in-node=&quot;149&quot; data-path-to-node=&quot;9&quot;&gt;WireGuard VPN&lt;/b&gt; 구축 과정을 기록합니다.&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;&lt;b&gt;OPNsense 대시보드&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2930&quot; data-origin-height=&quot;1590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgDXRB/dJMcahpAexu/SIBbzP8QR2KrEAKoxi9iFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgDXRB/dJMcahpAexu/SIBbzP8QR2KrEAKoxi9iFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgDXRB/dJMcahpAexu/SIBbzP8QR2KrEAKoxi9iFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgDXRB%2FdJMcahpAexu%2FSIBbzP8QR2KrEAKoxi9iFk%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;612&quot; height=&quot;332&quot; data-origin-width=&quot;2930&quot; data-origin-height=&quot;1590&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;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b data-path-to-node=&quot;14&quot; data-index-in-node=&quot;30&quot;&gt;'Edit' 모드&lt;/b&gt;를 통해 필요한 위젯을 입맛대로 배치할 수 있습니다. 저는 하드웨어 상태를 직관적으로 모니터링하기 위해 아래와 같이 구성했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;15,0,0&quot; data-index-in-node=&quot;0&quot;&gt;System Information:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;OPNsense 버전, 커널 정보, CPU 로드율 등을 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;15,1,0&quot; data-index-in-node=&quot;0&quot;&gt;Thermal Sensors:&lt;/b&gt;&lt;span&gt; CPU의 온도르 보여줍니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;15,2,0&quot; data-index-in-node=&quot;0&quot;&gt;Interface Statistics:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;WAN/LAN 트래픽 흐름을 파이 차트로 보여줍니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;15,3,0&quot; data-index-in-node=&quot;0&quot;&gt;Services:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;DHCP, DNS 등 핵심 서비스가 잘 돌고 있는지 한눈에 체크합니다.&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;&lt;b&gt;Zenarmor (L7 Inspection)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 공유기들은 &quot;누가 접속했다&quot; 정도만 보여주지만, 저는 &lt;b data-index-in-node=&quot;44&quot; data-path-to-node=&quot;19&quot;&gt;&quot;누가, 어떤 앱으로, 어디와 통신하는지&quot;&lt;/b&gt; 알고 싶었습니다. 그래서 &lt;b data-index-in-node=&quot;82&quot; data-path-to-node=&quot;19&quot;&gt;Zenarmor(구 Sensei)&lt;/b&gt; 플러그인을 설치했습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;20&quot; data-ke-size=&quot;size16&quot;&gt;Zenarmor는 &lt;b data-index-in-node=&quot;10&quot; data-path-to-node=&quot;20&quot;&gt;NGFW(차세대 방화벽)&lt;/b&gt; 기능을 제공하여, 패킷의 내용(L7 Layer)까지 들여다보고 애플리케이션 단위로 제어할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;20&quot; 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;2424&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8gH6D/dJMcafkZtKX/pPGCXJ6DoT7sP3cbnFqP6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8gH6D/dJMcafkZtKX/pPGCXJ6DoT7sP3cbnFqP6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8gH6D/dJMcafkZtKX/pPGCXJ6DoT7sP3cbnFqP6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8gH6D%2FdJMcafkZtKX%2FpPGCXJ6DoT7sP3cbnFqP6K%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;2424&quot; height=&quot;624&quot; data-origin-width=&quot;2424&quot; data-origin-height=&quot;624&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;설치 및 DB 선택&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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 data-index-in-node=&quot;0&quot; data-path-to-node=&quot;21,0,0&quot;&gt;설치 경로:&lt;/b&gt; System &amp;gt; Firmware &amp;gt; Plugins &amp;gt; os-sunnyvalley &amp;amp; os-sensei&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;21,1,0&quot;&gt;DB 선택:&lt;/b&gt; 설정 중 데이터베이스를 선택해야 하는데, 저는 &lt;b data-index-in-node=&quot;33&quot; data-path-to-node=&quot;21,1,0&quot;&gt;SQLite&lt;/b&gt;를 선택했습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;21,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;21,1,1,0,0&quot;&gt;선택 이유:&lt;/b&gt; 대규모 트래픽이 발생하는 기업 환경이라면 Elasticsearch나 MongoDB가 필요하겠지만, 홈랩 수준의 트래픽에서는 &lt;b data-index-in-node=&quot;76&quot; data-path-to-node=&quot;21,1,1,0,0&quot;&gt;SQLite&lt;/b&gt;로도 충분하다고 생각했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2908&quot; data-origin-height=&quot;1460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCj3IA/dJMcabv7Ozx/kEekmEEyCr0HAjlGa3S8x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCj3IA/dJMcabv7Ozx/kEekmEEyCr0HAjlGa3S8x1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCj3IA/dJMcabv7Ozx/kEekmEEyCr0HAjlGa3S8x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCj3IA%2FdJMcabv7Ozx%2FkEekmEEyCr0HAjlGa3S8x1%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;2908&quot; height=&quot;1460&quot; data-origin-width=&quot;2908&quot; data-origin-height=&quot;1460&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2936&quot; data-origin-height=&quot;1576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5T9rM/dJMcacaJoXI/5KhpR3K6Jnf6rRs4WB1g91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5T9rM/dJMcacaJoXI/5KhpR3K6Jnf6rRs4WB1g91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5T9rM/dJMcacaJoXI/5KhpR3K6Jnf6rRs4WB1g91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5T9rM%2FdJMcacaJoXI%2F5KhpR3K6Jnf6rRs4WB1g91%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;2936&quot; height=&quot;1576&quot; data-origin-width=&quot;2936&quot; data-origin-height=&quot;1576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zenarmor 대시보드를 보면 내부망의 어떤 애플리케이션을 이용하는지, 보안 위협이 차단(Blocked)되었는지 그래프로 시각화 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;24&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;24&quot;&gt;WireGuard: 어디서든 내 홈랩에 접속하기 (VPN)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;외부에서 내 홈랩(NAS, Proxmox)에 접근하기 위해 WireGuard를 구축했습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;65&quot; data-path-to-node=&quot;7&quot;&gt;OPNsense 24.1 버전 이상&lt;/b&gt;을 사용한다면 WireGuard가 이미 커널에 내장되어 있어 &lt;b data-index-in-node=&quot;118&quot; data-path-to-node=&quot;7&quot;&gt;별도의 플러그인 설치가 필요 없습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;(이전 버전 사용 시 os-wireguard 설치 필요)&lt;/p&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; STEP 1. Local (Instance) 설정: 서버 만들기&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;내 OPNsense를 VPN 서버로 만드는 과정입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;VPN&lt;/b&gt; &amp;gt; &lt;b&gt;WireGuard&lt;/b&gt; &amp;gt; &lt;b&gt;Instances&amp;nbsp;&lt;/b&gt;에서 인스턴스를 아래와 같이 생성했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;601&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckT3qZ/dJMcaaRxdcd/8ia0ZKMyC2nmlD6JTsiQHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckT3qZ/dJMcaaRxdcd/8ia0ZKMyC2nmlD6JTsiQHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckT3qZ/dJMcaaRxdcd/8ia0ZKMyC2nmlD6JTsiQHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckT3qZ%2FdJMcaaRxdcd%2F8ia0ZKMyC2nmlD6JTsiQHK%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;627&quot; height=&quot;417&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;601&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;STEP 2. Peer 등록: OPNsense에 기기 등록&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핸드폰이나 노트북에 WireGuard 어플리케이션을 다운로드 후, OPNsense와 기기 사이에서 키를 교환하며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Peer 작업을 해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eAJxa1/dJMcagYuVAP/CkxmbJMAqJDl7ZQktre6H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eAJxa1/dJMcagYuVAP/CkxmbJMAqJDl7ZQktre6H0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eAJxa1/dJMcagYuVAP/CkxmbJMAqJDl7ZQktre6H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeAJxa1%2FdJMcagYuVAP%2FCkxmbJMAqJDl7ZQktre6H0%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;170&quot; height=&quot;368&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;960&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1609&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbzBJe/dJMcadm8aSk/DCnFK0Ij1MZ9J92Jd7tiZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbzBJe/dJMcadm8aSk/DCnFK0Ij1MZ9J92Jd7tiZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbzBJe/dJMcadm8aSk/DCnFK0Ij1MZ9J92Jd7tiZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbzBJe%2FdJMcadm8aSk%2FDCnFK0Ij1MZ9J92Jd7tiZ0%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;790&quot; height=&quot;247&quot; data-origin-width=&quot;1609&quot; data-origin-height=&quot;504&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;STEP 3. 방화벽 규칙 (Firewall Rules) 오픈&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-path-to-node=&quot;28&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;28&quot;&gt;1) WAN 인터페이스 (외부 &amp;rarr; 방화벽)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;29&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;경로: Firewall &amp;gt; Rules &amp;gt; WAN&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1576&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FtGsI/dJMcaaqszRK/AwaFY9gDbyJMSPYaGu9AT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FtGsI/dJMcaaqszRK/AwaFY9gDbyJMSPYaGu9AT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FtGsI/dJMcaaqszRK/AwaFY9gDbyJMSPYaGu9AT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFtGsI%2FdJMcaaqszRK%2FAwaFY9gDbyJMSPYaGu9AT0%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;1576&quot; height=&quot;785&quot; data-origin-width=&quot;1576&quot; data-origin-height=&quot;785&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;30&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;30&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;30&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;30&quot;&gt;2) WireGuard 인터페이스 (VPN 터널 &amp;rarr; 내부망)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;31&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;경로: Firewall &amp;gt; Rules &amp;gt; WireGuard&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1589&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b04bAb/dJMcacaJ8mD/0g8VIk7LhveRq91j803mkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b04bAb/dJMcacaJ8mD/0g8VIk7LhveRq91j803mkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b04bAb/dJMcacaJ8mD/0g8VIk7LhveRq91j803mkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb04bAb%2FdJMcacaJ8mD%2F0g8VIk7LhveRq91j803mkK%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;1589&quot; height=&quot;814&quot; data-origin-width=&quot;1589&quot; data-origin-height=&quot;814&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;STEP 4. 결과&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 외부에 있어도 노트북이나 핸드폰으로도 접속이 가능해집니다!!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Js7X4/dJMcagc9b6C/YvbteYrdf6bKOyyCiCvX40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Js7X4/dJMcagc9b6C/YvbteYrdf6bKOyyCiCvX40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Js7X4/dJMcagc9b6C/YvbteYrdf6bKOyyCiCvX40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJs7X4%2FdJMcagc9b6C%2FYvbteYrdf6bKOyyCiCvX40%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;306&quot; height=&quot;662&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;960&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>homelab</category>
      <category>N100</category>
      <category>opnsense</category>
      <category>VPN</category>
      <category>WireGuard</category>
      <category>Zenarmor</category>
      <category>모니터링</category>
      <category>방화벽</category>
      <category>홈랩</category>
      <category>홈서버</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/30</guid>
      <comments>https://jiione.tistory.com/30#entry30comment</comments>
      <pubDate>Fri, 9 Jan 2026 22:30:43 +0900</pubDate>
    </item>
    <item>
      <title>[HomeLab] 놀고 있는 N100 미니 PC로 고성능 방화벽(OPNsense) 구축하기 1부</title>
      <link>https://jiione.tistory.com/29</link>
      <description>&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;얼마 전, 홈랩 확장을 위해 메인 서버를 새로 조립했습니다. 더 강력한 성능이 필요해 서버를 올리고 나니, 기존에 알리익스프레스에서 구매해서 잘 사용하던 &lt;b data-index-in-node=&quot;89&quot; data-path-to-node=&quot;8&quot;&gt;N100 미니 PC&lt;/b&gt;가 남게 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5bSG7/dJMcadm5Xsl/hvyTWYbkQeTKeUPjwupuW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5bSG7/dJMcadm5Xsl/hvyTWYbkQeTKeUPjwupuW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5bSG7/dJMcadm5Xsl/hvyTWYbkQeTKeUPjwupuW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5bSG7%2FdJMcadm5Xsl%2FhvyTWYbkQeTKeUPjwupuW1%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;537&quot; height=&quot;403&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;721&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;이전 N100 홈랩 포스팅&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767447192812&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[HomeLab] Proxmox 내부망 구축기 (DHCP/NAT)&quot; data-og-description=&quot;목차들어가며: 왜 가상 라우터가 필요한가?Step 1: Proxmox 격리 브리지(vmbr1) 생성Step 2: 라우터 VM 네트워크 설정 (Netplan)Step 3: 인터넷 연결을 위한 NAT 설정 (IPtables)Step 4: 자동 IP 할당을 위한 DHCP 서버 &quot; data-og-host=&quot;jiione.tistory.com&quot; data-og-source-url=&quot;https://jiione.tistory.com/27&quot; data-og-url=&quot;https://jiione.tistory.com/27&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cdoUgf/hyZQ4Vn9pL/JH16OVaqQIEDqMomEzyNpk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/w4XTu/hyZQY1XJu8/qYzL8GwuUBBNykVyom6Hrk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bMhXyj/hyZQ3PI9o8/zLlpSNKqfQiZf7xPaPAdc1/img.png?width=1281&amp;amp;height=798&amp;amp;face=0_0_1281_798&quot;&gt;&lt;a href=&quot;https://jiione.tistory.com/27&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jiione.tistory.com/27&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cdoUgf/hyZQ4Vn9pL/JH16OVaqQIEDqMomEzyNpk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/w4XTu/hyZQY1XJu8/qYzL8GwuUBBNykVyom6Hrk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bMhXyj/hyZQ3PI9o8/zLlpSNKqfQiZf7xPaPAdc1/img.png?width=1281&amp;amp;height=798&amp;amp;face=0_0_1281_798');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[HomeLab] Proxmox 내부망 구축기 (DHCP/NAT)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;목차들어가며: 왜 가상 라우터가 필요한가?Step 1: Proxmox 격리 브리지(vmbr1) 생성Step 2: 라우터 VM 네트워크 설정 (Netplan)Step 3: 인터넷 연결을 위한 NAT 설정 (IPtables)Step 4: 자동 IP 할당을 위한 DHCP 서버&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jiione.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 녀석을 어떻게 해야하나 고민하던 찰나, 우리 집 네트워크도 '통신사 공유기'의 제약에서 벗어나 VLAN도 나누고 보안 정책도 직접 컨트롤해보고 싶다는 욕심이 생겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 &lt;b&gt;'남는 N100을 활용한 OPNsense 방화벽 구축 프로젝트'&lt;/b&gt;가 시작되었습니다.&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;b&gt;목차&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Why N100? 왜 방화벽 머신으로 적합한가&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;14&quot; data-index-in-node=&quot;0&quot;&gt;OPNsense 설치 준비&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,0&quot;&gt;BIOS 설정:&lt;/b&gt; 설치 준비와 정전 대비를 한 번에&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,4,0&quot;&gt;설치 진행&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;38&quot; data-index-in-node=&quot;0&quot;&gt;네트워크 초기 설정 (Console)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,6,0&quot;&gt;트러블 슈팅:&lt;/b&gt; N100의 ACPI 이슈 해결&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,7,0&quot;&gt;1부를 마치며:&lt;/b&gt; 다음 예고 (Zenarmor &amp;amp; WireGuard)&lt;/li&gt;
&lt;/ol&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Why N100? 왜 방화벽 머신으로 적합한가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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 data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;저전력 &amp;amp; 팬리스 (Fanless):&lt;/b&gt; 방화벽은 24시간 365일 켜져 있어야 합니다. N100은 IDLE 전력 소모가 매우 낮고 팬리스라 소음이 없어 책상 구석에 두기에 좋았습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;듀얼 랜포트의 존재 :&lt;/b&gt; 제가 보유한 &lt;b data-index-in-node=&quot;17&quot; data-path-to-node=&quot;6,1,0&quot;&gt;Firebat T8&lt;/b&gt; 모델은 작은 크기임에도 불구하고 &lt;b data-index-in-node=&quot;46&quot; data-path-to-node=&quot;6,1,0&quot;&gt;RJ45 랜포트가 2개&lt;/b&gt; 탑재되어 있습니다. 덕분에 별도의 USB 랜카드를 달지 않고도, &lt;b data-index-in-node=&quot;100&quot; data-path-to-node=&quot;6,1,0&quot;&gt;WAN(외부망)과 LAN(내부망)을 물리적으로 깔끔하게 분리&lt;/b&gt;할 수 있었습니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,2,0&quot;&gt;AES-NI 명령어 지원:&lt;/b&gt; 추후 VPN(WireGuard 등)을 돌릴 때 암호화/복호화 속도에 큰 영향을 줍니다. 기가비트급 VPN 속도를 내려면 필수적인 기능입니다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,3,0&quot;&gt;차고 넘치는 성능:&lt;/b&gt; 단순 라우팅만 한다면 오버스펙일 수 있지만, 추후 &lt;b&gt;Zenarmor(차세대 방화벽 플러그인)&lt;/b&gt;나 &lt;b data-index-in-node=&quot;67&quot; data-path-to-node=&quot;6,3,0&quot;&gt;Suricata(침입 탐지)&lt;/b&gt; 같은 무거운 패킷 분석 툴을 돌리기에 아주 넉넉한 자원을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;14&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14&quot;&gt;2. OPNsense 설치 준비&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;OS는 pfsense와 OPNsense 중 고민하다 UI가 좀 더 현대적이고 업데이트 주기가 빠른 &lt;b data-index-in-node=&quot;55&quot; data-path-to-node=&quot;15&quot;&gt;OPNsense&lt;/b&gt;를 선택했습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;DVD(ISO) vs VGA(IMG): 무엇을 받아야 할까?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;보통 OS를 설치한다고 하면 .iso 파일을 생각하기 쉽습니다. 하지만 OPNsense 다운로드 페이지에는 dvd, vga, serial 등 낯선 아키텍처 타입들이 보입니다. 여기서 내 환경(N100 미니 PC)에 맞는 이미지를 선택하는 것이 중요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;8&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,0,0&quot;&gt;dvd (ISO 파일):&lt;/b&gt; 주로 &lt;b&gt;가상머신(VMware, Proxmox, ESXi)&lt;/b&gt;에 설치할 때 사용합니다. 가상 CD-ROM에 마운트 하는 방식이죠.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,1,0&quot;&gt;vga (IMG 파일):&lt;/b&gt; 모니터(VGA/HDMI)와 키보드를 연결해 설치하는 &lt;b&gt;물리 장비(Bare Metal)&lt;/b&gt;용입니다. USB에 구워서 부팅하기에 최적화된 포맷입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1767448296427&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Download - OPNsense&quot; data-og-description=&quot;Depending on your hardware and use case different installation files are provided to Install OPNsense&amp;reg;. Select the right version for your system and download the best open source firewall.&quot; data-og-host=&quot;opnsense.org&quot; data-og-source-url=&quot;https://opnsense.org/download/&quot; data-og-url=&quot;https://opnsense.org/download/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://opnsense.org/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://opnsense.org/download/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download - OPNsense&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Depending on your hardware and use case different installation files are provided to Install OPNsense&amp;reg;. Select the right version for your system and download the best open source firewall.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;opnsense.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;저는 N100 미니 PC라는 실물 하드웨어에 설치하므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b data-path-to-node=&quot;20&quot; data-index-in-node=&quot;31&quot;&gt;vga 타입&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;을 선택했습니다. 다운로드한 파일의 압축을 풀면 .img 파일이 나오는데, 이를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b data-path-to-node=&quot;20&quot; data-index-in-node=&quot;82&quot;&gt;Rufus&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b data-path-to-node=&quot;20&quot; data-index-in-node=&quot;89&quot;&gt;BalenaEtcher&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;같은 툴을 이용해 USB에 구워줍니다.&lt;/span&gt;&lt;/p&gt;
&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;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UWSWm/dJMcadUV2tg/T1aEC7FkBTXIOuNoH0qfu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UWSWm/dJMcadUV2tg/T1aEC7FkBTXIOuNoH0qfu1/img.png&quot; data-alt=&quot;Rufus&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UWSWm/dJMcadUV2tg/T1aEC7FkBTXIOuNoH0qfu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUWSWm%2FdJMcadUV2tg%2FT1aEC7FkBTXIOuNoH0qfu1%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;285&quot; height=&quot;571&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Rufus&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;3&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3&quot;&gt;3. BIOS 설정: 설치 준비와 정전 대비를 한 번에&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;설치 USB가 준비되었다면 이제 미니 PC에 꽂고 부팅 순서를 잡아야 합니다. 이때 &lt;b data-index-in-node=&quot;47&quot; data-path-to-node=&quot;4&quot;&gt;부팅 순서만 바꾸지 말고, 꼭 같이 설정해야 할 중요한 옵션&lt;/b&gt;이 하나 더 있습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;5&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5&quot;&gt;BIOS 진입 및 부팅 순서 변경&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;USB를 꽂고 부팅 시 Del 키(또는 F7)를 연타하여 BIOS 설정 화면으로 진입합니다. 가장 먼저 Boot 탭으로 이동하여&lt;b&gt; USB 메모리가 최우선 순위&lt;/b&gt;가 되도록 설정합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7&quot;&gt;정전 대비 설정 (State After G3)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;BIOS에 들어온 김에 &lt;b data-index-in-node=&quot;13&quot; data-path-to-node=&quot;8&quot;&gt;전력 관리(Power Management)&lt;/b&gt; 설정도 함께 만져줍니다. 방화벽은 정전 후 전기가 다시 들어왔을 때, 사람이 직접 버튼을 누르지 않아도 &lt;b data-index-in-node=&quot;95&quot; data-path-to-node=&quot;8&quot;&gt;자동으로 켜져야 하기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxLwfD/dJMcaaxcbkx/TDrmWGzQXQ53WWIQOlsqek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxLwfD/dJMcaaxcbkx/TDrmWGzQXQ53WWIQOlsqek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxLwfD/dJMcaaxcbkx/TDrmWGzQXQ53WWIQOlsqek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxLwfD%2FdJMcaaxcbkx%2FTDrmWGzQXQ53WWIQOlsqek%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;472&quot; height=&quot;354&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;721&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;G3(정전)&lt;/b&gt; 상황이 왔을 때, 넘어갈 상태를 결정해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 기본값은 &lt;b&gt;S5 State(꺼짐 유지)&lt;/b&gt;로 되어 있는데, 이걸 &lt;b&gt;S0 State(무조건 켜짐)&lt;/b&gt;로 바꿔줍니다. 이 설정을 해두면 집에 정전이 났다가 복구되었을 때, 퇴근 후 집에 와서 전원 버튼을 누르지 않아도 인터넷이 자동으로 복구됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;31&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;31&quot;&gt;4. 설치 진행&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;32&quot; data-ke-size=&quot;size16&quot;&gt;USB로 부팅에 성공하면 까만 화면에 텍스트가 흐르고 로그인 창이 뜹니다. &lt;b&gt;여기서 주의할 점! 이 화면은 설치된 화면이 아니라, USB로 구동된 'Live 환경'입니다.&lt;/b&gt; 여기서 설정을 백날 해봤자 재부팅하면 다 날아갑니다.&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;31&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;31&quot;&gt;4-1. Installer 로그인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;32&quot; data-ke-size=&quot;size16&quot;&gt;설치 마법사를 실행하기 위해 아래 계정으로 로그인합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;33&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;33,0,0&quot;&gt;ID:&lt;/b&gt; installer&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;33,1,0&quot;&gt;PW:&lt;/b&gt; opnsense&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;34&quot;&gt;(참고: root로 로그인하면 설치 과정 없이 바로 쉘로 진입하게 되니 주의하세요!)&lt;/i&gt;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;38&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-path-to-node=&quot;38&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;38&quot;&gt;5. 네트워크 초기 설정 (Console)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;39&quot; data-ke-size=&quot;size16&quot;&gt;설치가 완료되고 재부팅하면 콘솔 메뉴가 나타납니다. 여기서 네트워크 연결을 위한 핵심 설정 두 가지를 진행해야 합니다.&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;40&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;40&quot;&gt;5-1. 인터페이스 할당 (1) Assign Interfaces&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;41&quot; data-ke-size=&quot;size16&quot;&gt;먼저 메뉴 1번을 통해 물리 포트와 논리 인터페이스를 매핑합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;42&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;42,0,0&quot;&gt;WAN (re0):&lt;/b&gt; 통신사 모뎀과 연결 (DHCP 설정)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;42,1,0&quot;&gt;LAN (re1):&lt;/b&gt; 내 PC 또는 허브와 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CFd0U/dJMcagRHP2w/zmEQtx9AwXhrfh3fzVKvkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CFd0U/dJMcagRHP2w/zmEQtx9AwXhrfh3fzVKvkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CFd0U/dJMcagRHP2w/zmEQtx9AwXhrfh3fzVKvkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCFd0U%2FdJMcagRHP2w%2FzmEQtx9AwXhrfh3fzVKvkk%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;622&quot; height=&quot;536&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;38&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;43&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;43&quot;&gt;5-2. IP 주소 및 DHCP 설정 (2) Set interface IP address&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;44&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스 할당이 끝났으면, 내부망 PC가 IP를 받아올 수 있도록 LAN 설정을 해야 합니다. 메뉴 2번으로 진입합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;45&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;45,0,0&quot;&gt;Configure IPv4 address LAN interface via DHCP?&lt;/b&gt; -&amp;gt; &lt;b data-index-in-node=&quot;50&quot; data-path-to-node=&quot;45,0,0&quot;&gt;No&lt;/b&gt; (고정 IP 사용)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;45,1,0&quot;&gt;IPv4 Address:&lt;/b&gt; 192.168.1.1 (게이트웨이 주소)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;45,2,0&quot;&gt;Enable DHCP server on LAN?&lt;/b&gt; -&amp;gt; &lt;b data-index-in-node=&quot;30&quot; data-path-to-node=&quot;45,2,0&quot;&gt;Yes&lt;/b&gt; (중요!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;46&quot; data-ke-size=&quot;size16&quot;&gt;이 과정에서 &lt;b data-index-in-node=&quot;7&quot; data-path-to-node=&quot;46&quot;&gt;DHCP 서버를 켜주어야(Yes)&lt;/b&gt;, LAN 포트에 연결된 PC가 자동으로 IP(예: 192.168.1.100)를 할당받아 관리자 페이지에 접속할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIDWDR/dJMcafec2hw/dVFRQM4Ee01KP0HyS3Q21K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIDWDR/dJMcafec2hw/dVFRQM4Ee01KP0HyS3Q21K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIDWDR/dJMcafec2hw/dVFRQM4Ee01KP0HyS3Q21K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIDWDR%2FdJMcafec2hw%2FdVFRQM4Ee01KP0HyS3Q21K%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;639&quot; height=&quot;480&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;874&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8hIjX/dJMcahb0FWV/o8RKYrpZTGwDWKgdiYgpdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8hIjX/dJMcahb0FWV/o8RKYrpZTGwDWKgdiYgpdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8hIjX/dJMcahb0FWV/o8RKYrpZTGwDWKgdiYgpdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8hIjX%2FdJMcahb0FWV%2Fo8RKYrpZTGwDWKgdiYgpdK%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;1804&quot; height=&quot;874&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;874&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;h3 data-path-to-node=&quot;48&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;48&quot;&gt;6. 트러블 슈팅: N100의 ACPI 이슈 해결&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;49&quot; data-ke-size=&quot;size16&quot;&gt;기분 좋게 설치를 마쳤는데, 종료(Shutdown)나 재부팅이 매끄럽지 않고 로그에 &lt;b data-index-in-node=&quot;47&quot; data-path-to-node=&quot;49&quot;&gt;ACPI 에러&lt;/b&gt;가 발생하는 현상이 있었습니다. N100 칩셋이 비교적 최신이다 보니 FreeBSD 커널과의 전원 관리 호환성 문제가 좀 있는 편입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;50&quot; data-ke-size=&quot;size16&quot;&gt;이 문제는 Web GUI에 접속 후 System &amp;gt; Settings &amp;gt; Tunables에서 값을 조정하여 해결했습니다. 설정을 마치니 비로소 안정적인 '서버'다운 모습을 갖추게 되었습니다.&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;926&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lm25h/dJMcaivbkYj/V6AVu2ql1krxtRyCd56H7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lm25h/dJMcaivbkYj/V6AVu2ql1krxtRyCd56H7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lm25h/dJMcaivbkYj/V6AVu2ql1krxtRyCd56H7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flm25h%2FdJMcaivbkYj%2FV6AVu2ql1krxtRyCd56H7k%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;926&quot; height=&quot;500&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1566&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lyojT/dJMcafL2iuV/iOwg1FHNdJGIcreFgLRTW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lyojT/dJMcafL2iuV/iOwg1FHNdJGIcreFgLRTW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lyojT/dJMcafL2iuV/iOwg1FHNdJGIcreFgLRTW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlyojT%2FdJMcafL2iuV%2FiOwg1FHNdJGIcreFgLRTW0%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;1566&quot; height=&quot;194&quot; data-origin-width=&quot;1566&quot; data-origin-height=&quot;194&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;52&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;52&quot;&gt;1부를 마치며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-path-to-node=&quot;53&quot; data-ke-size=&quot;size16&quot;&gt;이제 하드웨어 세팅과 기본적인 라우팅 준비는 끝났습니다. 하지만 여기까지는 그저 '비싼 유선 공유기'를 만든 것에 불과합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;54&quot; data-ke-size=&quot;size16&quot;&gt;진짜 재미는 이제부터입니다. 다음 &lt;b data-index-in-node=&quot;19&quot; data-path-to-node=&quot;54&quot;&gt;2부&lt;/b&gt;에서는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;55&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;55,0,0&quot;&gt;Zenarmor&lt;/b&gt;를 활용해 내 네트워크 트래픽을 화려한 대시보드로 시각화하고,&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;55,1,0&quot;&gt;WireGuard&lt;/b&gt;를 설치해 카페나 회사에서도 안전하게 우리 집 내부망에 접속하는 과정을 다뤄보겠습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-path-to-node=&quot;56&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;56&quot;&gt;(다음 편에 계속...)&lt;/b&gt;&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>firebat</category>
      <category>homelab</category>
      <category>N100</category>
      <category>opnsense</category>
      <category>T8</category>
      <category>미니컴퓨터</category>
      <category>방화벽</category>
      <category>홈랩</category>
      <category>홈서버</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/29</guid>
      <comments>https://jiione.tistory.com/29#entry29comment</comments>
      <pubDate>Sun, 4 Jan 2026 14:52:54 +0900</pubDate>
    </item>
    <item>
      <title>[HomeLab] Docker와 BIND9으로 Private DNS 구축하기</title>
      <link>https://jiione.tistory.com/28</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;877&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0xclt/dJMcaaRmQiR/pMv6EKb1h45yAzxr841Ko0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0xclt/dJMcaaRmQiR/pMv6EKb1h45yAzxr841Ko0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0xclt/dJMcaaRmQiR/pMv6EKb1h45yAzxr841Ko0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0xclt%2FdJMcaaRmQiR%2FpMv6EKb1h45yAzxr841Ko0%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;2048&quot; height=&quot;877&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;877&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;지난 포스팅 요약:&lt;/b&gt; Proxmox 내부에 격리된 사설 네트워크(&lt;code&gt;192.168.10.x&lt;/code&gt;)를 만들고, 라우터 VM을 통해 인터넷 연결(NAT)과 IP 자동 할당(DHCP)까지 성공했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 여전히 문제가 하나 남았습니다. &lt;b&gt;&quot;서버 IP(&lt;code&gt;192.168.10.xx&lt;/code&gt;)를 일일이 외우기가 너무 귀찮다!&quot;&lt;/b&gt;&lt;br /&gt;이번 포스팅에서는 &lt;b&gt;Docker&lt;/b&gt;와 &lt;b&gt;BIND9&lt;/b&gt;을 활용해, 내부망에서만 동작하는 &lt;b&gt;Private DNS Server&lt;/b&gt;를 구축하고, &lt;code&gt;www.jiwon1.com&lt;/code&gt; 같은 도메인으로 서버에 접속하는 과정을 정리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, 구축 과정에서 겪었던 &lt;b&gt;포트 53번 충돌 문제&lt;/b&gt;와 &lt;b&gt;Docker 환경에서의 Self-Lookup 실패(NAT Loopback) 이슈&lt;/b&gt;에 대한 기술적 고찰을 중점적으로 다룹니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: DNS 서버를 위한 고정 IP 할당&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS 서버 주소가 바뀌면 네트워크 전체가 마비되겠죠? 가장 먼저 새로운 Ubuntu VM(또는 기존 서버)의 IP를 고정해 줍니다. 저는 &lt;code&gt;192.168.10.20&lt;/code&gt;으로 정했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;파일 경로:&lt;/b&gt; &lt;code&gt;/etc/netplan/50-cloud-init.yaml&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;network:
  ethernets:
    ens18:
      dhcp4: false
      addresses:
        - 192.168.10.20/24  # DNS 서버의 고정 IP
      routes:
        - to: default
          via: 192.168.10.1 # 지난번 만든 Router VM 주소
      nameservers:
        addresses:
          - 8.8.8.8        
  version: 2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/soSIq/dJMb99LGtzG/ZMVfbD9ufovbNIeBtQwK8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/soSIq/dJMb99LGtzG/ZMVfbD9ufovbNIeBtQwK8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/soSIq/dJMb99LGtzG/ZMVfbD9ufovbNIeBtQwK8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsoSIq%2FdJMb99LGtzG%2FZMVfbD9ufovbNIeBtQwK8K%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;815&quot; height=&quot;310&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: BIND9 설정 파일 작성&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 컨테이너로 띄울 것이므로, 호스트에 설정 파일들을 미리 작성해 둡니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. &lt;code&gt;named.conf.options&lt;/code&gt; (기본 옵션)&lt;/b&gt;&lt;br /&gt;내부 도메인은 내가 처리하고, 모르는 외부 도메인(예: google.com)은 구글(&lt;code&gt;8.8.8.8&lt;/code&gt;)에게 토스(Forwarding)합니다.&lt;/p&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;options {
    directory &quot;/var/cache/bind&quot;;
    recursion yes;
    allow-query { any; };
    listen-on { any; };
    forwarders { 8.8.8.8; };
    dnssec-validation no;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;309&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjBrJq/dJMcac2FDBi/t4RI06fAMTbsAtxVZIQcRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjBrJq/dJMcac2FDBi/t4RI06fAMTbsAtxVZIQcRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjBrJq/dJMcac2FDBi/t4RI06fAMTbsAtxVZIQcRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjBrJq%2FdJMcac2FDBi%2Ft4RI06fAMTbsAtxVZIQcRk%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;309&quot; height=&quot;140&quot; data-origin-width=&quot;309&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. &lt;code&gt;named.conf.local&lt;/code&gt; (존 선언)&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;zone &quot;jiwon1.com&quot; {
    type master;
    file &quot;/etc/bind/zones/db.jiwon1.com&quot;;
};

zone &quot;jiwon2.com&quot; {
    type master;
    file &quot;/etc/bind/zones/db.jiwon2.com&quot;;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;359&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tWxXG/dJMcajnbj2x/JYRL3GKGpHmeAa2h1bkouK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tWxXG/dJMcajnbj2x/JYRL3GKGpHmeAa2h1bkouK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tWxXG/dJMcajnbj2x/JYRL3GKGpHmeAa2h1bkouK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtWxXG%2FdJMcajnbj2x%2FJYRL3GKGpHmeAa2h1bkouK%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;359&quot; height=&quot;170&quot; data-origin-width=&quot;359&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. &lt;code&gt;db.jiwon1.com&lt;/code&gt; (정방향 존 파일)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 도메인과 IP를 매칭하는 핵심 파일입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;$TTL    86400
@       IN      SOA     ns.jiwon1.com. admin.jiwon1.com. (
                              2025022701   ; Serial (수정 시 +1 필수)
                              3600         ; Refresh
                              1800         ; Retry
                              604800       ; Expire
                              86400 )      ; Negative Cache TTL
;
@       IN      NS      ns.jiwon1.com.
@       IN      A       192.168.10.20
ns      IN      A       192.168.10.20
www     IN      A       192.168.10.20  ; [www.jiwon1.com](https://www.jiwon1.com) -&amp;gt; 10.20 연결&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdI4Se/dJMcafE8DLs/0YwreNjjPr8uIaPIFe0yo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdI4Se/dJMcafE8DLs/0YwreNjjPr8uIaPIFe0yo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdI4Se/dJMcafE8DLs/0YwreNjjPr8uIaPIFe0yo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdI4Se%2FdJMcafE8DLs%2F0YwreNjjPr8uIaPIFe0yo0%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;455&quot; height=&quot;236&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 3: Docker 환경 구성 및 실행&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 53번 포트 충돌 해결 (systemd-resolved)  &lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ubuntu는 기본적으로 &lt;code&gt;systemd-resolved&lt;/code&gt; 서비스가 53번 포트를 점유하고 있습니다. 이 상태로 도커를 실행하면 &lt;b&gt;Port Conflict&lt;/b&gt;가 발생합니다. 과감하게 비활성화합니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 1. 서비스 중지 및 비활성화
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved

# 2. 꼬여있는 resolv.conf 파일 재설정 (Host는 구글 DNS 사용)
sudo rm /etc/resolv.conf
echo &quot;nameserver 8.8.8.8&quot; | sudo tee /etc/resolv.conf&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Dockerfile 작성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ubuntu 베이스 이미지에 BIND9을 설치하고 설정 파일을 복사합니다.&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;FROM ubuntu:latest

RUN apt-get update &amp;amp;&amp;amp; apt-get install -y bind9 dnsutils &amp;amp;&amp;amp; apt-get clean
RUN mkdir -p /etc/bind/zones

# 작성해둔 설정 파일 복사
COPY named.conf.options /etc/bind/named.conf.options
COPY named.conf.local   /etc/bind/named.conf.local
COPY db.jiwon1.com      /etc/bind/zones/db.jiwon1.com
COPY db.jiwon2.com      /etc/bind/zones/db.jiwon2.com

EXPOSE 53/tcp
EXPOSE 53/udp

CMD [&quot;/usr/sbin/named&quot;, &quot;-c&quot;, &quot;/etc/bind/named.conf&quot;, &quot;-g&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evpe58/dJMcai2SD0b/BL0RiMRk4Y10Hxvkg6N5x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evpe58/dJMcai2SD0b/BL0RiMRk4Y10Hxvkg6N5x1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evpe58/dJMcai2SD0b/BL0RiMRk4Y10Hxvkg6N5x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fevpe58%2FdJMcai2SD0b%2FBL0RiMRk4Y10Hxvkg6N5x1%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;712&quot; height=&quot;187&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;187&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 빌드 및 실행&lt;/h4&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 이미지 빌드
sudo docker build -t mybind9 .

# 컨테이너 실행 (UDP/TCP 53번 포트 개방 필수)
sudo docker run -d --name private-dns \
  -p 53:53/udp -p 53:53/tcp \
  --restart always \
  mybind9&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 4: Router DHCP 설정 변경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 내부망의 모든 VM들이 자동으로 이 DNS 서버를 사용하도록, &lt;b&gt;Router VM&lt;/b&gt;의 설정을 변경합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Router VM (&lt;code&gt;/etc/dhcp/dhcpd.conf&lt;/code&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 기존 8.8.8.8 대신 내 Private DNS IP로 변경
option domain-name-servers 192.168.10.20;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 후 &lt;code&gt;sudo systemctl restart isc-dhcp-server&lt;/code&gt;를 입력하면 적용됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;559&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bslat1/dJMcacIqbSz/eR4sy9YsuKnZZ0i0LlDeKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bslat1/dJMcacIqbSz/eR4sy9YsuKnZZ0i0LlDeKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bslat1/dJMcacIqbSz/eR4sy9YsuKnZZ0i0LlDeKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbslat1%2FdJMcacIqbSz%2FeR4sy9YsuKnZZ0i0LlDeKK%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;559&quot; height=&quot;134&quot; data-origin-width=&quot;559&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  기술적 고찰: 왜 DNS 서버 본인은 조회가 안 될까?&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) 다른 VM(Client)에서 조회 시: 성공 ✅&lt;/b&gt;&lt;br /&gt;&lt;code&gt;Server: 192.168.10.20&lt;/code&gt;이 응답하며 정확한 IP를 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2) DNS 서버 본체(Host)에서 조회 시: 실패 ❌&lt;/b&gt;&lt;br /&gt;&lt;code&gt;NXDOMAIN&lt;/code&gt;이 뜨거나 타임아웃이 발생하며, 결국 &lt;code&gt;8.8.8.8&lt;/code&gt;로 넘어가서 찾지 못합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;  원인: Docker NAT Loopback (Hairpinning) 이슈&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 내 컴퓨터 안에 DNS가 떠 있는데, 왜 정작 주인인 나는 내 서버를 못 찾는 걸까요? 이는 &lt;b&gt;Docker 네트워크의 구조적 특성&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;&lt;b&gt;외부 VM 접속:&lt;/b&gt; 패킷이 &lt;code&gt;192.168.10.20&lt;/code&gt; NIC로 들어옴 &amp;rarr; Docker의 포트 포워딩 규칙(PREROUTING)에 걸림 &amp;rarr; 컨테이너로 전달 (성공)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Host 본체 접속:&lt;/b&gt; 패킷이 내부에서 발생(OUTPUT) &amp;rarr; 외부에서 들어오는 트래픽이 아니므로 Docker의 NAT 규칙을 타지 않음 &amp;rarr; &lt;b&gt;&quot;내가 나한테(10.20) 쏘는데?&quot;&lt;/b&gt; 하며 패킷이 길을 잃거나 루프백 처리가 꼬임.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마치며&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로써 &lt;b&gt;Router(DHCP/NAT)&lt;/b&gt;부터 &lt;b&gt;Private DNS&lt;/b&gt;까지, Proxmox 홈랩을 위한 기초 인프라 공사가 끝났습니다. 이제 IP 주소 대신 &lt;code&gt;www.jiwon1.com&lt;/code&gt; 같은 도메인을 사용해 쾌적하게 서비스를 올릴 준비가 되었습니다!  &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;369&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmZwHK/dJMb99SsEr0/CKcTC7KujJugFnU58RKmrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmZwHK/dJMb99SsEr0/CKcTC7KujJugFnU58RKmrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmZwHK/dJMb99SsEr0/CKcTC7KujJugFnU58RKmrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmZwHK%2FdJMb99SsEr0%2FCKcTC7KujJugFnU58RKmrK%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;369&quot; height=&quot;145&quot; data-origin-width=&quot;369&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>DNS</category>
      <category>Docker</category>
      <category>Private DNS</category>
      <category>홈서버</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/28</guid>
      <comments>https://jiione.tistory.com/28#entry28comment</comments>
      <pubDate>Sat, 13 Dec 2025 15:55:06 +0900</pubDate>
    </item>
    <item>
      <title>[HomeLab] Proxmox 내부망 구축기 (DHCP/NAT)</title>
      <link>https://jiione.tistory.com/27</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&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;/li&gt;
&lt;li&gt;&lt;b&gt;Step 1:&lt;/b&gt; Proxmox 격리 브리지(vmbr1) 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Step 2:&lt;/b&gt; 라우터 VM 네트워크 설정 (Netplan)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Step 3:&lt;/b&gt; 인터넷 연결을 위한 NAT 설정 (IPtables)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Step 4:&lt;/b&gt; 자동 IP 할당을 위한 DHCP 서버 구축&lt;/li&gt;
&lt;li&gt;&lt;b&gt;마치며:&lt;/b&gt; 나만의 작은 데이터센터 완성&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;들어가며: 왜 가상 라우터가 필요한가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 N100 미니 PC를 구입하여 &lt;b&gt;Proxmox VE&lt;/b&gt;를 올리고 홈랩(HomeLab)을 구축하고 있습니다. 처음에는 단순히 VM을 생성해서 공유기 IP를 받아 썼지만, VM이 늘어날수록 IP 관리가 번거롭고 보안도 신경 쓰이기 시작했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;클라우드(AWS)의 VPC처럼 외부와 격리된 나만의 사설 네트워크를 만들 순 없을까?&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 질문에서 시작해, **Proxmox 내부에 격리된 네트워크(LAN)**를 만들고, 그 안의 VM들에게 IP를 나눠주고 인터넷까지 연결해 주는 **'가상 라우터(Router)'**를 구축해 보았습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: Proxmox 격리 브리지(vmbr1) 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 내부 VM끼리만 통신할 수 있는 &lt;b&gt;'무인도(Isolated Network)'&lt;/b&gt;를 만들어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Proxmox 노드 &amp;rarr; &lt;b&gt;[System]&lt;/b&gt; &amp;rarr; &lt;b&gt;[Network]&lt;/b&gt;에서 &lt;code&gt;Linux Bridge&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;b&gt;Name:&lt;/b&gt; &lt;code&gt;vmbr1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IPv4/CIDR:&lt;/b&gt; (비워둠)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bridge ports:&lt;/b&gt; &lt;b&gt;(반드시 비워둠)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Comment:&lt;/b&gt; Internal Network&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nPzt4/dJMcaaKvJs2/kzrPtrGufLRPxcALp8vO2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nPzt4/dJMcaaKvJs2/kzrPtrGufLRPxcALp8vO2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nPzt4/dJMcaaKvJs2/kzrPtrGufLRPxcALp8vO2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnPzt4%2FdJMcaaKvJs2%2FkzrPtrGufLRPxcALp8vO2K%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;1915&quot; height=&quot;308&quot; data-origin-width=&quot;1915&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: 라우터 VM 네트워크 설정 (Netplan)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ubuntu Server 22.04로 &lt;b&gt;Router VM&lt;/b&gt;을 생성하고, 하드웨어 설정에서 &lt;b&gt;랜카드를 2개&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;&lt;b&gt;net0 (ens18):&lt;/b&gt; &lt;code&gt;vmbr0&lt;/code&gt; 연결 (WAN - 인터넷용)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;net1 (ens19):&lt;/b&gt; &lt;code&gt;vmbr1&lt;/code&gt; 연결 (LAN - 내부 관리용)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VM 내부에서 &lt;code&gt;netplan&lt;/code&gt;을 통해 IP를 고정하고 게이트웨이 역할을 부여합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;파일 경로:&lt;/b&gt; &lt;code&gt;/etc/netplan/50-cloud-init.yaml&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    ens18:              # 외부 (WAN)
      dhcp4: true       # 집 공유기에서 IP 자동 할당
    ens19:              # 내부 (LAN)
      dhcp4: false
      addresses:
        - 192.168.10.1/24  # 이 라우터의 내부 IP (게이트웨이 주소)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 후 &lt;code&gt;sudo netplan apply&lt;/code&gt; 로 적용합니다. 이제 &lt;code&gt;ens19&lt;/code&gt; 인터페이스는 내부망의 게이트웨이 역할을 수행합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 3: 인터넷 연결을 위한 NAT 설정 (IPtables)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부망(&lt;code&gt;192.168.10.x&lt;/code&gt;)은 사설 IP이므로, 이 상태로는 인터넷(네이버, 구글)에 접속할 수 없습니다. 나가는 패킷의 주소를 라우터의 공인 IP(&lt;code&gt;192.168.0.x&lt;/code&gt;)로 변조해 주는 &lt;b&gt;NAT(Masquerade)&lt;/b&gt; 설정이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. IP 포워딩 활성화&lt;/b&gt;&lt;br /&gt;&lt;code&gt;/etc/sysctl.conf&lt;/code&gt; 파일에서 주석을 해제합니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;net.ipv4.ip_forward=1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. IPTables 마스커레이드 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;sudo iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해석:&lt;/b&gt; &quot;나가는 문(&lt;code&gt;ens18&lt;/code&gt;)을 통과하는 패킷은 내 IP로 변장(Masquerade)시켜라.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 설정 영구 저장&lt;/b&gt;&lt;br /&gt;재부팅 후에도 규칙이 유지되도록 &lt;code&gt;iptables-persistent&lt;/code&gt;를 설치하여 저장했습니다.&lt;br /&gt;&lt;code&gt;sudo apt install iptables iptables-persistent&lt;/code&gt; 이 후 전부 &lt;code&gt;OK&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czHPYi/dJMcacBziXo/IAbScUjG2p7Zes5PnJMbrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czHPYi/dJMcacBziXo/IAbScUjG2p7Zes5PnJMbrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czHPYi/dJMcacBziXo/IAbScUjG2p7Zes5PnJMbrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczHPYi%2FdJMcacBziXo%2FIAbScUjG2p7Zes5PnJMbrK%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;1281&quot; height=&quot;798&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 4: 자동 IP 할당을 위한 DHCP 서버 구축&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부망에 연결되는 VM들이 일일이 IP를 설정하지 않아도 되도록 &lt;b&gt;DHCP 서버&lt;/b&gt;를 구축했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치:&lt;/b&gt; &lt;code&gt;sudo apt install isc-dhcp-server&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 인터페이스 지정 (&lt;code&gt;/etc/default/isc-dhcp-server&lt;/code&gt;)&lt;/b&gt;&lt;br /&gt;외부망으로 IP를 뿌리면 집 인터넷이 마비될 수 있으므로, 반드시 내부 인터페이스(&lt;code&gt;ens19&lt;/code&gt;)만 지정합니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;INTERFACESv4=&quot;ens19&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD6BLT/dJMcaiaH4lp/Ike1x3mGSgzgmrIQqsKciK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD6BLT/dJMcaiaH4lp/Ike1x3mGSgzgmrIQqsKciK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD6BLT/dJMcaiaH4lp/Ike1x3mGSgzgmrIQqsKciK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD6BLT%2FdJMcaiaH4lp%2FIke1x3mGSgzgmrIQqsKciK%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;1276&quot; height=&quot;798&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. DHCP 범위 설정 (&lt;code&gt;/etc/dhcp/dhcpd.conf&lt;/code&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;subnet 192.168.10.0 netmask 255.255.255.0 {
  range 192.168.10.100 192.168.10.200;      # 할당 범위 (100~200)
  option routers 192.168.10.1;             # 게이트웨이 (나 자신)
  option subnet-mask 255.255.255.0;
  option domain-name-servers 8.8.8.8;      # DNS (Google)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 재시작(&lt;code&gt;sudo systemctl restart isc-dhcp-server&lt;/code&gt;) 후 &lt;code&gt;Active (running)&lt;/code&gt; 상태를 확인.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;131&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8eobF/dJMcafyhNhF/XYKDL93MOh2wUNIPGYZToK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8eobF/dJMcafyhNhF/XYKDL93MOh2wUNIPGYZToK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8eobF/dJMcafyhNhF/XYKDL93MOh2wUNIPGYZToK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8eobF%2FdJMcafyhNhF%2FXYKDL93MOh2wUNIPGYZToK%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;456&quot; height=&quot;131&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;131&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트러블 슈팅&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Status Active failed 문제&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lzjdn/dJMcahCRTpB/4VkNxC4RAjZeHooSBh0070/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lzjdn/dJMcahCRTpB/4VkNxC4RAjZeHooSBh0070/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lzjdn/dJMcahCRTpB/4VkNxC4RAjZeHooSBh0070/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLzjdn%2FdJMcahCRTpB%2F4VkNxC4RAjZeHooSBh0070%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;1279&quot; height=&quot;340&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;sudo dhcpd -t&lt;/code&gt;를 사용해서 맞춤법 검사&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;283&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v3DJm/dJMcab3JbRI/ieqF8oZfPxkbAxkVIF99K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v3DJm/dJMcab3JbRI/ieqF8oZfPxkbAxkVIF99K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v3DJm/dJMcab3JbRI/ieqF8oZfPxkbAxkVIF99K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv3DJm%2FdJMcab3JbRI%2FieqF8oZfPxkbAxkVIF99K0%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;636&quot; height=&quot;283&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;283&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/etc/dhcp/dhcpd/conf&lt;/code&gt; 113 줄에서 오타 발견하고 해결&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm9yhW/dJMcagRuHZZ/ncHpawLZzKHSbNwzodJTo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm9yhW/dJMcagRuHZZ/ncHpawLZzKHSbNwzodJTo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm9yhW/dJMcagRuHZZ/ncHpawLZzKHSbNwzodJTo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm9yhW%2FdJMcagRuHZZ%2FncHpawLZzKHSbNwzodJTo1%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;1281&quot; height=&quot;512&quot; data-origin-width=&quot;1281&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;&lt;b&gt;ping 8.8.8.8 안됨&lt;/b&gt;&lt;br /&gt;DHCP(IP 받기)는 성공했지만, NAT(인터넷 연결) 설정이 풀렸거나 적용이 안된 경우&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o0uW9/dJMcadtE7WX/VBJxHBW9pErVea5ttG5E00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o0uW9/dJMcadtE7WX/VBJxHBW9pErVea5ttG5E00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o0uW9/dJMcadtE7WX/VBJxHBW9pErVea5ttG5E00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo0uW9%2FdJMcadtE7WX%2FVBJxHBW9pErVea5ttG5E00%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;658&quot; height=&quot;91&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;91&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;IP 포워딩 확인&lt;/b&gt;&lt;br /&gt;&lt;code&gt;sysctl net.ipv4.ip_forward&lt;/code&gt; 으로 ip 포워딩 확인 &lt;code&gt;= 1&lt;/code&gt; 이면 정상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NAT 규칙 확인&lt;/b&gt;&lt;br /&gt;&lt;code&gt;sudo iptables -t nat -L -n -v&lt;/code&gt; 으로 iptables 규칙 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/THcGJ/dJMcabQbLak/Ab3zJlMcrkO9JJWFOSkLcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/THcGJ/dJMcabQbLak/Ab3zJlMcrkO9JJWFOSkLcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/THcGJ/dJMcabQbLak/Ab3zJlMcrkO9JJWFOSkLcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTHcGJ%2FdJMcabQbLak%2FAb3zJlMcrkO9JJWFOSkLcK%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;706&quot; height=&quot;254&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;254&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;아래 명령어로 ens18(외부망)에 NAT 규칙 추가&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;sudo iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
sudo netfilter-persistent save&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3SiKr/dJMcaioeWZP/XGd68FMryrFJUz5FgBMKYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3SiKr/dJMcaioeWZP/XGd68FMryrFJUz5FgBMKYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3SiKr/dJMcaioeWZP/XGd68FMryrFJUz5FgBMKYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3SiKr%2FdJMcaioeWZP%2FXGd68FMryrFJUz5FgBMKYk%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;738&quot; height=&quot;219&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마치며&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 공유기 밑에 VM을 두는 것을 넘어, 직접 리눅스로 &lt;b&gt;라우터, DHCP, NAT&lt;/b&gt;를 밑바닥부터 구축해보니 네트워크의 흐름(DORA, SNAT 등)이 훨씬 명확하게 이해되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 &lt;b&gt;격리된 내부망(192.168.10.x)&lt;/b&gt;은 저만의 안전한 &lt;b&gt;'Private Cloud'&lt;/b&gt;가 되었습니다. 다음 포스팅에서는 이 환경 위에 &lt;b&gt;Public/Private DNS&lt;/b&gt;를 구축하여 도메인 기반으로 서비스를 분리하는 실습을 진행해 보겠습니다.&lt;/p&gt;</description>
      <category>IT 이것저것 요모조모/Infra</category>
      <category>dhcp</category>
      <category>NAT</category>
      <category>proxmox</category>
      <category>가상화</category>
      <author>Jiione</author>
      <guid isPermaLink="true">https://jiione.tistory.com/27</guid>
      <comments>https://jiione.tistory.com/27#entry27comment</comments>
      <pubDate>Sat, 29 Nov 2025 23:43:37 +0900</pubDate>
    </item>
  </channel>
</rss>