<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Guides 보관 - 커리어 인사이트</title>
	<atom:link href="https://lindarex-career-insight.com/category/tech/dev-guides/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>현업 개발자의 실무 기록과 커리어 인사이트</description>
	<lastBuildDate>Tue, 10 Feb 2026 03:22:13 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://lindarex-career-insight.com/wp-content/uploads/2024/06/cropped-fa-512-C-32x32.jpg</url>
	<title>Guides 보관 - 커리어 인사이트</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>개발자 AI 도구 분석: Copilot·Cursor·Claude·JetBrains AI 실무 검증</title>
		<link>https://lindarex-career-insight.com/developer-ai-tools-2026/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 03:13:44 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[AI 코드 리뷰]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Cursor IDE]]></category>
		<category><![CDATA[GitHub Copilot]]></category>
		<category><![CDATA[IntelliJ IDEA]]></category>
		<category><![CDATA[Java 개발자]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[VS Code]]></category>
		<category><![CDATA[개발자]]></category>
		<category><![CDATA[개발자 AI 도구]]></category>
		<category><![CDATA[개발자 생산성]]></category>
		<category><![CDATA[개발자 워크플로우]]></category>
		<category><![CDATA[사회초년생]]></category>
		<category><![CDATA[코딩 보조 AI]]></category>
		<category><![CDATA[팀 개발 문화]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=927</guid>

					<description><![CDATA[<p>&#8220;개발자 AI 도구&#8221;는 생산성 논쟁을 넘어 ‘어떻게 쓰느냐’가 실력을 가르는 기준이 되고 있습니다. &#8220;아직도 AI 없이 코딩하고 계신가요?&#8221; 2026년 현재, 개발자 AI 도구는 더 이상 실…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/developer-ai-tools-2026/">개발자 AI 도구 분석: Copilot·Cursor·Claude·JetBrains AI 실무 검증</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>&#8220;개발자 AI 도구&#8221;는 생산성 논쟁을 넘어 ‘어떻게 쓰느냐’가 실력을 가르는 기준이 되고 있습니다.</p>



<p>&#8220;아직도 AI 없이 코딩하고 계신가요?&#8221;</p>



<p>2026년 현재, 개발자 AI 도구는 더 이상 실험 대상이 아닙니다. <br><a href="https://survey.stackoverflow.co/" target="_blank" rel="noreferrer noopener">Stack Overflow Developer Survey</a>와 다수 현업 사례를 종합하면, <br>대다수 개발자가 코딩 보조 AI를 실제 업무에 사용하고 있으며 <br>업무 시간 단축 효과는 약 <strong>30~60% 수준</strong>으로 반복 관찰됩니다. <br>(⚠️ 업무 성격·숙련도·팀 구조에 따라 편차는 큽니다)</p>



<p>문제는 <strong>어떤 코딩 보조 AI를, 어떻게 써야 개발자 생산성이 실제로 오르느냐</strong>입니다. <br>이 글은 많은 개발자가 실제로 사용하고 공식 설문·발표로 검증된 도구와 사용법만 정리했습니다.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="684" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/developer-productivity-ai-2026-1024x684.jpg" alt="2026년 AI와 협업하여 생산성을 높이는 현대적인 개발자 AI 도구 환경" class="wp-image-928" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/developer-productivity-ai-2026-1024x684.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/developer-productivity-ai-2026-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/developer-productivity-ai-2026-768x513.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/developer-productivity-ai-2026.jpg 1279w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">🚀 2026개발자 AI 도구 한눈 정리</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><td><strong>도구</strong></td><td><strong>핵심 역할</strong></td><td><strong>현실적인 포지션</strong></td></tr></thead><tbody><tr><td><strong>ChatGPT</strong></td><td>사고·설계·학습</td><td>생각 정리 및 기획 초안</td></tr><tr><td><strong>GitHub Copilot</strong></td><td>IDE 자동완성</td><td>반복 코드 지우개</td></tr><tr><td><strong>JetBrains AI</strong></td><td>IDE 맥락 이해</td><td>정교한 리팩토링 및 코드 이해</td></tr><tr><td><strong>VS Code AI</strong></td><td>경량 IDE AI</td><td>가벼운 보조 및 무료 대안</td></tr><tr><td><strong>Cursor</strong></td><td>AI 네이티브 IDE</td><td>대량 수정 및 에이전트 작업</td></tr><tr><td><strong>Claude Code</strong></td><td>코드 추론·리뷰</td><td>고난도 논리 판단 및 리뷰</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1️⃣ ChatGPT – 사고·설계에 강한 개발자 AI 도구</h2>



<p>OpenAI의 ChatGPT는 개발자가 가장 먼저 실행하는 개발자 AI 도구입니다.</p>



<ul class="wp-block-list">
<li><strong>실제로 생산성이 오르는 지점:</strong> 기능·아키텍처 초안 작성, 에러 로그 원인 후보 정리, 레거시 코드 설명, 테스트 시나리오 아이디어 도출.</li>



<li><strong>한계:</strong> 최신 라이브러리/버전은 직접 검증이 필수이며, 프로젝트 전체 맥락을 자동으로 인식하지는 못함</li>



<li><strong>트러블슈팅 팁:</strong> 답변이 추측성일 때를 대비해 &#8220;이 답변이 추측이라면 어느 부분이 불확실한지 명시해줘&#8221;라고 요청.</li>
</ul>



<h2 class="wp-block-heading">2️⃣ GitHub Copilot – 생산성을 높이는 코딩 보조 AI 표준</h2>



<p><a href="https://github.com/features/copilot" target="_blank" rel="noreferrer noopener">GitHub Copilot</a>은 가장 많은 개발자가 실제로 사용하는 도구입니다.</p>



<ul class="wp-block-list">
<li><strong>Java / Spring Boot 실무 강점:</strong> 단순히 CRUD 작성을 넘어, <strong>DTO ↔ Entity 매핑 로직</strong>이나 <strong>JPA Repository 인터페이스의 쿼리 메서드 생성</strong>처럼 규칙성이 명확한 보일러플레이트 코드에서 오타율을 0%에 수렴시킴</li>



<li><strong>실제 장애 사례:</strong> Copilot이 생성한 테스트가 &#8216;성공 케이스&#8217;만 검증하고 경계값 테스트를 누락하여 운영에서 데이터 누락 장애가 발생한 사례가 보고됨. 테스트의 &#8216;의도&#8217;는 반드시 사람이 설계해야 함.</li>
</ul>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/java-spring-boot-ai-coding-1024x682.jpg" alt="Java 및 Spring Boot 환경에서 개발자 AI 도구를 활용한 효율적인 코딩과 테스트 자동화" class="wp-image-929" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/java-spring-boot-ai-coding-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/java-spring-boot-ai-coding-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/java-spring-boot-ai-coding-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/java-spring-boot-ai-coding.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">3️⃣ JetBrains AI – “IDE가 프로젝트를 이해한다”</h2>



<p><a href="https://www.jetbrains.com/ai/" target="_blank" rel="noreferrer noopener">JetBrains AI Assistant</a>는 IntelliJ 기반 개발자에게 가장 현실적인 선택입니다.</p>



<ul class="wp-block-list">
<li><strong>강점:</strong> AST(추상 구문 트리) 기반 코드 이해로 레거시 탐색 및 리팩토링 영향 범위 파악이 탁월함.</li>



<li><strong>실제 이슈:</strong> 리팩토링 적용 후 비즈니스 의도가 미묘하게 변경되어 테스트는 통과하지만, 결과값이 달라지는 경우가 있으니 주의 필요.</li>
</ul>



<h2 class="wp-block-heading">💡 IntelliJ vs Cursor – 개발자 AI 도구 선택 가이드</h2>



<p><strong>IntelliJ 유저라면? (The Developer’s Dilemma)</strong></p>



<p>2026년에도 Java 개발자들이 <a href="https://www.cursor.com/" target="_blank" rel="noreferrer noopener">Cursor</a>로 완전히 넘어가지 못하는 이유는 IntelliJ의 강력한 정적 분석·디버깅 도구.</p>



<ul class="wp-block-list">
<li><strong>추천 전략 (Hybrid):</strong> 신규 도메인 설계 및 레거시 분석은 <strong>Cursor</strong>, 서비스 고도화와 정교한 리팩토링은 <strong>IntelliJ + Copilot</strong>을 사용하는 하이브리드 전략이 가장 효율적</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4️⃣ Cursor – AI 네이티브 IDE의 양날의 검</h2>



<p>Cursor는 대량 수정에서 강력하지만, 통제하지 않으면 사고가 가장 많이 납니다.</p>



<h3 class="wp-block-heading">❌ 실제 장애 패턴 &amp; 대응</h3>



<ul class="wp-block-list">
<li><strong>문제:</strong> AI가 편의를 위해 <strong>@Autowired</strong>를 남발하거나 서비스 간 <strong>Circular Dependency(순환 참조)</strong>를 발생시켜 Spring Boot 런타임 장애를 유발</li>



<li><strong>해결:</strong> AI에게 반드시 <strong>&#8220;생성자 주입(Constructor Injection)만 사용하고, 순환 참조가 발생하지 않도록 레이어를 분리해줘&#8221;</strong>라고 제약을 걸음</li>



<li><strong>전문가 팁 (.cursorrules):</strong> 프로젝트 루트에 규칙 파일을 설정하세요. 1인 개발자라도 주니어 개발자 1명 분의 코드 리뷰 효과를 얻을 수 있음</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5️⃣ Claude Code – “코드를 이해하는 AI”</h2>



<p>Anthropic의 <a href="https://www.anthropic.com/claude" target="_blank" rel="noreferrer noopener">Claude</a>는 자동완성보다 코드 추론 및 판단에 강합니다. 긴 코드 흐름을 이해하고 &#8220;왜 이렇게 작성되었는지&#8221; 설명하는 능력이 독보적입니다.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/ai-code-review-team-collaboration-1024x682.jpg" alt="개발자 AI 도구를 도입한 개발 팀의 효율적인 코드 리뷰와 협업 모습" class="wp-image-930" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/ai-code-review-team-collaboration-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/ai-code-review-team-collaboration-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/ai-code-review-team-collaboration-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/ai-code-review-team-collaboration.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">🔧 개발자 AI 도구 분업 전략 – 충돌 없이 쓰는 법</h2>



<ul class="wp-block-list">
<li><strong>Claude / ChatGPT:</strong> 설계 및 로직 판단</li>



<li><strong>GitHub Copilot:</strong> 빠른 반복 코드 생성</li>



<li><strong>JetBrains AI:</strong> 코드 이해 및 정교한 리뷰</li>



<li><strong>Cursor:</strong> 대량 수정 및 MVP 제작 (통제 필수)</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">🧭 팀 단위 개발자 AI 도구 도입 및 서바이벌 가이드</h2>



<h3 class="wp-block-heading">❌ AI 금지가 실패하는 이유</h3>



<p>원인 분석 없이 도구부터 금지하면 결국 음성적 사용만 늘고 보안 사고 위험은 더 커집니다. <br>AI 금지는 통제 실패의 다른 표현일 뿐입니다.</p>



<h3 class="wp-block-heading">✅ 팀 AI 정책 템플릿 (최소 조건)</h3>



<ol start="1" class="wp-block-list">
<li><strong>역할 정의:</strong> AI는 &#8216;초안 작성자&#8217;, 사람은 &#8216;최종 승인자&#8217;</li>



<li><strong>금지 영역:</strong> 보안 민감 로직, 결제 및 법규 관련 코드는 수동 검증 필수</li>



<li><strong>리뷰 기준:</strong> AI 생성 코드는 반드시 작성자가 한 줄씩 설명할 수 있어야 함</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">🎯 Spring Boot 전용 개발자 AI 도구 사용 체크리스트</h2>



<p>AI에게 코딩을 시킬 때 다음 3가지는 반드시 확인하세요.</p>



<ol start="1" class="wp-block-list">
<li><strong>Lombok 활용:</strong> &#8220;Lombok 어노테이션을 활용해서 보일러플레이트를 줄여줘.&#8221;</li>



<li><strong>Layered Architecture:</strong> &#8220;Controller-Service-Repository 레이어 책임을 명확히 분리해줘.&#8221;</li>



<li><strong>Exception Handling:</strong> &#8220;전역 예외 처리(GlobalExceptionHandler)에 맞는 예외 타입을 사용해줘.&#8221;</li>
</ol>



<p>👉 다른 개발 관련 글들은 <a href="https://lindarex-career-insight.com/">커리어 인사이트 메인 페이지</a>에서 계속 정리하고 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">결론: 2026년 개발자의 진짜 실력</h2>



<p>AI는 실수를 만듭니다. 다만 실수를 <strong>&#8216;더 빨리&#8217;</strong> 만들 뿐입니다. <br>2026년의 실력 있는 개발자는 <strong>“AI가 짠 코드의 냄새(Code Smell)를 맡을 줄 아는 사람”</strong>입니다. </p>



<p>AI 결과물을 냉정하게 의심하고, <br>아키텍처 원칙에 맞는지, <br>마지막까지 확인하는 개발자만이 생산성 향상의 과실을 딸 수 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">[FAQ: 자주 묻는 질문]</h3>



<p><strong>Q. AI 도구 하나만 추천한다면?</strong></p>



<p>A. 하나만 쓰기보다 <strong>Copilot(속도)</strong>과 <strong>Claude(판단)</strong>의 조합이 가장 안정적인 성능을 보여줍니다.</p>



<p><strong>Q. AI 때문에 내 자리가 없어질까요?</strong></p>



<p>A. AI가 개발자를 대체하는 것이 아니라, <strong>AI를 잘 쓰는 개발자가 그렇지 못한 개발자를 대체</strong>하게 될 것입니다.</p>



<p><strong>Q. 코딩 보조 AI를 쓰면 실력이 떨어질까요?</strong> </p>



<p>A. 결과물을 맹목적으로 복사하지 않고 &#8220;왜 이렇게 짰어?&#8221;라고 AI에게 되묻는 습관을 들인다면 오히려 학습 속도가 빨라집니다.</p>
<p>게시물 <a href="https://lindarex-career-insight.com/developer-ai-tools-2026/">개발자 AI 도구 분석: Copilot·Cursor·Claude·JetBrains AI 실무 검증</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IntelliJ AI 충돌 해결: Copilot·Gemini·JetBrains AI 분업화 전략</title>
		<link>https://lindarex-career-insight.com/intellij-copilot-gemini-jetbrains-ai-conflict/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Tue, 03 Feb 2026 03:16:23 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI 도구 충돌]]></category>
		<category><![CDATA[AI 분업화 전략]]></category>
		<category><![CDATA[AI 에이전트]]></category>
		<category><![CDATA[AI 코드 자동완성]]></category>
		<category><![CDATA[Alt+Enter]]></category>
		<category><![CDATA[Gemini Code Assist]]></category>
		<category><![CDATA[GitHub Copilot]]></category>
		<category><![CDATA[IDE 생산성]]></category>
		<category><![CDATA[intellij]]></category>
		<category><![CDATA[IntelliJ 단축키]]></category>
		<category><![CDATA[JetBrains AI]]></category>
		<category><![CDATA[Tab 키 충돌]]></category>
		<category><![CDATA[개발 환경 최적화]]></category>
		<category><![CDATA[개발자]]></category>
		<category><![CDATA[개발자 도구]]></category>
		<category><![CDATA[멀티 AI 사용]]></category>
		<category><![CDATA[코딩 생산성]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=872</guid>

					<description><![CDATA[<p>IntelliJ Copilot Gemini JetBrains AI Assistant(Codex)충돌 문제는 최근 IntelliJ 사용자들이 가장 자주 겪는 이슈 중 하나입니다.GitHub Copilot, Gemini Code Assi…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/intellij-copilot-gemini-jetbrains-ai-conflict/">IntelliJ AI 충돌 해결: Copilot·Gemini·JetBrains AI 분업화 전략</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>IntelliJ Copilot Gemini JetBrains AI Assistant(Codex)충돌 문제는 최근 IntelliJ 사용자들이 가장 자주 겪는 이슈 중 하나입니다.<br>GitHub Copilot, Gemini Code Assist, JetBrains AI를 동시에 사용하면 Tab 충돌, 인라인 자동완성 깜빡임, IDE 버벅임이 반복적으로 발생합니다.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-copilot-gemini-jetbrains-ai-conflict-1024x683.jpg" alt="IntelliJ Copilot Gemini JetBrains AI 충돌과 분업화 전략" class="wp-image-873" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-copilot-gemini-jetbrains-ai-conflict-1024x683.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-copilot-gemini-jetbrains-ai-conflict-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-copilot-gemini-jetbrains-ai-conflict-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-copilot-gemini-jetbrains-ai-conflict-1536x1024.jpg 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-copilot-gemini-jetbrains-ai-conflict-2048x1365.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">IntelliJ Copilot Gemini JetBrains AI 충돌은 왜 계속 발생할까?</h2>



<p><strong>IntelliJ Copilot Gemini JetBrains AI 충돌의 해법은 단 하나입니다.</strong><br>👉 <strong>대규모 수정·에이전트 작업은 JetBrains AI에게,<br>👉 실시간 타이핑(인라인 자동완성)은 GitHub Copilot에게 맡기는 ‘분업화 전략’입니다.</strong></p>



<p>이 원칙 하나만 지켜도 <strong>Tab 충돌, 제안 깜빡임, IDE 버벅임의 90%는 사라집니다.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ에서 Copilot·Gemini·JetBrains AI가 충돌하는 구조적 원인</h2>



<p>GitHub의 <strong>GitHub Copilot</strong>,<br>Google의 <strong>Gemini Code Assist</strong>,<br>JetBrains의 <strong>JetBrains AI</strong>는 모두 공통적으로 다음 구조를 가집니다.</p>



<ul class="wp-block-list">
<li>타이핑 중 <strong>같은 위치(Inline Completion 레이어)</strong>에 제안을 띄우고</li>



<li><strong>Tab / Esc / Alt 계열 키</strong>로 수락·취소를 제어하며</li>



<li>동시에 켜지면 <strong>어느 제안이 우선인지 IntelliJ가 판단하기 어려움</strong></li>
</ul>



<p>그래서 발생하는 현상은 버그처럼 보이지만, 실제로는 <strong>설계상 경쟁 상태</strong>입니다.<br>이 구조가 바로 IntelliJ에서 여러 AI 도구를 함께 사용할 때 충돌이 발생하는 근본 원인입니다.</p>



<p>참고로 각 도구의 인라인 자동완성 동작 방식은 공식 문서에서도 확인할 수 있습니다.</p>



<ul class="wp-block-list">
<li>GitHub Copilot 인라인 제안 단축키: <a href="https://docs.github.com/ko/copilot/reference/keyboard-shortcuts" target="_blank" rel="noreferrer noopener">https://docs.github.com/ko/copilot/reference/keyboard-shortcuts</a></li>



<li>JetBrains AI Code Completion 설명: <a href="https://www.jetbrains.com/help/ai-assistant/code-completion.html" target="_blank" rel="noreferrer noopener">https://www.jetbrains.com/help/ai-assistant/code-completion.html</a></li>



<li>Gemini Code Assist 개요: <a href="https://codeassist.google" target="_blank" rel="noreferrer noopener">https://codeassist.google</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ Copilot Gemini JetBrains AI 충돌 유형 체크리스트</h2>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="681" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-tab-alt-enter-conflict-1024x681.jpg" alt="IntelliJ Copilot Gemini JetBrains AI 충돌 Tab Alt Enter 단축키" class="wp-image-874" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-tab-alt-enter-conflict-1024x681.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-tab-alt-enter-conflict-300x199.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-tab-alt-enter-conflict-768x511.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-tab-alt-enter-conflict-1536x1021.jpg 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-tab-alt-enter-conflict-2048x1362.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">1️⃣ Tab 키 충돌 (가장 치명적)</h3>



<p>Tab은 Copilot / JetBrains AI / Gemini 인라인 제안 수락과 IntelliJ 기본 들여쓰기에 동시에 사용됩니다.<br>인라인 자동완성이 2개 이상 켜진 순간, “엉뚱한 제안 수락 / 들여쓰기만 되고 제안 사라짐” 같은 충돌이 바로 재현됩니다.</p>



<p>➡️ 결론: 인라인 자동완성은 반드시 1개만 ON(실시간 타이핑은 Copilot 권장)</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2️⃣ Alt + Enter 충돌 (IDE 핵심 UX 훼손)</h3>



<ul class="wp-block-list">
<li>IntelliJ: Quick Fix / Intention</li>



<li>Copilot / JetBrains AI / Gemini: AI 액션</li>
</ul>



<h3 class="wp-block-heading">✅ 단축키 충돌이 가장 먼저 체감되는 이유</h3>



<ul class="wp-block-list">
<li><strong>Tab</strong>: 인라인 제안 수락 키이므로, 인라인 자동완성은 <strong>딱 1개만 ON</strong>(Copilot 권장)</li>



<li><strong>Alt+Enter</strong>: IntelliJ의 Quick Fix/Intention이 핵심이므로 <strong>IDE 전용으로 유지</strong></li>



<li>AI 액션(채팅/리팩터링/테스트 생성)은 <strong>별도 키로 분리</strong>하거나, <strong>Ctrl+Shift+A(액션 검색)</strong>로 호출하는 편이 안정적</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3️⃣ 인라인 자동완성 + Next Edit 예측 충돌</h3>



<ul class="wp-block-list">
<li>Gemini의 <strong>Next Edit Predictions</strong>는 커서 이후 편집까지 개입</li>



<li>체감 속도는 빨라질 수 있으나</li>



<li>다른 인라인 자동완성과 함께 켜면 <strong>커서 튐·제안 깜빡임 증가</strong></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Alt+Enter 충돌이 IntelliJ UX를 망치는 이유</h3>



<p><code>Alt+Enter</code>는 IntelliJ에서 <strong>Quick Fix / Intention</strong>을 여는 핵심 단축키입니다.<br>여기에 AI 액션이 섞이면, IDE의 기본 사용 흐름이 무너집니다.</p>



<ul class="wp-block-list">
<li>IntelliJ: Quick Fix / Intention</li>



<li>Copilot / JetBrains AI / Gemini: AI 제안 액션</li>
</ul>



<p>Alt+Enter 충돌이 발생하면,</p>



<ul class="wp-block-list">
<li>원래 기대하던 Quick Fix가 안 뜨거나</li>



<li>AI 메뉴가 튀어나오면서 작업 흐름이 끊깁니다.</li>
</ul>



<p>👉 <strong>IntelliJ AI 충돌을 줄이려면 Alt+Enter는 IDE 전용으로 유지</strong>하는 것이 가장 안정적입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">IntelliJ Copilot·Gemini·JetBrains AI 단축키 분업 원칙</h3>



<p>단축키 충돌을 피하려면, AI를 “똑같이 쓰지 말고 역할로 나눠야” 합니다.</p>



<ul class="wp-block-list">
<li><strong>Copilot</strong>
<ul class="wp-block-list">
<li>실시간 타이핑 전담</li>



<li>인라인 자동완성 + Tab 수락</li>
</ul>
</li>



<li><strong>JetBrains AI</strong>
<ul class="wp-block-list">
<li>에이전트·대규모 수정 전담</li>



<li>단축키보다는 AI Action / 액션 검색 중심</li>
</ul>
</li>



<li><strong>Gemini</strong>
<ul class="wp-block-list">
<li>분석·설명·설계 보조</li>



<li>인라인 자동완성 OFF, 단축키 개입 최소화</li>
</ul>
</li>
</ul>



<p>이렇게 나누면<br><strong>IntelliJ Copilot Gemini JetBrains AI 충돌은 단축키 단계에서 대부분 사라집니다.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ에서 여러 AI 도구를 함께 사용할 때 성능이 떨어지는 이유</h2>



<p>다음 작업이 동시에 발생합니다.</p>



<ul class="wp-block-list">
<li>인덱싱 + 코드 분석</li>



<li>AI 컨텍스트 수집</li>



<li>인라인 제안 생성</li>
</ul>



<p>이 셋이 동시에 돌면:</p>



<ul class="wp-block-list">
<li>타이핑 지연</li>



<li>UI 멈춤</li>



<li>제안 표시 불안정</li>
</ul>



<p>특히 여러 AI 인라인 자동완성이 동시에 켜진 상태에서 체감 성능 저하가 가장 큽니다.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="546" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-ide-performance-issue-1024x546.jpg" alt="IntelliJ Copilot Gemini JetBrains AI 충돌로 IDE 성능 저하" class="wp-image-875" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-ide-performance-issue-1024x546.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-ide-performance-issue-300x160.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-ide-performance-issue-768x410.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-ide-performance-issue-1536x819.jpg 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/intellij-ide-performance-issue.jpg 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ 다중 AI 사용 환경에서 주의해야 할 보안·품질 이슈</h2>



<ul class="wp-block-list">
<li>AI 생성 코드는 <strong>빠르지만 항상 안전하지는 않습니다</strong></li>



<li>입력 검증·예외 처리·권한 체크는 <strong>사람이 반드시 리뷰</strong></li>
</ul>



<p><strong>안전 운영 원칙</strong></p>



<ul class="wp-block-list">
<li>멀티파일 자동 수정은 <strong>1개 에이전트만</strong></li>



<li>터미널 실행·대규모 변경은 <strong>필요할 때만</strong></li>



<li>항상 <strong>diff 기반 검토</strong></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ Copilot Gemini JetBrains AI 충돌 해결 전략: 분업화가 정답인 이유</h2>



<h3 class="wp-block-heading">왜 분업화 전략이 IntelliJ AI 충돌의 해법인가?</h3>



<ul class="wp-block-list">
<li><strong>인라인 자동완성(실시간 타이핑)</strong><br>→ 빠르고 방해 없는 UX가 핵심</li>



<li><strong>대규모 수정·리팩터링·테스트 생성(에이전트)</strong><br>→ 프로젝트 컨텍스트 이해·안정성이 핵심</li>
</ul>



<p>이 두 요구사항을 <strong>하나의 AI에게 동시에 맡기면 반드시 충돌</strong>합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ Copilot Gemini JetBrains AI 충돌을 피하는 최종 분업화 구성</h2>



<h3 class="wp-block-heading">역할 1 — 실시간 타이핑 전담: <strong>GitHub Copilot</strong></h3>



<ul class="wp-block-list">
<li>인라인 자동완성 <strong>ON</strong></li>



<li>Tab / Esc / Alt+[ ] 기본 흐름 유지</li>



<li>“코드 타이핑 속도”에만 집중</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">역할 2 — 에이전트·대규모 수정 전담: <strong>JetBrains AI</strong></h3>



<ul class="wp-block-list">
<li>멀티파일 리팩터링</li>



<li>테스트 생성</li>



<li>프로젝트 단위 변경</li>



<li>IDE 컨텍스트 기반 작업</li>
</ul>



<p>➡️ <strong>IntelliJ Copilot Gemini JetBrains AI 충돌을 피하려면,<br>에이전트 역할은 JetBrains AI 단독이 가장 안정적</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">역할 3 — 분석·보조 브레인: <strong>Gemini</strong></h3>



<ul class="wp-block-list">
<li>긴 로직 설명</li>



<li>설계 대안</li>



<li>엣지 케이스 질문</li>



<li><strong>인라인 자동완성은 OFF</strong></li>
</ul>



<p>👉 이 블로그의 다른 개발 환경 최적화 글들은<br><a href="/">커리어 인사이트 메인 페이지</a>에서 계속 정리하고 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">요약하면</h3>



<ul class="wp-block-list">
<li><strong>타이핑은 Copilot</strong></li>



<li><strong>고치고 바꾸는 일은 JetBrains AI</strong></li>



<li><strong>생각하고 검토하는 일은 Gemini</strong></li>
</ul>



<p>이 구조가 <strong>IntelliJ Copilot Gemini JetBrains AI 충돌을 막는 가장 현실적인 해답</strong>입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ Copilot Gemini JetBrains AI 충돌 없는 최종 설정 체크리스트</h2>



<h3 class="wp-block-heading">✅ 인라인 자동완성 (반드시 1개만)</h3>



<ul class="wp-block-list">
<li>Copilot 인라인: <strong>ON</strong></li>



<li>JetBrains AI Cloud completion: <strong>OFF</strong></li>



<li>Gemini 인라인 / Next Edit: <strong>OFF</strong></li>
</ul>



<h3 class="wp-block-heading">✅ 멀티파일 수정</h3>



<ul class="wp-block-list">
<li>JetBrains AI <strong>단독</strong></li>
</ul>



<h3 class="wp-block-heading">✅ 단축키</h3>



<ul class="wp-block-list">
<li>Alt+Enter: IntelliJ Quick Fix 유지</li>



<li>AI 액션은 별도 키로 분리</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">IntelliJ Copilot Gemini JetBrains AI 충돌 증상별 빠른 트러블슈팅</h2>



<h3 class="wp-block-heading">❓ Tab 누르면 엉뚱한 코드가 들어간다</h3>



<ul class="wp-block-list">
<li>원인: 인라인 자동완성 2개 이상</li>



<li>해결: <strong>Copilot만 남기고 전부 OFF</strong></li>
</ul>



<h3 class="wp-block-heading">❓ IDE가 갑자기 무거워졌다</h3>



<ul class="wp-block-list">
<li>원인: 인라인 + 채팅 + 에이전트 동시 사용</li>



<li>해결: 인라인 1개 + 채팅은 필요할 때만</li>
</ul>



<h3 class="wp-block-heading">❓ 어떤 날은 Copilot, 어떤 날은 Gemini만 반응</h3>



<ul class="wp-block-list">
<li>원인: 업데이트 후 설정 재활성화</li>



<li>해결: <strong>Inline Completion 설정부터 확인</strong></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>즉, IntelliJ에서 AI를 여러 개 쓰는 문제는<br><strong>“AI 성능”이 아니라 “단축키 충돌 관리”의 문제</strong>입니다.</p>
</blockquote>



<h2 class="wp-block-heading">결론</h2>



<p><strong>IntelliJ Copilot Gemini JetBrains AI 충돌의 정답은<br>“누가 더 똑똑한가”가 아니라<br>“역할을 어떻게 나눴는가”입니다.</strong></p>



<p>👉 <strong>대규모 수정은 JetBrains AI,<br>👉 실시간 타이핑은 Copilot —<br>이 분업화 전략이 가장 안정적입니다.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>
<p>게시물 <a href="https://lindarex-career-insight.com/intellij-copilot-gemini-jetbrains-ai-conflict/">IntelliJ AI 충돌 해결: Copilot·Gemini·JetBrains AI 분업화 전략</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spring AI MCP 실습: Phase 0~3 로그 기반 실제 오류 정리</title>
		<link>https://lindarex-career-insight.com/spring-ai-mcp-lab/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Mon, 02 Feb 2026 03:39:44 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[H2]]></category>
		<category><![CDATA[Java 17]]></category>
		<category><![CDATA[Java 21]]></category>
		<category><![CDATA[MCP]]></category>
		<category><![CDATA[MCP Inspector]]></category>
		<category><![CDATA[Model Context Protocol]]></category>
		<category><![CDATA[Redis]]></category>
		<category><![CDATA[Spring AI]]></category>
		<category><![CDATA[Spring Profile]]></category>
		<category><![CDATA[STDIO]]></category>
		<category><![CDATA[Streamable HTTP]]></category>
		<category><![CDATA[개발자]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=844</guid>

					<description><![CDATA[<p>Spring AI MCP 실습: Phase 0~3에서 실제로 터진 오류와 검증 기반 해결 정리 Spring AI MCP 실습 과정에서 Phase 0~3까지 진행 중 실제로 터진 오류를 로그 기반으로 정리했습니다. Spring AI M…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/spring-ai-mcp-lab/">Spring AI MCP 실습: Phase 0~3 로그 기반 실제 오류 정리</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading">Spring AI MCP 실습: Phase 0~3에서 실제로 터진 오류와 검증 기반 해결 정리</h1>



<p>Spring AI MCP 실습 과정에서 Phase 0~3까지 진행 중 실제로 터진 오류를 로그 기반으로 정리했습니다.</p>



<p><strong>Spring AI MCP 실습</strong>을 하다 보면, 단순한 “Hello World”를 넘어서 실제 운영 환경에 가까운 구조를 만들 때 예상보다 많은 문제를 만나게 됩니다.</p>



<p>특히 다음과 같은 상황은 문서만 보고는 판단하기 어렵습니다.</p>



<ul class="wp-block-list">
<li>STDIO 방식에서 JSON 파싱 오류가 연쇄적으로 발생하는 경우</li>



<li>Phase별로 분리했다고 생각했는데, 다른 Phase의 Bean이 섞여 올라오는 문제</li>



<li>Java 빌드 버전과 런타임 버전 불일치로 인한 즉시 종료</li>



<li>MCP Inspector에서는 연결되는데 실제 Tool 호출이 실패하는 경우</li>
</ul>



<p>이 글은 이론 정리나 공식 문서 요약이 아닙니다. 실제 MCP 실습 과정에서 <strong>직접 발생한 오류 로그와 그에 대한 검증 결과</strong>를 바탕으로, 어디서 왜 막히는지와 어떤 기준으로 다음 Phase로 넘어가야 하는지를 <strong>Phase 0부터 Phase 3까지 누락 없이</strong> 정리한 기록입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 환경 &amp; 전제 (검증 기준)</h2>



<p>아래 환경에서 직접 실행해 실패/성공을 재현했습니다.</p>



<ul class="wp-block-list">
<li>운영체제: Windows 11</li>



<li>IDE: IntelliJ IDEA</li>



<li>빌드 도구: Gradle</li>



<li>프레임워크: Spring Boot + Spring AI MCP</li>



<li>Java 런타임: 기본 PATH는 Java 17, 일부 시점에서 Java 21로 빌드된 Jar 실행 시도</li>



<li>MCP 테스트 도구: MCP Inspector(UI + Proxy), IntelliJ HTTP Request</li>
</ul>



<p><strong>중요한 전제</strong></p>



<ul class="wp-block-list">
<li><strong>Phase별 실행은 서로 완전히 독립적</strong>이어야 합니다.</li>



<li>한 Phase에서 문제가 발생하면 <strong>다음 Phase로 진행하지 않는 것이 원칙</strong>입니다.</li>
</ul>



<p>이 기준을 지키지 않으면, 이후 문제의 원인이 현재 Phase인지 이전 Phase 잔재인지 구분할 수 없게 됩니다.</p>



<h3 class="wp-block-heading">실습 소스 코드 기준</h3>



<p>이 글에서 다루는 모든 Phase(0~3)는 실제 실행 및 오류 재현이 가능하도록 구성된 실습 코드를 기준으로 검증되었습니다.</p>



<p>실습 저장소: <a href="https://github.com/rexx4314/rex-mcp-lab" target="_blank" rel="noreferrer noopener">https://github.com/rexx4314/rex-mcp-lab</a></p>



<p>추가 자료나 다른 글은 블로그 홈에서 확인하실 수 있습니다: <a href="/">Tech &gt; Guides 전체 보기</a></p>



<p>해당 저장소에는 Phase별 프로파일 분리 구조, MCP Tool 등록 방식, Streamable HTTP/STDIO 실험 환경, DB/Redis/Sandbox/Git 연계 예제 등이 포함됩니다. 이 글은 저장소의 코드를 그대로 설명하는 문서가 아니라, 실행 과정에서 실제로 발생한 오류와 원인을 로그 기준으로 정리한 기록입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 Phase 0 — 최소 MCP 서버 검증 (가장 중요)</h2>



<p><strong>목적</strong></p>



<ul class="wp-block-list">
<li>MCP 서버가 정상 기동</li>



<li>Inspector에서 tools/list 노출</li>



<li>Tool 호출 시 정상 JSON 응답</li>
</ul>



<p><strong>여기서 막히면 Phase 1~3은 진행하지 않는 것이 맞습니다.</strong> 프로토콜/등록/환경 쪽 문제일 때가 많습니다.</p>



<div class="wp-block-group phase-card is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">✅ Phase 0 요약 카드</h3>



<p><strong>핵심 검증</strong>: Inspector 연결 성공 → tools/list에서 echo/health 등 확인 → 각 Tool 호출 시 즉시 JSON 응답</p>



<p><strong>여기서 막히면</strong>: Phase 1~3 진행 ❌ (등록/프로토콜/환경 문제 가능성)</p>
</div>



<p>이 글은 <strong>Spring AI MCP 실습</strong> 과정에서 실제로 겪은 실패 지점을 기준으로, 다음 Phase로 넘어가기 전 무엇을 확인해야 하는지에 초점을 둡니다.</p>



<h3 class="wp-block-heading">Spring AI MCP 실습 실행 및 확인 절차</h3>



<h4 class="wp-block-heading">실행 명령어 (재현용)</h4>



<pre class="wp-block-code"><code># 공통 빌드
./gradlew clean build

# bootJar 생성
./gradlew clean bootJar

# MCP Inspector 실행
npx @modelcontextprotocol/inspector</code></pre>



<p>위 명령어는 재현을 위한 최소 세트이며, 
실습의 핵심은 명령 실행 자체보다 <strong>Inspector에서 tools/list와 Tool 호출이 성공하는지 여부</strong>입니다.</p>



<ul class="wp-block-list">
<li>Gradle로 bootJar 생성</li>



<li>MCP Inspector 실행</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="479" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-cli-startup-1024x479.png" alt="PowerShell에서 npx @modelcontextprotocol/inspector 명령어를 실행한 화면. 
MCP Inspector가 로컬 포트에서 UI와 Proxy를 함께 기동했음을 로그로 확인할 수 있다." class="wp-image-845" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-cli-startup-1024x479.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-cli-startup-300x140.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-cli-startup-768x359.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-cli-startup.png 1303w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="481" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-initial-ui-1024x481.png" alt="Spring AI MCP 실습에서 MCP Inspector 초기 화면. Transport Type, Command, Arguments 입력 영역이 보이며 서버 연결 전 상태를 나타낸다." class="wp-image-846" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-initial-ui-1024x481.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-initial-ui-300x141.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-initial-ui-768x361.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-initial-ui-1536x721.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-initial-ui.png 1915w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li>Transport를 STDIO 또는 Streamable HTTP 중 하나로 선택</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="485" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-before-list-tools-1024x485.png" alt="MCP Inspector에서 서버에 연결된 상태의 메인 화면. 
상단 메뉴에 Resources, Prompts, Tools 탭이 있으며, 
아직 tools/list 호출 전 상태이다." class="wp-image-847" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-before-list-tools-1024x485.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-before-list-tools-300x142.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-before-list-tools-768x364.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-before-list-tools-1536x728.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-before-list-tools.png 1917w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li>서버 연결 후 tools/list 확인</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="485" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tools-list-1024x485.png" alt="Spring AI MCP 실습에서 MCP Inspector의 tools/list 호출 결과 화면. health, echo, getTimeUtc 도구가 정상 노출되어 MCP 서버 Tool 등록이 올바름을 확인한다." class="wp-image-848" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tools-list-1024x485.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tools-list-300x142.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tools-list-768x364.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tools-list-1536x728.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tools-list.png 1914w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="482" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-health-1024x482.png" alt="Spring AI MCP 실습에서 health 도구 실행 결과 화면. 서버 상태가 정상이며 JSON 응답이 반환되는지 확인한다." class="wp-image-849" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-health-1024x482.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-health-300x141.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-health-768x362.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-health-1536x723.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-health.png 1916w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="484" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-echo-1024x484.png" alt="MCP Inspector에서 echo 도구를 실행한 화면. 
입력한 문자열이 그대로 반환되어 MCP Tool 호출이 정상 동작함을 확인한다." class="wp-image-850" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-echo-1024x484.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-echo-300x142.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-echo-768x363.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-echo-1536x726.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-echo.png 1916w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="483" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-gettimeutc-1024x483.png" alt="MCP Inspector에서 getTimeUtc 도구 실행 결과. 
UTC 기준 현재 시간이 JSON 응답으로 반환된다." class="wp-image-851" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-gettimeutc-1024x483.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-gettimeutc-300x142.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-gettimeutc-768x363.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-gettimeutc-1536x725.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/mcp-inspector-tool-gettimeutc.png 1919w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">실제 발생한 오류와 검증된 원인</h3>



<h4 class="wp-block-heading">1) STDIO JSON 파싱 오류 대량 발생</h4>



<p><strong>증상</strong>: Unexpected token / not valid JSON 오류가 반복 출력</p>



<p><strong>원인(검증됨)</strong>: STDIO transport는 표준 출력에 MCP JSON만 있어야 하는데, Spring Boot 로그가 stdout으로 섞여 들어가면서 Node MCP SDK가 파싱에 실패합니다.</p>



<p><strong>결론</strong>: 실습 단계에서는 <strong>Streamable HTTP 방식이 훨씬 안정적</strong>입니다. STDIO는 로그 분리/비활성화 등 추가 설정이 없으면 추천하기 어렵습니다.</p>



<h4 class="wp-block-heading">2) Jar 실행 경로 오류</h4>



<p><strong>증상</strong>: Unable to access jarfile …</p>



<p><strong>원인</strong>: build/libs 경로 누락 또는 상대 경로 기준 혼동</p>



<p><strong>검증 결과</strong>: 절대 경로 또는 정확한 build/libs 경로를 사용하면 즉시 해결됩니다.</p>



<h4 class="wp-block-heading">3) Java 버전 불일치 오류</h4>



<p><strong>증상</strong>: UnsupportedClassVersionError (예: class file version 65.0 vs runtime 61.0)</p>



<p><strong>원인</strong>: Java 21로 빌드된 Jar를 Java 17 런타임으로 실행</p>



<p><strong>해결 선택지</strong>: (1) 빌드 버전을 17로 낮추거나 (2) 런타임 Java를 21로 맞춥니다. 실습 속도 기준으로는 <strong>Java 17 통일이 가장 빠른 선택</strong>인 경우가 많습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 Phase 1~3 실행 요약 (공통)</h2>



<p>Phase 0이 정상적으로 통과되었다면, 
이제 Phase 1~3은 아래 명령어로 각각 실행해 검증할 수 있습니다.
각 Phase는 서로 독립적으로 실행해야 하며, 동시에 띄우지 않는 것이 원칙입니다.</p>



<pre class="wp-block-code"><code># Phase 1
./gradlew bootRun --args="--spring.profiles.active=phase1"

# Phase 2
./gradlew bootRun --args="--spring.profiles.active=phase2"

# Phase 3
./gradlew bootRun --args="--spring.profiles.active=phase3"</code></pre>



<p>각 Phase 실행 시 서버 포트, 활성 프로파일, Inspector 연결 대상이 서로 일치하는지
반드시 로그로 확인한 뒤 다음 Phase로 넘어가야 합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 Phase 1 — 내부 HTTP 호출 Tool 검증</h2>



<div class="wp-block-group phase-card is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">✅ Phase 1 요약 카드</h3>



<p><strong>목적</strong>: MCP Tool → 내부 HTTP API 호출 구조 검증(정상/지연/실패 전파)</p>



<p><strong>자주 발생</strong>: Connection refused(포트 혼선), 404(컨트롤러 없음)</p>
</div>



<p><strong>목적</strong>: MCP Tool → 내부 HTTP API 호출 구조를 안정적으로 검증하고, 지연/실패/타임아웃 전파가 올바르게 되는지 확인합니다.</p>



<h3 class="wp-block-heading">Spring AI MCP 실습 Phase 1 실행</h3>



<p>공통 요약에서 한 번 실행했다면, Phase 1은 아래 명령으로 단독 실행 중인지 다시 확인합니다.</p>



<pre class="wp-block-code"><code>./gradlew bootRun --args="--spring.profiles.active=phase1"</code></pre>



<h3 class="wp-block-heading">Spring AI MCP 실습 실행 및 테스트 흐름</h3>



<ul class="wp-block-list">
<li>Phase 1 프로파일로 서버 실행</li>



<li>IntelliJ HTTP Request로 내부 API 직접 호출(정상/지연/실패)</li>
</ul>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="718" height="410" src="https://lindarex-career-insight.com/wp-content/uploads/2026/02/image.png" alt="IntelliJ HTTP Request로 내부 API 직접 호출(정상)" class="wp-image-856" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/02/image.png 718w, https://lindarex-career-insight.com/wp-content/uploads/2026/02/image-300x171.png 300w" sizes="auto, (max-width: 718px) 100vw, 718px" /></figure>



<ul class="wp-block-list">
<li>동일 동작을 MCP Tool로 호출</li>
</ul>



<h3 class="wp-block-heading">실제 발생 오류</h3>



<h4 class="wp-block-heading">1) Connection refused</h4>



<p><strong>원인</strong>: 기본 8080으로 요청했으나 실제 서버 포트는 3001 등으로 설정되어 있었던 케이스</p>



<p><strong>검증</strong>: server.port 값과 요청 포트를 일치시키면 즉시 해결됩니다.</p>



<h4 class="wp-block-heading">2) 404 Not Found</h4>



<p><strong>원인</strong>: 내부 API 컨트롤러/매핑 자체가 없는 상태</p>



<p><strong>중요한 판단</strong>: Phase 1은 Tool만으로 검증하기 어렵고, <strong>HTTP 엔드포인트가 반드시 존재</strong>해야 IntelliJ HTTP Request로 선검증이 가능합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 Phase 2 — DB / Redis 연계 (운영 관점 핵심)</h2>



<div class="wp-block-group phase-card is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">✅ Phase 2 요약 카드</h3>



<p><strong>목적</strong>: DB/Redis 같은 내부 리소스 접근 + 조회 제한/마스킹 같은 운영 요구사항 반영</p>



<p><strong>핵심 검증</strong>: limit 강제, 민감정보 마스킹, redis set/get 일치, 프로파일 완전 분리</p>
</div>



<p><strong>목적</strong>: “사내 리소스 접근” 단계로 넘어가며 DB/Redis 같은 내부 자원과 연결합니다. 이 단계에서는 기능 구현 자체보다도 <strong>결과 제한(예: limit 강제), 마스킹, 운영·보안 요구사항</strong>이 포함되는지 확인하는 것이 중요합니다.</p>



<h3 class="wp-block-heading">주요 검증 포인트</h3>



<ul class="wp-block-list">
<li>검색 결과 limit이 강제로 적용되는지</li>



<li>민감 정보가 마스킹되어 노출되는지</li>



<li>Redis set/get이 기대대로 일치하는지</li>
</ul>



<h3 class="wp-block-heading">실제로 가장 많이 막힌 문제</h3>



<h4 class="wp-block-heading">1) Phase 0 실행 시 Phase 2 Bean 로딩</h4>



<p><strong>증상</strong>: Phase 0으로 실행했는데 Repository bean not found 등으로 종료</p>



<p><strong>원인(확인됨)</strong>: Phase 2 Bean에 Profile 분리가 적용되지 않아 다른 Phase에서도 생성되는 구조</p>



<p><strong>결론</strong>: 모든 Phase 전용 Bean(Tools/Service/Repository/Controller/Config)은 반드시 해당 Phase 프로파일로 묶여야 합니다.</p>



<h4 class="wp-block-heading">2) data.sql 실행 오류</h4>



<p><strong>증상</strong>: Table not found</p>



<p><strong>원인</strong>: JPA 테이블 생성 이전에 data.sql이 먼저 실행되는 초기화 순서 문제</p>



<p><strong>해결 방향</strong>: (1) JPA ddl-auto 이후 실행되도록 설정하거나 (2) schema.sql / data.sql 분리 등으로 초기화 책임을 명확히 분리합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 Phase 3 — 위험 도구 통제 검증</h2>



<div class="wp-block-group phase-card is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">✅ Phase 3 요약 카드</h3>



<p><strong>목적</strong>: 파일/Git 같은 위험 도구를 “안전하게” 노출하고 통제가 올바른지 검증</p>



<p><strong>성공 기준</strong>: “작동”이 아니라 “차단”이 기대대로 되는지(화이트리스트/샌드박스/경로 차단)</p>
</div>



<p><strong>목적</strong>: Phase 3은 “되게 만드는 단계”가 아니라 <strong>안전하게 막는 단계</strong>입니다. 샌드박스, 화이트리스트, 경로 traversal 차단, 승인(approval) 같은 통제가 핵심입니다.</p>



<h3 class="wp-block-heading">핵심 검증 케이스</h3>



<ul class="wp-block-list">
<li>디렉터리 traversal(예: ../) 차단</li>



<li>허용된 파일만 접근 가능</li>



<li>허용 리스트 밖 명령은 무조건 DENY</li>



<li>Git status는 저장소(.git) 루트가 아니면 명확한 에러를 반환</li>
</ul>



<p>각 케이스는 가능하면 MCP Inspector에서 직접 호출한 결과 화면을 함께 남겨두면, 나중에 원인 분리가 훨씬 쉬워집니다.</p>



<h3 class="wp-block-heading">파일이 안 바뀐 것처럼 보이는 경우(혼동 지점)</h3>



<p>writeSandbox 같은 호출을 했는데 파일이 안 바뀐 것처럼 보이는 상황은 현업에서도 흔합니다. 이번 실습 흐름 기준으로 가장 가능성이 높은 원인은 다음 3가지였습니다.</p>



<ul class="wp-block-list">
<li><strong>서버 프로세스가 여러 개 떠 있음</strong> (IDE 실행 + jar 실행 + Inspector 재연결 등)</li>



<li><strong>Inspector가 다른 포트/다른 프로파일 서버에 붙어 있음</strong></li>



<li><strong>내가 보고 있는 파일 경로와 실제 sandbox-dir 경로가 다름</strong></li>
</ul>



<p><strong>검증 방법</strong>: 서버 로그에서 active profile 확인 → 포트 리슨 PID 하나만 남기기 → readSandbox로 “서버가 보는 내용”을 교차검증하면 원인 분리가 쉬워집니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Spring AI MCP 실습 공통 트러블슈팅 플로우 (의사결정 기준)</h2>



<p>Phase가 올라갈수록 문제가 복잡해지므로, 아래 순서를 고정하면 원인 분리가 매우 쉬워집니다.</p>



<ol class="wp-block-list">
<li>서버가 뜨는가?</li>



<li>active profile이 의도한 Phase인가?</li>



<li>tools/list가 보이는가?</li>



<li>HTTP로 먼저 검증 가능한가?</li>



<li>그 다음 MCP Tool 호출로 동일 결과가 나오는가?</li>
</ol>



<p>이 순서를 지키면 “현재 Phase 문제인지, 이전 Phase 잔재인지”를 빠르게 분리할 수 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">마무리</h2>



<p>Spring AI MCP 실습에서 가장 크게 느낀 점은 하나였습니다.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>MCP는 “되게 만드는 기술”이 아니라, 통제와 분리를 얼마나 정확히 하느냐가 핵심</strong>입니다.</p>
</blockquote>



<p>이 글이 도움이 되는 분들은 보통 아래 상황에 해당하는 경우가 많습니다.</p>



<ul class="wp-block-list">
<li>MCP / Spring AI를 실제 프로젝트에 쓰려다 막힌 경우</li>



<li>로그는 많은데 어디서부터 정리해야 할지 모르는 경우</li>



<li>다음 단계로 넘어가도 되는지 판단이 어려운 경우</li>
</ul>



<h3 class="wp-block-heading">요약</h3>



<ul class="wp-block-list">
<li>Spring AI MCP 실습기(Phase 0~3) 실제 오류 기반 정리</li>



<li>STDIO vs Streamable HTTP: 실습에서는 HTTP가 안정적인 경향</li>



<li>프로파일 분리, Java 버전 불일치, DB 초기화 순서 이슈가 대표적인 장애 포인트</li>



<li>Phase 3은 “작동”보다 “차단”이 성공 기준</li>
</ul>
<p>게시물 <a href="https://lindarex-career-insight.com/spring-ai-mcp-lab/">Spring AI MCP 실습: Phase 0~3 로그 기반 실제 오류 정리</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Windows Gemini CLI 설치 가이드: PowerShell + API 키 설정</title>
		<link>https://lindarex-career-insight.com/windows-gemini-cli-install-springboot-gradle-todo/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Thu, 29 Jan 2026 06:37:13 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Gemini CLI]]></category>
		<category><![CDATA[GEMINI_API_KEY]]></category>
		<category><![CDATA[Git Bash]]></category>
		<category><![CDATA[Google AI Studio]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[npm]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Windows 11]]></category>
		<category><![CDATA[Windows Gemini CLI 설치]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=808</guid>

					<description><![CDATA[<p>Windows Gemini CLI 설치를 Windows 11에서 직접 진행하면서, PowerShell에서 정상 동작하는지까지 검증했습니다. 이 글은 Windows Gemini CLI 설치 과정에서 자주 막히는 npm.ps1 실행 정책…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/windows-gemini-cli-install-springboot-gradle-todo/">Windows Gemini CLI 설치 가이드: PowerShell + API 키 설정</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Windows <strong>Gemini CLI 설치</strong>를 Windows 11에서 직접 진행하면서, PowerShell에서 정상 동작하는지까지 검증했습니다. 이 글은 <strong>Windows Gemini CLI 설치</strong> 과정에서 자주 막히는 <code>npm.ps1</code> 실행 정책, System32 EPERM 경고, GEMINI.md 루프, Gradle Wrapper 오류를 “증상 → 원인 → 해결 → 확인 명령”으로 정리한 실전 기록입니다.</p>



<p>설치가 끝나면 <strong>Windows Gemini CLI 설치</strong>만으로 Spring Boot + Gradle Todo REST API 데모 프로젝트를 만들고 <code>./gradlew test</code>, <code>./gradlew bootRun</code>, curl 테스트까지 한 번에 확인할 수 있습니다.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>이 글은 “정답만 요약한 설치 글”이 아니라, 실제 오류 로그 + 원인 + 해결 + 확인 명령까지 포함한 실전 기록입니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">테스트 환경</h2>



<ul class="wp-block-list">
<li><strong>OS</strong>: Windows 11 Pro</li>



<li><strong>Node.js</strong>: v24.13.0</li>



<li><strong>npm</strong>: 11.6.2</li>



<li><strong>gemini-cli</strong>: 0.25.2</li>



<li><strong>검증 날짜</strong>: 2026-01-27</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>⚠️ 버전이 다르면 증상/해결 방식이 달라질 수 있습니다. 이 글 하단 “업데이트 로그”에 변경 사항을 누적합니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">전체 진행 흐름 한눈에 보기</h2>



<ol class="wp-block-list">
<li>Windows에 Node.js 설치하기 (필수)</li>



<li>Gemini CLI 설치</li>



<li>Gemini API 키 발급 및 환경 변수 설정</li>



<li>Gemini CLI로 Spring Boot + Gradle Todo REST 프로젝트 생성</li>



<li>Gemini CLI로 코드 생성 · 수정 · 실행</li>



<li>보안 주의사항</li>



<li>REST API 동작 테스트</li>



<li>자주 묻는 질문 (FAQ)</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. Windows Gemini CLI 설치: Node.js 설치 (필수)</h2>



<p>Gemini CLI는 <strong>Node.js 기반 CLI 도구</strong>입니다.</p>



<p>따라서 Node.js가 설치되어 있지 않으면 Gemini CLI는 동작하지 않습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.1. Node.js 버전 기준</h3>



<ul class="wp-block-list">
<li><strong>최소 요구:</strong> Node.js 18 이상</li>



<li><strong>권장:</strong> 최신 LTS 버전</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>⚠️ 설치 과정에서 반드시 <strong>“Add to PATH” 옵션이 체크되어 있어야 합니다.</strong></p>



<p>이 옵션이 빠지면 설치 후 <code>node</code>, <code>npm</code> 명령이 인식되지 않습니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.2. Node.js 설치 전, 기존 설치 여부 확인</h3>



<pre class="wp-block-code"><code>node -v
npm -v</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> node -v
v24.13.0
PS C:\\Windows\\System32> npm -v
11.6.2</code></pre>



<ul class="wp-block-list">
<li>두 명령 모두 버전이 나오면 이미 설치된 상태입니다.</li>



<li><code>node -v</code>는 되는데 <code>npm -v</code>에서 오류가 난다면 → <strong>PowerShell 실행 정책 문제</strong>일 가능성이 큽니다. (아래 1.4. 참고)</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.3. Node.js 처음 설치하는 경우</h3>



<p>1.3.1. 공식 웹사이트에서 다운로드</p>



<ul class="wp-block-list">
<li><a href="https://nodejs.org/en/download" target="_blank" rel="noreferrer noopener">https://nodejs.org/en/download</a> 접속</li>



<li>&#8220;Windows Installer&#8221; 버튼 클릭하여 LTS 버전 다운로드</li>
</ul>



<p>1.3.2. Node.js 설치 파일(Installer) 실행</p>



<p>1.3.3. 설치 마법사에서 다음을 반드시 확인</p>



<h3 class="wp-block-heading">반드시 체크할 항목</h3>



<ul class="wp-block-list">
<li>✅ <strong>Add to PATH</strong></li>



<li>✅ 기본 설치 옵션 유지 (특별한 이유가 없다면 변경하지 않음)</li>
</ul>



<p>1.3.4. 설치 완료 후, <strong>열려 있던 모든 터미널 종료 및 새로 실행</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1.4. Windows Gemini CLI 설치 전: PowerShell에서 npm.ps1 실행 오류 해결</h3>



<ul class="wp-block-list">
<li><strong>PowerShell 실행 정책(Execution Policy)</strong> 때문이며, Node.js나 npm 설치 자체의 문제는 아닙니다.</li>
</ul>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> node -v
v24.13.0
PS C:\\Windows\\System32> npm -v
npm : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\\Program Files\\nodejs\\npm.ps1 파일을 로드할 수 없습니다. 자세한 내용은 about_Executio
n_Policies(&lt;https://go.microsoft.com/fwlink/?LinkID=135170>)를 참조하십시오.
위치 줄:1 문자:1
+ npm -v
+ ~~~
    + CategoryInfo          : 보안 오류: (:) &#91;], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess</code></pre>



<ul class="wp-block-list">
<li>아래와 같은 오류가 발생할 수 있습니다.
<ul class="wp-block-list">
<li><code>npm.ps1 파일을 로드할 수 없습니다</code></li>



<li><code>이 시스템에서 스크립트를 실행할 수 없습니다</code></li>



<li><code>PSSecurityException</code></li>
</ul>
</li>



<li>해결
<ul class="wp-block-list">
<li>PowerShell을 “관리자 권한”으로 실행한 뒤, 아래 명령을 실행하세요.</li>
</ul>
</li>
</ul>



<pre class="wp-block-code"><code>Set-ExecutionPolicy RemoteSigned -Scope CurrentUser</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\system32> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

실행 규칙 변경
실행 정책은 신뢰하지 않는 스크립트로부터 사용자를 보호합니다. 실행 정책을 변경하면 about_Execution_Policies 도움말
항목(&lt;https://go.microsoft.com/fwlink/?LinkID=135170>)에 설명된 보안 위험에 노출될 수 있습니다. 실행 정책을 변경하시겠습니까?
&#91;Y] 예(Y)  &#91;A] 모두 예(A)  &#91;N] 아니요(N)  &#91;L] 모두 아니요(L)  &#91;S] 일시 중단(S)  &#91;?] 도움말 (기본값은 "N"): A</code></pre>



<ul class="wp-block-list">
<li>Node.js 설치 여부 확인</li>
</ul>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> node -v
v24.13.0
PS C:\\Windows\\System32> npm -v
11.6.2</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. Windows Gemini CLI 설치: Windows용 Gemini CLI 설치</h2>



<p>Gemini CLI는 npm 전역 패키지로 설치합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.1. Gemini CLI 설치</h3>



<pre class="wp-block-code"><code>npm install -g @google/gemini-cli</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> npm install -g @google/gemini-cli
npm warn deprecated node-domexception@1.0.0: Use your platform's native DOMException instead

added 615 packages in 31s

166 packages are looking for funding
  run `npm fund` for details
npm notice
npm notice New minor version of npm available! 11.6.2 -> 11.8.0
npm notice Changelog: &lt;https://github.com/npm/cli/releases/tag/v11.8.0>
npm notice To update run: npm install -g npm@11.8.0
npm notice</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2.2. 설치 확인</h3>



<pre class="wp-block-code"><code>gemini --version
Get-Command gemini | Format-List CommandType,Source,Name</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> gemini --version
0.25.2
PS C:\\Windows\\System32> Get-Command gemini | Format-List CommandType,Source,Name

CommandType : ExternalScript
Source      : C:\\Users\\rexjo\\AppData\\Roaming\\npm\\gemini.ps1
Name        : gemini.ps1</code></pre>



<ul class="wp-block-list">
<li>버전이 출력되고 실행 경로가 확인되면, 설치는 정상적으로 완료된 상태입니다.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. Windows Gemini CLI 설치 후 기본 실행/사용법</h2>



<h3 class="wp-block-heading">3.1. 대화형 실행</h3>



<pre class="wp-block-code"><code>gemini</code></pre>



<p>최초 실행 시 Google 계정 인증이 진행될 수 있습니다.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="446" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-first-run-google-login-1024x446.png" alt="Windows에서 Gemini CLI 최초 실행 시  화면" class="wp-image-809" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-first-run-google-login-1024x446.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-first-run-google-login-300x131.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-first-run-google-login-768x334.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-first-run-google-login.png 1268w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.2. 단일 프롬프트 실행</h3>



<pre class="wp-block-code"><code>gemini "안녕하세요. REX 테스트입니다."</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> gemini "안녕하세요. REX 테스트입니다."
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\config (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\config')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\Configuration (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\Configuration')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\DriverState (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\DriverState')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\ias (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\ias')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\MsDtc (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\MsDtc')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\networklist (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\networklist')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\SleepStudy (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\SleepStudy')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\sru (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\sru')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\Tasks (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\Tasks')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\WebThreatDefSvc (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\WebThreatDefSvc')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\WDI (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\WDI')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\Com\\dmp (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\Com\\dmp')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\drivers\\DriverData (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\drivers\\DriverData')
Loaded cached credentials.
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\config (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\config')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\Configuration (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\Configuration')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\DriverState (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\DriverState')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\ias (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\ias')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\MsDtc (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\MsDtc')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\networklist (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\networklist')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\SleepStudy (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\SleepStudy')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\sru (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\sru')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\Tasks (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\Tasks')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\WDI (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\WDI')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\WebThreatDefSvc (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\WebThreatDefSvc')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\Com\\dmp (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\Com\\dmp')
&#91;WARN] Skipping unreadable directory: C:\\Windows\\System32\\drivers\\DriverData (EPERM: operation not permitted, scandir 'C:\\Windows\\System32\\drivers\\DriverData')
안녕하세요. REX 테스트님. 설정이 완료되었습니다. 다음 명령을 기다리겠습니다.</code></pre>



<ul class="wp-block-list">
<li>위 로그는 짧은 문장에 대한 응답(마지막 줄)이 나왔기 때문에 정상입니다.
<ul class="wp-block-list">
<li>권한 경고(EPERM)는 현재 작업 디렉터리가 C:\Windows\System32라서 발생</li>
</ul>
</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.3. 작업 폴더를 “내 프로젝트 폴더”로 옮기기 (권한 경고 방지)</h3>



<pre class="wp-block-code"><code>cd $env:USERPROFILE
mkdir work
cd work
gemini "안녕! REX 테스트 2!"</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> cd $env:USERPROFILE
PS C:\\Users\\rexjo> mkdir work

    디렉터리: C:\\Users\\rexjo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----      2026-01-27   오후 1:59                work

PS C:\\Users\\rexjo> cd work
PS C:\\Users\\rexjo\\work> gemini "안녕! REX 테스트 2!"
Loaded cached credentials.
안녕하세요! 렉스 테스트 2를 시작하는 데 어떤 도움을 드릴까요?</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3.4. Gemini CLI에서 자주 쓰는 핵심 기능</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>기능</th><th>설명</th></tr></thead><tbody><tr><td><code>/init</code></td><td>현재 디렉터리에 <strong>GEMINI.md 생성</strong>. 프로젝트 맥락을 정의할 때 최초 1회만 사용하는 것이 좋습니다.</td></tr><tr><td><code>@파일경로</code></td><td>파일·폴더를 프롬프트에 첨부. <strong>기존 코드 맥락을 정확히 인식시키고 싶을 때 필수</strong>입니다.</td></tr><tr><td><code>!명령어</code></td><td>Gemini CLI 내부에서 실제 쉘 명령 실행. 파일 생성, Gradle 실행 등 <strong>실제 작업을 시킬 때 사용</strong>합니다.</td></tr><tr><td><code>/help</code></td><td>사용 가능한 명령 확인. 동작이 헷갈릴 때 빠르게 참고용으로 확인합니다.</td></tr></tbody></table></figure>



<p>이 중에서 실무에서 가장 많이 쓰는 것은 /init, @파일경로, !명령어 세 가지입니다. 특히 !명령어를 사용하지 않으면 실제 파일 생성이나 빌드 실행이 되지 않습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. Windows Gemini CLI 설치: API 키 설정 (GEMINI_API_KEY)</h2>



<p>Gemini CLI는 로그인 방식도 가능하지만,</p>



<p><strong>API 기반 개발 및 안정적인 사용을 위해 API 키 설정을 권장</strong>합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.1. Google AI Studio에서 API 키 발급하기</h3>



<p>4.1.1. Google AI Studio에 접속 후 Google 계정으로 로그인</p>



<ul class="wp-block-list">
<li><a href="https://aistudio.google.com/app/api-keys" target="_blank" rel="noreferrer noopener">https://aistudio.google.com/app/api-keys</a></li>
</ul>



<p>4.1.2. “API 키” 또는 “Get API key” 관련 메뉴로 이동</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="407" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-menu-1024x407.png" alt="Google AI Studio에서 Gemini API 키 발급 페이지" class="wp-image-810" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-menu-1024x407.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-menu-300x119.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-menu-768x305.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-menu.png 1470w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>4.1.3. 프로젝트가 없다면 새 프로젝트 생성</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="484" height="199" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-create-project.png" alt="Google AI Studio에서 프로젝트 생성 단계" class="wp-image-811" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-create-project.png 484w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-create-project-300x123.png 300w" sizes="auto, (max-width: 484px) 100vw, 484px" /></figure>



<p>4.1.4. API 키를 관리할 프로젝트를 선택</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="488" height="254" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-create-api-key.png" alt="Google AI Studio에서 프로젝트 선택 후 API 키 생성 단계" class="wp-image-812" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-create-api-key.png 488w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-create-api-key-300x156.png 300w" sizes="auto, (max-width: 488px) 100vw, 488px" /></figure>



<p>4.1.5. 키 만들기 버튼 클릭</p>



<ul class="wp-block-list">
<li>생성된 API 키 문자열을 <strong>즉시 복사해 안전하게 보관</strong>합니다.</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="240" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-1024x240.png" alt="Google AI Studio에서 API 키 조회" class="wp-image-813" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-1024x240.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-300x70.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key-768x180.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/google-ai-studio-api-key.png 1457w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>AIzaSy***</p>
</blockquote>



<h3 class="wp-block-heading">⚠️ 매우 중요</h3>



<ul class="wp-block-list">
<li>API 키는 <strong>비밀번호와 동일한 수준의 민감 정보</strong>입니다.</li>



<li>코드, 깃 저장소, 블로그, 스크린샷에 노출하지 마십시오.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.2. Windows 환경 변수 설정</h3>



<ul class="wp-block-list">
<li>현재 사용자 기준 (권장)</li>
</ul>



<pre class="wp-block-code"><code>setx GEMINI_API_KEY "발급받은_API_키"</code></pre>



<pre class="wp-block-code"><code>PS C:\\Users\\rexjo\\work> setx GEMINI_API_KEY "AIzaSy*******************************"

성공: 지정한 값을 저장했습니다.</code></pre>



<ul class="wp-block-list">
<li>시스템 전체 (관리자 권한 필요)</li>
</ul>



<pre class="wp-block-code"><code>setx GEMINI_API_KEY "발급받은_API_키" /m</code></pre>



<pre class="wp-block-code"><code>## 관리자 권한이 없을 경우, 오류 발생
PS C:\\Users\\rexjo\\work> setx GEMINI_API_KEY "AIzaSy*******************************" /m
오류: 레지스트리 경로 액세스가 거부되었습니다.</code></pre>



<pre class="wp-block-code"><code>## 정상 처리
PS C:\\Windows\\system32> setx GEMINI_API_KEY "AIzaSy*******************************" /m

성공: 지정한 값을 저장했습니다.</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>설정 후 반드시 새 터미널을 열어야 반영됩니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4.3. 환경 변수 확인</h3>



<pre class="wp-block-code"><code>echo $env:GEMINI_API_KEY</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> echo $env:GEMINI_API_KEY
AIzaSy*******************************</code></pre>



<ul class="wp-block-list">
<li>값이 출력되면 정상입니다.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. Windows Gemini CLI 설치 후 Spring Boot + Gradle Todo 프로젝트 만들기</h2>



<p>이제부터는 <strong>IDE 없이</strong>, <strong>Gemini CLI만 사용</strong>해 프로젝트를 생성합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.1. 프로젝트 디렉터리 생성</h3>



<pre class="wp-block-code"><code>cd $env:USERPROFILE
mkdir todo-demo
cd todo-demo</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32&gt; cd $env:USERPROFILE
PS C:\\Users\\rexjo&gt; mkdir todo-demo

    디렉터리: C:\\Users\\rexjo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----      2026-01-27   오후 2:54                todo-demo

PS C:\\Users\\rexjo&gt; cd todo-demo
PS C:\\Users\\rexjo\\todo-demo&gt;
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.2. Gemini CLI 실행 및 프로젝트 맥락 정의</h3>



<p>5.2.1 Gemini CLI 대화형 실행</p>



<pre class="wp-block-code"><code>gemini</code></pre>



<p>5.2.2. 현재 디렉터리에 <strong>GEMINI.md 생성</strong></p>



<pre class="wp-block-code"><code>/init</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="946" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-md-init-1024x946.png" alt="Windows 환경의 Gemini CLI에서 /init 명령으로 GEMINI.md 생성" class="wp-image-814" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-md-init-1024x946.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-md-init-300x277.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-md-init-768x709.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-md-init.png 1255w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>5.2.3. 프로젝트 맥락 정의 실행</p>



<pre class="wp-block-code"><code>너는 Spring Boot + Gradle 기반 Todo List REST API 데모 프로젝트를 만드는 코딩 에이전트다.

요구사항:
- Java 21
- Spring Boot 3.x
- Gradle
- 의존성: Spring Web, Spring Data JPA, H2
- Todo CRUD API 제공
- POST /api/todos
- GET /api/todos
- PATCH /api/todos/{id}
- DELETE /api/todos/{id}
- H2 in-memory DB, /h2-console 활성화
- Windows에서 ./gradlew bootRun 가능</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.3. Gemini CLI로 Spring Boot 프로젝트 생성</h3>



<pre class="wp-block-code"><code>이제 실제 Spring Boot 프로젝트를 생성하자.

조건:
- Java 21
- Spring Boot 3.x
- Gradle
- Group: com.example
- Artifact: todo-demo
- Package: com.example.todo
- Dependencies:
  - Spring Web
  - Spring Data JPA
  - H2

요구사항:
- 현재 디렉터리에 todo-demo 프로젝트를 생성할 것
- Spring Initializr ZIP을 내려받아 압축 해제할 것
- PowerShell 환경에서 Invoke-WebRequest + Expand-Archive 방식 사용
- 생성이 끝나면 어떤 파일이 만들어졌는지 요약해 줄 것

실제 파일 생성이 필요하니,
필요한 경우 !powershell 명령을 사용해서 직접 실행해라.</code></pre>



<ul class="wp-block-list">
<li>loop 발생 시, 아래 6.3. 참고</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="795" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-loop-break-example-1024x795.png" alt="Windows 환경의 Gemini CLI에서 GEMINI.md 반복 루프 발생" class="wp-image-815" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-loop-break-example-1024x795.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-loop-break-example-300x233.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-loop-break-example-768x596.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-loop-break-example.png 1257w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>→ 관련 내용은 <a href="#fix-gemini-error" type="internal" id="#fix-gemini-error">실전 실패 로그 모음</a>에서 이어집니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5.4. Todo 코드 생성 요청</h3>



<pre class="wp-block-code"><code>이제 Todo List REST API 코드를 실제로 구현해줘. (IDE 없이, 실제 파일을 생성/수정해야 함)

전제:
- 현재 작업 디렉터리는 Spring Boot + Gradle 프로젝트 루트(todo-demo)다.
- Java 21, Spring Boot 3.x, Gradle
- 의존성: Spring Web, Spring Data JPA, H2
- H2 in-memory DB, /h2-console 활성화
- Windows에서 ./gradlew bootRun 가능해야 함

해야 할 일(반드시 순서대로):
1) application.yml 생성/수정
- H2 in-memory 설정
- h2-console enabled, path: /h2-console
- JPA ddl-auto: update
- server.port: 8080

2) 패키지/클래스 생성 (패키지: com.example.todo.todo)
- Todo 엔티티
  - id: Long (자동 생성)
  - title: String (not null)
  - completed: boolean (default false)
  - createdAt: Instant (생성 시 now, not null)
- TodoRepository (JpaRepository&lt;Todo, Long>)
- TodoService
  - List&lt;Todo> findAll()
  - Todo create(String title)
  - Todo updateTitle(Long id, String title)  (선택: title 수정도 지원)
  - Todo setCompleted(Long id, boolean completed)
  - void delete(Long id)
- TodoController
  - POST /api/todos  { "title": "..." }  -> 201 Created
  - GET  /api/todos  -> 200 OK
  - PATCH /api/todos/{id} { "completed": true/false, "title": "..."(선택) } -> 200 OK
  - DELETE /api/todos/{id} -> 204 No Content

3) 예외 처리(최소)
- title이 비어있으면 400 Bad Request
- id를 못 찾으면 404 Not Found
- 에러 응답은 JSON으로 (message 필드 포함)

4) 실제로 파일을 만들고/고치고 난 뒤,
- 생성/수정한 파일 목록을 보여줘
- 그리고 아래 명령을 CLI에서 실행해 빌드/실행 검증까지 해줘:
  - !./gradlew test
  - !./gradlew bootRun

5) 실행이 성공하면, 내가 바로 테스트할 수 있게 curl 명령을 출력해줘.
- 생성/목록/완료처리/삭제 4개 모두

주의사항:
- GEMINI.md는 더 이상 반복해서 읽거나 수정하지 마.
- 지금은 코드 파일 생성과 실행 검증이 목표야.
- 필요한 경우 ! 명령으로 파일 생성/수정(예: heredoc/echo)과 Gradle 실행을 직접 수행해.
- 모든 변경은 프로젝트 루트(todo-demo) 기준 경로로 적용해.</code></pre>



<ul class="wp-block-list">
<li>wrapper 누락 오류 시
<ul class="wp-block-list">
<li>Gemini CLI로 누락 오류 해결 요청 또는 아래 6.4. 참고</li>
</ul>
</li>
</ul>



<pre class="wp-block-code"><code>현재 프로젝트(C:\\Users\\rexjo\\todo-demo\\todo-demo)에서 Gradle Wrapper가 깨졌습니다.
상태:
- gradle/wrapper/gradle-wrapper.properties는 존재
- gradle/wrapper/gradle-wrapper.jar는 존재하지만 잘못된 jar로 보이며
  `.\\gradlew.bat --version` 실행 시
  `NoClassDefFoundError: org/gradle/wrapper/IDownload`가 발생합니다.

요구사항:
1) "배포판 ZIP에서 gradle-wrapper.jar를 찾아 복사" 같은 방식은 금지합니다.
2) 반드시 정석대로 wrapper를 재생성하세요:
   - 임시 폴더에 gradle-8.5-bin.zip 다운로드
   - 압축 해제
   - 압축 해제한 Gradle의 bin/gradle.bat로 이 프로젝트 루트에서 아래 명령 실행:
     gradle.bat wrapper --gradle-version 8.5 --distribution-type bin
3) 실행 전 꼬임 방지를 위해 아래 파일들을 삭제 후 재생성하세요:
   - gradle/wrapper/gradle-wrapper.jar
   - gradlew
   - gradlew.bat
4) 완료 후 아래 검증 명령이 모두 성공해야 합니다:
   - dir gradle\\wrapper\\
   - .\\gradlew.bat --version
   - .\\gradlew.bat clean build -x test --stacktrace

출력:
- 수행한 명령 로그
- 생성된 파일 목록
- .\\gradlew.bat --version 출력 결과</code></pre>



<ul class="wp-block-list">
<li>wrapper 누락 오류 해결 후, 정상 개발 모드로 전환하라고 지시</li>
</ul>



<pre class="wp-block-code"><code>이제 Gradle Wrapper는 정상입니다.

개발 모드로 전환하세요.
규칙:
- 코드 수정 후 반드시 gradle 명령으로 검증
- 실패 시 로그를 읽고 원인 분석 후 수정
- 불필요한 파일 생성/삭제 금지

첫 단계:
1) 프로젝트가 정상 빌드되는지 확인
   실행: .\\gradlew.bat clean build -x test
2) 빌드가 성공하면 테스트 실행
   실행: .\\gradlew.bat test
3) 테스트 실패 시 원인 분석 후 수정</code></pre>



<ul class="wp-block-list">
<li>Gemini CLI에 “할 일(To-do)”을 주는 법</li>
</ul>



<pre class="wp-block-code"><code>예시 1: API 추가
Todo API에 완료 처리 엔드포인트를 추가하세요.

요구사항:
- PUT /todos/{id}/complete
- 완료 여부(boolean completed) 저장
- 테스트 코드 추가
- gradle test 통과까지 진행

예시 2: 리팩토링
TodoService의 비즈니스 로직을 분리하세요.
- 중복 제거
- 예외는 GlobalExceptionHandler로 통합
- 테스트 유지</code></pre>



<ul class="wp-block-list">
<li>Gemini CLI에 !명령어 기능으로 빌드 및 실행하기</li>
</ul>



<pre class="wp-block-code"><code>!./gradlew test
!./gradlew bootRun</code></pre>



<ul class="wp-block-list">
<li>Gemini CLI에 줄 한 방 지시문</li>
</ul>



<pre class="wp-block-code"><code>다음 순서로 작업을 진행하세요.

1) 프로젝트 실행
   - 명령: .\\gradlew.bat bootRun
   - 서버가 정상 기동될 때까지 대기
   - 실행 로그에서 포트 번호 확인 (기본 8080)

2) 실행 상태 확인 후 curl 테스트 수행
   - GET &lt;http://localhost:8080>
   - 만약 404면, 사용 가능한 엔드포인트 목록을 로그/코드에서 확인

3) Todo 관련 API가 있으면 curl 테스트 수행
   예시:
   - GET &lt;http://localhost:8080/todos>
   - POST &lt;http://localhost:8080/todos>
     Body: { "title": "test todo" }

4) curl 결과(요청/응답)를 그대로 출력

5) 이후 자동 테스트 실행
   - 명령: .\\gradlew.bat test
   - 실패 시 로그 분석 후 수정</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Gemini CLI로 빌드 및 실행부터 curl 테스트까지 모든 명령을 실행할 수 있습니다.</p>
</blockquote>



<ul class="wp-block-list">
<li>Gemini 종료 후 사용량 확인</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="945" height="561" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-model-usage.png" alt="Windows 환경의 Gemini CLI에서 Gemini 종료 후 사용량 확인 결과" class="wp-image-816" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-model-usage.png 945w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-model-usage-300x178.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-gemini-model-usage-768x456.png 768w" sizes="auto, (max-width: 945px) 100vw, 945px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="fix-gemini-error">6. Windows Gemini CLI 설치 중 실전 실패 로그 모음 (재현 가능)</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>이 섹션은 직접 설치·실행 과정에서 실제로 발생한 오류만 정리했습니다.</p>



<p>단순 요약이 아니라, <strong>같은 환경에서 그대로 재현 → 해결 → 검증 가능</strong>하도록 구성했습니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">✅ 검증 환경 (버전 고정)</h3>



<ul class="wp-block-list">
<li><strong>OS</strong>: Windows 11 Pro</li>



<li><strong>Node.js</strong>: v24.13.0</li>



<li><strong>npm</strong>: 11.6.2</li>



<li><strong>gemini-cli</strong>: 0.25.2</li>



<li><strong>검증 날짜</strong>: 2026-01-27</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>⚠️ 버전이 다르면 증상이나 해결 방식이 달라질 수 있습니다.</p>



<p>이후 변경 사항은 본문 하단 “업데이트 로그”로 이어서 관리합니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.1. Windows Gemini CLI 설치 중: npm.ps1 실행 정책 오류 해결</h3>



<h3 class="wp-block-heading">증상</h3>



<pre class="wp-block-code"><code>npm : 이 시스템에서 스크립트를 실행할 수 없으므로
C:\\Program Files\\nodejs\\npm.ps1 파일을 로드할 수 없습니다.</code></pre>



<h3 class="wp-block-heading">원인</h3>



<ul class="wp-block-list">
<li>PowerShell 기본 실행 정책이 <code>Restricted</code></li>



<li>Node.js / npm 설치 오류가 아니라 <strong>보안 정책 문제</strong></li>
</ul>



<h3 class="wp-block-heading">해결</h3>



<p>PowerShell을 <strong>관리자 권한</strong>으로 실행 후, 아래 명령을 1회 실행합니다.</p>



<pre class="wp-block-code"><code>Set-ExecutionPolicy RemoteSigned -Scope CurrentUser</code></pre>



<h3 class="wp-block-heading">확인 명령</h3>



<pre class="wp-block-code"><code>node -v
npm -v</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> node -v
v24.13.0
PS C:\\Windows\\System32> npm -v
11.6.2</code></pre>



<ul class="wp-block-list">
<li>두 명령 모두 정상 출력되면 해결 완료</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.2. System32 EPERM 경고 (gemini 실행 시 권한 오류)</h3>



<h3 class="wp-block-heading">증상</h3>



<pre class="wp-block-code"><code>&#91;WARN] Skipping unreadable directory:
C:\\Windows\\System32\\config (EPERM: operation not permitted)</code></pre>



<h3 class="wp-block-heading">원인</h3>



<ul class="wp-block-list">
<li>현재 작업 디렉터리가 <code>C:\\Windows\\System32</code></li>



<li>Gemini CLI가 <strong>현재 디렉터리를 스캔</strong>하면서 발생하는 권한 경고</li>
</ul>



<h3 class="wp-block-heading">해결</h3>



<p>현재 디렉터리 확인 명령</p>



<pre class="wp-block-code"><code>pwd</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> pwd

Path
----
C:\\Windows\\System32</code></pre>



<p>작업 디렉터리를 <strong>사용자 홈 디렉터리</strong>로 이동합니다.</p>



<pre class="wp-block-code"><code>cd $env:USERPROFILE
mkdir work
cd work</code></pre>



<h3 class="wp-block-heading">확인 명령</h3>



<pre class="wp-block-code"><code>gemini "테스트 메시지"</code></pre>



<ul class="wp-block-list">
<li>EPERM 경고 없이 응답이 나오면 정상</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.3. Gemini CLI에서 GEMINI.md만 반복해서 읽는 루프 발생</h3>



<h3 class="wp-block-heading">증상</h3>



<ul class="wp-block-list">
<li>명령을 내려도 실제 파일 생성 없이</li>



<li><code>GEMINI.md 내용을 다시 요약</code>하거나 반복 응답</li>
</ul>



<h3 class="wp-block-heading">원인</h3>



<ul class="wp-block-list">
<li>Gemini CLI가 **“설계 문서 모드”**에 머물러 있음</li>



<li>실제 파일 생성 지시가 약하거나, 이전 맥락이 과도하게 남아 있음</li>
</ul>



<h3 class="wp-block-heading">해결</h3>



<p>루프 탈출 명령어 (<strong>강제 중단 문장)</strong></p>



<pre class="wp-block-code"><code>GEMINI.md는 더 이상 수정하지 말고,
지금은 실제 프로젝트 파일을 생성하는 작업만 수행해라.</code></pre>



<p>또는 기존 GEMINI.md 삭제 (실무에서 가장 확실한 방법)</p>



<pre class="wp-block-code"><code>del GEMINI.md
gemini
/init</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="948" height="1024" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-init-948x1024.png" alt="Windows 환경의 Gemini CLI에서 /init 명령 실행" class="wp-image-817" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-init-948x1024.png 948w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-init-278x300.png 278w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-init-768x830.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/gemini-cli-init.png 1266w" sizes="auto, (max-width: 948px) 100vw, 948px" /></figure>



<h3 class="wp-block-heading">확인 명령</h3>



<ul class="wp-block-list">
<li><code>build.gradle</code>, <code>src/</code> 등 <strong>실제 파일 생성 여부 확인</strong></li>
</ul>



<pre class="wp-block-code"><code>dir</code></pre>



<pre class="wp-block-code"><code>PS C:\\Users\\rexjo\\todo-demo&gt; cd .\\todo-demo\\
PS C:\\Users\\rexjo\\todo-demo\\todo-demo&gt; dir

    디렉터리: C:\\Users\\rexjo\\todo-demo\\todo-demo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----      2026-01-27   오후 3:11                gradle
d-----      2026-01-27   오후 3:11                src
-a----      2026-01-27   오후 3:10            553 build.gradle
-a----      2026-01-27   오후 3:11           4779 gradlew
-a----      2026-01-27   오후 3:11           1845 gradlew.bat
-a----      2026-01-27   오후 3:10             31 settings.gradle
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6.4. Gradle Wrapper 깨짐 (NoClassDefFoundError) 해결</h3>



<h3 class="wp-block-heading">증상</h3>



<pre class="wp-block-code"><code>NoClassDefFoundError: org/gradle/wrapper/IDownload</code></pre>



<h3 class="wp-block-heading">원인</h3>



<ul class="wp-block-list">
<li><code>gradle-wrapper.jar</code> 손상</li>



<li>ZIP에서 JAR만 복사한 <strong>비정상 복구 방식</strong></li>
</ul>



<h3 class="wp-block-heading">해결</h3>



<p>6.4.1. 기존 wrapper 파일 삭제</p>



<pre class="wp-block-code"><code>del gradlew
del gradlew.bat
del gradle\\wrapper\\gradle-wrapper.jar</code></pre>



<p>6.4.2. Gradle 공식 배포판으로 wrapper 재생성</p>



<pre class="wp-block-code"><code>gradle.bat wrapper --gradle-version 8.5 --distribution-type bin</code></pre>



<p>6.4.3. wrapper 재생성 후 파일 확인</p>



<pre class="wp-block-code"><code>dir gradle\\wrapper\\</code></pre>



<h3 class="wp-block-heading">확인 명령</h3>



<pre class="wp-block-code"><code>.\\gradlew.bat --version
.\\gradlew.bat clean build -x test</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. 원클릭 점검용 자동화 스크립트</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>설치 환경 점검을 한 번에 확인하기 위한 스크립트입니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7.1. PowerShell 버전 확인</h3>



<p>파워쉘 창에 아래 명령어를 입력합니다.</p>



<pre class="wp-block-code"><code>$PSVersionTable.PSVersion</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      26100  7627</code></pre>



<ul class="wp-block-list">
<li><strong>Major 5</strong>: 윈도우 기본 설치 버전 (Windows PowerShell). 인코딩에 민감합니다.</li>



<li><strong>Major 7</strong>: 최신 오픈소스 버전 (PowerShell Core). 대부분의 인코딩 문제를 알아서 해결합니다.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7.2. verify-gemini-env.ps1 생성 (메모장)</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>메모장 없이 파워쉘에서 바로 실행하는 방법은 아래 7.3. 참고</p>
</blockquote>



<ul class="wp-block-list">
<li>파일 생성 (메모장)</li>
</ul>



<pre class="wp-block-code"><code>cd $env:USERPROFILE
notepad verify-gemini-env.ps1</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> cd $env:USERPROFILE
PS C:\\Users\\rexjo> notepad verify-gemini-env.ps1
PS C:\\Users\\rexjo> </code></pre>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="448" height="216" src="https://lindarex-career-insight.com/wp-content/uploads/2026/01/windows-notepad-create-ps1.png" alt="Windows Gemini CLI 설치 과정에서 메모장으로 새 파일 생성" class="wp-image-818" srcset="https://lindarex-career-insight.com/wp-content/uploads/2026/01/windows-notepad-create-ps1.png 448w, https://lindarex-career-insight.com/wp-content/uploads/2026/01/windows-notepad-create-ps1-300x145.png 300w" sizes="auto, (max-width: 448px) 100vw, 448px" /></figure>



<ul class="wp-block-list">
<li>메모장에 아래 내용 붙여넣기</li>
</ul>



<pre class="wp-block-code"><code>Write-Host "`n=== Gemini CLI Environment Check ===" -ForegroundColor Cyan

# &#91;1] Node.js Check
Write-Host "`n&#91;1] Node.js Version" -ForegroundColor Yellow
node -v
if ($LASTEXITCODE -ne 0) { 
    Write-Host "&#91;-] Node.js is NOT installed" -ForegroundColor Red 
} else { 
    Write-Host "&#91;OK] Node.js is detected" -ForegroundColor Green 
}

# &#91;2] npm Check
Write-Host "`n&#91;2] npm Version" -ForegroundColor Yellow
npm -v
if ($LASTEXITCODE -ne 0) { 
    Write-Host "&#91;-] npm Execution Failed" -ForegroundColor Red 
} else { 
    Write-Host "&#91;OK] npm is detected" -ForegroundColor Green 
}

# &#91;3] Gemini CLI Check
Write-Host "`n&#91;3] Gemini CLI Version" -ForegroundColor Yellow
gemini --version
if ($LASTEXITCODE -ne 0) { 
    Write-Host "&#91;-] Gemini CLI is NOT installed" -ForegroundColor Red 
} else { 
    Write-Host "&#91;OK] Gemini CLI is detected" -ForegroundColor Green 
}

# &#91;4] API Key Check
Write-Host "`n&#91;4] Environment Variable" -ForegroundColor Yellow
if ($env:GEMINI_API_KEY) {
    $prefix = $env:GEMINI_API_KEY.ToString().Substring(0,5)
    Write-Host "&#91;OK] GEMINI_API_KEY is Set (Start with: $prefix...)" -ForegroundColor Green
} else {
    Write-Host "&#91;-] GEMINI_API_KEY is NOT Found" -ForegroundColor Red
}

# &#91;5] Directory Check
Write-Host "`n&#91;5] Current Directory" -ForegroundColor Yellow
$dir = (Get-Location).Path
Write-Host $dir
if ($dir -like "*System32*") {
    Write-Host "&#91;!] Warning: Running in System32. Please move to another folder." -ForegroundColor Yellow
} else {
    Write-Host "&#91;OK] Directory is Suitable" -ForegroundColor Green
}

Write-Host "`n=== Check Completed ===" -ForegroundColor Cyan</code></pre>



<ul class="wp-block-list">
<li>파일 확인</li>
</ul>



<pre class="wp-block-code"><code>dir ./verify-gemini-env.ps1</code></pre>



<pre class="wp-block-code"><code>PS C:\\Users\\rexjo> dir ./verify-gemini-env.ps1

    디렉터리: C:\\Users\\rexjo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----      2026-01-29   오후 1:41           1451 verify-gemini-env.ps1</code></pre>



<ul class="wp-block-list">
<li>실행</li>
</ul>



<pre class="wp-block-code"><code>.\\verify-gemini-env.ps1</code></pre>



<pre class="wp-block-code"><code>PS C:\\Users\\rexjo> ./verify-gemini-env.ps1

=== Gemini CLI Environment Check ===

&#91;1] Node.js Version
v24.13.0
&#91;OK] Node.js is detected

&#91;2] npm Version
11.6.2
&#91;OK] npm is detected

&#91;3] Gemini CLI Version
0.25.2
&#91;OK] Gemini CLI is detected

&#91;4] Environment Variable
&#91;OK] GEMINI_API_KEY is Set (Start with: AIzaS...)

&#91;5] Current Directory
C:\\Users\\rexjo
&#91;OK] Directory is Suitable

=== Check Completed ===</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7.3. verify-gemini-env.ps1 생성 (PowerShell)</h3>



<ul class="wp-block-list">
<li>경로 이동</li>
</ul>



<pre class="wp-block-code"><code>cd $env:USERPROFILE</code></pre>



<pre class="wp-block-code"><code>PS C:\\Windows\\System32> cd $env:USERPROFILE
PS C:\\Users\\rexjo> </code></pre>



<ul class="wp-block-list">
<li>아래 전체 코드를 복사해서 파워쉘에 붙여넣기</li>
</ul>



<pre class="wp-block-code"><code>$script = @'
Write-Host "`n=== Gemini CLI Environment Check ===" -ForegroundColor Cyan

# &#91;1] Node.js Check
Write-Host "`n&#91;1] Node.js Version" -ForegroundColor Yellow
node -v
if ($LASTEXITCODE -ne 0) {
    Write-Host "&#91;-] Node.js is NOT installed" -ForegroundColor Red
} else {
    Write-Host "&#91;OK] Node.js is Normal" -ForegroundColor Green
}

# &#91;2] npm Check
Write-Host "`n&#91;2] npm Version" -ForegroundColor Yellow
npm -v
if ($LASTEXITCODE -ne 0) {
    Write-Host "&#91;-] npm Execution Failed" -ForegroundColor Red
} else {
    Write-Host "&#91;OK] npm is Normal" -ForegroundColor Green
}

# &#91;3] Gemini CLI Check
Write-Host "`n&#91;3] Gemini CLI Version" -ForegroundColor Yellow
gemini --version
if ($LASTEXITCODE -ne 0) {
    Write-Host "&#91;-] Gemini CLI is NOT installed" -ForegroundColor Red
} else {
    Write-Host "&#91;OK] Gemini CLI is Normal" -ForegroundColor Green
}

# &#91;4] API Key Check (Enhanced for compatibility)
Write-Host "`n&#91;4] Environment Variable" -ForegroundColor Yellow
$apiKey = $env:GEMINI_API_KEY
if ($apiKey) {
    # Check length to avoid Substring error
    if ($apiKey.Length -ge 5) {
        $prefix = $apiKey.Substring(0,5)
    } else {
        $prefix = $apiKey
    }
    Write-Host "&#91;OK] GEMINI_API_KEY is Set (Start with: $prefix...)" -ForegroundColor Green
} else {
    Write-Host "&#91;-] GEMINI_API_KEY is NOT Found" -ForegroundColor Red
}

# &#91;5] Directory Check
Write-Host "`n&#91;5] Current Directory" -ForegroundColor Yellow
$currentPath = (Get-Location).Path
Write-Host $currentPath
if ($currentPath -like "*System32*") {
    Write-Host "&#91;!] Warning: Running in System32. Please move to another folder (e.g., C:\\work)." -ForegroundColor Yellow
} else {
    Write-Host "&#91;OK] Directory is Suitable" -ForegroundColor Green
}

Write-Host "`n=== Check Completed ===" -ForegroundColor Cyan
'@

# 파워쉘 5.1/7 모두에서 인코딩 문제 없이 파일을 저장하는 가장 안전한 방법 (.NET 활용)
&#91;System.IO.File]::WriteAllText("$pwd\\verify-gemini-env.ps1", $script, &#91;System.Text.Encoding]::UTF8)

Write-Host "`n&#91;Success] verify-gemini-env.ps1 has been created." -ForegroundColor Green
Write-Host "Type '.\\verify-gemini-env.ps1' to run the check." -ForegroundColor White</code></pre>



<ul class="wp-block-list">
<li>파일 확인</li>
</ul>



<pre class="wp-block-code"><code>dir ./verify-gemini-env.ps1</code></pre>



<pre class="wp-block-code"><code>PS C:\\Users\\rexjo> dir ./verify-gemini-env.ps1

    디렉터리: C:\\Users\\rexjo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----      2026-01-29   오후 1:41           1451 verify-gemini-env.ps1</code></pre>



<ul class="wp-block-list">
<li>실행</li>
</ul>



<pre class="wp-block-code"><code>.\\verify-gemini-env.ps1</code></pre>



<pre class="wp-block-code"><code>PS C:\\Users\\rexjo> ./verify-gemini-env.ps1

=== Gemini CLI Environment Check ===

&#91;1] Node.js Version
v24.13.0
&#91;OK] Node.js is Normal

&#91;2] npm Version
11.6.2
&#91;OK] npm is Normal

&#91;3] Gemini CLI Version
0.25.2
&#91;OK] Gemini CLI is Normal

&#91;4] Environment Variable
&#91;OK] GEMINI_API_KEY is Set (Start with: AIzaS...)

&#91;5] Current Directory
C:\\Users\\rexjo
&#91;OK] Directory is Suitable

=== Check Completed ===</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8. 보안 주의사항</h2>



<ul class="wp-block-list">
<li>❌ API 키를 <strong>블로그, 스크린샷, 깃 커밋에 절대 노출 금지</strong></li>



<li>✅ 반드시 <strong>환경 변수(GEMINI_API_KEY)</strong> 로만 관리</li>



<li>✅ <code>.gitignore</code>에 아래 항목 포함 권장</li>
</ul>



<pre class="wp-block-code"><code>.env
*.key
**/*api*key*</code></pre>



<ul class="wp-block-list">
<li>✅ GitHub에 푸시 전 점검 명령
<ul class="wp-block-list">
<li>가능하다면 <strong>GitHub Secret Scanning 활성화</strong> 권장</li>
</ul>
</li>
</ul>



<pre class="wp-block-code"><code>*# API 키 노출 검사*
git grep -i "gemini_api_key"
git grep -E "AIza&#91;0-9A-Za-z_-]{35}" *# Gemini API 키 패턴*</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9. Todo REST API 테스트</h2>



<pre class="wp-block-code"><code>curl -X POST &lt;http://localhost:8080/api/todos> \\
  -H "Content-Type: application/json" \\
  -d '{"title":"첫 번째 할 일"}'</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">자주 묻는 질문 (FAQ)</h2>



<h3 class="wp-block-heading">Q. Windows에서 Gemini CLI 설치에 Node.js가 꼭 필요한가요?</h3>



<p><strong>A.</strong> 네. Gemini CLI는 Node.js 기반 도구이므로 필수입니다.</p>



<h3 class="wp-block-heading">Q. PowerShell에서 오류가 많은데 괜찮나요?</h3>



<p><strong>A.</strong> 대부분 실행 정책 또는 작업 디렉터리(System32) 문제이며, 설정 후 정상 사용 가능합니다.</p>



<h3 class="wp-block-heading">Q. Gemini CLI로 실제 프로젝트가 가능한가요?</h3>



<p><strong>A.</strong> 가능합니다. 이 포스트의 Todo 데모는 IDE 없이 CLI만으로 구성됩니다.</p>



<h3 class="wp-block-heading">Q. npm -v는 되는데 왜 npm install은 안 되나요?</h3>



<p><strong>A.</strong> PowerShell 실행 정책 때문입니다. Set-ExecutionPolicy RemoteSigned 명령으로 해결하세요.</p>



<h3 class="wp-block-heading">Q. System32 경고가 계속 나오는데 무시해도 되나요?</h3>



<p><strong>A.</strong> 무시 가능하나, 작업 디렉터리를 $env:USERPROFILE로 옮기면 깔끔합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">마무리 정리</h2>



<ul class="wp-block-list">
<li>Windows에서 Gemini CLI는 <strong>Node.js → npm → API 키 설정</strong> 흐름이 핵심입니다.</li>



<li>Gemini CLI는 단순 챗봇이 아니라 <strong>개발 자동화를 수행하는 CLI 에이전트</strong>입니다.</li>



<li>Spring Boot + Gradle 기반 Todo REST API는 <strong>Gemini CLI만으로 충분히 구현 가능합니다.</strong></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">업데이트 로그 관리 안내</h2>



<ul class="wp-block-list">
<li>2026-01-27
<ul class="wp-block-list">
<li>Node v24 / gemini-cli 0.25.2 기준 검증</li>
</ul>
</li>



<li>이후 버전 변경 시
<ul class="wp-block-list">
<li>본문 상단 “검증 환경” 섹션 업데이트 예정</li>
</ul>
</li>
</ul>
<p>게시물 <a href="https://lindarex-career-insight.com/windows-gemini-cli-install-springboot-gradle-todo/">Windows Gemini CLI 설치 가이드: PowerShell + API 키 설정</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Windows 11 Docker Redis 최신 버전 실행 방법 (Spring Boot 연동)</title>
		<link>https://lindarex-career-insight.com/windows-11-docker-redis-latest/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Fri, 19 Dec 2025 06:47:20 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Redis]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Windows 11]]></category>
		<category><![CDATA[개발자]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=712</guid>

					<description><![CDATA[<p>Windows 11 Docker Redis 환경에서 Redis를 사용하는 가장 깔끔한 방법은, Windows에 직접 설치하지 않고 Docker로 Redis를 실행하는 것입니다. 특히 Windows 11 Docker Redis 조합은 …</p>
<p>게시물 <a href="https://lindarex-career-insight.com/windows-11-docker-redis-latest/">Windows 11 Docker Redis 최신 버전 실행 방법 (Spring Boot 연동)</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Windows 11 Docker Redis 환경에서 Redis를 사용하는 가장 깔끔한 방법은, Windows에 직접 설치하지 않고 Docker로 Redis를 실행하는 것입니다.</p>



<p>특히 Windows 11 Docker Redis 조합은 로컬 개발 환경에서 많이 사용되며, Redis 버전 업데이트가 잦기 때문에 설치 방식과 버전 관리 전략이 매우 중요합니다.</p>



<p>이번 글에서는 <strong>Redis를 처음 사용하는 백엔드 개발자</strong>를 기준으로 다음 내용을 <strong>최소 설정 + 실습 중심</strong>으로 정리합니다.</p>



<ul class="wp-block-list">
<li>Windows 11 + Docker Desktop 환경</li>



<li>Redis <strong>최신 버전 확인 방법</strong></li>



<li>Redis <strong>특정 버전으로 고정 실행하는 방법</strong></li>



<li>Windows 부팅 시 Redis 자동 실행</li>



<li>Spring Boot에서 Redis 연동</li>



<li>IntelliJ HTTP Request로 테스트</li>
</ul>



<figure class="wp-block-image aligncenter size-large"><a href="https://lindarex-career-insight.com/" target="_blank" rel=" noreferrer noopener"><img loading="lazy" decoding="async" width="1024" height="683" src="https://lindarex-career-insight.com/wp-content/uploads/2025/12/windows11-docker-redis-springboot-1024x683.jpg" alt="Windows 11 Docker 환경에서 Redis 최신 버전을 실행하고 Spring Boot와 연동하는 개발 가이드" class="wp-image-713" srcset="https://lindarex-career-insight.com/wp-content/uploads/2025/12/windows11-docker-redis-springboot-1024x683.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/windows11-docker-redis-springboot-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/windows11-docker-redis-springboot-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/windows11-docker-redis-springboot-1536x1025.jpg 1536w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/windows11-docker-redis-springboot.jpg 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<h2 class="wp-block-heading">1. Windows 11 Docker 환경에서 Redis 최신 버전 확인 방법</h2>



<p>Redis는 계속 업데이트되므로 글에 특정 “최신 버전 번호”를 <strong>단정적으로 적는 것은 위험</strong>합니다.</p>



<p>Redis Docker 공식 이미지는 Docker Hub에서 관리되며, 최신 버전과 태그 정보는 공식 페이지에서 확인할 수 있습니다. <a href="https://hub.docker.com/_/redis" target="_blank" rel="noreferrer noopener nofollow">https://hub.docker.com/_/redis</a></p>



<p>Redis 공식 문서에서는 Docker 환경에서 Redis를 실행하는 방법과 설정 예제를 자세히 설명하고 있습니다.<br><a href="https://redis.io/docs/latest/" target="_blank" rel="noreferrer noopener">https://redis.io/docs/latest/</a></p>



<h3 class="wp-block-heading">가장 정확한 최신 버전 확인 방법</h3>



<pre class="wp-block-code"><code>docker search redis</code></pre>



<p>또는 <strong>Docker Hub 공식 Redis 이미지 페이지</strong>에서 확인합니다.</p>



<ul class="wp-block-list">
<li>Docker Hub → redis (Official Image)</li>



<li>Tags 탭에서 <code>latest</code>, 8<code>.x</code>, 7<code>.x</code> 확인</li>
</ul>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="478" src="https://lindarex-career-insight.com/wp-content/uploads/2025/12/dockerhub-redis-tags-1024x478.png" alt="Docker Hub에서 Redis 공식 이미지의 최신 버전과 태그 목록을 확인하는 화면" class="wp-image-714" srcset="https://lindarex-career-insight.com/wp-content/uploads/2025/12/dockerhub-redis-tags-1024x478.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/dockerhub-redis-tags-300x140.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/dockerhub-redis-tags-768x358.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/dockerhub-redis-tags-1536x717.png 1536w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/dockerhub-redis-tags.png 1896w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">2. Redis 최신 버전으로 실행하기 (주의 포함)</h2>



<h3 class="wp-block-heading">최신 버전(<code>latest</code>) 실행 예시</h3>



<pre class="wp-block-code"><code>docker run -d ^
  --name redis ^
  -p 6379:6379 ^
  redis:latest</code></pre>



<h3 class="wp-block-heading">⚠️ 주의사항</h3>



<ul class="wp-block-list">
<li><code>latest</code>는 자동으로 버전이 변경됨</li>



<li>설정이나 내부 동작이 바뀔 수 있음</li>



<li>팀 개발에서는 재현성 문제 발생</li>
</ul>



<p>👉 <strong>학습용 / 개인 테스트용으로만 권장</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. Docker 기반 Redis 특정 버전 고정 실행하기 (Windows 11)</h2>



<h3 class="wp-block-heading">예: Redis 8.x 고정 실행</h3>



<pre class="wp-block-code"><code>docker run -d ^
  --name redis ^
  -p 6379:6379 ^
  redis:8.4
</code></pre>



<p>또는 이전 버전:</p>



<pre class="wp-block-code"><code>docker run -d ^
  --name redis ^
  -p 6379:6379 ^
  redis:6.2.2</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<h2 class="wp-block-heading">4. Windows 부팅 시 Redis 자동 실행 설정</h2>



<pre class="wp-block-code"><code>docker update --restart unless-stopped redis</code></pre>



<pre class="wp-block-code"><code>docker inspect redis --format='{{.HostConfig.RestartPolicy.Name}}'</code></pre>



<p>출력:</p>



<pre class="wp-block-code"><code>unless-stopped</code></pre>



<ul class="wp-block-list">
<li>Docker 재시작 시 자동 실행</li>



<li>개발 환경에서 가장 안전한 옵션</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. Spring Boot + Redis 최소 연동 구성</h2>



<h3 class="wp-block-heading">build.gradle</h3>



<pre class="wp-block-code"><code>dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">application.yml</h3>



<pre class="wp-block-code"><code>spring:
  redis:
    host: localhost
    port: 6379</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. Redis 설정 클래스</h2>



<pre class="wp-block-code"><code>@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate&lt;String, String> redisTemplate(
            RedisConnectionFactory connectionFactory) {

        RedisTemplate&lt;String, String> template = new RedisTemplate&lt;>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. Redis 서비스</h2>



<pre class="wp-block-code"><code>@Service
public class RedisService {

    private final RedisTemplate&lt;String, String> redisTemplate;

    public RedisService(RedisTemplate&lt;String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void setValue(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public String getValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8. 테스트용 컨트롤러</h2>



<pre class="wp-block-code"><code>@RestController
@RequestMapping("/redis")
public class RedisController {

    private final RedisService redisService;

    public RedisController(RedisService redisService) {
        this.redisService = redisService;
    }

    @GetMapping("/set")
    public String set(@RequestParam String key,
                      @RequestParam String value) {
        redisService.setValue(key, value);
        return "OK";
    }

    @GetMapping("/get")
    public String get(@RequestParam String key) {
        return redisService.getValue(key);
    }
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9. IntelliJ HTTP Request로 테스트하기</h2>



<pre class="wp-block-code"><code>### Redis 값 저장
GET http://localhost:8080/redis/set?key=hello&amp;value=world

### Redis 값 조회
GET http://localhost:8080/redis/get?key=hello</code></pre>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="641" height="244" src="https://lindarex-career-insight.com/wp-content/uploads/2025/12/intellij-http-redis-test.png" alt="IntelliJ HTTP Request 파일을 사용해 Redis 데이터를 저장하고 조회하는 테스트 화면" class="wp-image-715" srcset="https://lindarex-career-insight.com/wp-content/uploads/2025/12/intellij-http-redis-test.png 641w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/intellij-http-redis-test-300x114.png 300w" sizes="auto, (max-width: 641px) 100vw, 641px" /></figure>



<h2 class="wp-block-heading">10. Redis CLI로 직접 버전 확인 (중요)</h2>



<pre class="wp-block-code"><code>docker exec -it redis redis-cli</code></pre>



<pre class="wp-block-code"><code>info server</code></pre>



<p>출력:</p>



<pre class="wp-block-code"><code>redis_version:8.x.x</code></pre>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="536" src="https://lindarex-career-insight.com/wp-content/uploads/2025/12/redis-cli-version-check-1024x536.png" alt="redis-cli에서 info server 명령으로 Redis 버전을 확인하는 화면" class="wp-image-716" srcset="https://lindarex-career-insight.com/wp-content/uploads/2025/12/redis-cli-version-check-1024x536.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/redis-cli-version-check-300x157.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/redis-cli-version-check-768x402.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2025/12/redis-cli-version-check.png 1301w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>이 가이드는 Windows 11에서 Docker로 Redis를 사용하는 로컬 개발 환경을 기준으로 작성되었습니다.<br>Windows 환경에서 Docker 기반 Redis를 사용하면 운영체제에 직접 설치하는 방식보다 훨씬 안정적이며,<br>Spring Boot와 함께 사용할 때도 로컬 환경을 빠르게 구성할 수 있습니다.</p>



<h2 class="wp-block-heading">마무리 정리</h2>



<ul class="wp-block-list">
<li>Redis 최신 버전은 <strong>Docker Hub 기준으로 확인</strong></li>



<li><code>latest</code>는 테스트용, 실무는 <strong>버전 고정</strong></li>



<li>Docker restart policy로 Windows 부팅 시 자동 실행</li>



<li>Spring Boot 연동은 최소 설정으로 충분</li>
</ul>



<p>이 글은 Redis Docker 공식 이미지를 기준으로 작성되었으며,<br>실제 최신 버전은 Docker Hub redis 공식 페이지에서 반드시 확인하시기 바랍니다.</p>



<p></p>
<p>게시물 <a href="https://lindarex-career-insight.com/windows-11-docker-redis-latest/">Windows 11 Docker Redis 최신 버전 실행 방법 (Spring Boot 연동)</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리</title>
		<link>https://lindarex-career-insight.com/easy-practical-ai-guide/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Wed, 24 Sep 2025 22:02:18 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI 실무]]></category>
		<category><![CDATA[ChatGPT]]></category>
		<category><![CDATA[GPT]]></category>
		<category><![CDATA[KPI]]></category>
		<category><![CDATA[LLM 활용]]></category>
		<category><![CDATA[QC]]></category>
		<category><![CDATA[개발자]]></category>
		<category><![CDATA[결과 검증]]></category>
		<category><![CDATA[데이터 거버넌스]]></category>
		<category><![CDATA[도구 통합]]></category>
		<category><![CDATA[보안]]></category>
		<category><![CDATA[생산성]]></category>
		<category><![CDATA[생성형 AI]]></category>
		<category><![CDATA[업무 자동화]]></category>
		<category><![CDATA[워크플로 자동화]]></category>
		<category><![CDATA[윤리]]></category>
		<category><![CDATA[체크리스트]]></category>
		<category><![CDATA[템플릿]]></category>
		<category><![CDATA[팀 표준]]></category>
		<category><![CDATA[품질 관리]]></category>
		<category><![CDATA[프롬프트]]></category>
		<category><![CDATA[프롬프트 엔지니어링]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=668</guid>

					<description><![CDATA[<p>AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리 AI를 잘 쓰는 핵심은 최신 도구를 많이 아는 것이 아니라, 일을 처리하는 기본 흐름을 몸에 익히는 것입니다. 본 가이드는 그 흐름을 다섯 가지(문제정의 → 프롬프트…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/easy-practical-ai-guide/">AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리</p>



<p>AI를 잘 쓰는 핵심은 최신 도구를 많이 아는 것이 아니라, 일을 처리하는 <strong>기본 흐름</strong>을 몸에 익히는 것입니다. </p>



<p>본 가이드는 그 흐름을 다섯 가지(<em>문제정의 → 프롬프트 → 결과 검증 → 도구 통합 → 윤리·보안)</em>로 정리해 설명합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">요약</h2>



<ol class="wp-block-list">
<li><strong>문제정의:</strong> 무엇을, 누구에게, 언제까지, 어떤 기준으로 할지 짧게 적는다.</li>



<li><strong>프롬프트:</strong> 역할과 맥락을 알려주고, 출력 형식과 금지/필수 조건을 분명히 한다.</li>



<li><strong>결과 검증:</strong> 사실, 범위, 일관성, 출처를 빠르게 점검한다.</li>



<li><strong>도구 통합:</strong> 수집→요약/분류→생성→개인화→발송을 가볍게 묶는다.</li>



<li><strong>윤리·보안:</strong> 민감정보는 넣지 않고, 저작권과 편향을 항상 확인한다.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<h2 class="wp-block-heading">1. 문제정의 &#8211; AI가 바로 이해할 수 있게 쓰는 법</h2>



<p>AI가 잘못된 답을 내는 이유의 상당수는 <em>요청이 애매하기 때문</em>입니다. 다음 세 줄만 적어도 결과가 훨씬 좋아집니다.</p>



<pre class="wp-block-code"><code>&#91;1] 목표/대상: {{무엇을}} {{누구에게}} 전달/제공한다.
&#91;2] 제약/범위: {{채널/톤/길이/형식}}을 지키고 {{하면 안 되는 것}}은 피한다.
&#91;3] 평가/기한: {{성공 기준(KPI·QC)}}으로 검수하고 {{언제/어떻게}} 제출한다.</code></pre>



<ul class="wp-block-list">
<li><strong>개발 예시:</strong> “API 변경 공지, 내부 개발자 대상, 500자 이내, 파라미터 표 포함, 예시는 한 언어만.”</li>



<li><strong>마케팅 예시:</strong> “15초 영상 스크립트 3안, 각 안에 후킹 1문장·행동유도 1개, 중복 금지.”</li>



<li><strong>운영 예시:</strong> “문의 유형 6개로 분류, 라벨 정확도 95% 목표.”</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. 프롬프트 &#8211; 한눈에 읽히는 구조로</h2>



<p>프롬프트는 길다고 좋은 것이 아닙니다. 역할과 맥락, 출력 조건만 또렷하면 됩니다.</p>



<pre class="wp-block-code"><code>&#91;역할] 당신은 {{직무/전문가}}입니다. 목표는 {{목표}}입니다.
&#91;맥락] 제품/사용자/상황을 3줄로 요약합니다.
&#91;출력] 형식(표/리스트/코드), 분량, 언어/톤, 필수/금지 요소를 지정합니다.
&#91;검증] 모호한 부분은 질문 3개를 먼저 제시하고, 답안에 반영합니다.
&#91;평가] 아래 QC 기준을 만족하면 '최종본'으로 표시합니다.</code></pre>



<p>품질을 올리는 간단한 요령은 아래 다섯 가지입니다. </p>



<ul class="wp-block-list">
<li><strong>역할을 구체화</strong>하고, </li>



<li><strong>좋은/나쁜 예시</strong>를 보여 주고, </li>



<li><strong>금지/필수 조건</strong>을 적고, </li>



<li><strong>평가 기준</strong>을 넣고, </li>



<li>마지막에 <strong>스스로 개선안</strong>을 요구하세요.</li>
</ul>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="357" src="https://lindarex-career-insight.com/wp-content/uploads/2025/09/image-1024x357.png" alt="AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리" class="wp-image-669" srcset="https://lindarex-career-insight.com/wp-content/uploads/2025/09/image-1024x357.png 1024w, https://lindarex-career-insight.com/wp-content/uploads/2025/09/image-300x105.png 300w, https://lindarex-career-insight.com/wp-content/uploads/2025/09/image-768x268.png 768w, https://lindarex-career-insight.com/wp-content/uploads/2025/09/image.png 1078w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. 결과 검증 &#8211; 빠르게, 그러나 놓치지 않게</h2>



<p>AI 결과물은 반드시 사람의 눈으로 한 번 더 봐야 합니다.</p>



<ul class="wp-block-list">
<li><strong>사실성:</strong> 숫자·날짜·고유명사 3개를 교차 확인합니다.</li>



<li><strong>범위/경계:</strong> 상·하한 포함 여부, 제외 조건, 반례를 점검합니다.</li>



<li><strong>일관성/재현성:</strong> 같은 입력으로 재시도했을 때 핵심 결론이 유지되는지 봅니다.</li>



<li><strong>출처:</strong> 가능하면 근거를 요구하고, 요약일 경우 출처를 간단히 적습니다.</li>
</ul>



<p>자동 검사(길이·형식·키워드·숫자 포맷)와 수동 검사(표본 3개 눈검수)를 <em>함께</em> 적용하면 속도와 정확도를 모두 올릴 수 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. 도구 통합 &#8211; 짧은 파이프라인으로 시작</h2>



<p>복잡한 자동화보다, <strong>짧고 단순한 흐름</strong>을 먼저 만들어 보세요. 기본 패턴은 다음과 같습니다: <em>수집 → 요약/분류 → 생성 → 개인화 → 발송/게시</em>. 초기에는 중간에 사람 검토 단계를 넣어 안전하게 운영해야 합니다.</p>



<ul class="wp-block-list">
<li><strong>뉴스레터:</strong> 키워드 수집 → 요약/카테고리화 → 섹션 초안 → 템플릿 적용 → 예약 발송</li>



<li><strong>리서치:</strong> 자료 스크랩 → 근거 포함 요약 → 표/도표 생성 → 결론 대안 3개 → 내부 리뷰</li>



<li><strong>CS:</strong> 티켓 자동 태깅 → 유사 사례 검색 → 답변 초안 → 품질 규칙 체크 → 발송</li>
</ul>



<p>입력/출력 형식(필드, 길이, 표 구조)을 <strong>문서로 고정</strong>하고, 실패 시 수동 처리로 전환할 <strong>우회 방안</strong>을 준비하세요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. 윤리·보안 &#8211; 기본을 습관으로</h2>



<ul class="wp-block-list">
<li><strong>민감정보 금지:</strong> 개인 정보, 계약 정보, 내부 코드는 입력하지 않습니다.</li>



<li><strong>저작권/출처:</strong> 인용은 짧게, 상업적 활용 전 라이선스를 확인합니다.</li>



<li><strong>편향 관리:</strong> 채용·신용·의료처럼 영향이 큰 분야는 근거와 책임자 승인을 남깁니다.</li>
</ul>



<p>아래와 같은 간단한 점검 질문도 도움이 됩니다. </p>



<ul class="wp-block-list">
<li>“이 입력은 정말 필요할까?”</li>



<li>“덜 민감한 대체 수단이 있을까?”</li>



<li>“누가 이 결과를 볼 수 있을까?”.</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-2-1024x682.jpg" alt="AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리" class="wp-image-298" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-2-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-2-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-2-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-2.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. 프롬프트 템플릿</h2>



<pre class="wp-block-code"><code>&#91;역할] 당신은 {{직무/연차/도메인}} 전문가입니다.
&#91;목표] {{무엇을}} {{누구에게}} {{언제/어디서}} 전달합니다. 성공 기준: {{KPI/QC}}.
&#91;맥락] 제품/시장/사용자 요약(3줄). 전제 또는 금지 사항을 적습니다.
&#91;데이터] 사용할 자료(포맷/범위/한계).
&#91;출력] 형식(표/리스트/코드), 분량, 언어/톤, 필수 키워드, 포함/제외 항목.
&#91;검증] 모호한 부분은 질문 3개 → 답변 반영 → 핵심 근거 2줄 요약.
&#91;제약] 법적/의학적 조언 금지. 개인/계약/내부 비밀정보 금지. 근거 없는 수치 생성 금지.
&#91;마무리] 개선안 2개 제시 후 최선안을 '최종본'으로 표시.</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. QC 체크리스트</h2>



<ul class="wp-block-list">
<li>사실/숫자/고유명사 3개 확인</li>



<li>경계조건(상·하한, 포함/제외) 테스트</li>



<li>재시도 2회 후 핵심 결론 비교</li>



<li>프롬프트·버전·파라미터 기록</li>



<li>출처 또는 근거 표시</li>



<li>요구한 형식·길이·톤 충족</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">마무리</h2>



<p>도구는 바뀌고 유행은 지나갑니다. 하지만 <em>좋은 문제정의, 깔끔한 프롬프트, 꼼꼼한 검증, 단순한 파이프라인, 기본을 지키는 윤리·보안</em>은 오래갑니다. 이 다섯 가지를 팀의 습관으로 만들면, 모델을 바꿔도 품질은 안정적으로 유지됩니다. 오늘 작은 과제부터 위 순서대로 시도해 보세요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">참고</h2>



<ul class="wp-block-list">
<li><a href="https://kisdi.re.kr/cmm/fileDown.do?key=170565&amp;type=bbs" target="_blank" rel="noreferrer noopener">https://kisdi.re.kr/cmm/fileDown.do?key=170565&amp;type=bbs</a></li>



<li><a href="https://tilnote.io/pages/68ba35d21e08f5ca788888f4" target="_blank" rel="noreferrer noopener">https://tilnote.io/pages/68ba35d21e08f5ca788888f4</a></li>



<li><a href="https://yozm.wishket.com/magazine/detail/3345/" target="_blank" rel="noreferrer noopener">https://yozm.wishket.com/magazine/detail/3345/</a></li>



<li><a href="https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=InstructionGuide_main&amp;nttId=54340&amp;pageIndex=1" target="_blank" rel="noreferrer noopener">https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=InstructionGuide_main&amp;nttId=54340&amp;pageIndex=1</a></li>



<li><a href="https://www.acrc.go.kr/briefs/849fd88ee13c7cd5dd9ac923ef2ed1549f966439a132a5597faa3c1df6f805c5/img/bro.pdf" target="_blank" rel="noreferrer noopener">https://www.acrc.go.kr/briefs/849fd88ee13c7cd5dd9ac923ef2ed1549f966439a132a5597faa3c1df6f805c5/img/bro.pdf</a></li>



<li><a href="https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-the-openai-api" target="_blank" rel="noreferrer noopener">https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-the-openai-api</a></li>



<li><a href="https://unesco.or.kr/wp-content/uploads/2024/06/%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5-%EC%9C%A4%EB%A6%AC%EC%99%80-%EB%B2%95-I_AI-%EC%9C%A4%EB%A6%AC%EC%9D%98-%EC%9F%81%EC%A0%90%EA%B3%BC-%EA%B1%B0%EB%B2%84%EB%84%8C%EC%8A%A4-%EC%97%B0%EA%B5%AC.pdf" target="_blank" rel="noreferrer noopener">https://unesco.or.kr/wp-content/uploads/2024/06/%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5-%EC%9C%A4%EB%A6%AC%EC%99%80-%EB%B2%95-I_AI-%EC%9C%A4%EB%A6%AC%EC%9D%98-%EC%9F%81%EC%A0%90%EA%B3%BC-%EA%B1%B0%EB%B2%84%EB%84%8C%EC%8A%A4-%EC%97%B0%EA%B5%AC.pdf</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<pre class="wp-block-code"><code>취업, 이직, 퇴사, 커리어 고민으로 힘든가요?

<a href="https://lindarex-career-insight.com/notices/" target="_blank" rel="noreferrer noopener">Notices</a>를 확인하고 상담 서비스를 받으세요.

1분만 투자하세요.
1분으로 1년을 아끼고, 10년의 커리어가 달라져요.</code></pre>
<p>게시물 <a href="https://lindarex-career-insight.com/easy-practical-ai-guide/">AI 실무 가이드: 문제정의·프롬프트·검증·통합·윤리 한 번에 정리</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ubuntu에 패키지로 BIND9 설치하기</title>
		<link>https://lindarex-career-insight.com/install-bind9-on-ubuntu-with-apt-complete-service-guide/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Sat, 20 Sep 2025 13:48:28 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[apt install bind9]]></category>
		<category><![CDATA[bind9 설치]]></category>
		<category><![CDATA[bind9.service]]></category>
		<category><![CDATA[dns 서버]]></category>
		<category><![CDATA[isc bind]]></category>
		<category><![CDATA[named -V]]></category>
		<category><![CDATA[systemctl]]></category>
		<category><![CDATA[ubuntu 18.04]]></category>
		<category><![CDATA[ubuntu dns]]></category>
		<category><![CDATA[패키지 제거]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=657</guid>

					<description><![CDATA[<p>BIND9 소개와 설치 목적 Ubuntu에 패키지로 BIND9 설치하기 BIND(Berkeley Internet Name Domain, bind9)는 유닉스/리눅스 계열에서 폭넓게 사용되는 고신뢰 DNS 서버입니다. MPL 2.0 라…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/install-bind9-on-ubuntu-with-apt-complete-service-guide/">Ubuntu에 패키지로 BIND9 설치하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">BIND9 소개와 설치 목적</h2>



<p>Ubuntu에 패키지로 BIND9 설치하기</p>



<p><strong>BIND(Berkeley Internet Name Domain, bind9)</strong>는 유닉스/리눅스 계열에서 폭넓게 사용되는 고신뢰 <strong>DNS 서버</strong>입니다. </p>



<p>MPL 2.0 라이선스의 오픈소스이며, 공용 DNS 정보를 게시하거나 내부 네트워크의 이름 해석을 처리할 수 있습니다. </p>



<p>사내/개인 환경에서 내부 <em>호스트명 ↔ 개인 IP</em>를 중앙집중적으로 관리하면, 시스템이 여러 대로 확장될수록 운영과 설정 유지보수가 크게 수월해집니다. 또한 IP 대신 <strong>FQDN</strong>을 일관되게 사용하면 애플리케이션/서비스 설정 가독성과 변경 용이성이 향상됩니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">준비사항(Prerequisites &amp; Test Setup)</h2>



<p>본 가이드는 <strong>Ubuntu</strong> 환경에서 <strong>apt</strong>를 이용해 BIND9를 설치·검증·운영·제거하는 절차를 설명합니다. 예시 테스트 환경은 VMware® Workstation 15 Pro 상의 <strong>Ubuntu 18.04.4 LTS(64-bit)</strong>와 <strong>BIND 9.11.3</strong>를 사용합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">요약(SUMMARY)</h2>



<ul class="wp-block-list">
<li><strong>설치</strong>: <code>apt install bind9 bind9utils bind9-doc</code>로 패키지 설치</li>



<li><strong>검증</strong>: <code>named -V</code> 명령으로 BIND9 빌드/라이브러리 정보를 확인</li>



<li><strong>운영</strong>: <code>systemctl</code>로 시작/중지/재시작/상태/활성화 등 서비스 관리</li>



<li><strong>제거(선택)</strong>: <code>apt remove</code> 또는 <code>apt purge</code> (+ <code>--auto-remove</code>)로 정리</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. apt로 BIND9 설치</h2>



<p>패키지 색인을 최신화한 다음 BIND9 본체와 유틸리티/문서를 함께 설치합니다.</p>



<pre class="wp-block-code"><code>$ sudo apt update &amp;amp;&amp;amp; sudo apt install bind9 bind9utils bind9-doc -y</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>LTS 별 기본 리포지터리의 BIND9 버전이 오래된 경우, 보안 업데이트 리포지터리나 배포판 제공 Backport를 검토하세요.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. 설치 검증(named -V)</h2>



<p><code>named -V</code>는 빌드 옵션과 연동 라이브러리 버전을 보여줍니다. 환경에 따라 값은 다를 수 있으며 아래는 예시입니다.</p>



<pre class="wp-block-code"><code>$ named -V
BIND 9.11.3-1ubuntu1.11-Ubuntu (Extended Support Version)
running on Linux x86_64 4.15.0-91-generic #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020
built by make with '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=/usr/include' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--disable-silent-rules' '--libdir=/usr/lib/x86_64-linux-gnu' '--libexecdir=/usr/lib/x86_64-linux-gnu' '--disable-maintainer-mode' '--disable-dependency-tracking' '--libdir=/usr/lib/x86_64-linux-gnu' '--sysconfdir=/etc/bind' '--with-python=python3' '--localstatedir=/' '--enable-threads' '--enable-largefile' '--with-libtool' '--enable-shared' '--enable-static' '--with-gost=no' '--with-openssl=/usr' '--with-gssapi=/usr' '--with-libjson=/usr' '--without-lmdb' '--with-gnu-ld' '--with-geoip=/usr' '--with-atf=no' '--enable-ipv6' '--enable-rrl' '--enable-filter-aaaa' '--enable-native-pkcs11' '--with-pkcs11=/usr/lib/softhsm/libsofthsm2.so' '--with-randomdev=/dev/urandom' '--with-eddsa=no' 'build_alias=x86_64-linux-gnu''CFLAGS=-g -O2 -fdebug-prefix-map=/build/bind9-uW3Pyl/bind9-9.11.3+dfsg=. -fstack-protector-strong -Wformat -Werror=format-security -fno-strict-aliasing -fno-delete-null-pointer-checks -DNO_VERSION_DATE -DDIG_SIGCHASE' 'LDFLAGS=-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'
compiled by GCC 7.4.0
compiled with OpenSSL version: OpenSSL 1.1.1 11 Sep 2018
linked to OpenSSL version: OpenSSL 1.1.1 11 Sep 2018
compiled with libxml2 version: 2.9.4
linked to libxml2 version: 20904
compiled with libjson-c version: 0.12.1
linked to libjson-c version: 0.12.1
compiled with zlib version: 1.2.11
linked to zlib version: 1.2.11
threads support is enabled</code></pre>



<p>출력에 BIND 버전, OpenSSL/라이브러리 연동 버전, 스레드 지원 여부 등이 나타나면 설치가 정상입니다.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-2-1024x682.jpg" alt="Ubuntu에 패키지로 BIND9 설치하기" class="wp-image-284" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-2-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-2-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-2-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-2.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. systemctl로 서비스 운영</h2>



<p>BIND9는 <code>bind9.service</code> 유닛으로 관리됩니다. 변경사항 반영, 기동/중단, 재시작, 설정 재적용, 상태 조회, 부팅 자동 시작, 비활성화, 강제 종료 등 주요 작업 예시는 다음과 같습니다.</p>



<h3 class="wp-block-heading">3.1 데몬 재로딩</h3>



<pre class="wp-block-code"><code>## 설정 반영
$ sudo systemctl daemon-reload</code></pre>



<h3 class="wp-block-heading">3.2 시작/중지/재시작/재적용</h3>



<pre class="wp-block-code"><code>## 시작
$ sudo systemctl start bind9.service

## 중지
$ sudo systemctl stop bind9.service

## 재시작
$ sudo systemctl restart bind9.service

## 설정 재적용
$ sudo systemctl reload bind9.service</code></pre>



<p><code>reload</code>는 설정 파일이 변경되었을 때 무중단 반영을 시도합니다(일부 변경은 <code>restart</code> 필요).</p>



<h3 class="wp-block-heading">3.3 상태·부팅 자동 시작·비활성화·강제 종료</h3>



<pre class="wp-block-code"><code>## 상태 조회
$ sudo systemctl status bind9.service

## 부팅 시 자동 시작
$ sudo systemctl enable bind9.service

## 부팅 자동 시작 해제
$ sudo systemctl disable bind9.service

## 관련 프로세스 강제 종료
$ sudo systemctl kill bind9.service</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. (선택) apt로 BIND9 제거</h2>



<p>불필요해진 경우 <code>remove</code> 또는 <code>purge</code>로 정리할 수 있습니다. <code>--auto-remove</code>를 함께 쓰면 사용되지 않는 의존 패키지도 함께 제거됩니다.</p>



<h3 class="wp-block-heading">4.1 apt remove</h3>



<pre class="wp-block-code"><code>## 설정 파일은 유지
$ sudo apt remove bind9*
$ sudo apt remove --auto-remove bind9*</code></pre>



<h3 class="wp-block-heading">4.2 apt purge</h3>



<pre class="wp-block-code"><code>## 설정 파일까지 삭제
$ sudo apt purge bind9*
$ sudo apt purge --auto-remove bind9*</code></pre>



<p>일부 사용자 홈 디렉터리 하위 설정은 남을 수 있습니다. 완전 초기화를 원한다면 수동 정리가 필요할 수 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">마무리(CONCLUSION)</h2>



<p>Ubuntu에 패키지로 BIND9 설치하기</p>



<p>Ubuntu에서 BIND9를 <strong>패키지</strong>로 설치하고, <strong>named -V</strong>로 설치 상태를 검증하며, <strong>systemctl</strong>로 서비스를 운영·관리하는 방법을 살펴봤습니다. </p>



<p>이어서 네임서버를 실제로 동작시키려면 <strong>존 구성</strong>(정방향/역방향)과 보안/가용성 설정(DNSSEC, 로깅, ACL 등)을 추가하세요. </p>



<p>상세한 설정법은 <a href="https://lindarex-career-insight.com/ubuntu-bind9-dns-local-nameserver-setup-guide/" target="_blank" rel="noreferrer noopener">Ubuntu에서 BIND9(DNS) 설정하기</a> 를 참고해 주세요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">참고(REFERENCES)</h2>



<ul class="wp-block-list">
<li><a href="https://www.linuxbabe.com/ubuntu/set-up-authoritative-dns-server-ubuntu-18-04-bind9" target="_blank" rel="noreferrer noopener">https://www.linuxbabe.com/ubuntu/set-up-authoritative-dns-server-ubuntu-18-04-bind9</a></li>



<li><a href="https://www.linuxtechi.com/install-configure-bind-9-dns-server-ubuntu-debian/" target="_blank" rel="noreferrer noopener">https://www.linuxtechi.com/install-configure-bind-9-dns-server-ubuntu-debian/</a></li>



<li><a href="https://www.digitalocean.com/community/tutorials/how-to-configure-bind-as-a-private-network-dns-server-on-ubuntu-18-04" target="_blank" rel="noreferrer noopener">https://www.digitalocean.com/community/tutorials/how-to-configure-bind-as-a-private-network-dns-server-on-ubuntu-18-04</a></li>



<li><a href="https://www.isc.org/bind/" target="_blank" rel="noreferrer noopener">https://www.isc.org/bind/</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<pre class="wp-block-code"><code>취업, 이직, 퇴사, 커리어 고민으로 힘든가요?

<a href="https://lindarex-career-insight.com/notices/" target="_blank" rel="noreferrer noopener">Notices</a>를 확인하고 상담 서비스를 받으세요.

1분만 투자하세요.
1분으로 1년을 아끼고, 10년의 커리어가 달라져요.</code></pre>
<p>게시물 <a href="https://lindarex-career-insight.com/install-bind9-on-ubuntu-with-apt-complete-service-guide/">Ubuntu에 패키지로 BIND9 설치하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ubuntu에서 BIND9(DNS) 설정하기</title>
		<link>https://lindarex-career-insight.com/ubuntu-bind9-dns-local-nameserver-setup-guide/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Sat, 20 Sep 2025 13:13:09 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[A 레코드]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[bind9]]></category>
		<category><![CDATA[dig]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[dnssec]]></category>
		<category><![CDATA[forward zone]]></category>
		<category><![CDATA[named.conf.options]]></category>
		<category><![CDATA[nslookup]]></category>
		<category><![CDATA[PTR]]></category>
		<category><![CDATA[reverse zone]]></category>
		<category><![CDATA[systemd]]></category>
		<category><![CDATA[ubuntu dns]]></category>
		<category><![CDATA[네임서버]]></category>
		<category><![CDATA[방화벽 53]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=652</guid>

					<description><![CDATA[<p>Ubuntu에서 BIND9(DNS) 설정하기 BIND9와 DNS 한눈에 보기 DNS 서버·네임서버·DNS 차이 요약 BIND9(Berkeley Internet Name Domain)은 오픈소스 DNS 서버 소프트웨어로, 호스트 이름과…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/ubuntu-bind9-dns-local-nameserver-setup-guide/">Ubuntu에서 BIND9(DNS) 설정하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ubuntu에서 BIND9(DNS) 설정하기</p>



<h2 class="wp-block-heading">BIND9와 DNS 한눈에 보기</h2>



<h3 class="wp-block-heading">DNS 서버·네임서버·DNS 차이 요약</h3>



<p><strong>BIND9</strong>(Berkeley Internet Name Domain)은 오픈소스 <strong>DNS 서버</strong> 소프트웨어로, 호스트 이름과 IP 주소 간의 매핑을 처리하는 <em>이름 해석</em> 기능을 제공합니다. </p>



<p><strong>DNS 서버</strong>는 네임서비스를 수행하는 서버 유형이며, <strong>네임서버</strong>는 이름 해석을 제공하는 서버 전반을 가리키는 더 넓은 개념입니다. </p>



<p>즉, 모든 DNS 서버는 네임서버에 포함되지만 모든 네임서버가 DNS 서버인 것은 아닙니다. 실무에서는 두 용어가 혼용되는 경우가 많습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">준비사항(Prerequisites &amp; Test Setup)</h2>



<p>이 가이드는 Ubuntu 환경에서 BIND9로 로컬 DNS 서버를 구성하는 방법을 다룹니다. </p>



<p>사전에 BIND9가 설치되어 있어야 하며 방화벽에서 <strong>TCP/UDP 53 포트</strong>가 허용되어야 합니다. </p>



<p>테스트 환경은 VMware® Workstation 15 Pro에서 <strong>Ubuntu 18.04.4 LTS(64-bit)</strong> 및 <strong>BIND 9.11.3</strong>을 사용하고, 네임서버 VM은 Host <code>ns</code> / FQDN <code>ns.rex.local</code> / IP <code>10.0.1.32</code>, 검증용 외부 VM은 Host <code>test</code> / FQDN <code>test.rex.local</code> / IP <code>10.0.1.31</code>를 사용합니다. </p>



<p><strong>FQDN</strong>은 호스트명과 도메인명으로 구성된 전체 도메인 이름을 의미합니다.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>bind9 설치 방법은 <a href="https://lindarex-career-insight.com/install-bind9-on-ubuntu-with-apt-complete-service-guide/" target="_blank" rel="noreferrer noopener">Ubuntu에 패키지로 BIND9 설치하기</a> 를 참고하시기 바랍니다.<br>방화벽 설정 방법은 <a href="https://lindarex-career-insight.com/ubuntu-ufw-firewall-setup/" target="_blank" rel="noreferrer noopener">Ubuntu에서 UFW 방화벽 설정하기</a> 또는 <a href="https://lindarex-career-insight.com/ubuntu-iptables-setup-guide/" target="_blank" rel="noreferrer noopener">Ubuntu에서 iptables 설정하기</a> 를 참고하시기 바랍니다.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">요약(SUMMARY)</h2>



<ul class="wp-block-list">
<li><strong>호스트 식별 구성</strong>: <code>/etc/hosts</code>, <code>/etc/hostname</code> 정리</li>



<li><strong>BIND9 옵션</strong>: <code>named.conf.options</code>에서 listen, forwarders, DNSSEC, recursion 설정</li>



<li><strong>존 구성</strong>: <code>named.conf.local</code>에 정/역방향 존 선언, 존 파일 2종 생성</li>



<li><strong>검증</strong>: <code>named-checkconf</code>, <code>named-checkzone</code>으로 문법 검사 후 서비스 재시작</li>



<li><strong>조회 테스트</strong>: 서버 VM·외부 VM에서 <code>nslookup</code>, <code>dig</code>로 정/역방향 확인</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<h2 class="wp-block-heading">1. DNS 서버 VM 호스트 식별 정보 설정</h2>



<h3 class="wp-block-heading">1.1 /etc/hosts 구성</h3>



<pre class="wp-block-code"><code>$ sudo vi /etc/hosts
127.0.0.1   localhost
127.0.1.1   ns.rex.local
10.0.1.32   ns.rex.local

# The following lines are desirable for IPv6 capable hosts
::1         ip6-localhost ip6-loopback
fe00::0     ip6-localnet
ff00::0     ip6-mcastprefix
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters</code></pre>



<h3 class="wp-block-heading">1.2 /etc/hostname 구성</h3>



<pre class="wp-block-code"><code>$ sudo vi /etc/hostname
ns.rex.local</code></pre>



<p>호스트명 변경 뒤에는 <strong>VM 재시작</strong>이 필요합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. BIND9 핵심 옵션(named.conf.options)</h2>



<pre class="wp-block-code"><code>$ sudo vi /etc/bind/named.conf.options
options {
    directory "/var/cache/bind";

    dnssec-validation auto;   // 루트 신뢰앵커 기반 DNSSEC 검증
    auth-nxdomain no;         // 구형 호환 필요 시 yes
    listen-on port 53 { localhost; 10.0.1.0/24; }; // 수신 인터페이스/포트
    allow-query { any; };     // 쿼리 허용 범위
    forwarders { 8.8.8.8; };  // 상위 포워더
    recursion yes;            // 재귀 질의 허용
};</code></pre>



<ul class="wp-block-list">
<li><strong>directory</strong>: BIND 작업 디렉터리(기본 <code>/var/cache/bind</code>)</li>



<li><strong>dnssec-validation</strong>: <code>auto</code>면 루트 신뢰앵커를 사용해 검증 (DNSSEC 유효성 검사 활성화)</li>



<li><strong>listen-on</strong>: 요청을 수신할 인터페이스/포트 지정</li>



<li><strong>allow-query</strong>: 질의 허용 대상</li>



<li><strong>forwarders</strong>: 외부 이름해석 시 참조할 상위 DNS (forwarding에 사용할 IP address)</li>



<li><strong>recursion</strong>: 로컬 캐싱 목적이면 <code>yes</code> 유지 (recursive query를 활성화)</li>
</ul>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-2-1024x682.jpg" alt="Ubuntu에서 BIND9(DNS) 설정하기" class="wp-image-238" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-2-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-2-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-2-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-2.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. 로컬 DNS 및 영역(Zone) 구성</h2>



<p>이 단계에서는 BIND9에 <strong>정방향(Forward)</strong>과 <strong>역방향(Reverse)</strong> 영역을 선언하고, 각각의 존 파일을 작성합니다. 정방향 존은 <em>호스트명/FQDN → IP 주소</em> 매핑을, 역방향 존은 <em>IP 주소 → 호스트명/FQDN</em> 매핑을 담당합니다.</p>



<h3 class="wp-block-heading">3.1 /etc/bind/named.conf.local 설정</h3>



<p>우선 BIND에 두 개의 존을 알려줍니다. 하나는 <code>rex.local</code> 도메인을 책임지는 정방향 존이고, 다른 하나는 <code>10.0.1.0/24</code> 네트워크를 커버하는 역방향 존입니다.</p>



<pre class="wp-block-code"><code>$ sudo vi /etc/bind/named.conf.local

// FORWARD ZONE
zone "rex.local" IN {
    type master;
    file "rex.local.zone";
};

// REVERSE ZONE
zone "1.0.10.in-addr.arpa" IN {
    type master;
    file "rex.local.zone.rev";
};</code></pre>



<ul class="wp-block-list">
<li><code>zone "rex.local" IN { ... }</code>
<ul class="wp-block-list">
<li>이 블록은 <code>rex.local</code> 도메인에 대한 권한 존(authoritative zone)을 선언합니다. </li>



<li><code>N</code>은 클래스(Class)로, 인터넷을 의미하며 일반적으로 생략하더라도 인터넷 클래스로 해석됩니다.</li>
</ul>
</li>



<li><code>type master;</code>
<ul class="wp-block-list">
<li>이 서버를 해당 존의 <em>마스터(Primary)</em>로 설정합니다. </li>



<li>상황에 따라 <code>slave</code>(Secondary), <code>stub</code>, <code>forward</code>, <code>mirror</code>, <code>hint</code>, <code>redirect</code>, <code>static-stub</code>, <code>delegation-only</code> 등으로 구성할 수도 있습니다.</li>
</ul>
</li>



<li><code>file "rex.local.zone";</code>
<ul class="wp-block-list">
<li>정방향 존 데이터가 기록될 파일 경로입니다. </li>



<li>절대경로가 아니면 <code>named.conf.options</code>의 <code>directory</code> 설정(기본: <code>/var/cache/bind</code>)을 기준으로 해석됩니다.</li>
</ul>
</li>



<li><code>zone "1.0.10.in-addr.arpa" IN { ... }</code>
<ul class="wp-block-list">
<li>역방향 존 선언입니다. <code>10.0.1.0/24</code> 대역의 <em>바이트 순서를 뒤집어</em> 표기합니다. </li>



<li>예를 들어, /24라면 <code>1.0.10.in-addr.arpa</code>가 되며, /16 대역(<code>10.0.0.0/16</code> 또는 <code>10.0.1.0/16</code> 유사 케이스)이라면 <code>0.10.in-addr.arpa</code>처럼 더 상위 옥텟 단위로 선언합니다.</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading">3.2 정방향 존 파일 생성</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>/var/cache/bind/rex.local.zone</p>
</blockquote>



<p>다음 파일은 <code>rex.local</code> 도메인에 대한 권한 레코드를 담습니다. SOA, NS, A 레코드의 최소 구성을 예시로 제시합니다.</p>



<pre class="wp-block-code"><code>$ sudo vi /var/cache/bind/rex.local.zone

$TTL 86400
@   IN  SOA ns.rex.local. root.ns.rex.local. (
        1        ; Serial
        604800   ; Refresh
        86400    ; Retry
        2419200  ; Expire
        86400 )  ; Negative Cache TTL
;
@       IN  NS  ns.rex.local.
ns      IN  A   10.0.1.32</code></pre>



<ul class="wp-block-list">
<li><code>$TTL 86400</code>
<ul class="wp-block-list">
<li>리졸버가 레코드를 캐시하는 기본 유효시간(초)입니다. </li>



<li><code>0</code>으로 두면 캐시하지 않습니다.</li>
</ul>
</li>



<li><code>@ IN SOA ns.rex.local. root.ns.rex.local. ( ... )</code>
<ul class="wp-block-list">
<li>SOA(Start of Authority)는 존의 메타데이터와 책임 서버, 관리자 메일(마침표 앞의 <code>root@ns.rex.local</code> 의미) 등을 정의합니다. </li>



<li>이 블록은 존마다 <strong>하나만</strong> 존재해야 합니다.
<ul class="wp-block-list">
<li><code>Serial</code>: 존 데이터가 변경될 때마다 증가시키는 버전 번호(무부호 32비트 범위).</li>



<li><code>Refresh</code>: 슬레이브가 마스터에 동기화를 요청하기 전 대기 시간.</li>



<li><code>Retry</code>: 동기화 실패 시 재시도 간격.</li>



<li><code>Expire</code>: 슬레이브가 마스터와 장시간 통신이 끊긴 경우 데이터를 더 이상 권한 있는 것으로 보지 않는 시점.</li>



<li><code>Negative Cache TTL</code>: NXDOMAIN과 같은 부정 응답의 캐시 지속시간(전통적으로 최대 3시간 권장).</li>
</ul>
</li>
</ul>
</li>



<li><code>@ IN NS ns.rex.local.</code>
<ul class="wp-block-list">
<li>이 존의 권한 네임서버를 지정합니다. </li>



<li>일반적인 텍스트 포맷은 <em>owner-name / class / type / type-specific-data</em> 순서를 따릅니다. </li>



<li>여기서 <code>@</code>은 현재 존의 루트(= <code>$ORIGIN</code>)를 의미합니다.</li>
</ul>
</li>



<li><code>ns IN A 10.0.1.32</code>
<ul class="wp-block-list">
<li><code>ns.rex.local</code> 호스트의 IPv4 주소를 명시합니다(A 레코드).</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading">3.3 역방향 존 파일 생성</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>/var/cache/bind/rex.local.zone.rev</p>
</blockquote>



<p>역방향 존 파일은 IP 주소에서 이름을 찾아야 할 때 사용합니다. 아래 예시는 <code>10.0.1.32</code> → <code>ns.rex.local</code> 로 해석되도록 구성합니다.</p>



<pre class="wp-block-code"><code>$ sudo vi /var/cache/bind/rex.local.zone.rev

$TTL 86400
@   IN  SOA ns.rex.local. root.ns.rex.local. (
        2        ; Serial
        604800   ; Refresh
        86400    ; Retry
        2419200  ; Expire
        86400 )  ; Negative Cache TTL
;
@       IN  NS  ns.
32      IN  PTR ns.rex.local.</code></pre>



<ul class="wp-block-list">
<li><code>@ IN NS ns.</code>
<ul class="wp-block-list">
<li>이 역방향 존의 권한 네임서버를 지정합니다. </li>



<li><code>ns.</code> 뒤의 마침표는 FQDN 종결을 의미하며, 상대 이름으로 처리되는 것을 방지합니다.</li>
</ul>
</li>



<li><code>32 IN PTR ns.rex.local.</code>
<ul class="wp-block-list">
<li><code>10.0.1.<strong>32</strong></code>의 호스트 부분(<code>32</code>)을 사용하여 <code>ns.rex.local</code>로 역방향 매핑합니다. </li>



<li>만약 서브넷이 <code>/16</code> 등으로 더 넓다면 <code>PTR</code> 레코드의 오너(owner) 표기가 달라질 수 있으므로(예: <code>32.1</code> 형태) 네트워크 경계를 기준으로 적절히 분리해 구성해야 합니다.</li>
</ul>
</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. 설정 검사와 서비스 재시작</h2>



<p>전체 설정 파일 확인</p>



<pre class="wp-block-code"><code>$ named-checkconf</code></pre>



<p>정방향/역방향 존 파일 확인</p>



<pre class="wp-block-code"><code># 정방향 존
$ named-checkzone rex.local /var/cache/bind/rex.local.zone
zone rex.local/IN: loaded serial 1
OK

# 역방향 존
$ named-checkzone 10.0.1.32 /var/cache/bind/rex.local.zone.rev
zone 10.0.1.32/IN: loaded serial 2
OK</code></pre>



<p>오류가 없다면 서비스 재시작</p>



<pre class="wp-block-code"><code>$ sudo systemctl restart bind9.service</code></pre>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-3-1024x683.jpg" alt="Ubuntu에서 BIND9(DNS) 설정하기" class="wp-image-277" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-3-1024x683.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-3-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-3-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-3.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. DNS 서버 VM에서 조회 검증(nslookup, dig)</h2>



<p>아래 명령은 <strong>BIND가 설치된 VM(10.0.1.32)</strong>에서 실행합니다.</p>



<h3 class="wp-block-heading">5.1 nslookup</h3>



<pre class="wp-block-code"><code>$ nslookup ns.rex.local
Server:  127.0.0.53
Address: 127.0.0.53#53

Non-authoritative answer:
Name:   ns.rex.local
Address: 10.0.1.32
Name:   ns.rex.local
Address: 127.0.1.1</code></pre>



<pre class="wp-block-code"><code>$ nslookup ns.rex.local localhost.localdomain
Server:  localhost.localdomain
Address: ::1#53

Name:   ns.rex.local
Address: 10.0.1.32</code></pre>



<h3 class="wp-block-heading">5.2 dig</h3>



<pre class="wp-block-code"><code>$ dig ns.rex.local
; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.11.x-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; ns.rex.local
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR
;; flags: qr rd ra; QUERY: 1, ANSWER: 2

;; QUESTION SECTION:
;ns.rex.local.        IN A

;; ANSWER SECTION:
ns.rex.local.  0 IN A 127.0.1.1
ns.rex.local.  0 IN A 10.0.1.32</code></pre>



<pre class="wp-block-code"><code>$ dig -x 10.0.1.32
; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.11.x-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; -x 10.0.1.32
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR
;; QUESTION SECTION:
;32.1.0.10.in-addr.arpa.   IN PTR

;; ANSWER SECTION:
32.1.0.10.in-addr.arpa. 0 IN PTR ns.rex.local.</code></pre>



<p><em>.local</em>은 mDNS 예약 도메인이라 테스트 환경에 따라 경고가 보일 수 있습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. 외부 VM에서 조회 검증(nslookup, dig)</h2>



<p>아래 명령은 <strong>외부 VM(10.0.1.0/24)</strong>에서 실행하며, 해당 VM의 네임서버를 <strong>10.0.1.32</strong>로 지정해 둡니다.</p>



<h3 class="wp-block-heading">6.1 nslookup</h3>



<pre class="wp-block-code"><code>$ nslookup ns.rex.local
Server:  10.0.1.32
Address: 10.0.1.32#53

Name:   ns.rex.local
Address: 10.0.1.32</code></pre>



<pre class="wp-block-code"><code>$ nslookup 10.0.1.32
32.1.0.10.in-addr.arpa   name = ns.rex.local.</code></pre>



<h3 class="wp-block-heading">6.2 dig</h3>



<pre class="wp-block-code"><code>$ dig ns.rex.local
; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.11.x-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; ns.rex.local
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, aa
;; QUESTION SECTION:
;ns.rex.local.        IN A

;; ANSWER SECTION:
ns.rex.local. 86400 IN A 10.0.1.32

;; AUTHORITY SECTION:
rex.local.   86400 IN NS ns.rex.local.</code></pre>



<pre class="wp-block-code"><code>$ dig -x 10.0.1.32
; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.11.x-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; -x 10.0.1.32
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, aa
;; QUESTION SECTION:
;32.1.0.10.in-addr.arpa.   IN PTR

;; ANSWER SECTION:
32.1.0.10.in-addr.arpa. 86400 IN PTR ns.rex.local.

;; AUTHORITY SECTION:
1.0.10.in-addr.arpa. 86400 IN NS ns.</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<h2 class="wp-block-heading">마무리(CONCLUSION)</h2>



<p>Ubuntu에서 BIND9(DNS) 설정하기</p>



<p>Ubuntu에서 <strong>BIND9</strong>로 로컬 DNS 서버를 준비, 구성, 검증하는 흐름을 단계별로 확인했습니다. 운영 환경에서는 <strong>DNSSEC</strong>, <strong>ACL(allow-query/allow-recursion)</strong>, <strong>로깅</strong>, <strong>보조(slave) 서버</strong>, <strong>뷰(View)</strong> 등의 보안·가용성 항목도 함께 고려해 안정성과 확장성을 높이길 권장합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<h2 class="wp-block-heading">참고 자료(REFERENCES)</h2>



<ul class="wp-block-list">
<li><a href="https://bind9.readthedocs.io/en/latest/index.html" target="_blank" rel="noreferrer noopener">https://bind9.readthedocs.io/en/latest/index.html</a></li>



<li><a href="https://wiki.debian.org/Bind9" target="_blank" rel="noreferrer noopener">https://wiki.debian.org/Bind9</a></li>



<li><a href="https://www.zytrax.com/books/dns/ch8/" target="_blank" rel="noreferrer noopener">https://www.zytrax.com/books/dns/ch8/</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<pre class="wp-block-verse">취업, 이직, 퇴사, 커리어 고민으로 힘든가요?<br><br><a href="https://lindarex-career-insight.com/notices/" target="_blank" rel="noreferrer noopener">Notices</a>를 확인하고 상담 서비스를 받으세요.<br><br>1분만 투자하세요.<br>1분으로 1년을 아끼고, 10년의 커리어가 달라져요.</pre>
<p>게시물 <a href="https://lindarex-career-insight.com/ubuntu-bind9-dns-local-nameserver-setup-guide/">Ubuntu에서 BIND9(DNS) 설정하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ubuntu에서 iptables 설정하기</title>
		<link>https://lindarex-career-insight.com/ubuntu-iptables-setup-guide/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Thu, 18 Sep 2025 15:09:42 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[INPUT FORWARD OUTPUT 정책]]></category>
		<category><![CDATA[iptables -L 옵션]]></category>
		<category><![CDATA[iptables -S 차이]]></category>
		<category><![CDATA[iptables 설정]]></category>
		<category><![CDATA[iptables 정책]]></category>
		<category><![CDATA[iptables 조회]]></category>
		<category><![CDATA[iptables 체인 만들기]]></category>
		<category><![CDATA[iptables 카운터 초기화]]></category>
		<category><![CDATA[Ubuntu 방화벽]]></category>
		<category><![CDATA[ufw 비활성화]]></category>
		<category><![CDATA[리눅스 방화벽]]></category>
		<category><![CDATA[우분투 iptables]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=648</guid>

					<description><![CDATA[<p>Ubuntu에서 iptables 설정하기 iptables는 Linux 커널의 Netfilter 기능을 사용자 공간에서 다루기 위한 도구로, 방화벽 정책과 NAT를 구성할 때 널리 사용됩니다. 시스템 관리자는 테이블(table), 체인…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/ubuntu-iptables-setup-guide/">Ubuntu에서 iptables 설정하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ubuntu에서 iptables 설정하기</p>



<p><code>iptables</code>는 Linux 커널의 Netfilter 기능을 사용자 공간에서 다루기 위한 도구로, 방화벽 정책과 NAT를 구성할 때 널리 사용됩니다. 시스템 관리자는 테이블(table), 체인(chain), 규칙(rule)의 세 가지 축을 조합해 네트워크 트래픽을 제어합니다.</p>



<p>프로토콜별 도구는 다음과 같이 구분됩니다.<br><code>iptables</code>(IPv4), <code>ip6tables</code>(IPv6), <code>arptables</code>(ARP), <code>ebtables</code>(이더넷 프레임).</p>



<p>일반적인 Linux 배포판에서는 <code>/usr/sbin/iptables</code> 경로에 설치됩니다. 또한 iptables의 뒤를 잇는 차세대 프레임워크로 <strong>nftables</strong>가 있으며, 코드 중복을 줄이고 처리 경로를 단순화했다는 점이 알려져 있습니다. (상세 소개는 <a href="https://en.wikipedia.org/wiki/Nftables" target="_blank" rel="noreferrer noopener">https://en.wikipedia.org/wiki/Nftables</a> 참고)</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h3 class="wp-block-heading">준비사항 (PREREQUISITE)</h3>



<p>테스트는 <strong>Ubuntu 서버 환경</strong>을 전제로 하며, 명령 실행에는 <strong>root 권한</strong>이 필요합니다. UFW(Uncomplicated Firewall)를 함께 쓰는 경우 충돌을 피하려면 설정 전에 <strong>UFW를 비활성화 또는 제거</strong>하는 편이 안전합니다.</p>



<p>예제는 <strong>VMware® Workstation 15 Pro(15.5.1 build-15018445)</strong> 상에서 구동되는 <strong>Ubuntu 18.04.4 LTS(Bionic Beaver, 64-bit, Server)</strong>로 검증했습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h3 class="wp-block-heading">요약 (SUMMARY)</h3>



<ul class="wp-block-list">
<li>iptables 확인·초기화 방법</li>



<li>규칙 조회 옵션과 출력 형식 구분</li>



<li>핵심 용어(타깃/체인/테이블/파라미터/커맨드) 정리</li>



<li>규칙 추가/확인/삭제/삽입/교체/정책/카운터 초기화 등 실전 명령</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h2 class="wp-block-heading">iptables 개요</h2>



<p><code>iptables</code>는 커널 2.4부터 <code>ipchains</code>를 대체한 방화벽 도구로, Netfilter의 패킷 필터링을 <strong>사용자 공간에서 선언적으로 제어</strong>합니다. 상태 추적, 애플리케이션 계층 매치, 속도 제한, 정책 관리 등 다양한 확장 모듈과 함께 활용됩니다. Ubuntu 18.04에는 기본적으로 <code>iptables</code>와 프런트엔드 도구인 <strong>UFW</strong>가 포함됩니다. 아래 예제는 <strong>root 권한</strong>을 가진 사용자가 직접 iptables를 다룬다는 가정으로 진행합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<h2 class="wp-block-heading">1. iptables 확인 및 초기화</h2>



<p><strong>주의:</strong> 원격 서버에서 초기화·정책 변경을 수행할 때는 SSH 차단을 피하기 위해 <strong>허용 규칙을 먼저 적용</strong>한 뒤 정책을 강화하세요.</p>



<h3 class="wp-block-heading">1.1. iptables 확인</h3>



<pre class="wp-block-code"><code># which iptables
/sbin/iptables

# iptables -V
iptables v1.6.1</code></pre>



<h3 class="wp-block-heading">1.2. iptables 초기화</h3>



<p>모든 체인의 모든 규칙 제거</p>



<pre class="wp-block-code"><code># iptables -F</code></pre>



<p>기본 체인을 제외한 사용자 정의 체인 제거</p>



<pre class="wp-block-code"><code># iptables -X</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<h2 class="wp-block-heading">2. iptables 조회</h2>



<p>아래 출력은 초기 상태를 가정한 예시입니다.</p>



<h3 class="wp-block-heading">기본 조회</h3>



<pre class="wp-block-code"><code># iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination</code></pre>



<h3 class="wp-block-heading">조회 옵션</h3>



<ul class="wp-block-list">
<li><code>-v</code>, <code>--verbose</code> : 체인별/규칙별 패킷·바이트 카운터, 인터페이스 등 상세 표시</li>



<li><code>-n</code>, <code>--numeric</code> : 호스트/서비스 이름 대신 <strong>IP·포트 숫자</strong>로 표시</li>



<li><code>-x</code>, <code>--exact</code> : 카운터를 정확한 값으로 확장</li>



<li><code>--line-numbers</code> : 각 규칙 앞에 번호를 부여</li>
</ul>



<h3 class="wp-block-heading">상세 조회 예시</h3>



<pre class="wp-block-code"><code># iptables -L -v
Chain INPUT (policy ACCEPT 10 packets, 676 bytes)
pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 5 packets, 812 bytes)
pkts bytes target prot opt in out source destination</code></pre>



<h3 class="wp-block-heading">IP/포트 숫자 표기로 조회</h3>



<pre class="wp-block-code"><code># iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination</code></pre>



<h3 class="wp-block-heading">정확한 값으로 확장</h3>



<pre class="wp-block-code"><code># iptables -L -x
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination</code></pre>



<h3 class="wp-block-heading">라인 번호 포함 조회</h3>



<pre class="wp-block-code"><code># iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination

Chain FORWARD (policy ACCEPT)
num target prot opt source destination

Chain OUTPUT (policy ACCEPT)
num target prot opt source destination</code></pre>



<h3 class="wp-block-heading">전체 규칙 ‘선언형’ 출력</h3>



<pre class="wp-block-code"><code># iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT</code></pre>



<h3 class="wp-block-heading">카운터 포함한 선언형 출력</h3>



<pre class="wp-block-code"><code># iptables -S -v
-P INPUT ACCEPT -c 117 8240
-P FORWARD ACCEPT -c 0 0
-P OUTPUT ACCEPT -c 103 13208</code></pre>



<ul class="wp-block-list">
<li><code>-L</code>은 사람이 읽기 좋은 목록(참조용), <code>-S</code>는 재적용 가능한 선언형 출력(iptables-restore용)입니다.</li>
</ul>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-1-1024x682.jpg" alt="우분투 환경에 iptables 설정하기" class="wp-image-234" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-1-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-1-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-1-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/001-1.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Ubuntu에서 iptables 설정하기</figcaption></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<h2 class="wp-block-heading">3. iptables 용어</h2>



<p>iptables는 <em>테이블(table)</em> → <em>체인(chain)</em> → <em>규칙(rule)</em>의 3단 구성으로 동작합니다. 각 규칙이 트래픽과 일치하면, 해당 규칙에 지정한 <strong>타깃(target)</strong> 동작이 실행됩니다.</p>



<h3 class="wp-block-heading">3.1. target(타깃)</h3>



<p><strong>타깃</strong>은 “규칙에 일치했을 때 무엇을 할지”를 정의합니다. 대표적인 타깃은 다음과 같습니다.</p>



<ul class="wp-block-list">
<li><strong>ACCEPT</strong> — 패킷을 통과시킵니다.</li>



<li><strong>DROP</strong> — 무응답으로 폐기합니다(상대는 타임아웃으로 인지).</li>



<li><strong>REJECT</strong> — 오류 응답(ICMP/포트 거부 등)을 돌려보내며 차단합니다.</li>



<li><strong>LOG</strong> — 규칙에 일치한 패킷을 syslog에 기록합니다(허용/차단과 별개).</li>



<li><strong>RETURN</strong> — 현재 체인 처리를 중단하고, 호출 지점의 다음 규칙으로 돌아갑니다.</li>



<li><strong>QUEUE</strong> — 패킷을 사용자 공간 큐로 전달합니다(특수한 패킷 처리에 사용).</li>



<li><strong>SNAT</strong> — 소스 주소 변환(출발지 IP/포트 재작성, 보통 <code>POSTROUTING</code>에서).</li>



<li><strong>DNAT</strong> — 목적지 주소 변환(도착지 IP/포트 재작성, 보통 <code>PREROUTING</code>에서).</li>
</ul>



<p><strong>예시:</strong> 80/tcp 허용과 23/tcp(telnet) 차단 로그</p>



<pre class="wp-block-code"><code>## 80 허용
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT

## 23 접근 시 로그 남기고 드롭
#iptables -A INPUT -p tcp --dport 23 -j LOG --log-prefix "TELNET_BLOCK "
#iptables -A INPUT -p tcp --dport 23 -j DROP</code></pre>



<h3 class="wp-block-heading">3.2. chain(체인)</h3>



<p><strong>체인</strong>은 “규칙들의 순서 있는 목록”입니다. 위에서 아래로 평가하며, 어떤 규칙에 일치해 타깃이 실행되면 그 체인에서는 더 내려가지 않습니다. 체인은 트래픽이 흐르는 시점/방향에 따라 다음과 같이 쓰입니다.</p>



<ul class="wp-block-list">
<li><strong>INPUT</strong> — 이 호스트로 <em>들어오는</em> 트래픽에 대한 정책.</li>



<li><strong>OUTPUT</strong> — 이 호스트에서 <em>나가는</em> 트래픽에 대한 정책.</li>



<li><strong>FORWARD</strong> — 라우팅되어 <em>경유</em>만 하는 트래픽(게이트웨이/라우터에서).</li>



<li><strong>PREROUTING</strong> — 라우팅 결정 <em>이전</em> 단계(주로 DNAT).</li>



<li><strong>POSTROUTING</strong> — 라우팅 처리 <em>이후</em> 단계(주로 SNAT/마스커레이드).</li>
</ul>



<p><code>INPUT</code>·<code>FORWARD</code>·<code>OUTPUT</code>는 기본 체인이므로 삭제할 수 없습니다. 필요하면 <code>-N</code>으로 사용자 정의 체인을 만들고, <code>-j</code>로 분기해 재사용 가능한 정책 블록을 구성합니다.</p>



<p><strong>예시:</strong> SSH 방화벽을 별도 체인으로 분리</p>



<pre class="wp-block-code"><code>## 체인 생성
# iptables -N SSH_GUARD

## INPUT에서 SSH_GUARD로 분기
# iptables -A INPUT -p tcp --dport 22 -j SSH_GUARD

## 내부망은 허용, 그 외는 지연 후 거부 같은 커스텀 로직 배치 가능
# iptables -A SSH_GUARD -s 10.0.0.0/8 -j ACCEPT
#i ptables -A SSH_GUARD -j REJECT</code></pre>



<h3 class="wp-block-heading">3.3. table(테이블)</h3>



<p><strong>테이블</strong>은 “어떤 목적의 처리를 할 것인지”를 구분합니다. 명령에 <code>-t</code>를 지정해 선택하며, 테이블마다 제공하는 기본 체인이 다릅니다.</p>



<ul class="wp-block-list">
<li><strong>filter:</strong> 접근 제어(허용/차단/로그)의 중심. 기본 테이블이므로 <code>-t</code>를 생략하면 <code>filter</code>가 선택됩니다. 
<ul class="wp-block-list">
<li>기본 체인: <code>INPUT</code>, <code>FORWARD</code>, <code>OUTPUT</code>.</li>
</ul>
</li>



<li><strong>nat:</strong> 주소 변환(SNAT/DNAT). 신규 연결 시 참조합니다. 
<ul class="wp-block-list">
<li>기본 체인: <code>PREROUTING</code>, <code>INPUT</code>, <code>OUTPUT</code>, <code>POSTROUTING</code>. (IPv6 NAT는 커널 버전에 따라 지원됨)</li>
</ul>
</li>



<li><strong>mangle:</strong> 패킷 성형/마킹(DSCP/TTL/mark 등). 
<ul class="wp-block-list">
<li>기본 체인: <code>PREROUTING</code>, <code>INPUT</code>, <code>FORWARD</code>, <code>OUTPUT</code>, <code>POSTROUTING</code>.</li>
</ul>
</li>



<li><strong>raw:</strong> 연결 추적(Conntrack) 예외 지정(NOTRACK). 
<ul class="wp-block-list">
<li>기본 체인: <code>PREROUTING</code>, <code>OUTPUT</code>.</li>
</ul>
</li>



<li><strong>security:</strong> SELinux 등 MAC(강제 접근 제어) 정책 연계. 
<ul class="wp-block-list">
<li>기본 체인: <code>INPUT</code>, <code>FORWARD</code>, <code>OUTPUT</code>.</li>
</ul>
</li>
</ul>



<p><strong>예시:</strong> NAT 포워딩</p>



<pre class="wp-block-code"><code>## 외부 203.0.113.10:8080 → 내부 10.0.1.50:80
# iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 8080 -j DNAT --to-destination 10.0.1.50:80

## 사설 대역을 외부로 NAT
# iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -o eth0 -j MASQUERADE</code></pre>



<h3 class="wp-block-heading">3.4. parameter(파라미터)</h3>



<p><strong>파라미터</strong>는 규칙의 “조건”과 “작동 방식”을 구체화합니다. 자주 쓰는 항목은 다음과 같습니다.</p>



<ul class="wp-block-list">
<li><code>-4</code> / <code>-6:</code> IPv4/IPv6 전용 규칙 파일과 혼용 시 구분에 사용(restore 스크립트에서 유용).</li>



<li><code>-p:</code> 프로토콜 지정(예: <code>tcp</code>, <code>udp</code>, <code>icmp</code>).</li>



<li><code>-s</code> / <code>-d:</code> 출발지/목적지(호스트명, IP, CIDR 모두 가능).</li>



<li><code>-i</code> / <code>-o:</code> 인바운드/아웃바운드 인터페이스.</li>



<li><code>-m &lt;모듈&gt;:</code> 확장 매치 사용(예: <code>-m state</code>, <code>-m conntrack</code>, <code>-m multiport</code> 등).</li>



<li><code>-j &lt;타깃&gt;:</code> 일치 시 실행할 동작 지정(ACCEPT/DROP/REJECT/LOG/SNAT/DNAT/…).</li>



<li><code>-g &lt;체인&gt;:</code> 지정 체인으로 “이동”하여 계속 처리(<code>-j</code>와 유사하지만 RETURN 동작 차이가 있습니다).</li>



<li><code>-f:</code> 조각난 IPv4 패킷의 두 번째 이후 조각만 매치.</li>



<li><code>-c:</code> 규칙 추가/교체 시 카운터(패킷/바이트) 초기값 설정.</li>
</ul>



<p><strong>예시:</strong> 여러 포트를 한 번에 허용(<code>multiport</code> 모듈)</p>



<pre class="wp-block-code"><code># iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT</code></pre>



<h3 class="wp-block-heading">3.5. command(커맨드)</h3>



<p><strong>커맨드</strong>는 “규칙을 어떻게 다룰지(추가/삽입/교체/삭제/조회/초기화 등)”를 지정합니다. 핵심 명령은 다음과 같습니다.</p>



<ul class="wp-block-list">
<li><code>-A</code> / <code>--append:</code> 선택한 체인의 <em>끝</em>에 규칙 추가.</li>



<li><code>-I</code> / <code>--insert:</code> 지정 위치(<em>번호</em>)에 규칙 삽입.</li>



<li><code>-R</code> / <code>--replace:</code> 특정 <em>번호</em> 규칙을 교체.</li>



<li><code>-D</code> / <code>--delete:</code> 규칙식 또는 <em>번호</em>로 삭제.</li>



<li><code>-C</code> / <code>--check:</code> 규칙이 이미 존재하는지 확인(중복 추가 방지에 유용).</li>



<li><code>-L</code> / <code>--list:</code> 읽기 쉬운 목록으로 조회(옵션: <code>-v</code>, <code>-n</code>, <code>-x</code>, <code>--line-numbers</code>).</li>



<li><code>-S</code> / <code>--list-rules:</code> <em>재적용 가능한</em> 선언형 출력(백업/배포 자동화에 적합).</li>



<li><code>-F</code> / <code>--flush:</code> 체인 내 규칙을 모두 비웁니다.</li>



<li><code>-N</code> / <code>-E</code> / <code>-X:</code> 사용자 정의 체인 생성/이름변경/삭제.</li>



<li><code>-P</code> / <code>--policy:</code> 기본 체인의 정책을 ACCEPT/DROP 등으로 설정.</li>



<li><code>-Z</code> / <code>--zero:</code> 규칙/체인의 카운터를 0으로 초기화.</li>
</ul>



<p><strong>예시:</strong> 규칙 삽입/교체/삭제</p>



<pre class="wp-block-code"><code>## 1번 위치에 SSH 허용 삽입
# iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT

## 1번 규칙을 내부망 허용으로 교체
# iptables -R INPUT 1 -p tcp -s 10.0.0.0/8 --dport 22 -j ACCEPT

## 1번 규칙 삭제
# iptables -D INPUT 1</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>타깃은 “일치 시 동작”, 체인은 “평가 순서와 방향”, 테이블은 “처리 목적”을 결정합니다. 파라미터로 조건을 상세히 정의하고, 커맨드로 규칙을 관리합니다. 이 네 요소를 일관된 원칙으로 설계하면, 정책 변경·배포·복구가 모두 쉬워집니다.</p>
</blockquote>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-1-1024x682.jpg" alt="우분투 환경에 iptables 설정하기" class="wp-image-237" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-1-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-1-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-1-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/002-1.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. iptables 사용 방법</h2>



<h3 class="wp-block-heading">4.1. 규칙 추가(append)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -A chain rule-specification
# iptables &#91;-t TABLE-NAME] -A chain -m MATCH-NAME &#91;match-options] -j TARGET-NAME &#91;target-options]</code></pre>



<pre class="wp-block-code"><code>## 로컬 루프백 허용
# iptables -A INPUT -i lo -j ACCEPT</code></pre>



<h3 class="wp-block-heading">4.2. 규칙 확인(check)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -C chain rule-specification
# iptables &#91;-t TABLE-NAME] -C chain -m MATCH-NAME &#91;match-options] -j TARGET-NAME &#91;target-options]</code></pre>



<pre class="wp-block-code"><code>## TCP 8080 허용 규칙 존재 여부
iptables -C INPUT -p tcp --dport 8080 -j ACCEPT</code></pre>



<h3 class="wp-block-heading">4.3. 규칙 삭제(delete, 규칙식)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -D chain rule-specification
# iptables &#91;-t TABLE-NAME] -D chain -m MATCH-NAME &#91;match-options] -j TARGET-NAME &#91;target-options]</code></pre>



<pre class="wp-block-code"><code>## TCP 22 REJECT 규칙 삭제
iptables -D INPUT -p tcp -m tcp --dport 22 -j REJECT</code></pre>



<h3 class="wp-block-heading">4.4. 규칙 삭제(delete, 번호)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -D chain rule-number
# iptables &#91;-t TABLE-NAME] -D chain rule-number</code></pre>



<pre class="wp-block-code"><code>## FORWARD 체인 1번 규칙 삭제
iptables -D FORWARD 1</code></pre>



<h3 class="wp-block-heading">4.5. 규칙 삽입(insert)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -I &#91;rule-number] rule-specification
# iptables &#91;-t TABLE-NAME] -I chain &#91;rule-number] -m MATCH-NAME &#91;match-options] -j TARGET-NAME &#91;target-options]</code></pre>



<pre class="wp-block-code"><code>## INPUT 1번 위치에 UDP 53 DROP
iptables -I INPUT 1 -p udp --dport 53 -j DROP
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h3 class="wp-block-heading">4.6. 규칙 교체(replace)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -R rule-number rule-specification
# iptables &#91;-t TABLE-NAME] -R chain rule-number -m MATCH-NAME &#91;match-options] -j TARGET-NAME &#91;target-options]</code></pre>



<pre class="wp-block-code"><code>## INPUT 1번을 10.0.1.0/24 → TCP 8080 허용으로 교체
iptables -R INPUT 1 -p tcp -s 10.0.1.0/24 --dport 8080 -j ACCEPT</code></pre>



<h3 class="wp-block-heading">4.7. 규칙 조회(list)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -L &#91;chain &#91;rule-number]] &#91;options]
# iptables &#91;-t TABLE-NAME] -L &#91;chain &#91;rule-number]] &#91;options]</code></pre>



<pre class="wp-block-code"><code>## 서비스 이름 기반
# iptables -L

## 포트 번호 기반
# iptables -L -n</code></pre>



<h3 class="wp-block-heading">4.8. 규칙 모두 삭제(flush)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -F &#91;chain &#91;rule-number]] &#91;options]
# iptables &#91;-t TABLE-NAME] -F &#91;chain &#91;rule-number]] &#91;options]</code></pre>



<pre class="wp-block-code"><code>## 모든 체인 비우기
# iptables -F

## FORWARD 체인만 비우기
# iptables -F FORWARD</code></pre>



<h3 class="wp-block-heading">4.9. 규칙 출력(list-rules)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -S &#91;chain &#91;rule-number]]
# iptables &#91;-t TABLE-NAME] -S &#91;chain &#91;rule-number]]</code></pre>



<pre class="wp-block-code"><code># iptables -S OUTPUT 1</code></pre>



<h3 class="wp-block-heading">4.10. 사용자 정의 체인 생성</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -N chain
# iptables &#91;-t TABLE-NAME] -N chain</code></pre>



<pre class="wp-block-code"><code># iptables -N rex-chain-income</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-dots"/>



<h3 class="wp-block-heading">4.11. 사용자 정의 체인 이름 변경</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -E old-chain-name new-chain-name
# iptables &#91;-t TABLE-NAME] -E old-chain-name new-chain-name</code></pre>



<pre class="wp-block-code"><code># iptables -E rex-chain-income rex-chain-income-new</code></pre>



<h3 class="wp-block-heading">4.12. 사용자 정의 체인 삭제</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -X &#91;chain]
# iptables &#91;-t TABLE-NAME] -X &#91;chain]</code></pre>



<pre class="wp-block-code"><code># iptables -X rex-chain-income-new</code></pre>



<h3 class="wp-block-heading">4.13. 기본 체인 정책(policy) 설정</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -P chain target
# iptables &#91;-t TABLE-NAME] -P chain -j TARGET-NAME &#91;target-options]</code></pre>



<pre class="wp-block-code"><code>## FORWARD 정책을 DROP으로 강화
# iptables -P FORWARD DROP</code></pre>



<h3 class="wp-block-heading">4.14. 카운터 초기화(zero)</h3>



<pre class="wp-block-code"><code># iptables &#91;table] -Z &#91;chain &#91;rule-number]] &#91;options]
# iptables &#91;-t TABLE-NAME] -Z &#91;chain &#91;rule-number]] &#91;options]</code></pre>



<pre class="wp-block-code"><code># iptables -Z FORWARD</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">마무리(CONCLUSION)</h2>



<p>Ubuntu에서 iptables 설정하기</p>



<p>여기까지 Ubuntu 환경에서 <code>iptables</code>로 방화벽과 NAT 정책을 구성·조회·관리하는 방법을 정리했습니다. 보안을 강화할 수 있지만, 규칙 순서·기본 정책 설정 오류로 원격 접속이 끊길 수 있으니 적용 전후로 꼭 점검하시기 바랍니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://www.linuxtopia.org/index.html" target="_blank" rel="noreferrer noopener">https://www.linuxtopia.org/index.html</a></li>



<li><a href="https://fedoraproject.org/wiki/How_to_edit_iptables_rules" target="_blank" rel="noreferrer noopener">https://fedoraproject.org/wiki/How_to_edit_iptables_rules</a></li>



<li><a href="https://ko.wikipedia.org/wiki/iptables" target="_blank" rel="noreferrer noopener">https://ko.wikipedia.org/wiki/iptables</a></li>



<li><a href="https://linux.die.net/man/8/iptables" target="_blank" rel="noreferrer noopener">https://linux.die.net/man/8/iptables</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<pre class="wp-block-verse">취업, 이직, 퇴사, 커리어 고민으로 힘든가요?<br><br><a href="https://lindarex-career-insight.com/notices/" target="_blank" rel="noreferrer noopener">Notices</a>를 확인하고 상담 서비스를 받으세요.<br><br>1분만 투자하세요.<br>1분으로 1년을 아끼고, 10년의 커리어가 달라져요.</pre>
<p>게시물 <a href="https://lindarex-career-insight.com/ubuntu-iptables-setup-guide/">Ubuntu에서 iptables 설정하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ubuntu에서 UFW 방화벽 설정하기</title>
		<link>https://lindarex-career-insight.com/ubuntu-ufw-firewall-setup/</link>
		
		<dc:creator><![CDATA[REX]]></dc:creator>
		<pubDate>Wed, 17 Sep 2025 07:03:22 +0000</pubDate>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[ubuntu firewall]]></category>
		<category><![CDATA[ubuntu ufw]]></category>
		<category><![CDATA[ubuntu 방화벽 설정]]></category>
		<category><![CDATA[ubuntu 보안 설정]]></category>
		<category><![CDATA[ufw ip 차단]]></category>
		<category><![CDATA[ufw ping 차단]]></category>
		<category><![CDATA[ufw rule 삭제]]></category>
		<category><![CDATA[ufw 사용법]]></category>
		<category><![CDATA[ufw 포트 허용]]></category>
		<category><![CDATA[리눅스 방화벽]]></category>
		<guid isPermaLink="false">https://lindarex-career-insight.com/?p=632</guid>

					<description><![CDATA[<p>Ubuntu에서 UFW 방화벽 설정하기 리눅스에서 보안을 강화하기 위해 방화벽 설정은 필수적입니다. Ubuntu에서는 iptables를 보다 쉽게 다룰 수 있도록 UFW(Uncomplicated Firewall) 라는 도구를 제공합니…</p>
<p>게시물 <a href="https://lindarex-career-insight.com/ubuntu-ufw-firewall-setup/">Ubuntu에서 UFW 방화벽 설정하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Ubuntu에서 UFW 방화벽 설정하기</p>



<p>리눅스에서 보안을 강화하기 위해 방화벽 설정은 필수적입니다. Ubuntu에서는 <code>iptables</code>를 보다 쉽게 다룰 수 있도록 <strong>UFW(Uncomplicated Firewall)</strong> 라는 도구를 제공합니다.</p>



<p>UFW는 Python으로 작성되었으며 GPL 라이선스로 배포되고, Ubuntu 18.04 LTS 이후 버전에서 기본적으로 사용할 수 있습니다.</p>



<p>이번 글에서는 Ubuntu 환경에서 UFW를 설치하고 활용하는 방법을 단계별로 정리했습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">준비사항 (Prerequisites)</h2>



<ul class="wp-block-list">
<li>Ubuntu 서버 및 관리자 권한(sudo)</li>



<li>테스트는 <strong>VMware Workstation 15 Pro</strong> 위에 설치된 <strong>Ubuntu 18.04.3 LTS Server(64-bit)</strong> 환경에서 진행되었습니다.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">주요 설정 항목 (Summary)</h2>



<ol class="wp-block-list">
<li>UFW 활성화 / 비활성화</li>



<li>방화벽 상태 확인</li>



<li>기본 정책(Default Rules) 조회 및 변경</li>



<li>특정 포트/프로토콜 허용·차단</li>



<li>룰(rule) 삭제</li>



<li>서비스명 기반 허용·차단</li>



<li>IP/서브넷 기반 제어</li>



<li>Ping(ICMP) 허용·차단</li>



<li>(선택) UFW 제거 방법</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. UFW 활성화 및 비활성화</h2>



<ul class="wp-block-list">
<li>UFW는 설치 직후 비활성화 상태입니다.</li>
</ul>



<pre class="wp-block-code"><code># 활성화
$ sudo ufw enable

# 비활성화
$ sudo ufw disable</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. 현재 상태 확인</h2>



<pre class="wp-block-code"><code>$ sudo ufw status verbose
Status: inactive</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. 기본 규칙(Default Rules) 확인</h2>



<pre class="wp-block-code"><code>$ sudo ufw show raw</code></pre>



<ul class="wp-block-list">
<li>규칙은 <code>/etc/ufw/user.rules</code> 파일에 저장되며, <code>ufw-user-input</code>, <code>ufw-before-logging-input</code> 등의 체인으로 관리됩니다.</li>
</ul>



<pre class="wp-block-code"><code>$ sudo cat /etc/ufw/user.rules
*filter
:ufw-user-input - &#91;0:0]
:ufw-user-output - &#91;0:0]
:ufw-user-forward - &#91;0:0]
:ufw-before-logging-input - &#91;0:0]
:ufw-before-logging-output - &#91;0:0]
:ufw-before-logging-forward - &#91;0:0]
:ufw-user-logging-input - &#91;0:0]
:ufw-user-logging-output - &#91;0:0]
:ufw-user-logging-forward - &#91;0:0]
:ufw-after-logging-input - &#91;0:0]
:ufw-after-logging-output - &#91;0:0]
:ufw-after-logging-forward - &#91;0:0]
:ufw-logging-deny - &#91;0:0]
:ufw-logging-allow - &#91;0:0]
:ufw-user-limit - &#91;0:0]
:ufw-user-limit-accept - &#91;0:0]
### RULES

### END RULES

### LOGGING
-A ufw-after-logging-input -j LOG --log-prefix "&#91;UFW BLOCK] " -m limit --limit 3/min --limit-burst 10
-A ufw-after-logging-forward -j LOG --log-prefix "&#91;UFW BLOCK] " -m limit --limit 3/min --limit-burst 10
-I ufw-logging-deny -m conntrack --ctstate INVALID -j RETURN -m limit --limit 3/min --limit-burst 10
-A ufw-logging-deny -j LOG --log-prefix "&#91;UFW BLOCK] " -m limit --limit 3/min --limit-burst 10
-A ufw-logging-allow -j LOG --log-prefix "&#91;UFW ALLOW] " -m limit --limit 3/min --limit-burst 10
### END LOGGING

### RATE LIMITING
-A ufw-user-limit -m limit --limit 3/minute -j LOG --log-prefix "&#91;UFW LIMIT BLOCK] "
-A ufw-user-limit -j REJECT
-A ufw-user-limit-accept -j ACCEPT
### END RATE LIMITING
COMMIT</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="678" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-1024x678.jpg" alt="Ubuntu에서 UFW 방화벽 설정하기" class="wp-image-133" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-1024x678.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-300x199.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/003-768x509.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/003.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">4. 기본 정책 변경</h2>



<pre class="wp-block-code"><code># 모든 연결 허용
$ sudo ufw default allow</code></pre>



<pre class="wp-block-code"><code># 모든 연결 차단
$ sudo ufw default deny</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. 포트 단위 규칙 추가/차단</h2>



<pre class="wp-block-code"><code># TCP 8080 허용
$ sudo ufw allow 8080/tcp

# TCP 8080 차단
$ sudo ufw deny 8080/tcp

# UDP 22 허용
$ sudo ufw allow 22/udp

# TCP/UDP 53 허용 (DNS)
$ sudo ufw allow 53</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. 규칙 삭제</h2>



<pre class="wp-block-code"><code>$ sudo ufw delete deny 8080/tcp
$ sudo ufw delete deny 22/udp
$ sudo ufw delete deny 53</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. 서비스명으로 제어</h2>



<ul class="wp-block-list">
<li>서비스 이름은 <code>/etc/services</code> 파일에서 확인할 수 있습니다.</li>
</ul>



<pre class="wp-block-code"><code># 서비스 목록 조회
$ cat /etc/services

# SSH 허용
$ sudo ufw allow ssh

# SSH 차단
$ sudo ufw deny ssh</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8. IP 기반 규칙</h2>



<pre class="wp-block-code"><code># 특정 IP 허용
$ sudo ufw allow from 192.168.10.20

# 특정 IP 차단
$ sudo ufw deny from 192.168.10.20

# 서브넷 허용
$ sudo ufw allow from 192.168.10.0/24

# 특정 IP, 포트 22만 허용
$ sudo ufw allow from 192.168.10.20 to any port 22 proto tcp</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="682" src="https://lindarex-career-insight.com/wp-content/uploads/2024/07/005-1024x682.jpg" alt="Ubuntu에서 UFW 방화벽 설정하기" class="wp-image-137" srcset="https://lindarex-career-insight.com/wp-content/uploads/2024/07/005-1024x682.jpg 1024w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/005-300x200.jpg 300w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/005-768x512.jpg 768w, https://lindarex-career-insight.com/wp-content/uploads/2024/07/005.jpg 1280w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:var(--wp--preset--spacing--60)" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">9. Ping(ICMP) 허용·차단</h2>



<ul class="wp-block-list">
<li>기본적으로 UFW는 ping 요청을 허용합니다. 
<ul class="wp-block-list">
<li>제한하려면 <code>/etc/ufw/before.rules</code> 파일을 수정해야 합니다.</li>
</ul>
</li>
</ul>



<pre class="wp-block-code"><code>$ sudo vi /etc/ufw/before.rules</code></pre>



<pre class="wp-block-code"><code># Ping(ICMP) 허용

...
### ok icmp codes
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type source-quench -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT
…</code></pre>



<pre class="wp-block-code"><code># Ping(ICMP) 차단

…
### ok icmp codes
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type source-quench -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP
…</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">10. (선택) UFW 제거</h2>



<pre class="wp-block-code"><code># 설정 파일 유지한 채 삭제
$ sudo apt remove ufw
$ sudo apt remove --auto-remove ufw

# 설정 파일까지 삭제 (단, 사용자 홈 디렉터리의 설정 파일은 유지)
$ sudo apt purge ufw
$ sudo apt purge --auto-remove ufw</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">마무리</h2>



<p>Ubuntu에서 UFW 방화벽 설정하기</p>



<p>이로써 Ubuntu 환경에서 <strong>UFW 방화벽 설정</strong>을 완료했습니다.<br>다음 글에서는 보다 세밀한 제어가 가능한 <strong>iptables 설정 방법</strong>을 다룰 예정입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://help.ubuntu.com/community/UFW" target="_blank" rel="noreferrer noopener">https://help.ubuntu.com/community/UFW</a></li>



<li><a href="http://manpages.ubuntu.com/manpages/bionic/en/man8/ufw.8.html" target="_blank" rel="noreferrer noopener">http://manpages.ubuntu.com/manpages/bionic/en/man8/ufw.8.html</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-wide"/>



<pre class="wp-block-verse">취업, 이직, 퇴사, 커리어 고민으로 힘든가요?<br><br><a href="https://lindarex-career-insight.com/notices/" target="_blank" rel="noreferrer noopener">Notices</a>를 확인하고 상담 서비스를 받으세요.<br><br>1분만 투자하세요.<br>1분으로 1년을 아끼고, 10년의 커리어가 달라져요.</pre>
<p>게시물 <a href="https://lindarex-career-insight.com/ubuntu-ufw-firewall-setup/">Ubuntu에서 UFW 방화벽 설정하기</a>이 <a href="https://lindarex-career-insight.com">커리어 인사이트</a>에 처음 등장했습니다.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
