<?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></title>
	<atom:link href="https://blog.kwt.co.kr/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.kwt.co.kr/</link>
	<description>여러분의 돈과 시간을 낭비하지마세요.</description>
	<lastBuildDate>Sun, 06 Sep 2026 21:56:02 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>

<image>
	<url>https://blog.kwt.co.kr/wp-content/uploads/2022/07/cropped-logo_bg-32x32.jpg</url>
	<title></title>
	<link>https://blog.kwt.co.kr/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Claude Code가 매번 코드를 다시 읽는 문제, Graft로 끊기: 설치·보안·제거 직접 검증</title>
		<link>https://blog.kwt.co.kr/graft-claude-code-context-layer-install-security/</link>
					<comments>https://blog.kwt.co.kr/graft-claude-code-context-layer-install-security/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Sun, 06 Sep 2026 21:56:02 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Agent Skills]]></category>
		<category><![CDATA[AI 코딩 에이전트]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Graft]]></category>
		<category><![CDATA[MCP]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/?p=2856</guid>

					<description><![CDATA[<p>Graft는 코드베이스를 한 번 그래프로 만들어 Claude Code·Codex의 반복 탐색을 없애는 MIT 오픈소스다. 격리 설치 검증, 텔레메트리 차단법, ARM64 미지원 이슈, Serena와의 비교까지 직접 확인했다.</p>
<p>The post <a href="https://blog.kwt.co.kr/graft-claude-code-context-layer-install-security/">Claude Code가 매번 코드를 다시 읽는 문제, Graft로 끊기: 설치·보안·제거 직접 검증</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Claude Code·Codex·Cursor에 반복 지시를 내리면 에이전트가 매번 프로젝트를 처음부터 탐색하는 낭비가 생긴다. Graft는 코드베이스를 한 번 그래프로 만들어 에이전트가 재탐색 없이 구조를 재사용하게 하는 오픈소스 컨텍스트 레이어다. GitHub 5,700★을 넘기며 최근 3일간 하루 평균 약 90~178개씩 별이 늘고 있고, 국내에는 개념 소개 글만 있어 설치·보안·제거까지 다룬 글은 아직 없다. 핵심 주의점은 두 가지다. 공식 벤치마크(토큰 42% 절감 등)는 모두 제작사 자체 측정이고, 리눅스 ARM64에서는 네이티브 모듈이 아예 실행되지 않는 공개 이슈(#119)가 있다.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>핵심 요약</strong></p>

<ul class="wp-block-list">
<li><strong>무엇</strong>: Graft — tree-sitter 기반 코드 그래프를 만들어 Claude Code/Codex/Cursor/Gemini 등에 연결하는 컨텍스트 레이어 (MIT, npm <code>@nanonets/graft</code>)</li>

<li><strong>누구에게</strong>: 큰 저장소에서 Claude Code/Codex를 매일 쓰는데 토큰·시간이 반복 탐색으로 낭비된 개발자</li>

<li><strong>검증 결과</strong>: 임시 홈에 npm 0.16.0 설치·postinstall 점검·실제 홈 무결성 검증 완료. 단, 이 글을 쓴 라즈베리파이(ARM64) 호스트에서는 네이티브 tree-sitter 미지원으로 CLI 실행 불가 — 공식 이슈 #119로 확인</li>

<li><strong>보안</strong>: 익명 텔레메트리(버킷 처리, <code>DO_NOT_TRACK=1</code> 또는 <code>graft telemetry disable</code>로 차단), <code>~/.codex/</code> 사용자 레벨 설정 기입(공개 문서화), API 키 불필요(기본 그래프)</li>

<li><strong>대체재</strong>: Serena(코드 내비게이션 MCP)·Graphify와 비교, LSP와는 보완 관계</li>
</ul>
</blockquote>



<h2 class="wp-block-heading">Graft가 해결하는 반복 탐색 문제</h2>



<p>Claude Code에 &#8220;인증 버그 고쳐줘&#8221;라고 하면 에이전트는 먼저 저장소를 탐색한다. grep으로 용어를 찾고, 파일을 열고, import를 따라가고, 다시 빠져나오는 과정을 반복한다. 한 시간 전에 만들었던 지도를 세션마다 버리고 다시 만드는 셈이다. Graft의 README는 이를 &#8220;에이전트는 매번 온보딩한다&#8221;고 표현한다.</p>



<p>Graft는 이 탐색을 한 번만 수행해 결과를 저장소 안 <code>graft/</code> 폴더에 마크다운 노드 그래프로 저장한다. 구조 분석은 tree-sitter로 로컬에서 결정적으로 이뤄지며, 기본 그래프 빌드에는 API 키도 네트워크 호출도 없다. 이후 에이전트는 파일을 열어 읽듯 그래프를 읽어 탐색 비용을 건너뛴다.</p>



<p>작동 구조를 단순화하면 다음과 같다.</p>



<ol class="wp-block-list">
<li><code>graft build</code> — tree-sitter로 심볼·호출·의존 관계를 추출해 <code>graft/</code> 폴더에 그래프 생성 (LLM 불필요, 무료)</li>

<li><code>graft init</code> — Claude Code(<code>.claude/</code>), Codex(<code>AGENTS.md</code>), Cursor(<code>.cursor/rules/</code>) 등 각 에이전트의 네이티브 설정 파일에 연결</li>

<li>세션 중 hooks — 프롬프트마다 관련 노드를 컨텍스트로 당기고, 편집 후 그래프를 자동 재동기화</li>
</ol>



<h2 class="wp-block-heading">검증 환경과 직접 확인한 사실 (2026-09-07)</h2>



<p>이 글의 모든 수치는 2026-09-07 기준 공식 저장소·npm·GitHub API에서 직접 조회한 값이다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>항목</th><th>값</th></tr></thead><tbody>
<tr><td>공식 저장소</td><td>github.com/trailhq/Graft (이전 NanoNets/Graft, 리다이렉트 확인)</td></tr>
<tr><td>라이선스</td><td>MIT (LICENSE 파일 직접 확인)</td></tr>
<tr><td>최신 릴리스</td><td>0.17.0 (2026-09-02, 커밋 로그) / npm latest 0.16.0</td></tr>
<tr><td>스타·포크</td><td>5,769★ / 538 fork (직접 조회)</td></tr>
<tr><td>실측 증가</td><td>24시간 +178★ (+3.18%), 최근 3일 흐름 하루 53→39→178개</td></tr>
<tr><td>npm 다운로드</td><td>최근 30일 23,499회, 최근 7일 9,305회 (npm 공개 API)</td></tr>
<tr><td>이슈 활동</td><td>81개 이슈, 8/27~8/31 사이 다수 클로즈 웨이브, 최신 오픈 2026-09-05</td></tr>
<tr><td>지원 언어</td><td>23개 (TS/JS·Python·Go·Java 등 고정밀 8종 + broad tier 15종)</td></tr>
</tbody></table></figure>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img fetchpriority="high" decoding="async" width="1035" height="555" src="https://blog.kwt.co.kr/wp-content/uploads/2026/09/graft_chart.png" alt="Graft 저장소의 4일간 실측 스타 증가 추이 막대그래프" class="wp-image-2855" style="width:640px;height:auto"/><figcaption class="wp-element-caption">Graft 4일간 실측 스타 증가 (24시간 관측 구간)<br>출처: GitHub API 직접 조회 (2026-09-03~09-06)</figcaption></figure></div>



<p><strong>임시 홈 격리 설치 검증.</strong> 실제 홈의 <code>~/.claude</code>, <code>~/.codex</code>, <code>~/.claude.json</code>, <code>~/.claude/settings.json</code> 해시를 설치 전후로 비교했다. 격리된 <code>/tmp</code> 홈에 npm 0.16.0 설치 후 네 개 경로 모두 무결성이 유지됐다(UNCHANGED 4/4). postinstall 스크립트(<code>scripts/postinstall.mjs</code>)를 직접 읽었고, 하는 일은 설치 이벤트 기록 한 건뿐임을 확인했다.</p>



<p><strong>ARM64 실행 실패 — 이것이 이 글의 한계다.</strong> 이 서버는 라즈베리파이(linux/arm64)다. 설치는 됐지만 CLI 첫 실행에서 <code>No native build was found for platform=linux arch=arm64</code> 에러로 중단됐다. 의존성 <code>tree-sitter@0.21.1</code>의 prebuild가 darwin-arm64/darwin-x64/linux-x64/win32-x64만 제공하기 때문이다. 이는 Graft의 공개 이슈 #119 &#8220;ARM64 Incompatibilities&#8221;(오픈 상태)와 정확히 일치하며, WASM 폴백을 추가하는 PR #214도 아직 머지 전이다. 따라서 이 글은 설치·설정 파일 구조·제거 절차의 문서 검증까지이고, x64 머신에서의 실제 그래프 빌드·토큰 절감 A/B는 독자가 직접 수행해야 한다.</p>



<p><strong>x64 사용자라면 이렇게 재현한다.</strong> 리눅스 x64·macOS·윈도우(WSL 포함)에서는 prebuild가 있어 이 단계가 정상 동작한다.</p>



<pre class="wp-block-code"><code># 임시 디렉터리에서 먼저 확인 (실제 프로젝트에 영향 없음)
mkdir /tmp/graft-trial &amp;&amp; cd /tmp/graft-trial
git init &amp;&amp; echo 'console.log(1)' &gt; index.js
DO_NOT_TRACK=1 npm install @nanonets/graft@0.16.0
DO_NOT_TRACK=1 ./node_modules/.bin/graft init --dry-run   # 변경될 파일 목록만 출력
DO_NOT_TRACK=1 ./node_modules/.bin/graft build            # 그래프 생성 (API 키 불필요)</code></pre>



<h2 class="wp-block-heading">Claude Code·Codex·Hermes 연결 방법</h2>



<p><strong>Claude Code (가장 깊은 통합).</strong> <code>graft init</code>을 실행하면 감지된 에이전트 목록이 뜨고, 선택한 에이전트의 설정 파일에 기입한다. Claude Code는 <code>.claude/skills/graft/SKILL.md</code>, 프로젝트 <code>.mcp.json</code>에 MCP 서버, statusline, hooks까지 설치된다. 기존 <code>CLAUDE.md</code>은 건드리지 않고 <code>.claude/settings.json</code>도 자기 블록만 병합한다고 문서화돼 있다.</p>



<p><strong>Codex.</strong> <code>AGENTS.md</code>에 Graft 섹션을 추가하고, <code>~/.codex/</code>가 있으면 사용자 레벨 <code>config.toml</code>(<code>[mcp_servers.graft]</code>), hooks 파일에도 기입한다. 이 부분은 <strong>모든 저장소에 적용되는 machine-wide 변경</strong>이므로 <code>--no-global</code> 플래그로 프로젝트 한정으로 설치하는 편이 안전하다.</p>



<p><strong>Hermes 포함 기타 에이전트.</strong> 표준 MCP 설정에 수동 등록하면 된다. 어떤 에이전트든 MCP 클라이언트라면 다음 JSON을 설정에 넣는다.</p>



<pre class="wp-block-code"><code>{ "mcpServers": { "graft": { "command": "npx", "args": ["-y", "@nanonets/graft", "mcp"] } } }</code></pre>



<p>MCP로 노출되는 도구는 6개다: <code>graft_find_code</code>(질문→랭킹된 노드), <code>graft_file_api</code>(파일 시그니처만), <code>graft_trace_calls</code>(호출자 추적), <code>graft_find_all</code>(정규식 검색), <code>graft_repo_map</code>(저장소 지도), <code>graft_check_freshness</code>(그래프 신선도).</p>



<p><strong>설치 시 실제로 바뀌는 경로 정리.</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>대상</th><th>경로</th><th>내용</th></tr></thead><tbody>
<tr><td>공통</td><td><code>graft/</code></td><td>코드 그래프(로컬 캐시, <code>.gitignore</code> 자동 추가)</td></tr>
<tr><td>Claude Code</td><td><code>.claude/skills/graft/SKILL.md</code>, <code>.mcp.json</code>, hooks, statusline</td><td>스킬·MCP·자동동기화</td></tr>
<tr><td>Codex</td><td><code>AGENTS.md</code>, <code>~/.codex/config.toml</code>, <code>~/.codex/hooks.json</code></td><td>안내 섹션·MCP·편집 훅</td></tr>
<tr><td>Cursor</td><td><code>.cursor/rules/graft.mdc</code></td><td>룰 파일</td></tr>
<tr><td>Gemini</td><td><code>GEMINI.md</code></td><td>안내 섹션</td></tr>
</tbody></table></figure>




<h2 class="wp-block-heading">제거·원상복구 절차</h2>



<p>Graft는 공식 제거 명령을 제공한다. 이 점이 검증 중 인상적이었던 부분이다.</p>



<pre class="wp-block-code"><code>graft uninstall          # 실제 삭제 전에 제거될 항목을 먼저 출력
graft uninstall -y       # 실제 삭제 (init의 역연산)
graft uninstall --no-global   # ~/.codex 등 저장소 밖 파일은 유지
npm uninstall -g @nanonets/graft   # CLI 자체 제거</code></pre>



<p><code>uninstall</code>은 init이 기입한 모든 파일과 설정 항목을 역으로 제거한다. <code>--keep-cache</code>로 그래프 캐시만 남길 수도 있다. 임시 검증 환경에서는 <code>rm -rf /tmp/graft-trial</code>로 폴더째 삭제하면 끝난다.</p>



<h2 class="wp-block-heading">보안·권한·텔레메트리: 숨기지 않는 정보</h2>



<ul class="wp-block-list">
<li><strong>네트워크 호출 3종만 존재</strong> (TELEMETRY.md 공식 계약): 사용자가 설정한 LLM 요청, 하루 1회 npm 버전 확인, 배치 처리된 사용 통계 1건. 코드·파일 경로·저장소명·심볼·쿼리는 전송하지 않으며, 모든 숫자는 버킷(예: &#8220;200-999 files&#8221;)으로만 전송된다. <code>src/telemetry/contract.ts</code>가 화이트리스트를 강제하고 미등록 속성은 전송 전 차단한다.</li>

<li><strong>텔레메트리 차단</strong>: <code>DO_NOT_TRACK=1</code> 환경변수, <code>graft telemetry disable</code> 명령, 또는 <code>graft init</code> 프롬프트에서 체크 해제. CI 환경에서는 자동으로 꺼진다.</li>

<li><strong>postinstall</strong>: npm 설치 직후 익명 설치 이벤트 1건을 detached 프로세스로 보낸다. 스크립트 소스를 직접 읽어 확인했고, 설치 실패를 유발하지 않는 구조다.</li>

<li><strong>권한 범위</strong>: 로컬 파일 읽기·그래프 쓰기가 전부. 데몬·서버 없음. <code>--deep</code> 모드에서만 사용자가 지정한 LLM 제공자로 코드 요약 요청이 나간다(자기 API 키 사용).</li>

<li><strong>machine-wide 변경 주의</strong>: Codex 선택 시 <code>~/.codex/</code> 전역 설정이 바뀐다. README가 이를 명시하고 <code>--no-global</code> 회피 경로를 제공하는 것은 투명한 태도다.</li>

<li><strong>공급망</strong>: OpenSSF Scorecard 배지, TypeScript strict, 29개 npm 버전, 기여자 다수. 악성코드 징후는 없었다.</li>

<li><strong>비용</strong>: 도구 자체 무료(MIT). <code>--deep</code> 사용 시 자기 LLM 키 비용 발생.</li>
</ul>



<h2 class="wp-block-heading">Serena·Graphify·LSP와 비교: 어떤 관계인가</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>구분</th><th>Graft</th><th>Serena (MCP)</th><th>LSP 직접 연결</th></tr></thead><tbody>
<tr><td>분류</td><td>컨텍스트 레이어(그래프 사전 구축)</td><td>코드 내비게이션 MCP</td><td>언어 서버 프로토콜</td></tr>
<tr><td>입력</td><td>저장소 전체를 사전 빌드</td><td>심볼 질의 시점 조회</td><td>심볼 질의 시점 조회</td></tr>
<tr><td>출력</td><td>마크다운 노드 그래프 + MCP 6도구</td><td>정의/참조/기호 편집 도구</td><td>정의/참조/완성</td></tr>
<tr><td>정확도</td><td>제작사 자체 벤치마크(SWE-bench V 54%→66%, 자체 측정)</td><td>LSP 기반으로 결정적</td><td>언어 서버 수준으로 결정적</td></tr>
<tr><td>수정 가능성</td><td>그래프는 재생성 가능한 캐시, 노드에 사용자 노트 보존</td><td>—</td><td>—</td></tr>
<tr><td>비용</td><td>기본 무료, &#8211;deep만 키 비용</td><td>무료</td><td>무료</td></tr>
<tr><td>데이터 처리</td><td>로컬 파일 + 설정한 LLM만</td><td>로컬</td><td>로컬</td></tr>
<tr><td>에이전트 연결</td><td>MCP + Claude Code hooks + 다수 CLI 파일</td><td>MCP</td><td>MCP 래퍼 필요</td></tr>
</tbody></table></figure>




<p>관계를 명확히 하면: Graft는 <strong>grep 반복 탐색에 대한 부분 직접 대체재</strong>이고, Serena는 시점 조회형 내비게이션이므로 <strong>목적이 겹치는 다른 하위 범주</strong>, LSP는 이미 심볼을 아는 경우의 도구라 <strong>보완 관계</strong>다. Graft 제작사가 HN 스레드에서 공개한 자체 비교로는 Graphify 대비 검색 정확도 MRR 0.73 vs 0.38 — 단 이 역시 자체 측정이다.</p>



<h2 class="wp-block-heading">안전한 설치 프롬프트 (복사해서 붙여넣으세요)</h2>



<p>아래 프롬프트를 Claude Code나 Codex에 붙여 넣으면 안전 절차를 따라 설치를 진행한다. 운영 프로젝트에서 바로 실행하지 말 것.</p>



<pre class="wp-block-code"><code>https://github.com/trailhq/Graft 문서를 읽고 다음 절차로 Graft를 설치해줘.

조건:
1. 버전 고정: @nanonets/graft@0.16.0 (npm 레지스트리에서 조회)
2. 먼저 임시 디렉터리(/tmp/graft-trial)에서 검증한다. 실제 프로젝트는 건드리지 마.
3. DO_NOT_TRACK=1 환경변수로 텔레메트리를 끄고 시작한다.
4. graft init --dry-run 출력을 먼저 보여주고, 내가 승인한 파일만 변경한다.
5. ~/.codex/ 전역 설정은 변경 금지 (--no-global 사용).
6. API 키 입력은 절대 요청하지 마. 기본 그래프 빌드만 수행한다.
7. graft build 결과와 graft check 출력을 보여줘.
8. 검증 후 graft uninstall -y와 npm uninstall로 /tmp/graft-trial을 완전히 정리하고,
   변경 전후 파일 목록을 비교해 원상복구를 확인해줘.</code></pre>



<h2 class="wp-block-heading">유용한 경우 vs 추천하지 않는 경우</h2>



<p><strong>도입을 검토할 만한 상황</strong></p>



<ul class="wp-block-list">
<li>수백~수천 파일 규모 저장소에서 Claude Code/Codex를 매일 사용한다</li>

<li>세션마다 반복 탐색으로 토큰이 급격히 소모된다</li>

<li>여러 팀원이 같은 저장소를 에이전트로 다룬다 (wiring만 커밋하면 각자 그래프 생성)</li>

<li>linux x64·macOS 환경이다</li>
</ul>



<p><strong>추천하지 않는 상황</strong></p>



<ul class="wp-block-list">
<li>라즈베리파이 등 <strong>linux ARM64 환경</strong> — 현재 실행 불가 (이슈 #119 오픈 중)</li>

<li>파일 몇 개짜리 소규모 프로젝트 — 탐색 비용 자체가 작아 이득이 없다</li>

<li>제작사 벤치마크 수치를 그대로 보증값으로 받아들이는 용도 — 어디까지나 자체 측정이다</li>

<li>텔레메트리가 자동으로 나가는 것이 원칙적으로 거부되는 환경 — 설치 후 즉시 비활성화 필요</li>
</ul>



<h2 class="wp-block-heading">설치 전 체크리스트</h2>



<ul class="wp-block-list">
<li>[ ] 내 환경이 linux x64 / darwin / win32 인지 확인 (ARM64는 #119 해결 전 불가)</li>

<li>[ ] <code>git status</code>로 커밋되지 않은 변경사항 정리 (백업)</li>

<li>[ ] 임시 디렉터리에서 <code>graft init --dry-run</code> 먼저 실행</li>

<li>[ ] <code>DO_NOT_TRACK=1</code> 설정 여부 확인</li>

<li>[ ] Codex 전역 변경 원치 않으면 <code>--no-global</code> 플래그 사용</li>

<li>[ ] <code>--deep</code> 사용 여부 결정 (LLM 키 비용 발생)</li>

<li>[ ] <code>graft uninstall</code> 시나리오를 미리 dry-run으로 확인</li>
</ul>



<h2 class="wp-block-heading">직접 검증한 것과 검증하지 못한 것</h2>



<p><strong>직접 검증 완료</strong></p>



<ul class="wp-block-list">
<li>npm 0.16.0 격리 설치, postinstall 소스 점검, 실제 홈 4개 경로 해시 무결성 (UNCHANGED 4/4)</li>

<li>LICENSE(MIT), README(42KB), TELEMETRY.md 전문 읽기</li>

<li>릴리스 타임라인(0.9.0~0.17.0), 커밋 로그(2026-09-02까지), 이슈 81개 활동</li>

<li>스타 증가 실측: 24시간 +178 (3일 연속 관측)</li>

<li>npm 다운로드 공개 API 조회: 월 23,499회</li>

<li>HN 토론(39pts/44댓글) 원문 확인, 제작자 응답 포함</li>
</ul>



<p><strong>검증하지 못한 것 (독자 과제)</strong></p>



<ul class="wp-block-list">
<li>x64 환경에서의 실제 그래프 빌드·CLI 동작 (ARM64 호스트 한계)</li>

<li>토큰 42% 절감 재현 — 제작사 자체 벤치마크이므로 독자의 프로젝트에서 A/B 필요</li>

<li><code>--deep</code> 모드의 LLM 요약 품질과 비용</li>

<li>자체 저장소에서의 <code>graft viz</code> 시각화 품질</li>
</ul>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">Graft는 무료인가?</h3>



<p>도구 자체는 MIT 라이선스 무료다. 기본 그래프 빌드는 API 키 없이 로컬에서 돈다. <code>--deep</code> 모드로 LLM 요약을 추가할 때만 자신의 API 키 비용이 발생한다.</p>



<h3 class="wp-block-heading">정말 토큰이 42% 절감되나?</h3>



<p>그 수치는 제작사가 162회 자체 벤치마크와 SWE-bench Verified 50케이스로 측정한 자체 발표 값이다. SWE-bench 결과(정확도 54%→66%)는 공식 채점기를 썼다고 명시하지만, 독립 검증은 아니다. 자기 프로젝트에서 같은 커밋·같은 작업으로 A/B 테스트하는 것이 가장 정확하다.</p>



<h3 class="wp-block-heading">ARM64 맥(애플 실리콘)에서도 안 되나?</h3>



<p>darwin-arm64 prebuild는 존재한다. 안 되는 것은 <strong>linux/arm64</strong> 조합뿐이다(라즈베리파이, ARM 리눅스 서버, ARM 도커 이미지). 이슈 #119에서 WASM 폴백 PR #214를 준비 중이다.</p>



<h3 class="wp-block-heading">기존 CLAUDE.md이나 설정이 덮어써지진 않나?</h3>



<p>README 명세상 Graft는 자체 섹션만 추가·갱신하고 기존 내용은 건드리지 않는다. statusLine도 Graft 것이 아닌 기존 설정은 그대로 둔다고 문서화돼 있다. 그래도 도입 전 <code>git add</code>로 백업하자.</p>



<h3 class="wp-block-heading">Serena와 Graft 중 무엇을 쓰야 하나?</h3>



<p>이미 심볼 이름을 알고 정의·참조를 추적한다면 Serena(LSP 기반)면 충분하다. &#8220;인증이 어디서 처리되나&#8221; 같은 개념 질의와 대형 저장소 오리엔테이션이 필요하면 Graft가 목적에 맞다. 둘은 경쟁보다 하위 범주가 다른 관계다.</p>



<h3 class="wp-block-heading">제거는 깨끗한가?</h3>



<p><code>graft uninstall -y</code>가 init의 역연산을 수행한다. dry-run으로 삭제 목록을 먼저 볼 수 있어 안전하다. npm 전역 설치라면 <code>npm uninstall -g @nanonets/graft</code>로 마무리한다.</p>



<h2 class="wp-block-heading">공식 참고자료</h2>



<ul class="wp-block-list">
<li>Graft 저장소: https://github.com/trailhq/Graft</li>

<li>npm 패키지: https://www.npmjs.com/package/@nanonets/graft</li>

<li>텔레메트리 문서(TELEMETRY.md): https://github.com/trailhq/Graft/blob/main/TELEMETRY.md</li>

<li>ARM64 이슈 #119: https://github.com/trailhq/Graft/issues/119</li>

<li>HN 토론 원문: https://news.ycombinator.com/item?id=49299985</li>

<li>Agent Skills 사양: https://agentskills.io/home</li>
</ul>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2856"
					data-ulike-nonce="ab12e3fee1"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2856"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/graft-claude-code-context-layer-install-security/">Claude Code가 매번 코드를 다시 읽는 문제, Graft로 끊기: 설치·보안·제거 직접 검증</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/graft-claude-code-context-layer-install-security/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Claude Code가 지난달의 나를 기억하게 만들기: deja-vu 설치·보안 검증</title>
		<link>https://blog.kwt.co.kr/deja-vu-coding-agent-memory-install-security/</link>
					<comments>https://blog.kwt.co.kr/deja-vu-coding-agent-memory-install-security/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Sat, 05 Sep 2026 21:40:12 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Codex]]></category>
		<category><![CDATA[MCP]]></category>
		<category><![CDATA[에이전트]]></category>
		<category><![CDATA[오픈소스]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/?p=2848</guid>

					<description><![CDATA[<p>Claude Code·Codex·Cursor 세션 로그를 색인해 설치 이전 기록까지 검색·회수하는 오픈소스 deja-vu를 격리 환경에서 직접 설치·검증했다. mem0·CLAUDE.md와의 차이, 비밀값 가림 동작, 제거 방법까지.</p>
<p>The post <a href="https://blog.kwt.co.kr/deja-vu-coding-agent-memory-install-security/">Claude Code가 지난달의 나를 기억하게 만들기: deja-vu 설치·보안 검증</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Claude Code·Codex·Cursor를 여러 개 쓰는 개발자라면 매일 같은 문제를 겪는다. 3월에 고쳤던 버그를 9월에 또 처음부터 디버깅하고, 다른 에이전트에서 해결했던 일을 지금 쓰는 에이전트는 전혀 모른다. 오픈소스 <strong>deja-vu</strong>는 이 간극을 메운다. 각 에이전트가 이미 디스크에 저장하는 세션 로그를 색인해서, 설치 이전 기록까지 포함해 검색·회수(recall)해 주는 로컬 메모리 레이어다. LLM 호출도 임베딩도 없고 Go 단일 바이너리로 동작하며, 색인 시점에 API 키·JWT 등 비밀값을 자동으로 가린다. 이 글은 공식 저장소와 직접 설치 검증(설치 → 색인 → 검색 → 가림 확인 → 제거)을 기준으로 정리했다. 주의점 하나: 세션 로그 전체를 읽는 도구이므로 신뢰할 수 있는 공식 릴리스(checksums.txt 검증)로만 설치해야 한다.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1400" height="788" src="https://blog.kwt.co.kr/wp-content/uploads/2026/09/dejavu-featured.jpg" alt="Claude Code 세션 로그를 색인해 과거 기록을 회수하는 deja-vu 로컬 메모리 도구" class="wp-image-2847"/><figcaption class="wp-element-caption">deja-vu의 문제 정의와 동작 방식 요약<br />출처: 직접 제작 (2026-09-06 기준 공식 저장소 정보)</figcaption></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>핵심 요약</strong></p>

<ul class="wp-block-list">
<li><strong>정체</strong>: 코딩 에이전트 세션 로그 색인·검색 로컬 메모리 (MCP 서버 + CLI, Go 단일 바이너리, MIT 라이선스)</li>

<li><strong>해결 문제</strong>: &#8220;이 문제 예전에 해결했었는데&#8221; — Claude Code/Codex/Cursor 등 22종 에이전트의 과거 세션을 통합 검색하고 MCP <code>recall</code> 도구로 자동 회수</li>

<li><strong>차별점</strong>: mem0·CLAUDE.md 같은 기존 메모리 도구는 &#8216;앞으로 쌓는&#8217; 방식, deja-vu는 &#8216;이미 디스크에 있는&#8217; 과거 기록부터 색인. 임베딩·LLM 없이 어휘 검색이라 비용 0원</li>

<li><strong>검증</strong>: 2026-09-06 격리 HOME에서 v0.19.3 설치·색인·검색·비밀값 가림·제거 직접 확인 (sha256 체크섬 일치)</li>

<li><strong>주의</strong>: 세션 로그 통독 도구이므로 출처·체크섬 확인 필수. macOS·Linux가 공식 지원, Windows는 Scoop·zip으로 설치</li>
</ul>
</blockquote>



<h2 class="wp-block-heading">deja-vu가 필요한 순간</h2>



<p>에이전트는 세션을 끝내면 대부분 잊는다. Claude Code는 <code>~/.claude/projects</code>에 JSONL로 대화를 쌓고, Codex는 <code>~/.codex</code>에, Cursor는 자체 스토어에 기록을 남긴다. 파일은 있는데 아무도 검색하지 않는다. 결과는 반복 노동이다.</p>



<p>deja-vu README의 표현이 정확하다. &#8220;모든 메모리 도구는 비어 있는 상태로 시작해 앞으로 기록한다. deja는 가득 찬 상태로 시작한다.&#8221; 설치 즉시 이미 디스크에 있는 수개월치 세션을 전부 색인하기 때문에, 별도 학습 없이 첫 순간부터 과거 기록을 검색할 수 있다.</p>



<p>실제로 이런 질문이 가능해진다:</p>



<pre class="wp-block-code"><code>"jwt refresh rotation 이전에 처리한 적 있지? 기억 확인해줘"</code></pre>



<p>에이전트가 MCP <code>recall</code> 도구를 스스로 호출해 8개월 전 세션의 해결 기록을 가져온다. <code>deja install --auto</code>를 켜면 세션 시작·프롬프트마다·파일 편집 전·명령 실패 후 등 훅 시점에 관련 기억을 자동으로 주입하도록 설정할 수도 있다.</p>



<h2 class="wp-block-heading">기본 정보와 검증 시점</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>항목</th><th>내용 (2026-09-06 기준)</th></tr></thead><tbody>
<tr><td>이름·유형</td><td>deja-vu — 코딩 에이전트용 로컬 메모리 (CLI + MCP 서버)</td></tr>
<tr><td>공식 저장소</td><td>github.com/vshulcz/deja-vu</td></tr>
<tr><td>공식 문서</td><td>vshulcz.github.io/deja-vu</td></tr>
<tr><td>최초 생성</td><td>2026-07-14</td></tr>
<tr><td>최근 푸시</td><td>2026-09-05 (매일 커밋·릴리스 활동 지속)</td></tr>
<tr><td>최신 릴리스</td><td>v0.19.3 (2026-09-04)</td></tr>
<tr><td>stars / forks</td><td>779 / 64</td></tr>
<tr><td>라이선스</td><td>MIT</td></tr>
<tr><td>구현 언어</td><td>Go (단일 바이너리, 의존성 없음)</td></tr>
<tr><td>지원 harness</td><td>22종 — Claude Code, Codex, Cursor, Gemini CLI, opencode, aider, Antigravity, Grok Build, Qwen, Kimi, goose, cline, roo, amp, zed, OpenClaw, Copilot, Hermes 등</td></tr>
<tr><td>외부 언급</td><td>Hacker News 2026-07-15 &#8220;Open-source memory for coding agents, synced over SSH&#8221; 131점·댓글 35개</td></tr>
</tbody></table></figure>




<p>stars 증가 속도는 이 스냅숏 체계로 관측 중이다. 이 도구는 2026-09-06 이번 실행에서 처음 관측해 779 stars를 기록했다. 1일·7일 증분은 아직 이력이 없어 <strong>unavailable</strong>로 표기하며, 총 stars에서 역산한 평균 속도(7월 14일 생성 이후 약 54일간 약 14.4 stars/일의 단순 평균, <strong>provisional</strong>)로만 참고한다. 확정 가능한 사실은 7월 중순 HN 131점 논의 이후 약 7주 만에 779 stars에 도달했고, 9월 4~5일에도 매일 기능 커밋·이슈 마감이 이뤄지고 있다는 유지보수 활동이다.</p>



<h2 class="wp-block-heading">Claude Code·Codex·Hermes 설치 방법</h2>



<h3 class="wp-block-heading">공통 준비 (macOS · Linux)</h3>



<pre class="wp-block-code"><code>curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh
deja install --auto</code></pre>



<p>설치 스크립트를 직접 열어 확인한 동작은 다음과 같다. (1) GitHub 최신 릴리스 태그 조회 (2) 플랫폼별 tar.gz와 checksums.txt 다운로드 (3) sha256 비교 (4) <code>~/.local/bin/deja</code> 설치 (5) PATH 등록 안내. 셸 프로필 수정은 대화형으로 y/N을 물어보고, 파이프 설치 시에는 안내 문구만 출력한다. <code>--yes</code> 플래그가 없으면 아무것도 강제로 바꾸지 않는다.</p>



<p><code>deja install --auto</code>가 실제 배선 단계다. 발견한 에이전트별 MCP 설정에 <code>recall</code> 도구를 등록하고, 세션 시작 회수가 가능한 에이전트에서는 훅도 켠다. 이 단계가 에이전트 설정 파일을 수정하는 유일한 지점이다.</p>



<h3 class="wp-block-heading">Claude Code (플러그인 마켓플레이스 방식)</h3>



<pre class="wp-block-code"><code>claude plugin marketplace add vshulcz/deja-vu
claude plugin install deja-vu@deja-vu</code></pre>



<h3 class="wp-block-heading">Codex / 기타 MCP 클라이언트</h3>



<p>MCP 서버로 연결한다. <code>deja install</code>이 <code>~/.codex/config.toml</code>에 자동 등록해 주며, 수동으로는 각 클라이언트의 MCP 설정에 <code>deja</code> 바이너리를 stdio 서버로 지정한다. 데스크톱 앱은 릴리스에 포함된 <code>.mcpb</code> 번들을 열면 된다.</p>



<h3 class="wp-block-heading">Hermes</h3>



<p><code>deja install</code>이 Hermes 프로파일(<code>~/.hermes/config.yaml</code>)도 감지해 배선한다. 격리 검증에서 <code>deja sources</code> 출력에 <code>hermes ~/.hermes/profiles</code> 스토어가 확인됐다.</p>



<h3 class="wp-block-heading">Windows</h3>



<p>install.sh는 셸 스크립트라 지원하지 않는다. Scoop 메인 버킷(<code>scoop install deja-vu</code>) 또는 릴리스의 <code>deja-vu_&lt;버전&gt;_windows_amd64.zip</code>을 받아 <code>%USERPROFILE%\.local\bin</code>에 두고 PATH에 추가한다.</p>



<h3 class="wp-block-heading">설치 시 바뀌는 경로·파일</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>경로</th><th>용도</th></tr></thead><tbody>
<tr><td><code>~/.local/bin/deja</code></td><td>바이너리 (11.9MB)</td></tr>
<tr><td><code>~/.cache/deja/</code></td><td>색인 데이터베이스·캐시</td></tr>
<tr><td><code>~/.config/deja/</code></td><td>설정·제외 패턴(<code>exclude</code>), 신뢰 정책(<code>policy.json</code>)</td></tr>
<tr><td><code>~/.claude.json</code> 등 각 에이전트 MCP 설정</td><td><code>recall</code> 도구 등록 (자동)</td></tr>
<tr><td><code>~/.claude/skills/deja-history/SKILL.md</code> 등</td><td>회수 가이드 스킬 (자동)</td></tr>
</tbody></table></figure>




<h3 class="wp-block-heading">제거·원상복구</h3>



<pre class="wp-block-code"><code>deja uninstall --all     # 각 에이전트에서 MCP 배선 제거 시도
rm -rf ~/.cache/deja     # 색인 데이터 완전 삭제
rm ~/.local/bin/deja     # 바이너리 삭제</code></pre>



<p><code>deja uninstall --all</code>은 자신이 수정한 배선을 되돌리려 시도하고, 색인 캐시는 별도 삭제가 필요하다. 원본 세션 로그(<code>~/.claude/projects</code> 등)는 건드리지 않는다 — 삭제해도 에이전트 기록은 그대로다.</p>



<h2 class="wp-block-heading">무엇을 검증했고 무엇을 못 했나</h2>



<h3 class="wp-block-heading">직접 검증한 것 (2026-09-06, 격리 HOME)</h3>



<ul class="wp-block-list">
<li>v0.19.3 linux_arm64 바이너리 다운로드 후 <strong>sha256 체크섬 일치 확인</strong> (checksums.txt의 <code>855661d4…</code>와 로컬 계산값 동일)</li>

<li>임시 HOME에서 <code>deja --version</code> → <code>deja 0.19.3</code> 출력</li>

<li>가상 Claude Code 세션 JSONL 3메시지 색인 → <code>deja index</code> 성공 (claude: 1 session, 3 messages)</li>

<li><code>deja "jwt refresh"</code> 검색 → 세션 매치·발췌 출력 정상</li>

<li><strong>비밀값 가림(redaction) 확인</strong>: 세션에 포함된 AWS 예제 키(AKIA…7EXAMPLE, AWS 공식 문서 예시용)를 검색했더니 색인에 없음. 색인 시점에 가려진다는 README 설명과 일치</li>

<li><code>deja doctor --offline</code>, <code>deja sources</code>로 지원 harness 목록·MCP 배선 상태 진단 정상 동작</li>

<li><code>deja uninstall --all</code> + 캐시 삭제로 임시 환경 정리. <strong>실제 사용자 HOME은 변경 없음 확인</strong></li>
</ul>



<h3 class="wp-block-heading">검증하지 못한 것</h3>



<ul class="wp-block-list">
<li>실사용 환경에서의 자동 recall 품질 (수개월치 실세션 대상 성능)</li>

<li><code>deja sync ssh</code> 기계 간 동기화, <code>deja handoff</code> 에이전트 전환</li>

<li>LongMemEval-S 85.3%·LoCoMo 69.6% 벤치마크 수치 재현 (README·공식 문서 발췌이며 제3자 검증 아님)</li>

<li>Windows 설치 경로</li>
</ul>



<p>벤치마크 수치는 제작자 자체 측정이고 재현 스크립트가 저장소에 포함되어 있지만 이번 실행에서 돌려보지는 못했다. &#8216;밀리초 조회&#8217; 성능 주장도 공식 문서 기준으로만 인용한다.</p>



<h2 class="wp-block-heading">권한·보안: 숨기지 않고 정리</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>항목</th><th>내용</th></tr></thead><tbody>
<tr><td>데이터 처리</td><td>색인·검색 전부 로컬. 네트워크 사용은 <code>deja update</code>, <code>deja sync ssh</code>, <code>deja doctor</code> 버전 확인뿐 (README 명시)</td></tr>
<tr><td>비밀값 가림</td><td>색인 시점에 AWS 키, <code>api_key=</code>/<code>token=</code> 할당, Bearer·JWT, PEM 블록, <code>scheme://user:pass@host</code>, 고엔트로피 값을 <code>[redacted:&lt;kind&gt;]</code>로 치환. <code>share</code>·<code>sync export</code>에서 재적용</td></tr>
<tr><td>가림의 한계</td><td>패턴 매칭 기반이라 알려지지 않은 형태의 비밀값은 통과할 수 있음 (공식 보안 모델 문서가 스스로 명시)</td></tr>
<tr><td>API 키·비용</td><td>도구 자체는 무료·키 불필요. LLM·임베딩 호출이 없어 추가 비용 0</td></tr>
<tr><td>텔레메트리</td><td>명시된 외부 전송 없음</td></tr>
<tr><td>공급망</td><td>설치 스크립트가 checksums.txt 검사 내장. 릴리스에는 SBOM(spdx.json)·서명 파일(.pem/.sig) 동봉</td></tr>
<tr><td>접근 범위</td><td>세션 로그 전체 통독이 기능의 본질 — 신뢰할 수 없는 환경의 세션까지 색인하면 안 됨. <code>~/.config/deja/exclude</code>로 프로젝트 제외 가능, <code>deja forget</code>으로 세션 단위 삭제(묘비 기록으로 재색인 방지)</td></tr>
</tbody></table></figure>




<p>세션 로그에는 평소 에이전트에게 보낸 코드·설명이 통째로 담긴다. &#8220;읽는 도구&#8221;가 생긴다는 점 자체가 보안 의사결정이다. 회사 정책상 민감한 프로젝트는 exclude 패턴으로 처음부터 배제하는 것이 안전하다.</p>



<h2 class="wp-block-heading">기존 도구와 비교: mem0·CLAUDE.md 대신 쓸 것인가</h2>



<p>비슷한 문제(에이전트 기억)를 푸는 대표 도구와의 관계를 정리한다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>구분</th><th>deja-vu</th><th>mem0</th><th>CLAUDE.md / 메모리 파일</th></tr></thead><tbody>
<tr><td>분류</td><td>세션 로그 색인·검색</td><td>벡터 메모리 레이어</td><td>수동 메모 노트</td></tr>
<tr><td>입력</td><td>이미 디스크에 있는 세션 로그</td><td>사용 중 발생하는 대화·메모</td><td>사람이 직접 작성</td></tr>
<tr><td>출력</td><td>어휘 검색 매치·세션 발췌, MCP <code>recall</code></td><td>임베딩 기반 회수</td><td>프롬프트에 주입되는 정적 텍스트</td></tr>
<tr><td>과거 기록</td><td>설치 이전 전부 색인</td><td>설치 이후부터</td><td>작성한 내용만</td></tr>
<tr><td>추가 비용·LLM</td><td>없음 (임베딩 없음)</td><td>임베딩·저장소 비용 발생 가능</td><td>없음</td></tr>
<tr><td>데이터 처리</td><td>전부 로컬</td><td>구성에 따라 외부 저장소·API</td><td>전부 로컬</td></tr>
<tr><td>정확도 성격</td><td>원문 그대로 인용 (수정 없음)</td><td>유사도 기반 (재구성 가능)</td><td>사람이 검증한 내용</td></tr>
<tr><td>에이전트 연결</td><td>MCP 표준 + 22종 자동 배선</td><td>SDK·API 중심</td><td>Claude Code 전용 관례</td></tr>
</tbody></table></figure>




<p><strong>분류: 보완재에 가깝다.</strong> mem0처럼 &#8216;앞으로 쌓는&#8217; 시맨틱 메모리와 deja-vu의 &#8216;이미 있는 것을 뒤지는&#8217; 어휘 검색은 해결 계층이 다르다. CLAUDE.md는 프로젝트 관례를 적는 자리지 과거 세션 검색 도구가 아니다. Claude Code를 쓰면서 &#8220;예전에 이거 고친 기록 어디 있지?&#8221;를 자주 겪는다면 deja-vu를 먼저 붙이고, 필요하면 시맨틱 메모리를 함께 쓰는 구성이 합리적이다.</p>



<h3 class="wp-block-heading">추천하는 경우</h3>



<ul class="wp-block-list">
<li>Claude Code·Codex·Cursor 등 둘 이상의 에이전트를 같이 쓰며 기록이 쌓여 있는 개발자</li>

<li>반복해서 비슷한 버그·설정 문제를 풀고, 과거 해결 이력을 못 찾아 답답한 팀·개인</li>

<li>클라우드·임베딩 비용 없이 로컬에서만 해결하려는 경우</li>

<li>세션 로그가 민감하지 않거나 exclude로 통제 가능한 환경</li>
</ul>



<h3 class="wp-block-heading">추천하지 않는 경우</h3>



<ul class="wp-block-list">
<li>세션 로그에 규정상 외부 도구가 색인하면 안 되는 코드·데이터가 섞여 있고 제외 통제가 어려운 환경</li>

<li>Windows 전용 개발 환경에서 공식 install.sh 경로를 원하는 경우 (Scoop·zip 우회 필요)</li>

<li>&#8216;요약된 지식&#8217;을 원하는 경우 — deja-vu는 원문 회수 도구지 요약 엔진이 아니다</li>

<li>벤치마크 수치를 근거로 도입을 결정해야 하는 조직 (제3자 검증 아직 부족)</li>
</ul>



<h2 class="wp-block-heading">설치 전 체크리스트</h2>



<ol class="wp-block-list">
<li>기존 세션 로그 백업: <code>cp -r ~/.claude ~/claude-backup</code> (필요 시)</li>

<li>공식 저장소·릴리스 확인: GitHub <code>vshulcz/deja-vu</code> Releases에서 최신 태그와 checksums.txt 확인</li>

<li>격리 검증 먼저: 임시 HOME에서 색인·검색 동작 확인 후 실제 환경 적용</li>

<li>민감 프로젝트 제외: <code>~/.config/deja/exclude</code>에 경로 패턴 사전 등록</li>

<li>배선 범위 확인: <code>deja doctor</code>로 어떤 에이전트 설정이 바뀌는지 먼저 조회</li>

<li>제거 절차 숙지: <code>deja uninstall --all</code> + <code>rm -rf ~/.cache/deja</code></li>

<li>운영 환경(실제 프로젝트 설정)에는 바로 적용하지 않고 개인 환경에서 먼저 운영</li>
</ol>



<h2 class="wp-block-heading">안전한 복사·붙여넣기 프롬프트</h2>



<p>이 글을 읽은 뒤 Claude Code나 Codex에 그대로 붙여넣어 설치를 요청할 수 있다. 아래 프롬프트는 버전 고정·체크섬 확인·백업·격리 검증·제거 절차를 포함한다.</p>



<pre class="wp-block-code"><code>deja-vu(v0.19.3, github.com/vshulcz/deja-vu, MIT) 설치를 도와줘.
다음 절차를 정확히 지켜줘:

1. 먼저 백업: ~/.claude 디렉터리와 각 에이전트 MCP 설정 파일을
   ~/deja-install-backup-$(date +%Y%m%d)/ 로 복사해 줘.
2. 버전 고정: v0.19.3 릴리스의 linux 바이너리와 checksums.txt를 내려받고
   sha256sum으로 체크섬이 일치하는지 확인한 뒤 진행해 줘.
   최신 버전이 v0.19.3보다 높으면 먼저 알려주고 기다려 줘.
3. 격리 검증 먼저: 임시 홈(예: /tmp/deja-test)에서 deja --version,
   deja sources, 가상 세션 1건 색인·검색이 동작하는지 확인해 줘.
   실제 홈의 에이전트 설정은 아직 건드리지 마.
4. 격리 검증 결과를 보여준 뒤, 내가 승인하면 실제 환경에
   ~/.local/bin에 설치하고 deja install --auto로 배선해 줘.
   어떤 설정 파일이 바뀌었는지 하나씩 나열해 줘.
5. 보안 확인: 색인 대상에서 제외할 민감 프로젝트가 있으면
   ~/.config/deja/exclude에 추가하고, redaction 동작을
   테스트 문장으로 확인해 줘.
6. 마지막에 제거 방법을 안내해 줘:
   deja uninstall --all &amp;&amp; rm -rf ~/.cache/deja

절대 하지 말 것: API 키·비밀 입력 요청, 운영 프로젝트 설정 변경,
체크섬 불일치 파일 실행, 백업 없이 에이전트 설정 수정.</code></pre>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">deja-vu는 에이전트 성능 벤치마크를 올려주는 도구인가?</h3>



<p>아니다. 모델 성능을 바꾸는 도구가 아니라, 과거 세션에서 관련 기록을 찾아 현재 세션에 주입하는 회수 계층이다. &#8220;같은 실수를 반복하지 않게&#8221; 돕는 도구로 이해해야 한다.</p>



<h3 class="wp-block-heading">임베딩 없이 어떻게 검색이 되나?</h3>



<p>어휘(lexical) 검색과 시간 가중을 조합한 로컬 색인을 쓴다. 다중 단어는 AND, 정확 매치가 없으면 어형 변형·유사 철자로 확장한다. README 기준 조회 중앙값 약 0.4ms이며 이는 공식 문서 발췌다.</p>



<h3 class="wp-block-heading">세션 로그가 크면 느려지지 않나?</h3>



<p>수 GB 히스토리에서 밀리초 단위 조회를 목표로 설계됐다고 공식 문서에 명시돼 있다. 다만 이 수치는 제작자 측정이므로 자기 환경 규모로 검증 후 도입을 권한다.</p>



<h3 class="wp-block-heading">mem0를 이미 쓰고 있는데 갈아탈 필요가 있나?</h3>



<p>갈아탈 이유가 아니다. 둘은 보완 관계다. 이미 쌓인 과거 세션을 활용하는 건 deja-vu, 앞으로의 대화에서 시맨틱하게 기억하는 건 mem0의 영역이다.</p>



<h3 class="wp-block-heading">회사 노트북에 설치해도 되나?</h3>



<p>세션 로그 통독이 본질인 도구이므로 보안 정책부터 확인한다. 민감 프로젝트는 <code>~/.config/deja/exclude</code>로 제외하고, 확실하지 않으면 보안 담당자에게 먼저 확인한다.</p>



<h3 class="wp-block-heading">설치했더니 에이전트가 느려진 것 같다</h3>



<p><code>deja install --auto</code>가 켠 세션 시작 훅은 수십 밀리초 수준이라고 문서에 명시돼 있다. 그래도 부담되면 자동 배선 없이 바이너리만 두고 필요할 때 <code>deja "&lt;query&gt;"</code>로 수동 검색하는 구성도 가능하다.</p>



<h2 class="wp-block-heading">공식 참고자료</h2>



<ul class="wp-block-list">
<li>공식 저장소: https://github.com/vshulcz/deja-vu</li>

<li>공식 문서: https://vshulcz.github.io/deja-vu/</li>

<li>보안 모델 문서: https://github.com/vshulcz/deja-vu/blob/main/docs/SECURITY-MODEL.md</li>

<li>벤치마크 페이지: https://vshulcz.github.io/deja-vu/guide/benchmarks.html</li>

<li>릴리스 (checksums·SBOM 포함): https://github.com/vshulcz/deja-vu/releases</li>

<li>Hacker News 논의 (2026-07-15): https://news.ycombinator.com/item?id=48923111</li>
</ul>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2848"
					data-ulike-nonce="095ebd16dd"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2848"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/deja-vu-coding-agent-memory-install-security/">Claude Code가 지난달의 나를 기억하게 만들기: deja-vu 설치·보안 검증</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/deja-vu-coding-agent-memory-install-security/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Agent Skill 설치 전 보안 검사: NVIDIA SkillSpector vs Snyk Agent Scan</title>
		<link>https://blog.kwt.co.kr/skillspector-agent-skill-security-snyk-agent-scan/</link>
					<comments>https://blog.kwt.co.kr/skillspector-agent-skill-security-snyk-agent-scan/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Wed, 02 Sep 2026 21:50:00 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Agent Skills]]></category>
		<category><![CDATA[AI 보안]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Codex]]></category>
		<category><![CDATA[MCP]]></category>
		<category><![CDATA[NVIDIA]]></category>
		<category><![CDATA[SkillSpector]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/?p=2838</guid>

					<description><![CDATA[<p>Agent Skill 설치 전 공급망 위험을 찾는 NVIDIA SkillSpector를 직접 격리 설치·검사·제거했다. Snyk Agent Scan과 입력, 권한, 외부 전송, 비용, 연결 방식을 비교한다.</p>
<p>The post <a href="https://blog.kwt.co.kr/skillspector-agent-skill-security-snyk-agent-scan/">Agent Skill 설치 전 보안 검사: NVIDIA SkillSpector vs Snyk Agent Scan</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Claude Code·Codex·Hermes에 외부 Agent Skill을 자주 붙이는 개발자라면 <strong>설치 전에 SkillSpector의 정적 검사를 먼저 돌릴 가치가 있다</strong>. Snyk Agent Scan이 이미 설치된 에이전트·MCP·Skill을 찾아 조직 단위로 점검하는 쪽에 강하다면, NVIDIA SkillSpector는 내려받기 전 Git 저장소·URL·ZIP·SKILL.md 하나를 71개 패턴으로 검사하는 데 초점을 둔다. 다만 정적 검사에서 0점이 나와도 절대 안전을 뜻하지 않으며, 선택적 LLM 분석은 코드와 지시문을 외부 모델 제공자에게 보낼 수 있다는 점을 먼저 알아야 한다.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>핵심 요약</strong></p>

<ul class="wp-block-list">
<li>SkillSpector v2.11.0은 Apache-2.0 오픈소스 Agent Skill 보안 스캐너다.</li>

<li>2026년 9월 3일 06:37 KST 기준 GitHub 15,664 stars, 1,320 forks이며 약 24.04시간 동안 실제로 123 stars(+0.791%) 늘었다.</li>

<li><code>--no-llm</code>은 API 키 없이 로컬 정적 검사를 수행한다. OSV 실시간 취약점 조회는 네트워크를 쓰며 실패 시 오프라인으로 폴백한다.</li>

<li>개별 Skill의 설치 전 검사에는 SkillSpector, 여러 에이전트 구성의 자동 발견과 중앙 관제에는 Snyk Agent Scan이 더 맞다.</li>

<li>MCP 모드는 제공되지만 공식 README가 stdio 초기화 지연 이슈 #199를 명시한다. CLI 검사를 기본 경로로 잡는 편이 안전하다.</li>
</ul>
</blockquote>



<h2 class="wp-block-heading">SkillSpector는 무엇을 해결하나</h2>



<p>Agent Skill은 단순 문서처럼 보여도 셸 스크립트, 패키지 설치, 파일 접근, 외부 URL 호출 지시를 함께 담을 수 있다. 설치 후 에이전트가 Skill을 신뢰하면 프롬프트 인젝션, 환경변수 수집, 과도한 파일 권한, 도구 오염이 실행 흐름에 섞일 수 있다.</p>



<p>SkillSpector는 설치 후보를 먼저 가져와 다음 두 단계로 검사한다.</p>



<ol class="wp-block-list">
<li>정규식·AST·taint·YARA 기반 정적 분석을 수행한다.</li>

<li>사용자가 선택한 경우에만 LLM 의미 분석을 더한다.</li>
</ol>



<p>입력은 로컬 디렉터리, 단일 <code>SKILL.md</code>, Git 저장소 URL, ZIP 파일을 지원한다. 출력은 터미널·JSON·Markdown·SARIF이며 위험 점수, 심각도, 설치 권고, 발견 항목과 분석 완전성을 함께 남긴다. 원격 입력은 100MiB, ZIP은 10,000개 항목으로 제한하며 한도를 넘으면 fail-closed로 중단한다.</p>



<h2 class="wp-block-heading">지금 주목할 근거: stars와 외부 수요</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>항목</th><th>확인값</th></tr></thead><tbody>
<tr><td>공식 저장소</td><td>https://github.com/NVIDIA/SkillSpector</td></tr>
<tr><td>유형</td><td>CLI 보안 스캐너·선택형 MCP 서버</td></tr>
<tr><td>생성일</td><td>2026-03-21</td></tr>
<tr><td>확인한 버전</td><td>v2.11.0</td></tr>
<tr><td>최신 릴리스</td><td>2026-08-28</td></tr>
<tr><td>검증 커밋</td><td><code>7805bb94843d91cb9937f57264ca52642164499b</code></td></tr>
<tr><td>검증 시각</td><td>2026-09-03 06:49 KST</td></tr>
<tr><td>GitHub</td><td>15,664 stars · 1,320 forks · 99 open issues</td></tr>
<tr><td>실측 증가</td><td>약 24.04시간 +123 stars · +0.791%</td></tr>
<tr><td>7일·30일 증가</td><td>이력 부족으로 unavailable</td></tr>
</tbody></table></figure>




<p>이번 수치는 생성 후 평균이 아니라 저장된 GitHub 스냅숏 두 개를 비교한 실측값이다. 2026-09-01 21:35:39Z의 15,541 stars와 2026-09-02 21:37:54Z의 15,664 stars를 비교했다. 7일·30일 구간은 아직 데이터가 없어 0으로 간주하지 않았다.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" width="1035" height="585" src="https://blog.kwt.co.kr/wp-content/uploads/2026/09/skillspector-github-star-growth.png" alt="2026년 9월 3일 주요 에이전트 확장 도구 후보의 GitHub stars 약 24시간 실측 증가 비교" class="wp-image-2837" style="width:500px;height:auto"/><figcaption class="wp-element-caption">주요 후보의 약 24.04시간 GitHub stars 증가<br />출처: GitHub API, 2026-09-03 조회</figcaption></figure></div>


<p>독립 수요 신호도 확인된다. Hacker News의 SkillSpector 원문 링크는 조회 시점 49 points와 4 comments를 기록했다. Google 자동완성에는 <code>skillspector nvidia</code>, <code>skillspector github</code>, <code>skillspector tutorial</code> 같은 후속 검색어가 나타났다. 한국어 검색 결과에는 소개·뉴스형 문서는 여럿 보이지만 v2.11.0 설치, 제거, 권한, Snyk 비교를 한 번에 다룬 최신 실무 문서는 제한적이었다.</p>



<h2 class="wp-block-heading">직접 설치·검사·제거한 결과</h2>



<p>실사용 홈을 건드리지 않도록 별도 임시 <code>HOME</code>, <code>XDG_CONFIG_HOME</code>, Python 3.12 가상환경을 만들었다. GitHub main의 당시 HEAD를 커밋 SHA로 고정해 설치했다. 검증 환경은 Linux aarch64, Python 3.12.3이다.</p>



<pre class="wp-block-code"><code>python3.12 -m venv --without-pip /tmp/skillspector-test/venv
python3 -m pip --python /tmp/skillspector-test/venv/bin/python \
  install 'git+https://github.com/NVIDIA/SkillSpector.git@7805bb94843d91cb9937f57264ca52642164499b'

/tmp/skillspector-test/venv/bin/skillspector --version
/tmp/skillspector-test/venv/bin/skillspector scan /tmp/safe-example \
  --no-llm --format json</code></pre>



<p>실제 출력에서 버전은 <code>SkillSpector v2.11.0</code>으로 인식됐다. 119바이트짜리 무해한 테스트 Skill을 검사하자 <code>score: 0</code>, <code>severity: LOW</code>, <code>recommendation: SAFE</code>, <code>coverage_percent: 100.0</code>, <code>execution_successful: true</code>가 나왔다. LLM은 요청하지 않았고 <code>llm_requested: false</code>, <code>llm_available: false</code>도 확인했다.</p>



<p>검사 뒤 가상환경과 임시 루트를 삭제했으며 실행 파일이 사라진 것도 확인했다. Docker 방식도 시도했지만 현재 계정에 <code>/var/run/docker.sock</code> 권한이 없어 빌드·실행 검증에는 쓰지 못했다. MCP 서버의 end-to-end 도구 호출과 유료 LLM 분석은 수행하지 않았다.</p>



<p>소스 아카이브의 SHA-256도 별도로 계산했다.</p>



<pre class="wp-block-code"><code>5476c03107ce7505b5045556a0e32b9dfc80805b51b28e21cbc98442ce789401</code></pre>



<p>이 체크섬은 커밋 <code>7805bb9...</code>의 GitHub tar.gz에만 해당한다. 커밋이나 아카이브가 바뀌면 다시 계산해야 한다.</p>



<h2 class="wp-block-heading">설치 전 권한·데이터·비용 체크</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>점검 항목</th><th>SkillSpector 동작</th><th>실무 판단</th></tr></thead><tbody>
<tr><td>로컬 파일</td><td>지정한 Skill·저장소를 읽고 보고서를 쓴다</td><td>읽기 전용 복사본이나 컨테이너 마운트 권장</td></tr>
<tr><td>원격 입력</td><td>Git URL·ZIP·파일 URL을 내려받는다</td><td>커밋 고정과 출처 확인 필요</td></tr>
<tr><td>취약점 조회</td><td>OSV.dev에 실시간 질의할 수 있다</td><td>완전 오프라인 요구 시 네트워크 차단 후 동작 확인 필요</td></tr>
<tr><td>LLM 전송</td><td>OpenAI·Anthropic·Bedrock·NVIDIA 또는 지정 엔드포인트로 의미 분석을 보낸다</td><td>민감 코드에는 <code>--no-llm</code> 또는 승인된 로컬 모델 사용</td></tr>
<tr><td>API 키</td><td>정적 검사에는 불필요하다</td><td>키를 명령행에 직접 넣지 말고 격리된 환경변수·비밀 저장소 사용</td></tr>
<tr><td>텔레메트리</td><td>공식 문서에서 별도 옵트아웃 텔레메트리 설정을 확인하지 못했다</td><td>미확인으로 기록하고 egress 로그로 검증 권장</td></tr>
<tr><td>비용</td><td>CLI와 정적 검사는 오픈소스다</td><td>외부 LLM·클라우드 사용료는 제공자 요금에 따라 발생</td></tr>
<tr><td>라이선스</td><td>Apache-2.0</td><td>기업 사용 가능하나 의존성별 라이선스도 확인 필요</td></tr>
<tr><td>공급망</td><td>소스 설치가 많은 Python 의존성을 끌어온다</td><td>커밋 고정, 격리 환경, lock·SBOM 확인 권장</td></tr>
<tr><td>HTTP MCP</td><td>인증 없이 동작한다</td><td><code>127.0.0.1</code> 유지, 외부 바인딩 시 인증 프록시 필요</td></tr>
</tbody></table></figure>




<p>가장 중요한 경고는 결과 해석이다. <code>SAFE</code>는 검사한 버전과 검사 모드에서 발견 규칙에 걸리지 않았다는 뜻이다. 난독화, 런타임 다운로드, 조건부 동작, 모델이 놓친 의미 위험까지 없다는 보증은 아니다.</p>



<h2 class="wp-block-heading">Claude Code·Codex·Hermes 연결법</h2>



<p>먼저 CLI를 커밋 고정으로 격리 설치한다. <code>uv</code>를 쓸 수 있다면 공식 설치 흐름은 다음과 같다.</p>



<pre class="wp-block-code"><code>uv tool install \
  'git+https://github.com/NVIDIA/SkillSpector.git@7805bb94843d91cb9937f57264ca52642164499b'

skillspector --version
skillspector scan ./검사할-skill --no-llm</code></pre>



<p>MCP가 필요하면 extra를 포함해 다시 설치한다.</p>



<pre class="wp-block-code"><code>uv tool install --force \
  'skillspector[mcp] @ git+https://github.com/NVIDIA/SkillSpector.git@7805bb94843d91cb9937f57264ca52642164499b'</code></pre>



<h3 class="wp-block-heading">Claude Code</h3>



<p>공식 README의 등록 명령은 다음과 같다. 사용자 전체가 아니라 현재 프로젝트부터 시험하려면 Claude Code의 기본 local scope를 유지한다.</p>



<pre class="wp-block-code"><code>claude mcp add skillspector -- skillspector mcp
claude mcp list</code></pre>



<p>문제가 있으면 설정에서 <code>skillspector</code> 항목을 제거하고 <code>claude mcp remove skillspector</code>로 원상복구한다. 공식 저장소가 명시한 stdio 초기화 지연 이슈 #199가 재현되면 MCP를 억지로 유지하지 말고 CLI <code>scan</code>으로 돌아가는 편이 낫다.</p>



<h3 class="wp-block-heading">Codex</h3>



<p>현재 Codex CLI의 <code>mcp add</code> 구문에 맞춘 연결은 다음과 같다.</p>



<pre class="wp-block-code"><code>codex mcp add skillspector -- skillspector mcp
codex mcp list</code></pre>



<p>제거는 <code>codex mcp remove skillspector</code> 뒤 <code>codex mcp list</code>로 확인한다. Codex 설정은 보통 <code>~/.codex/config.toml</code>에 기록되므로 변경 전 백업을 남기는 편이 안전하다.</p>



<h3 class="wp-block-heading">Hermes Agent</h3>



<p>Hermes는 <code>~/.hermes/config.yaml</code>의 <code>mcp_servers</code>를 읽는다. 다음 블록을 수동으로 추가하기 전에 파일을 백업한다.</p>



<pre class="wp-block-code"><code>mcp_servers:
  skillspector:
    command: skillspector
    args: ["mcp"]</code></pre>



<p>Hermes를 다시 시작해 MCP 도구 목록을 확인한다. 제거할 때는 백업에서 해당 블록만 복원하고 다시 시작한다. 다만 MCP 초기화 이슈를 감안하면 Hermes에서도 터미널 도구로 <code>skillspector scan ... --no-llm</code>을 호출하는 경로가 더 단순하다. Hermes의 Skill 디렉터리는 <code>~/.hermes/skills/</code>이며, 외부 Skill을 검사한 뒤에만 이 경로로 옮기는 순서를 권한다.</p>



<h2 class="wp-block-heading">SkillSpector vs Snyk Agent Scan</h2>



<p>두 도구는 <strong>개별 Skill 검사에서는 직접 대체재</strong>, 조직 전체 에이전트 자산 관리에서는 <strong>부분 대체재이자 보완재</strong>다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>비교 기준</th><th>NVIDIA SkillSpector</th><th>Snyk Agent Scan</th></tr></thead><tbody>
<tr><td>제품 범주</td><td>설치 전 Skill 스캐너·MCP 게이트</td><td>에이전트·MCP·Skill 발견 및 위험 스캐너</td></tr>
<tr><td>주요 입력</td><td>Git URL, ZIP, 디렉터리, 단일 파일</td><td>로컬 머신의 에이전트 구성과 지정 파일</td></tr>
<tr><td>출력</td><td>터미널, JSON, Markdown, SARIF, 위험 점수</td><td>실험적 CLI 위험 출력, 기업용 Evo 연계</td></tr>
<tr><td>정확도 방식</td><td>71개 정적 패턴+선택적 LLM, 분석 완전성 표시</td><td>15개 위험군, Snyk 분석 API와 구성 자동 발견</td></tr>
<tr><td>수정 가능성</td><td>baseline으로 오탐 억제, 로컬 규칙·소스 수정 가능</td><td>CLI 출력은 변경 가능성이 있다고 공식 경고</td></tr>
<tr><td>재현성</td><td>버전·커밋 고정과 <code>--no-llm</code>로 높일 수 있다</td><td>standalone checksum·GPG 서명 제공</td></tr>
<tr><td>비용 모델</td><td>정적 검사는 무료, LLM 제공자 비용 별도</td><td>Snyk 가입과 <code>SNYK_TOKEN</code> 필요, 기업 기능 별도</td></tr>
<tr><td>데이터 경계</td><td>정적 모드는 로컬 중심, OSV·원격 입력·LLM 선택 시 외부 통신</td><td>분석 API 전송과 기업 플랫폼 연계를 전제로 한다</td></tr>
<tr><td>권한 위험</td><td>지정 입력을 읽고 선택한 출력에 쓴다</td><td>MCP 구성 검사 시 명시된 서버 명령을 실제 실행할 수 있다</td></tr>
<tr><td>에이전트 연결</td><td>CLI 또는 stdio/HTTP MCP</td><td>설치된 Claude·Codex·Cursor 등 자동 발견</td></tr>
</tbody></table></figure>




<p><strong>SkillSpector를 고를 때</strong>는 새 Skill 한두 개를 설치 전에 검사하고, API 키 없이 정적 결과와 SARIF를 남기고 싶을 때다. <strong>Snyk Agent Scan을 고를 때</strong>는 여러 개발자의 에이전트 구성과 MCP 서버를 자동 발견하고 조직 단위로 추적할 때다. 둘을 함께 쓴다면 SkillSpector로 반입 전 검사를 하고, Snyk Agent Scan으로 설치 후 자산 발견과 지속 점검을 맡기면 된다.</p>



<p>Snyk의 중요한 차이는 MCP 설정을 읽는 데서 끝나지 않고 stdio 서버 명령을 실행해 도구 설명을 가져올 수 있다는 점이다. 공식 문서도 낯선 MCP 구성은 샌드박스에서 검사하라고 경고한다. 반대로 SkillSpector의 HTTP MCP는 인증이 없으므로 외부 인터페이스에 직접 바인딩하면 안 된다.</p>



<h2 class="wp-block-heading">추천하는 경우와 추천하지 않는 경우</h2>



<h3 class="wp-block-heading">추천하는 경우</h3>



<ul class="wp-block-list">
<li>skills.sh나 GitHub에서 받은 Agent Skill을 자주 시험하는 개인 개발자</li>

<li>Claude Code·Codex·Hermes가 공유할 Skill 반입 절차를 만들려는 팀</li>

<li>API 키 없이 정적 검사부터 시작하려는 환경</li>

<li>JSON·SARIF 결과를 CI 승인 게이트에 연결하려는 팀</li>

<li>프롬프트 인젝션뿐 아니라 스크립트·공급망·MCP 권한 패턴까지 함께 보고 싶은 경우</li>
</ul>



<h3 class="wp-block-heading">추천하지 않는 경우</h3>



<ul class="wp-block-list">
<li><code>SAFE</code> 한 줄을 보안 보증서처럼 사용하려는 경우</li>

<li>모델 제공자에게 소스가 나가면 안 되는데 기본 LLM 설정을 검토하지 않은 경우</li>

<li>인증 없는 HTTP MCP를 사내망이나 인터넷에 그대로 노출하려는 경우</li>

<li>조직 전체의 설치 현황 자동 발견과 중앙 관제가 핵심인 경우</li>

<li>Python 의존성 공급망을 검토할 여력이 전혀 없는 경우</li>
</ul>



<h2 class="wp-block-heading">안전한 복사·붙여넣기 프롬프트</h2>



<p>아래 프롬프트와 이 글 URL을 Claude Code나 Codex에 함께 주면 운영 환경을 건드리지 않는 검증부터 요청할 수 있다.</p>



<pre class="wp-block-code"><code>이 글의 SkillSpector 절차를 참고하되 바로 설치하지 말라.
1) 공식 저장소와 Apache-2.0 라이선스, 현재 릴리스, 커밋
   7805bb94843d91cb9937f57264ca52642164499b를 다시 확인하라.
2) 기존 ~/.claude, ~/.codex, ~/.hermes, ~/.agents를 해시 또는 백업하고
   별도 임시 HOME/XDG_CONFIG_HOME/작업 디렉터리만 사용하라.
3) 소스 tar.gz SHA-256이
   5476c03107ce7505b5045556a0e32b9dfc80805b51b28e21cbc98442ce789401와
   같은지 확인하라. 다르면 중단하라.
4) Python 3.12 가상환경 또는 읽기 전용 마운트 컨테이너에 커밋을 고정해 설치하라.
5) API 키, 로그인, 결제, 운영 저장소 수정, 셸 프로필 변경을 금지한다.
6) 먼저 --version, --help, --no-llm 정적 검사를 실행하고 생성 파일과
   네트워크·파일·셸 권한을 보고하라.
7) MCP 등록은 별도 승인 전 실행하지 말고 변경될 설정 경로와 정확한 diff만 제시하라.
8) 검증 뒤 패키지·가상환경·임시 설정을 제거하고 원래 홈의 해시가 같은지 확인하라.
9) 직접 실행한 결과와 문서에서만 확인한 항목을 분리해 보고하라.</code></pre>



<h2 class="wp-block-heading">설치 전 체크리스트</h2>



<ul class="wp-block-list">
<li>[ ] 저장소 소유자와 URL이 <code>NVIDIA/SkillSpector</code>인지 확인했다.</li>

<li>[ ] 커밋 또는 릴리스를 고정했다.</li>

<li>[ ] 아카이브 체크섬을 다시 계산했다.</li>

<li>[ ] 임시 HOME·가상환경·읽기 전용 입력을 사용했다.</li>

<li>[ ] 첫 검사는 <code>--no-llm</code>으로 실행했다.</li>

<li>[ ] OSV와 Git 다운로드에 필요한 네트워크만 허용했다.</li>

<li>[ ] LLM 분석 전 코드 외부 전송과 비용을 승인받았다.</li>

<li>[ ] MCP는 <code>127.0.0.1</code> 또는 stdio로 제한했다.</li>

<li>[ ] 결과의 coverage와 skipped analyzer를 함께 읽었다.</li>

<li>[ ] 제거 명령과 설정 백업 복원까지 시험했다.</li>
</ul>



<p>Agent Skill 자체를 어떻게 배치하는지 먼저 보고 싶다면 <a href="https://blog.kwt.co.kr/claude-code-skills-%ec%84%b8%ed%8c%85-%ec%99%84%eb%b2%bd-%ea%b0%80%ec%9d%b4%eb%93%9c/">Claude Code Skills 세팅 가이드</a>가 기초가 된다. 실제 설치 후보가 어떤 형태인지 보려면 <a href="https://blog.kwt.co.kr/video-shotcraft-claude-code-codex-agent-skill/">video-shotcraft Agent Skill 가이드</a>를 함께 볼 수 있다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">정적 검사만으로 충분한가</h3>



<p>충분하지 않다. 정적 검사는 알려진 패턴과 코드 구조를 빠르게 찾는 1차 필터다. 설치 후 네트워크 행위, 조건부 다운로드, 실제 에이전트 권한은 격리 실행과 수동 검토로 보완해야 한다.</p>



<h3 class="wp-block-heading"><code>--no-llm</code>이면 완전히 오프라인인가</h3>



<p>항상 그렇지는 않다. 로컬 경로를 입력해도 OSV 실시간 조회 기능이 네트워크를 사용할 수 있다. 원격 Git·URL 입력은 당연히 다운로드 통신이 필요하다. 완전 오프라인 요구가 있다면 방화벽으로 egress를 차단하고 결과의 fallback·skipped 항목을 확인해야 한다.</p>



<h3 class="wp-block-heading">Claude Code와 Codex에서 같은 MCP를 써도 되나</h3>



<p>가능하다. 둘 다 stdio 명령으로 <code>skillspector mcp</code>를 등록할 수 있다. 다만 현재 공식 README가 stdio 초기화 지연 이슈를 명시하므로 CLI 검사를 기본으로 두고 MCP는 별도 격리 환경에서 먼저 확인하는 편이 낫다.</p>



<h3 class="wp-block-heading">Snyk Agent Scan을 이미 쓰면 필요 없나</h3>



<p>목적이 일부 겹친다. 새 Skill의 반입 전 로컬 정적 검사와 세부 보고서가 필요하면 SkillSpector가 보완한다. 설치된 구성 자동 발견과 기업 중앙 관제가 목적이면 Snyk 쪽 비중이 더 크다.</p>



<h3 class="wp-block-heading">제거하면 무엇이 남나</h3>



<p><code>uv tool uninstall skillspector</code>로 도구를 제거한다. MCP에 등록했다면 Claude Code·Codex·Hermes 설정의 <code>skillspector</code> 항목도 따로 지워야 한다. 생성한 JSON·SARIF·baseline 파일과 캐시는 사용자가 정한 보존 정책에 따라 별도로 삭제한다.</p>



<script type="application/ld+json">
{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"정적 검사만으로 충분한가","acceptedAnswer":{"@type":"Answer","text":"충분하지 않다. 정적 검사는 1차 필터이며 격리 실행과 수동 검토로 보완해야 한다."}},{"@type":"Question","name":"--no-llm이면 완전히 오프라인인가","acceptedAnswer":{"@type":"Answer","text":"항상 그렇지는 않다. OSV 실시간 조회와 원격 Git·URL 입력은 네트워크를 사용할 수 있다."}},{"@type":"Question","name":"Snyk Agent Scan을 이미 쓰면 SkillSpector가 필요한가","acceptedAnswer":{"@type":"Answer","text":"새 Skill의 반입 전 로컬 정적 검사가 필요하면 SkillSpector가 보완한다. 설치 구성 자동 발견과 기업 중앙 관제가 목적이면 Snyk Agent Scan의 비중이 더 크다."}}]}
</script>



<h2 class="wp-block-heading">공식 참고자료</h2>



<ul class="wp-block-list">
<li><a href="https://github.com/NVIDIA/SkillSpector">NVIDIA SkillSpector 공식 저장소</a></li>

<li><a href="https://github.com/NVIDIA/SkillSpector/releases/tag/v2.11.0">SkillSpector v2.11.0 릴리스</a></li>

<li><a href="https://docs.nvidia.com/skills/scanning-agent-skills">NVIDIA Agent Skill 검사 가이드</a></li>

<li><a href="https://agentskills.io/specification">Agent Skills 공식 사양</a></li>

<li><a href="https://github.com/snyk/agent-scan">Snyk Agent Scan 공식 저장소</a></li>

<li><a href="https://news.ycombinator.com/item?id=48509844">Hacker News SkillSpector 토론</a></li>

<li><a href="https://hermes-agent.nousresearch.com/docs/user-guide/features/skills">Hermes Agent Skills 문서</a></li>

<li><a href="https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp">Hermes Agent MCP 문서</a></li>
</ul>



<p>자료와 수치는 2026년 9월 3일에 다시 확인했다. stars는 변동값이며, 기능 수와 탐지 패턴 수는 분류 기준이 달라 단순히 숫자가 큰 도구가 더 정확하다는 뜻이 아니다.</p>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2838"
					data-ulike-nonce="b5f435b4b8"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2838"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/skillspector-agent-skill-security-snyk-agent-scan/">Agent Skill 설치 전 보안 검사: NVIDIA SkillSpector vs Snyk Agent Scan</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/skillspector-agent-skill-security-snyk-agent-scan/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>video-shotcraft란? Claude Code와 Codex로 제품 영상을 만드는 Agent Skill</title>
		<link>https://blog.kwt.co.kr/video-shotcraft-claude-code-codex-agent-skill/</link>
					<comments>https://blog.kwt.co.kr/video-shotcraft-claude-code-codex-agent-skill/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Wed, 02 Sep 2026 00:47:18 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Agent Skills]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Codex]]></category>
		<category><![CDATA[Higgsfield]]></category>
		<category><![CDATA[Remotion]]></category>
		<category><![CDATA[video-shotcraft]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/?p=2819</guid>

					<description><![CDATA[<p>video-shotcraft의 기능과 Claude Code·Codex 설치 방법을 최신 커밋에서 검증하고 Higgsfield와 비교했다. 실제 제품 UI·수정 가능성·실사 생성·비용·보안 관점에서 어떤 도구가 맞는지 정리했다.</p>
<p>The post <a href="https://blog.kwt.co.kr/video-shotcraft-claude-code-codex-agent-skill/">video-shotcraft란? Claude Code와 Codex로 제품 영상을 만드는 Agent Skill</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>video-shotcraft는 Claude Code나 Codex가 웹·데스크톱 제품의 홍보 영상을 Remotion 코드로 만들도록 돕는 Agent Skill이다. 설치는 저장소 주소를 에이전트에 건네는 방식으로 간단하지만, 영상 제작 과정에서 프로젝트 파일·브라우저·셸을 폭넓게 사용한다. 따라서 장난감 프롬프트 모음보다는 <strong>권한을 검토한 뒤 격리된 프로젝트에서 사용하는 제작 도구</strong>로 보는 편이 정확하다.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1400" height="788" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/video-shotcraft-agent-skill.jpg" alt="video-shotcraft로 Claude Code와 Codex에서 제품 영상을 만드는 흐름" class="wp-image-2818"/><figcaption class="wp-element-caption">video-shotcraft의 제품 영상 제작 흐름<br />출처: 직접 제작</figcaption></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>핵심 요약</strong></p>

<ul class="wp-block-list">
<li>2026년 7월 19일 공개된 뒤 약 45일 만에 GitHub 별 7,015개를 모은 급상승 Agent Skill이다.</li>

<li>157개 샷 레시피와 214개 모션 미리보기, Remotion 템플릿을 제공한다.</li>

<li>Claude Code와 Codex 설치를 격리된 임시 환경에서 직접 확인했고 제거까지 정상 동작했다.</li>

<li>설치 스캐너 결과는 Gen Safe, Socket 0 alerts였지만 Snyk는 High Risk로 표시했다. 여러 스캐너 판단이 엇갈리므로 무조건 안전하다고 단정하면 안 된다.</li>

<li>제품 화면을 캡처하므로 고객 정보, API 키, 내부 데이터가 노출되지 않도록 별도 검토가 필요하다.</li>

<li>Higgsfield처럼 영상을 직접 생성하는 서비스와 달리 실제 제품 화면을 Remotion 코드로 조립한다. 두 도구는 대체재라기보다 서로 다른 장면에 맞는 보완재에 가깝다.</li>
</ul>
</blockquote>



<h2 class="wp-block-heading">video-shotcraft가 해결하는 문제</h2>



<p>제품 소개 영상을 직접 만들려면 화면 캡처, 장면 구성, 애니메이션, 전환, 배경음악과 효과음, 렌더링을 각각 처리해야 한다. 개발자가 Remotion으로 영상을 만들 수는 있지만, 어떤 카메라 움직임과 전환을 써야 하는지부터 다시 설계하면 시간이 오래 걸린다.</p>



<p>video-shotcraft는 이 과정을 에이전트가 따라갈 수 있는 제작 절차로 정리한 Skill이다. 저장소에는 다음 자산이 포함돼 있다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>구성</th><th>저장소가 안내하는 내용</th></tr></thead><tbody>
<tr><td>샷 레시피</td><td>157개</td></tr>
<tr><td>모션 미리보기</td><td>214개</td></tr>
<tr><td>영상 엔진</td><td>React 기반 Remotion</td></tr>
<tr><td>완성 템플릿</td><td>36.2초, 1920×1080, 30fps Ink Press 템플릿</td></tr>
<tr><td>사운드</td><td>16개 범주, 149개 효과음과 BGM 후보</td></tr>
<tr><td>지원 에이전트</td><td>Claude Code, Codex 등 Agent Skills 호환 도구</td></tr>
<tr><td>라이선스</td><td>저장소는 Apache-2.0, Remotion과 개별 음원은 별도 조건 확인 필요</td></tr>
</tbody></table></figure>




<p>단순히 “멋진 영상을 만들어줘”라는 프롬프트를 추가하는 구조는 아니다. 에이전트가 제품을 확인하고, 실제 화면을 캡처하고, 샷 카드를 고르고, Remotion 프로젝트를 수정하고, 렌더링 결과를 다시 검사하는 작업 흐름을 제공한다.</p>



<h2 class="wp-block-heading">왜 지금 살펴볼 만한가</h2>



<p>GitHub API에서 확인한 2026년 9월 2일 기준 수치는 다음과 같다.</p>



<ul class="wp-block-list">
<li>저장소 생성: 2026년 7월 19일</li>

<li>GitHub stars: 7,015</li>

<li>forks: 623</li>

<li>확인한 커밋: <code>6c116cbd24eeb43c99d396696b509f8d88e58789</code></li>

<li>저장소 생성 후 경과: 약 44.5일</li>

<li>생성 이후 단순 평균 증가량: 약 158 stars/일</li>
</ul>



<p>이 값은 매일의 실제 별 증가량이 아니라 현재 별 수를 저장소 나이로 나눈 단순 평균이다. 그래도 한 달 남짓한 기간에 7천 개 이상을 모았다는 점은 초기 관심이 빠르게 커졌다는 신호로 볼 수 있다.</p>



<p>관심도만으로 추천한 것은 아니다. 이번 글에서는 실제 저장소를 내려받고 Agent Skills CLI로 Claude Code와 Codex 대상 설치를 실행했다. 설치 후 파일 위치와 목록을 확인하고 제거 명령으로 원상복구되는 것까지 검증했다.</p>



<h2 class="wp-block-heading">어떤 상황에서 유용한가</h2>



<p>다음과 같은 작업에 잘 맞는다.</p>



<ul class="wp-block-list">
<li>SaaS나 웹 서비스의 출시·업데이트 소개 영상</li>

<li>데스크톱 앱의 주요 기능 홍보 영상</li>

<li>랜딩 페이지에 넣을 짧은 제품 영상</li>

<li>화면 녹화만으로는 밋밋한 기능 데모</li>

<li>Remotion을 사용하지만 장면 구성과 움직임 설계가 어려운 경우</li>

<li>디자인 전문 인력 없이 개발자가 초안을 빠르게 만들려는 경우</li>
</ul>



<p>반대로 인터뷰, 실사 촬영, 캐릭터 애니메이션, 장편 영상 편집이 중심이라면 이 Skill의 주력 범위와 다르다. 저장소도 웹·데스크톱 제품 홍보 영상에 초점을 맞추고 있다.</p>



<h2 class="wp-block-heading">Higgsfield와 비교하면 무엇이 다른가</h2>



<p>Higgsfield도 제품·광고 영상을 만들 수 있어 결과만 보면 video-shotcraft와 비슷해 보인다. 그러나 제작 방식은 다르다. Higgsfield는 여러 이미지·영상 생성 모델을 한곳에서 사용하는 클라우드 플랫폼이고, video-shotcraft는 Claude Code나 Codex가 실제 제품 화면과 Remotion 코드를 다루도록 만드는 로컬 Agent Skill이다.</p>



<p>Higgsfield 공식 MCP 페이지는 Soul, Cinema Studio, Flux, Seedream, Kling, Minimax Hailuo, Veo 등을 포함한 30개 이상의 모델을 제공한다고 안내한다. 텍스트나 참조 이미지에서 최대 15초 영상을 생성하며, 에이전트는 Higgsfield 계정 인증 후 기존 구독 크레딧을 사용한다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>비교 기준</th><th>video-shotcraft</th><th>Higgsfield</th></tr></thead><tbody>
<tr><td>제품 분류</td><td>로컬 Agent Skill과 Remotion 제작 자산</td><td>클라우드 생성형 미디어 플랫폼·모델 집계 계층</td></tr>
<tr><td>주요 입력</td><td>실제 웹·앱 화면, 프로젝트 파일, 브랜드 토큰</td><td>텍스트 프롬프트, 이미지, 이전 생성 결과</td></tr>
<tr><td>결과 생성 방식</td><td>React·Remotion 코드로 장면을 조립하고 렌더링</td><td>선택한 생성 모델이 이미지·영상을 생성</td></tr>
<tr><td>제품 UI 정확도</td><td>실제 스크린숏을 사용하므로 높이기 쉽다</td><td>생성 과정에서 UI·문자·수치가 달라질 수 있다</td></tr>
<tr><td>인물·실사 장면</td><td>주력 범위가 아니다</td><td>UGC, 패션, 인물, 광고 장면에 적합하다</td></tr>
<tr><td>수정 방식</td><td>코드·타이밍·문구·색상을 지정해 다시 렌더링</td><td>프롬프트·참조 이미지를 바꿔 다시 생성</td></tr>
<tr><td>재현성</td><td>코드와 고정 자산을 유지하면 비교적 높다</td><td>같은 프롬프트도 결과가 달라질 수 있다</td></tr>
<tr><td>길이</td><td>장면을 이어 구성하며 36.2초 템플릿도 제공</td><td>공식 MCP 안내 기준 개별 영상 최대 15초</td></tr>
<tr><td>비용 구조</td><td>Skill은 오픈소스지만 에이전트·모델·렌더링·Remotion 조건이 별도다</td><td>모델과 해상도에 따라 구독 크레딧을 소비한다</td></tr>
<tr><td>데이터 처리</td><td>로컬 작업이 가능하지만 사용하는 에이전트·모델의 전송 범위는 별도 확인이 필요하다</td><td>프롬프트와 입력 자산을 클라우드 서비스에 전달한다</td></tr>
<tr><td>에이전트 연결</td><td>로컬 Skill 파일을 Claude Code·Codex에 설치</td><td>공식 MCP 연결 후 Higgsfield 계정으로 인증</td></tr>
</tbody></table></figure>




<h3 class="wp-block-heading">실제 제품 화면이 중요하면 video-shotcraft</h3>



<p>SaaS 기능 소개 영상에는 버튼 이름, 요금 숫자, 차트, 화면 배치가 정확해야 한다. 생성형 영상 모델은 분위기 있는 장면을 빠르게 만들 수 있지만 작은 UI 문자와 실제 화면 구조를 그대로 유지하는 데 불리하다. video-shotcraft는 실제 화면을 캡처한 뒤 카메라 이동과 전환을 코드로 더하므로 제품 정확도를 유지하기 쉽다.</p>



<p>수정 방식도 다르다. “가격 문구만 바꾸고 두 번째 장면을 12프레임 늦춰 달라”와 같은 요청은 코드 기반 영상이 유리하다. 장면과 타이밍이 소스에 남아 있어 해당 부분만 고쳐 다시 렌더링할 수 있기 때문이다.</p>



<h3 class="wp-block-heading">인물과 실사 광고 컷이 필요하면 Higgsfield</h3>



<p>사용자가 제품을 들고 말하는 UGC 광고, 패션 촬영, 영화 같은 배경과 카메라 움직임, 실제로 촬영하기 어려운 장면은 Higgsfield 쪽이 맞다. 공식 MCP는 30개 이상의 모델을 제공하고, 에이전트가 작업에 맞는 모델을 고르거나 사용자가 직접 지정할 수 있다고 안내한다.</p>



<p>대신 생성 결과를 여러 번 비교하는 과정이 필요할 수 있다. 모델·해상도마다 크레딧이 다르고 재시도도 비용에 포함되므로, 월간 크레딧을 곧바로 “영상 몇 개”로 환산하면 안 된다.</p>



<h3 class="wp-block-heading">구독 가격과 오픈소스만 비교하면 안 된다</h3>



<p>2026년 9월 2일 한국 지역 응답으로 확인한 Higgsfield 가격 API에는 Starter 월 15달러·200크레딧, Plus 월 49달러·1,000크레딧이 표시됐다. 연간 결제와 상위 요금제는 별도 금액과 할인이 적용될 수 있으며, 계정별 실험군이 바뀔 수 있으므로 실제 체크아웃 가격이 최종 기준이다.</p>



<p>video-shotcraft 저장소는 Apache-2.0이지만 비용이 0이라는 뜻은 아니다. Claude Code·Codex 사용 비용, 선택한 모델 비용, 렌더링 장비와 시간, 회사 사용 시 Remotion 라이선스가 별도로 발생할 수 있다. Higgsfield는 크레딧 비용이 명확한 대신 로컬 렌더링 환경을 직접 구축할 필요가 적다.</p>



<h3 class="wp-block-heading">둘을 함께 쓰는 방법도 있다</h3>



<p>두 도구는 직접 대체재보다 보완재에 가깝다. 제품 영상이라면 다음 구성이 현실적이다.</p>



<ol class="wp-block-list">
<li>Higgsfield로 시선을 끄는 오프닝, 인물 UGC, 배경 B-roll을 만든다.</li>

<li>video-shotcraft로 실제 제품 UI, 기능 설명, 차트와 자막 장면을 만든다.</li>

<li>Remotion 타임라인에서 생성 영상과 실제 제품 장면을 합치고 사운드·자막을 맞춘다.</li>
</ol>



<p>브랜드 분위기와 실사 장면은 생성형 모델에 맡기고, 틀리면 안 되는 제품 정보는 실제 화면과 코드로 유지하는 방식이다. 정확도와 시각적 임팩트를 동시에 확보하려면 이 혼합 방식이 가장 실용적이다.</p>



<h2 class="wp-block-heading">Claude Code와 Codex에 설치하는 방법</h2>



<p>Node.js와 npm을 사용할 수 있는 환경이라면 Agent Skills CLI로 설치할 수 있다.</p>



<pre class="wp-block-code"><code>npx skills add Vincentwei1021/video-shotcraft \
  -g \
  -a claude-code codex \
  -s video-shotcraft \
  -y</code></pre>



<p>격리된 임시 HOME에서 이 명령을 실행한 결과 설치 종료 코드는 0이었다. 공용 Skill은 다음 위치에 생성됐다.</p>



<pre class="wp-block-code"><code>~/.agents/skills/video-shotcraft</code></pre>



<p>Claude Code용 경로에는 공용 Skill을 가리키는 심볼릭 링크가 만들어졌다.</p>



<pre class="wp-block-code"><code>~/.claude/skills/video-shotcraft</code></pre>



<p>Codex는 공용 Agent Skills 경로를 사용하는 방식으로 설치 요약에 표시됐다. 설치 결과는 다음 명령으로 확인할 수 있다.</p>



<pre class="wp-block-code"><code>npx skills list -g --json</code></pre>



<h3 class="wp-block-heading">포스팅 주소를 에이전트에 붙여 넣어 설치시키는 프롬프트</h3>



<p>다음 프롬프트와 이 글의 주소를 Claude Code나 Codex에 함께 전달하면 된다.</p>



<pre class="wp-block-code"><code>이 글의 설치 절차와 공식 GitHub 저장소를 읽어줘.
현재 환경이 Claude Code인지 Codex인지 확인하고,
설치 전에 변경될 경로와 필요한 권한을 먼저 설명해줘.

skills.sh 보안 평가에서 Snyk High Risk 경고가 있었으므로
SKILL.md와 실행 스크립트를 검토하고, 위험한 동작이나
외부 전송 가능성이 있으면 설치를 중단하고 알려줘.

문제가 없으면 video-shotcraft를 설치하고
npx skills list -g --json으로 설치 결과를 확인해줘.
검증한 기준 커밋은 6c116cbd24eeb43c99d396696b509f8d88e58789이며,
현재 HEAD가 다르면 주요 변경 사항을 먼저 요약해줘.

글 주소:
여기에 이 포스팅 주소를 붙여 넣기</code></pre>



<p>저장소 README의 가장 짧은 방식은 <code>Install this skill for me:</code> 뒤에 GitHub 주소를 붙이는 것이다. 그러나 에이전트가 저장소의 현재 main 브랜치를 가져올 수 있으므로 위처럼 변경 경로와 최신 차이를 먼저 확인하도록 요청하는 편이 안전하다.</p>



<h2 class="wp-block-heading">설치 전 반드시 확인할 보안 경고</h2>



<p>Agent Skills CLI가 설치 전에 표시한 보안 결과는 다음과 같았다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>검사기</th><th>결과</th></tr></thead><tbody>
<tr><td>Gen</td><td>Safe</td></tr>
<tr><td>Socket</td><td>0 alerts, Low Risk, score 87</td></tr>
<tr><td>Snyk</td><td>High Risk</td></tr>
</tbody></table></figure>




<p>세 검사 결과가 일치하지 않는다. 해당 감사 API는 Snyk가 High Risk로 분류했다는 결과와 분석 시각만 제공하고 상세 근거는 반환하지 않았다. 따라서 “다른 검사기가 안전하다고 했으니 문제없다”거나 “High Risk이므로 악성 코드다”라고 어느 한쪽으로 단정하기 어렵다.</p>



<p>저장소를 직접 확인했을 때 루트 <code>package.json</code>에는 테스트 명령만 있었고 <code>preinstall</code>이나 <code>postinstall</code> 스크립트는 없었다. 템플릿의 <code>package.json</code>도 Remotion 실행 명령과 고정된 주요 패키지 버전으로 구성돼 있었다. 검색한 범위에서 자동 설치 단계에 원격 스크립트를 내려받아 실행하는 패턴은 확인되지 않았다.</p>



<p>다만 Skill의 본래 작업 범위가 넓다. 제품 프로젝트를 읽고, 로컬 개발 서버를 실행하고, 브라우저로 화면을 캡처하고, 파일을 복사·수정하고, npm 패키지를 설치하고, 최종 영상을 렌더링한다. Agent Skill은 에이전트 권한으로 실행되므로 설치 파일 자체가 단순해도 실제 사용 단계의 권한은 크다.</p>



<p>안전하게 사용하려면 다음 기준을 지키는 편이 좋다.</p>



<ol class="wp-block-list">
<li>처음에는 운영 프로젝트가 아닌 복제본이나 별도 worktree에서 실행한다.</li>

<li><code>.env</code>, 고객 정보, 관리자 화면, 내부 URL을 캡처 대상에서 제외한다.</li>

<li>에이전트가 실행하려는 설치·셸 명령을 먼저 보여 달라고 요청한다.</li>

<li>현재 저장소 HEAD가 이 글에서 검증한 커밋과 다르면 변경 내용을 확인한다.</li>

<li>회사에서 사용한다면 Remotion의 별도 라이선스를 확인한다.</li>

<li>완성 영상에 포함된 음원·이미지·제품 데이터의 사용 조건을 최종 검토한다.</li>
</ol>



<h2 class="wp-block-heading">실제 사용 방법</h2>



<p>설치한 뒤에는 제품 경로나 주소와 원하는 제작 방식을 함께 알려주는 편이 좋다.</p>



<pre class="wp-block-code"><code>video-shotcraft를 사용해 이 프로젝트의 30초 제품 소개 영상을 만들어줘.
프로젝트 경로는 /path/to/project야.
먼저 읽기 전용으로 제품과 화면 상태를 확인하고,
민감한 데이터가 캡처될 가능성을 정리해줘.
그다음 사용할 제작 모드와 샷 구성을 추천해줘.</code></pre>



<p>Skill은 완성 영상 제작 방식을 세 가지로 구분한다.</p>



<ul class="wp-block-list">
<li><strong>Ink Press 템플릿 사용</strong>: 기존 36.2초 템플릿의 장면 구조를 유지하고 제품 화면과 문구를 교체한다.</li>

<li><strong>자율 제작</strong>: 에이전트가 제품 분석부터 장면·사운드·렌더링까지 연속해서 진행한다.</li>

<li><strong>공동 제작</strong>: 제품 요약, 시각 방향, 샷 구성과 스토리보드를 단계별로 확인하며 진행한다.</li>
</ul>



<p>처음 사용한다면 공동 제작이 안전하다. 자율 제작은 빠르지만 제품 화면과 데이터 처리, 설치되는 패키지, 결과물 방향을 중간에 놓치기 쉽다.</p>



<h2 class="wp-block-heading">실행 비용과 현실적인 제약</h2>



<p>Skill 설치만으로 영상이 즉시 생성되는 것은 아니다. 실제 렌더링에는 Remotion 프로젝트 의존성과 Chromium 계열 브라우저, 저장 공간, CPU 시간이 필요하다. 저장소를 얕게 복제한 상태만 약 97MB였고, <code>node_modules</code>와 렌더링 결과는 여기에 포함되지 않았다.</p>



<p>저장소는 저사양 헤드리스 Linux에서 다음 문제를 별도로 안내한다.</p>



<ul class="wp-block-list">
<li>CPU 코어가 적으면 Remotion 동시성을 1로 낮춰야 할 수 있다.</li>

<li>최신 Chromium에서는 기존 headless 모드가 제거돼 <code>chrome-headless-shell</code>이 필요할 수 있다.</li>

<li>Remotion 다운로드 도메인이 차단되면 로컬 브라우저 실행 파일을 직접 지정해야 한다.</li>
</ul>



<p>즉, Skill 설치와 영상 제작 환경 구축은 다른 단계다. 설치 성공만 확인하고 “바로 영상 생성이 끝난다”고 기대하면 안 된다.</p>



<h2 class="wp-block-heading">삭제하는 방법</h2>



<p>이번 검증에서는 다음 명령으로 공용 Skill과 Claude Code 심볼릭 링크가 모두 제거되는 것을 확인했다.</p>



<pre class="wp-block-code"><code>npx skills remove video-shotcraft -g -y</code></pre>



<p>제거 후 다음 두 경로가 남아 있지 않은지 확인하면 된다.</p>



<pre class="wp-block-code"><code>ls ~/.agents/skills/video-shotcraft
ls ~/.claude/skills/video-shotcraft</code></pre>



<p>Skill을 이용해 별도의 Remotion 프로젝트를 만들었다면 그 프로젝트와 설치된 <code>node_modules</code>, 렌더링 결과물은 별도로 정리해야 한다. Skill 제거 명령이 사용자가 생성한 영상 프로젝트까지 지워주는 것은 아니다.</p>



<h2 class="wp-block-heading">결론: 누구에게 추천할 수 있나</h2>



<p>video-shotcraft는 AI가 영상을 직접 생성하는 모델이라기보다, 코딩 에이전트가 Remotion 기반 제품 영상을 만들도록 제작 지식과 자산을 제공하는 Skill이다. 제품 화면을 실제로 활용하고 코드로 수정 가능한 영상을 만들고 싶다면 살펴볼 가치가 있다.</p>



<p>다만 설치가 쉽다는 이유만으로 운영 저장소에서 바로 실행할 도구는 아니다. 보안 스캐너 판단이 엇갈리고, 실제 제작 과정에서 파일·브라우저·셸 권한을 폭넓게 사용한다. 별도 작업 복사본에서 시작하고 변경 명령과 캡처 데이터를 확인하는 조건이라면 개발자가 제품 영상 초안을 빠르게 만드는 데 유용한 도구에 가깝다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">Claude Code와 Codex에서 모두 사용할 수 있나?</h3>



<p>Agent Skills CLI로 두 대상을 지정해 설치할 수 있다. 이번 검증에서는 공용 Skill 경로와 Claude Code용 심볼릭 링크가 생성됐고 설치 목록에서도 정상 확인됐다.</p>



<h3 class="wp-block-heading">API 키가 반드시 필요한가?</h3>



<p>Skill 자체 설치에는 별도의 API 키가 필요하지 않았다. 다만 사용 중인 Claude Code나 Codex의 이용 환경은 별도로 필요하며, 영상 제작 과정에서 추가 서비스나 패키지를 선택하면 해당 조건이 생길 수 있다.</p>



<h3 class="wp-block-heading">영상 제작에 Remotion 유료 라이선스가 필요한가?</h3>



<p>Remotion은 별도 라이선스 정책을 사용한다. 저장소 안내에 따르면 개인과 소규모 팀은 무료 범위가 있지만 회사 사용자는 유료 조건이 적용될 수 있다. 실제 사용 시 Remotion 공식 라이선스 문서를 확인해야 한다.</p>



<h3 class="wp-block-heading">Snyk High Risk이면 설치하면 안 되는가?</h3>



<p>이 결과만으로 악성 Skill이라고 단정할 수는 없다. 다른 검사기는 Safe 또는 0 alerts를 표시했다. 반대로 다른 결과가 좋다는 이유로 안전을 보장할 수도 없다. 권한 범위와 현재 소스를 검토하고 격리된 프로젝트에서 실행하는 것이 핵심이다.</p>



<h3 class="wp-block-heading">Higgsfield 대신 video-shotcraft를 쓰면 되는가?</h3>



<p>완전한 대체 관계는 아니다. 실제 제품 UI와 수정 가능한 모션 그래픽이 중요하면 video-shotcraft가 맞고, 인물·실사풍 광고와 생성형 B-roll이 필요하면 Higgsfield가 맞다. 두 종류의 장면이 모두 필요하면 함께 사용하는 편이 좋다.</p>



<h3 class="wp-block-heading">설치 후 업데이트는 어떻게 하나?</h3>



<p>Agent Skills CLI의 <code>npx skills update</code> 계열 명령을 사용할 수 있다. 다만 업데이트하면 이 글에서 확인한 커밋과 달라질 수 있으므로 변경 내역을 먼저 검토하는 편이 좋다.</p>



<h2 class="wp-block-heading">함께 읽으면 좋은 글</h2>



<ul class="wp-block-list">
<li><a href="https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/">AI 에이전트 추적 실무: OpenTelemetry로 지연·토큰·도구 호출 연결하기</a></li>

<li><a href="https://blog.kwt.co.kr/ai-agent-observability-tools-comparison/">AI 에이전트 관측 도구 비교: Langfuse vs LangSmith vs Phoenix vs OpenTelemetry</a></li>
</ul>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://github.com/Vincentwei1021/video-shotcraft">video-shotcraft 공식 GitHub 저장소</a></li>

<li><a href="https://vincentwei1021.github.io/video-shotcraft/">video-shotcraft 모션 Gallery</a></li>

<li><a href="https://skills.sh/Vincentwei1021/video-shotcraft">skills.sh의 video-shotcraft 페이지</a></li>

<li><a href="https://agentskills.io/home">Agent Skills 공식 문서</a></li>

<li><a href="https://github.com/remotion-dev/remotion/blob/main/LICENSE.md">Remotion 공식 라이선스</a></li>

<li><a href="https://higgsfield.ai/mcp">Higgsfield 공식 MCP 안내</a></li>

<li><a href="https://higgsfield.ai/pricing">Higgsfield 공식 요금제</a></li>

<li><a href="https://docs.higgsfield.ai/docs">Higgsfield API 문서</a></li>
</ul>



<p>*검증 기준일: 2026년 9월 2일. GitHub 별 수, 저장소 내용과 보안 감사 결과는 이후 변경될 수 있다.*</p>



<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"video-shotcraft는 영상을 직접 생성하는 AI 모델인가?","acceptedAnswer":{"@type":"Answer","text":"아니다. Claude Code나 Codex가 Remotion 코드를 작성하고 스크린숏, 타이포그래피, 애니메이션을 조합하도록 안내하는 Agent Skill이다."}},{"@type":"Question","name":"Higgsfield를 대체할 수 있나?","acceptedAnswer":{"@type":"Answer","text":"완전한 대체재는 아니다. 실제 제품 UI와 수정 가능한 모션 그래픽은 video-shotcraft가 적합하고, 인물 UGC와 실사풍 B-roll 생성은 Higgsfield가 적합하다. 두 도구를 함께 사용할 수도 있다."}},{"@type":"Question","name":"Claude Code와 Codex에 모두 설치할 수 있나?","acceptedAnswer":{"@type":"Answer","text":"Agent Skills CLI에서 Claude Code와 Codex를 대상으로 지정해 설치할 수 있다. 실제 설치 결과 공용 Skill 경로와 Claude Code 연결이 생성됐다."}},{"@type":"Question","name":"상업 영상에 바로 사용할 수 있나?","acceptedAnswer":{"@type":"Answer","text":"저장소는 Apache-2.0이지만 Remotion의 회사 사용 조건, 외부 음원과 폰트의 라이선스, 제품 데이터의 공개 가능 여부를 별도로 확인해야 한다."}},{"@type":"Question","name":"안전하게 테스트하려면 어떻게 해야 하나?","acceptedAnswer":{"@type":"Answer","text":"임시 HOME과 복제 프로젝트에서 먼저 설치하고, 생성되는 파일과 네트워크 요청을 확인한 뒤 운영 프로젝트로 옮기는 방식이 안전하다."}}]}</script>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2819"
					data-ulike-nonce="4d66c88738"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2819"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/video-shotcraft-claude-code-codex-agent-skill/">video-shotcraft란? Claude Code와 Codex로 제품 영상을 만드는 Agent Skill</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/video-shotcraft-claude-code-codex-agent-skill/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ollama가 GPU 대신 CPU를 쓸 때: Docker GPU 미인식 10분 진단법</title>
		<link>https://blog.kwt.co.kr/ollama-docker-gpu-not-detected-fix/</link>
					<comments>https://blog.kwt.co.kr/ollama-docker-gpu-not-detected-fix/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Sun, 30 Aug 2026 06:00:26 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[GPU]]></category>
		<category><![CDATA[Ollama]]></category>
		<category><![CDATA[로컬 LLM]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/ollama-docker-gpu-not-detected-fix/</guid>

					<description><![CDATA[<p>Ollama Docker가 GPU를 인식하지 못할 때 호스트 드라이버, NVIDIA Container Toolkit, GPU 전달, Ollama 로그와 VRAM 오프로딩을 10분 순서로 진단한다.</p>
<p>The post <a href="https://blog.kwt.co.kr/ollama-docker-gpu-not-detected-fix/">Ollama가 GPU 대신 CPU를 쓸 때: Docker GPU 미인식 10분 진단법</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ollama Docker 컨테이너가 GPU 대신 CPU를 쓴다면 <strong>호스트 드라이버 → NVIDIA Container Toolkit → 컨테이너 GPU 전달 → Ollama 로그와 <code>ollama ps</code></strong> 순서로 확인하면 된다. 호스트의 <code>nvidia-smi</code>부터 실패하면 Docker 설정을 고칠 단계가 아니다. 테스트 컨테이너에서는 GPU가 보이는데 Ollama만 CPU를 쓴다면 지원 드라이버·GPU, Jetson 환경변수, 모델·컨텍스트의 VRAM 초과를 분리해 봐야 한다.</p>



<div class="wp-block-group has-border-color has-background" style="border-color:#bfdbfe;border-width:1px;background-color:#eff6ff;padding-top:20px;padding-right:22px;padding-bottom:20px;padding-left:22px"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-1 wp-block-group-is-layout-constrained">


<h2 class="wp-block-heading has-medium-font-size">핵심 요약</h2>



<ul class="wp-block-list">
<li><strong>호스트 실패:</strong> <code>nvidia-smi</code>가 실패하면 GPU 드라이버와 커널 상태를 먼저 해결한다.</li>



<li><strong>테스트 컨테이너 실패:</strong> NVIDIA Container Toolkit 설치와 <code>nvidia-ctk runtime configure --runtime=docker</code>, Docker 재시작을 확인한다.</li>



<li><strong>Ollama만 실패:</strong> 컨테이너를 <code>--gpus=all</code>로 재생성하고 서버 로그의 GPU discovery 오류를 확인한다.</li>



<li><strong>GPU 일부 사용:</strong> 감지 실패가 아니라 모델 가중치·KV 캐시·컨텍스트가 VRAM을 넘겨 CPU로 일부 오프로딩된 상태일 수 있다.</li>



<li><strong>환경 분기:</strong> Jetson은 <code>JETSON_JETPACK</code>, AMD는 ROCm 이미지와 <code>/dev/kfd</code>·<code>/dev/dri</code> 전달을 별도로 확인한다.</li>
</ul>


</div></div>



<h2 class="wp-block-heading">먼저 GPU 미인식과 VRAM 부족을 구분한다</h2>



<p>“GPU를 안 쓴다”는 증상은 하나가 아니다. GPU 자체가 컨테이너에 전달되지 않은 경우, Ollama가 GPU를 발견하지 못한 경우, GPU는 정상 감지됐지만 모델이나 컨텍스트가 커서 일부 레이어를 CPU에 둔 경우가 서로 다른 해결책을 요구한다. 성능이 느리다는 느낌만으로 드라이버를 다시 설치하지 말고 관찰값부터 분류해야 한다.</p>



<figure class="wp-block-table"><table><thead><tr><th>관찰값</th><th>판정</th><th>다음 단계</th></tr></thead><tbody><tr><td>호스트 <code>nvidia-smi</code> 실패</td><td>호스트 드라이버·커널 문제</td><td>Docker보다 드라이버 상태를 먼저 복구</td></tr><tr><td>호스트 성공, 테스트 컨테이너 실패</td><td>Container Toolkit·Docker runtime 문제</td><td>runtime 구성과 Docker 재시작</td></tr><tr><td>테스트 컨테이너 성공, Ollama 컨테이너 실패</td><td>GPU 전달 옵션·Ollama 감지 문제</td><td>컨테이너 재생성·로그 확인</td></tr><tr><td><code>ollama ps</code>에 CPU/GPU 혼합</td><td>VRAM 초과에 따른 부분 오프로딩 가능성</td><td>모델·컨텍스트·동시 실행량 축소</td></tr><tr><td>절전 복귀 뒤 갑자기 CPU 사용</td><td>NVIDIA UVM 드라이버 문제 가능성</td><td>공식 안내의 UVM 재로드 검토</td></tr></tbody></table></figure>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1050" height="920" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/ollama-docker-gpu-flow.png" alt="호스트 GPU부터 컨테이너 런타임과 Ollama까지 확인하는 GPU 진단 흐름" class="wp-image-2826" style="width:640px;height:auto"/><figcaption class="wp-element-caption">호스트 GPU부터 Ollama 실행 상태까지 확인하는 5단계 흐름<br />출처: Ollama·NVIDIA 공식 문서 기반 구성</figcaption></figure></div>


<h2 class="wp-block-heading">1단계: 호스트에서 드라이버와 지원 조건을 확인한다</h2>



<p>Linux 호스트에서 다음 명령이 GPU 이름, 드라이버 버전, 메모리 상태를 반환해야 한다. 여기서 실패하면 컨테이너는 정상 GPU 장치를 받을 수 없다. Ollama 공식 하드웨어 문서는 현재 NVIDIA compute capability 5.0 이상과 드라이버 550 이상을 지원 기준으로 안내하며, compute capability 5.0~6.2 GPU에는 드라이버 570 이상을 요구한다. 실제 GPU의 compute capability와 드라이버 조합을 공식 목록에서 다시 확인해야 한다.</p>



<pre class="wp-block-code"><code>nvidia-smi
nvidia-smi -L
cat /proc/driver/nvidia/version
sudo systemctl status docker --no-pager
docker version</code></pre>



<ul class="wp-block-list">
<li><strong><code>nvidia-smi</code> 자체가 없다:</strong> NVIDIA 드라이버 설치가 끝나지 않았거나 실행 경로에 없다.</li>



<li><strong>GPU가 보이지만 드라이버가 지원 기준보다 낮다:</strong> 배포판의 공식 패키지 방식으로 호환 드라이버를 갱신한다.</li>



<li><strong>절전 복귀 후만 실패한다:</strong> Ollama 공식 문서는 Linux suspend/resume 뒤 NVIDIA GPU discovery가 실패할 수 있다고 설명하며 <code>nvidia_uvm</code> 재로드를 우회책으로 제시한다.</li>



<li><strong>가상머신이다:</strong> 게스트 OS에 GPU가 실제 passthrough됐는지 확인한다. 호스트에 GPU가 있다는 사실만으로 게스트 컨테이너에 전달되지는 않는다.</li>
</ul>



<h2 class="wp-block-heading">2단계: Ollama보다 먼저 테스트 컨테이너에서 GPU를 확인한다</h2>



<p>호스트 GPU가 정상이면 NVIDIA Container Toolkit 계층만 분리해서 테스트한다. Ollama 공식 Docker 문서는 Toolkit 설치 후 <code>nvidia-ctk</code>로 Docker runtime을 구성하고 Docker를 재시작하도록 안내한다. 재시작을 빼먹으면 설치 파일은 있어도 실행 중 daemon 설정에는 반영되지 않을 수 있다.</p>



<pre class="wp-block-code"><code>sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
docker run --rm --gpus all ubuntu nvidia-smi
docker info | grep -i -E &#x27;runtime|nvidia&#x27;
sudo nvidia-ctk runtime configure --runtime=docker --dry-run</code></pre>



<p>테스트 컨테이너의 <code>nvidia-smi</code>가 실패하면 Ollama 이미지를 교체해도 해결되지 않는다. 이 단계에서는 Toolkit 패키지, Docker daemon 설정, cgroup·CDI 구성, 호스트 보안 정책을 점검한다. NVIDIA 공식 설치 문서는 systemd cgroup 환경에서 <code>daemon-reload</code> 뒤 컨테이너가 GPU 접근을 잃는 알려진 조건도 안내하므로 재현 시 해당 문서의 최신 제한사항을 확인해야 한다.</p>



<h2 class="wp-block-heading">3단계: Ollama 컨테이너를 GPU 옵션과 함께 재생성한다</h2>



<p>기존 CPU 전용 컨테이너에 설정만 덧붙이는 것보다 정확한 GPU 옵션으로 재생성하는 편이 확실하다. 공식 Ollama Docker 명령은 <code>--gpus=all</code>을 사용한다. Compose에서는 현재 Docker Compose가 지원하는 <code>gpus: all</code> 또는 GPU device reservation을 사용할 수 있지만, 배포 서버의 Compose 버전이 해당 문법을 지원하는지 먼저 확인해야 한다.</p>



<pre class="wp-block-code"><code>docker rm -f ollama 2&gt;/dev/null || true

docker run -d   --gpus=all   -v ollama:/root/.ollama   -p 11434:11434   --name ollama   --restart unless-stopped   ollama/ollama

services:
  ollama:
    image: ollama/ollama
    gpus: all
    volumes:
      - ollama:/root/.ollama
    ports:
      - &quot;11434:11434&quot;
    restart: unless-stopped

volumes:
  ollama:</code></pre>



<ol class="wp-block-list">
<li><strong>컨테이너를 재생성한다.</strong> Compose 파일만 바꾸고 기존 컨테이너를 그대로 두지 않는다.</li>



<li><strong>컨테이너 안에서 장치 노출을 확인한다.</strong> NVIDIA 테스트는 호스트와 별도로 성공해야 한다.</li>



<li><strong>Ollama 서버 로그를 확인한다.</strong> GPU inventory와 초기화 오류 코드를 찾는다.</li>



<li><strong>작은 모델을 한 번 실행한다.</strong> 모델을 로드하지 않은 상태의 낮은 GPU 사용률만 보고 실패로 판단하지 않는다.</li>



<li><strong><code>ollama ps</code>에서 processor를 확인한다.</strong> CPU 100%, GPU 100%, 혼합 상태를 구분한다.</li>
</ol>



<pre class="wp-block-code"><code>docker inspect ollama --format &#x27;{{json .HostConfig.DeviceRequests}}&#x27;
docker logs --tail 200 ollama
docker exec ollama ollama run llama3.2:3b &quot;한 문장으로 답해줘: GPU 확인&quot;
docker exec ollama ollama ps
watch -n 1 nvidia-smi</code></pre>



<h2 class="wp-block-heading">4단계: Ollama 로그의 GPU discovery 오류를 읽는다</h2>



<p>Ollama 공식 troubleshooting 문서는 GPU 초기화 실패가 서버 로그에서 오류 코드 3, 46, 100, 999 등으로 보일 수 있다고 설명한다. 숫자 하나를 만능 원인으로 해석하면 안 되며, 같은 시점의 드라이버 로그와 컨테이너 GPU 테스트 결과를 함께 봐야 한다.</p>



<figure class="wp-block-table"><table><thead><tr><th>로그·상태</th><th>의미 후보</th><th>확인할 것</th></tr></thead><tbody><tr><td>no device·오류 100</td><td>GPU 장치가 보이지 않음</td><td><code>--gpus</code>, DeviceRequests, 테스트 컨테이너</td></tr><tr><td>not initialized·오류 3</td><td>드라이버 초기화 실패</td><td>호스트 드라이버, UVM, 커널 로그</td></tr><tr><td>device unavailable·오류 46</td><td>장치 사용 불가</td><td>다른 프로세스·드라이버 상태·재부팅 필요성</td></tr><tr><td>unknown·오류 999</td><td>범용 NVIDIA 오류</td><td><code>dmesg</code>, <code>journalctl</code>, 드라이버 재로드</td></tr><tr><td>GPU 감지 성공+CPU/GPU 혼합</td><td>부분 오프로딩 가능성</td><td>VRAM, 모델 크기, 컨텍스트, 병렬 실행</td></tr></tbody></table></figure>



<pre class="wp-block-code"><code>docker logs ollama 2&gt;&amp;1 | grep -i -E &#x27;gpu|cuda|nvidia|vram|library|error&#x27;
dmesg | grep -i -E &#x27;nvrm|xid|nvidia&#x27; | tail -n 100
journalctl -u docker --since &#x27;-15 min&#x27; --no-pager</code></pre>



<p>운영 서버에서 커널 모듈을 내리는 명령은 실행 중인 GPU 작업을 중단할 수 있다. Ollama 공식 문서의 <code>sudo rmmod nvidia_uvm &amp;&amp; sudo modprobe nvidia_uvm</code>는 절전 복귀 문제의 우회책이지 모든 GPU 오류에 먼저 적용할 명령이 아니다. 다른 CUDA 작업이 없는지 확인하고 유지보수 시간에 판단해야 한다.</p>



<h2 class="wp-block-heading">GPU가 일부만 사용되면 모델·컨텍스트·동시성을 줄인다</h2>



<p>GPU가 정상 감지됐는데 <code>ollama ps</code>가 CPU와 GPU 혼합을 표시하거나 시스템 RAM 사용량이 커진다면 컨테이너 passthrough보다 메모리 예산 문제일 가능성이 높다. 모델 가중치뿐 아니라 KV 캐시와 컨텍스트, 동시 요청이 VRAM을 사용한다. 최근 공개 Ollama 이슈에서도 큰 컨텍스트 메타데이터로 소비자 하드웨어에서 OOM이 발생하거나 GPU 메모리를 일부만 쓰고 시스템 RAM으로 넘어간다는 질문이 반복됐다. 이 사례는 수요 신호일 뿐, 모든 환경의 원인으로 단정할 수 없다.</p>



<ul class="wp-block-list">
<li><strong>더 작은 양자화·모델로 비교한다.</strong> 같은 컨테이너에서 작은 모델이 GPU 100%라면 passthrough 자체는 정상일 가능성이 높다.</li>



<li><strong>컨텍스트를 낮춘다.</strong> 긴 컨텍스트는 KV 캐시를 키우므로 작업에 필요한 범위로 제한한다.</li>



<li><strong>동시 실행 모델과 요청을 줄인다.</strong> 여러 모델을 유지하거나 병렬 요청을 늘리면 가용 VRAM이 나뉜다.</li>



<li><strong><code>nvidia-smi</code>와 <code>ollama ps</code>를 함께 본다.</strong> 순간 utilization만이 아니라 VRAM 점유와 Ollama processor 표시를 비교한다.</li>



<li><strong>기존 메모리 계산과 연결한다.</strong> <a href="https://blog.kwt.co.kr/local-llm-memory-ram-vram-guide/">로컬 LLM RAM·VRAM 계산 가이드</a>에서 모델 크기와 KV 캐시 예산을 먼저 잡는 편이 낫다.</li>
</ul>



<h2 class="wp-block-heading">Jetson과 AMD는 NVIDIA 데스크톱 절차를 그대로 쓰면 안 된다</h2>



<p>Ollama 공식 Docker 문서는 NVIDIA JetPack 시스템에서 버전을 자동 발견하지 못하므로 <code>JETSON_JETPACK=5</code> 또는 <code>JETSON_JETPACK=6</code>을 컨테이너에 전달하도록 안내한다. 최근 JetPack 7.2·Orin 환경의 공개 이슈에서는 네이티브와 Docker 모두 CUDA 오류가 발생해, 컨테이너 설정만으로 설명할 수 없는 호환성 문제도 확인됐다. 공식 지원 범위와 해당 릴리스 상태를 확인하기 전 임의 환경변수로 새 JetPack 세대를 가장하면 안 된다.</p>



<pre class="wp-block-code"><code>-d -e JETSON_JETPACK=6 --gpus=all ... ollama/ollama

docker run -d   --device /dev/kfd   --device /dev/dri   -v ollama:/root/.ollama   -p 11434:11434   --name ollama   ollama/ollama:rocm</code></pre>



<p>AMD는 NVIDIA Toolkit과 <code>nvidia-smi</code>가 아니라 ROCm 지원 GPU·드라이버와 장치 전달을 확인한다. Ollama 공식 하드웨어 문서는 Linux에서 현재 AMD ROCm v7 드라이버를 요구하며, 추가 AMD GPU에는 Vulkan 경로를 제공한다. GPU 제조사와 운영체제에 맞는 분기를 선택해야 한다.</p>



<h2 class="wp-block-heading">환경별 빠른 선택표</h2>



<figure class="wp-block-table"><table><thead><tr><th>환경</th><th>첫 명령</th><th>컨테이너 설정</th><th>실패 시 우선순위</th></tr></thead><tbody><tr><td>Linux+NVIDIA</td><td><code>nvidia-smi</code></td><td>Toolkit + <code>--gpus=all</code></td><td>드라이버 → runtime → Ollama 로그</td></tr><tr><td>Jetson</td><td>JetPack 버전 확인</td><td>공식 지원 범위의 <code>JETSON_JETPACK</code></td><td>JetPack·Ollama 호환성</td></tr><tr><td>Linux+AMD</td><td>ROCm 장치·드라이버 확인</td><td>ROCm 이미지 + <code>/dev/kfd</code>, <code>/dev/dri</code></td><td>ROCm 지원 목록·권한</td></tr><tr><td>Windows Docker Desktop</td><td>호스트 GPU·WSL 상태 확인</td><td>Desktop GPU 통합과 Linux 컨테이너</td><td>WSL·Desktop·드라이버 계층</td></tr><tr><td>가상머신</td><td>게스트에서 GPU 확인</td><td>게스트 Docker runtime</td><td>하이퍼바이저 passthrough</td></tr></tbody></table></figure>



<p>Docker host 자체가 메모리 부족으로 불안정하다면 <a href="https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/">Docker Compose 메모리 제한과 OOM 가이드</a>도 함께 확인해야 한다. GPU 감지 실패와 호스트 OOM은 증상이 느린 응답·컨테이너 재시작으로 겹칠 수 있지만 진단 계층은 다르다.</p>



<h2 class="wp-block-heading">10분 진단 체크리스트</h2>



<ol class="wp-block-list">
<li><strong>1분:</strong> 호스트 <code>nvidia-smi</code>와 드라이버 버전을 기록한다.</li>



<li><strong>2분:</strong> <code>docker run --rm --gpus all ubuntu nvidia-smi</code>를 실행한다.</li>



<li><strong>2분:</strong> <code>docker inspect</code>로 Ollama 컨테이너의 DeviceRequests를 확인한다.</li>



<li><strong>2분:</strong> 작은 모델을 실행하면서 <code>docker logs</code>, <code>ollama ps</code>, <code>nvidia-smi</code>를 함께 본다.</li>



<li><strong>1분:</strong> Jetson·AMD·VM이면 해당 환경 분기로 이동한다.</li>



<li><strong>2분:</strong> 감지는 성공했지만 혼합 실행이면 모델·컨텍스트·동시성을 한 단계 낮춰 비교한다.</li>
</ol>



<p>최종 기록에는 호스트 OS, GPU, 드라이버, Docker·Ollama 버전, 실행 명령, 테스트 컨테이너 결과, Ollama 로그, <code>ollama ps</code>를 남긴다. 그래야 드라이버 문제와 Ollama 회귀, 모델별 메모리 문제를 재현 가능한 형태로 구분할 수 있다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">nvidia-smi는 되는데 Ollama만 CPU를 쓰는 이유는 무엇인가</h3>



<p>호스트 GPU 확인만 통과했고 컨테이너 GPU 전달이 빠졌거나, Ollama가 장치를 초기화하지 못했거나, 모델·컨텍스트가 VRAM을 초과했을 수 있다. 테스트 컨테이너, DeviceRequests, Ollama 로그, <code>ollama ps</code> 순서로 범위를 좁혀야 한다.</p>



<h3 class="wp-block-heading">GPU 사용률이 0%면 무조건 미인식인가</h3>



<p>아니다. 모델이 로드되지 않았거나 요청 사이 유휴 상태일 수 있다. 실제 추론 중 <code>nvidia-smi</code>의 VRAM·utilization과 <code>ollama ps</code>의 processor를 함께 확인해야 한다.</p>



<h3 class="wp-block-heading">privileged: true를 넣으면 해결되는가</h3>



<p>진단 없이 사용할 해결책이 아니다. 필요한 GPU device request보다 훨씬 넓은 권한을 준다. NVIDIA Container Toolkit과 <code>--gpus</code> 또는 Compose GPU 설정으로 필요한 장치만 전달해야 한다.</p>



<h3 class="wp-block-heading">JetPack 7에서도 JETSON_JETPACK=6을 넣으면 되는가</h3>



<p>공식 문서가 안내한 값의 범위를 넘어 임의로 가장하면 안 된다. 최근 JetPack 7.2 공개 이슈는 네이티브와 Docker 모두 오류가 난 사례이므로 최신 Ollama 지원 상태와 릴리스 이슈를 확인해야 한다.</p>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://docs.ollama.com/docker">Ollama Docker 공식 문서</a></li>



<li><a href="https://docs.ollama.com/gpu">Ollama Hardware support</a></li>



<li><a href="https://docs.ollama.com/troubleshooting">Ollama Troubleshooting</a></li>



<li><a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html">NVIDIA Container Toolkit 설치 가이드</a></li>



<li><a href="https://docs.docker.com/compose/how-tos/gpu-support/">Docker Compose GPU support</a></li>



<li><a href="https://github.com/ollama/ollama/issues/18067">JetPack 7.2·Orin GPU 미인식 공개 이슈</a></li>



<li><a href="https://github.com/ollama/ollama/issues/18074">큰 컨텍스트와 OOM 관련 공개 이슈</a></li>



<li><a href="https://github.com/ollama/ollama/issues/17971">부분 GPU 메모리 사용 관련 공개 이슈</a></li>
</ul>



<p>공식 문서와 공개 이슈 확인 기준일은 2026년 8월 30일이다. 공개 이슈는 사용자 수요와 재현 사례를 보여 주는 자료이며, 해결책과 모든 환경의 원인을 확정하는 근거로 사용하지 않았다.</p>



<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"nvidia-smi는 되는데 Ollama만 CPU를 쓰는 이유는 무엇인가","acceptedAnswer":{"@type":"Answer","text":"컨테이너 GPU 전달 누락, Ollama 장치 초기화 실패, 모델과 컨텍스트의 VRAM 초과를 테스트 컨테이너와 로그, ollama ps 순서로 구분해야 한다."}},{"@type":"Question","name":"GPU 사용률이 0%면 무조건 미인식인가","acceptedAnswer":{"@type":"Answer","text":"유휴 상태일 수 있다. 실제 추론 중 VRAM과 utilization, ollama ps의 processor를 함께 확인해야 한다."}},{"@type":"Question","name":"privileged true를 넣으면 해결되는가","acceptedAnswer":{"@type":"Answer","text":"필요 이상 권한을 주므로 권장하지 않는다. NVIDIA Container Toolkit과 GPU device request를 올바르게 구성해야 한다."}},{"@type":"Question","name":"JetPack 7에서도 JETSON_JETPACK 6을 넣으면 되는가","acceptedAnswer":{"@type":"Answer","text":"공식 지원 범위를 넘어 임의로 가장하지 말고 최신 Ollama 지원 상태와 릴리스 이슈를 확인해야 한다."}}]}</script>
		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2827"
					data-ulike-nonce="805e927005"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2827"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/ollama-docker-gpu-not-detected-fix/">Ollama가 GPU 대신 CPU를 쓸 때: Docker GPU 미인식 10분 진단법</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/ollama-docker-gpu-not-detected-fix/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>docker.sock permission denied 해결: chmod 666 없이 안전하게 고치는 법</title>
		<link>https://blog.kwt.co.kr/docker-sock-permission-denied-safe-fix/</link>
					<comments>https://blog.kwt.co.kr/docker-sock-permission-denied-safe-fix/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Thu, 27 Aug 2026 05:46:12 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Docker Compose]]></category>
		<category><![CDATA[docker.sock]]></category>
		<category><![CDATA[컨테이너 보안]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/docker-sock-permission-denied-safe-fix/</guid>

					<description><![CDATA[<p>컨테이너의 docker.sock permission denied 오류를 숫자 GID, Compose group_add, rootless socket, socket proxy로 안전하게 해결하는 진단 순서를 정리했다.</p>
<p>The post <a href="https://blog.kwt.co.kr/docker-sock-permission-denied-safe-fix/">docker.sock permission denied 해결: chmod 666 없이 안전하게 고치는 법</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>컨테이너 안에서 <code>/var/run/docker.sock: connect: permission denied</code>가 발생하면 <strong>먼저 호스트 소켓의 숫자 GID를 컨테이너의 보조 그룹으로 전달해야 한다.</strong> 그러나 모든 서비스에 소켓을 직접 마운트하는 방식은 호스트 Docker를 사실상 관리자 권한으로 조작하게 만든다. 조회만 필요하다면 socket proxy, 호스트가 rootless Docker라면 실제 사용자 소켓 경로를 쓰는 편이 안전하다. <code>chmod 666</code>, 무분별한 <code>privileged: true</code>, 인증 없는 TCP 2375 공개는 해결책에서 제외해야 한다.</p>



<div class="wp-block-group has-border-color has-background" style="border-color:#bfdbfe;border-width:1px;background-color:#eff6ff;padding-top:20px;padding-right:22px;padding-bottom:20px;padding-left:22px"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-2 wp-block-group-is-layout-constrained">


<h2 class="wp-block-heading has-medium-font-size">핵심 요약</h2>



<ul class="wp-block-list">
<li><strong>Linux rootful Docker:</strong> <code>stat -c %g /var/run/docker.sock</code>으로 GID를 확인하고 Compose <code>group_add</code>에 같은 숫자를 넣는다.</li>



<li><strong>Rootless Docker:</strong> 보통 <code>/run/user/$UID/docker.sock</code>을 사용한다. rootful 경로를 계속 마운트하면 권한을 고쳐도 다른 daemon을 가리킨다.</li>



<li><strong>보안:</strong> Docker 공식 문서는 소켓과 Docker 그룹이 root 수준 권한을 준다고 경고한다. <code>:ro</code>만 붙여 API 쓰기 권한이 제한된다고 가정하면 안 된다.</li>



<li><strong>최소 권한:</strong> 컨테이너 목록·이벤트 조회만 필요하면 허용 API를 줄인 socket proxy를 별도 내부 네트워크에 둔다.</li>
</ul>


</div></div>



<h2 class="wp-block-heading">오류 원인은 파일 권한보다 숫자 GID 불일치인 경우가 많다</h2>



<p>Unix socket 접근은 경로 문자열이나 그룹 이름이 아니라 커널이 보는 숫자 UID·GID와 권한 비트로 결정된다. 호스트의 <code>docker</code> 그룹이 GID 998인데 컨테이너 이미지 안의 같은 이름 그룹이 GID 999라면 이름이 같아도 권한이 맞지 않는다. 반대로 이미지에 <code>docker</code>라는 그룹이 없어도 실행 프로세스가 보조 그룹 998을 가지면 소켓의 그룹 읽기·쓰기 권한을 사용할 수 있다.</p>



<figure class="wp-block-table"><table><thead><tr><th>증상</th><th>우선 확인</th><th>가능성이 큰 원인</th></tr></thead><tbody><tr><td>소켓 파일이 보이지만 permission denied</td><td>호스트 소켓 GID와 컨테이너 프로세스 그룹</td><td>숫자 GID 불일치</td></tr><tr><td>no such file or directory</td><td>호스트와 컨테이너의 실제 소켓 경로</td><td>rootless 경로 또는 Docker Desktop 차이</td></tr><tr><td>호스트에서는 되지만 컨테이너에서 실패</td><td>컨테이너의 <code>id</code>, 실행 사용자</td><td>비루트 사용자의 보조 그룹 누락</td></tr><tr><td>연결은 되지만 특정 작업 실패</td><td>Docker API 응답과 proxy 정책</td><td>허용 endpoint·HTTP method 제한</td></tr><tr><td>재부팅·재배포 뒤 다시 실패</td><td>소켓 GID와 Compose 보간값</td><td>배포 시 하드코딩한 GID가 현재 호스트와 다름</td></tr></tbody></table></figure>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1050" height="840" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/docker-sock-diagnostic-flow.png" alt="docker.sock 실제 경로와 UID GID를 확인한 뒤 최소 권한 방식을 선택하는 진단 순서" class="wp-image-2814" style="width:640px;height:auto"/><figcaption class="wp-element-caption">소켓 경로·숫자 GID·권한 범위를 차례로 확인하는 진단 흐름<br />출처: Docker 공식 문서 기반 구성</figcaption></figure></div>


<h2 class="wp-block-heading">1단계: 경로·소유권·프로세스 그룹을 숫자로 확인한다</h2>



<p>권한을 바꾸기 전에 아래 세 결과를 같은 시점에 수집한다. 첫 블록은 Docker 호스트에서, 두 번째 블록은 문제가 난 컨테이너 안에서 실행한다. <code>ls -l</code>의 그룹 이름만 보지 말고 <code>ls -ln</code> 또는 <code>stat</code>의 숫자를 비교해야 한다.</p>



<pre class="wp-block-code"><code>stat -c &#x27;mode=%a uid=%u gid=%g path=%n&#x27; /var/run/docker.sock
ls -ln /var/run/docker.sock
id

docker inspect --format &#x27;{{.Config.User}} {{json .HostConfig.GroupAdd}}&#x27; SERVICE_CONTAINER

docker exec SERVICE_CONTAINER sh -c &#x27;
  id; ls -ln /var/run/docker.sock; test -S /var/run/docker.sock &amp;&amp; echo socket-ok
&#x27; </code></pre>



<p>일반적인 rootful Docker 소켓은 root 소유이며 Docker 그룹에 접근 권한이 있다. 다만 배포판과 설치 방식에 따라 GID는 달라질 수 있으므로 글이나 다른 서버의 숫자를 복사하면 안 된다. SELinux·AppArmor가 적용된 환경에서는 Unix 권한이 맞아도 보안 정책이 막을 수 있다. 이 경우 감사 로그와 Docker 공식 보안 프로필 문서를 별도로 확인해야 한다.</p>



<h2 class="wp-block-heading">2단계: Compose group_add로 호스트 GID를 전달한다</h2>



<p>호스트가 Linux rootful Docker이고 서비스가 소켓을 직접 사용해야 한다면 다음 구성이 가장 단순하다. Docker Compose 공식 명세의 <code>group_add</code>는 컨테이너 사용자가 속할 추가 그룹을 지정한다. 숫자 GID를 넘기면 이미지 내부 그룹 이름에 의존하지 않는다.</p>



<pre class="wp-block-code"><code>export DOCKER_GID=&quot;$(stat -c &#x27;%g&#x27; /var/run/docker.sock)&quot;
docker compose up -d --force-recreate

services:
  manager:
    image: example/manager:latest
    user: &quot;1000:1000&quot;
    group_add:
      - &quot;${DOCKER_GID}&quot;
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    security_opt:
      - no-new-privileges:true</code></pre>



<ol class="wp-block-list">
<li><strong>현재 호스트에서 <code>DOCKER_GID</code>를 계산한다.</strong> <code>.env</code>에 오래된 숫자를 영구 저장하지 않는다.</li>



<li><strong>서비스를 재생성한다.</strong> 실행 중 컨테이너의 그룹 목록은 Compose 파일만 수정해도 자동으로 바뀌지 않는다.</li>



<li><strong><code>docker exec ... id</code>로 보조 그룹을 확인한다.</strong> 소켓 GID와 같은 숫자가 보여야 한다.</li>



<li><strong>최소 API 호출을 검증한다.</strong> Docker CLI가 있으면 <code>docker version</code>, 없으면 애플리케이션의 health check나 Unix socket <code>/_ping</code>을 쓴다.</li>



<li><strong>애플리케이션이 정말 소켓 전체 권한을 필요로 하는지 재검토한다.</strong> 조회 목적이면 다음 단계의 proxy가 더 적합하다.</li>
</ol>



<p>이 구성은 permission denied를 해결하지만 권한을 축소하지는 않는다. Docker 공식 <code>docker run</code> 문서는 소켓과 Docker 바이너리를 함께 마운트하면 컨테이너가 호스트 daemon의 컨테이너를 생성·조작할 수 있는 전체 접근권을 얻는다고 명시한다.</p>



<h2 class="wp-block-heading">3단계: rootless Docker라면 소켓 경로부터 바꾼다</h2>



<p>Rootless mode는 daemon과 컨테이너를 비루트 사용자로 실행한다. Docker 공식 설치 출력은 사용자별 소켓과 <code>DOCKER_HOST</code> 설정을 안내한다. 흔한 형태는 <code>unix:///run/user/1000/docker.sock</code>이지만 UID를 하드코딩하지 말고 현재 context와 환경변수로 확인해야 한다.</p>



<pre class="wp-block-code"><code>docker context show
docker context inspect &quot;$(docker context show)&quot;
echo &quot;$DOCKER_HOST&quot;
ls -ln &quot;/run/user/$(id -u)/docker.sock&quot;

services:
  manager:
    environment:
      DOCKER_HOST: unix:///run/docker-user.sock
    volumes:
      - /run/user/${ROOTLESS_UID}/docker.sock:/run/docker-user.sock</code></pre>



<p>Rootless socket은 사용자 runtime 디렉터리 아래에 있으므로 서비스 부팅 순서와 로그인 세션 유지 설정도 영향을 준다. rootless daemon이 시작되지 않았거나 사용자 runtime 디렉터리가 사라졌다면 권한 수정이 아니라 daemon·systemd user service 상태를 고쳐야 한다. rootful <code>/var/run/docker.sock</code>과 rootless 사용자 소켓을 동시에 두고 잘못된 쪽을 가리키는 구성도 피해야 한다.</p>



<h2 class="wp-block-heading">4단계: 조회 목적이면 socket proxy로 권한을 줄인다</h2>



<p>대시보드·모니터링·자동 업데이트 도구가 Docker API의 일부만 필요한다면 소켓을 각 컨테이너에 직접 배포하지 않는 편이 낫다. <code>Tecnativa/docker-socket-proxy</code>는 Docker 공식 구성요소가 아닌 공개 소스 프로젝트지만 endpoint 종류와 POST 허용 여부를 환경변수로 제한하는 대표적인 선택지다.</p>



<pre class="wp-block-code"><code>services:
  docker-proxy:
    image: tecnativa/docker-socket-proxy:latest
    environment:
      CONTAINERS: 1
      IMAGES: 0
      SERVICES: 0
      POST: 0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks: [docker-api]
    restart: unless-stopped

  dashboard:
    environment:
      DOCKER_HOST: tcp://docker-proxy:2375
    networks: [docker-api]

networks:
  docker-api:
    internal: true</code></pre>



<ul class="wp-block-list">
<li><strong>proxy 포트를 호스트의 <code>0.0.0.0:2375</code>에 공개하지 않는다.</strong> 필요한 서비스만 참여하는 내부 Docker 네트워크에 둔다.</li>



<li><strong><code>POST=0</code>부터 시작한다.</strong> 컨테이너 시작·중지·삭제가 필요하다고 확인된 경우에만 관련 endpoint와 쓰기를 추가한다.</li>



<li><strong>허용 목록을 버전 관리한다.</strong> 애플리케이션 업데이트가 새 endpoint를 요구하면 오류를 보고 검토한 뒤 열어야 한다.</li>



<li><strong>proxy 자체도 고가치 구성요소로 취급한다.</strong> 이미지 버전을 고정하고 로그·네트워크·업데이트 정책을 관리한다.</li>
</ul>



<p><code>:ro</code> bind 옵션만으로 Docker API를 읽기 전용으로 만들었다고 판단하면 안 된다. 이 옵션은 마운트된 경로의 파일시스템 쓰기를 제한하는 설정이지 daemon API의 HTTP method를 인가하는 정책이 아니다. 실제 API 작업을 제한하려면 proxy의 method·endpoint 정책이나 별도 권한 계층이 필요하다.</p>



<h2 class="wp-block-heading">환경별 선택 매트릭스</h2>



<figure class="wp-block-table"><table><thead><tr><th>환경·목적</th><th>권장 시작점</th><th>피해야 할 선택</th><th>검증</th></tr></thead><tbody><tr><td>Linux rootful, 관리 작업 필요</td><td>현재 소켓 GID + <code>group_add</code></td><td>GID 하드코딩, chmod 666</td><td>컨테이너 <code>id</code>와 <code>docker version</code></td></tr><tr><td>Linux rootless</td><td>사용자 socket 경로 + 올바른 <code>DOCKER_HOST</code></td><td>rootful 경로를 관성적으로 마운트</td><td>context, user service, socket 존재</td></tr><tr><td>모니터링·대시보드 조회</td><td>내부망 socket proxy + POST 차단</td><td>각 서비스에 socket 직접 마운트</td><td>허용 GET 성공, POST 거부</td></tr><tr><td>Docker Desktop</td><td>Desktop가 제공하는 Linux socket 연동 확인</td><td>호스트 OS 경로를 Linux와 동일시</td><td>컨테이너 유형·Desktop 설정 확인</td></tr><tr><td>CI에서 원격 daemon 사용</td><td>SSH 또는 인증된 TLS 연결 검토</td><td>인증 없는 TCP 2375</td><td>인증·네트워크 범위·감사 로그</td></tr></tbody></table></figure>



<p>Windows Docker Desktop에서 Windows 컨테이너와 Linux 컨테이너는 경로 의미가 다를 수 있다. 최근 공개 이슈에서도 <code>/var/run/docker.sock</code> 하드코딩 때문에 Windows named pipe 대체 경로가 없어 실패한 사례가 확인됐다. 이미지가 특정 플랫폼만 지원하는지 먼저 확인하고, 경로 치환만으로 해결되지 않으면 제품의 공식 지원 범위를 따라야 한다.</p>



<h2 class="wp-block-heading">보안을 악화시키는 빠른 해결책 세 가지</h2>



<ul class="wp-block-list">
<li><strong><code>chmod 666 /var/run/docker.sock</code>:</strong> 모든 로컬 사용자가 daemon에 명령을 보낼 수 있게 한다. 재시작 뒤 사라지는 임시 처방이면서 공격 범위를 넓힌다.</li>



<li><strong><code>privileged: true</code> 추가:</strong> 단순 GID 문제보다 훨씬 큰 권한을 컨테이너에 준다. 소켓 Unix 권한을 해결하려고 사용할 이유가 없다.</li>



<li><strong>TCP 2375를 외부에 공개:</strong> 인증·TLS 없는 Docker API는 원격 호스트 제어 경로가 될 수 있다. Docker 공식 보안 문서는 신뢰된 네트워크·VPN, SSH 또는 TLS 보호를 요구한다.</li>
</ul>



<p>소켓이 필요한 관리 도구는 공급망 위험도 함께 가진다. 이미지가 침해되면 공격자는 마운트된 socket을 사용해 호스트 파일시스템을 마운트한 새 컨테이너를 만들 수 있다. 따라서 이미지 digest 또는 명시적 버전 고정, 자동 업데이트 범위 제한, 내부 네트워크, 최소 endpoint 허용, 로그 보존을 함께 적용해야 한다.</p>



<h2 class="wp-block-heading">배포 전 체크리스트</h2>



<figure class="wp-block-table"><table><thead><tr><th>확인 항목</th><th>통과 기준</th></tr></thead><tbody><tr><td>실제 daemon</td><td>rootful·rootless·Desktop 중 어느 daemon인지 명확하다.</td></tr><tr><td>소켓 경로</td><td>호스트에 존재하며 컨테이너에도 의도한 경로로 보인다.</td></tr><tr><td>숫자 GID</td><td>호스트 socket GID가 컨테이너 프로세스의 보조 그룹에 있다.</td></tr><tr><td>권한 범위</td><td>직접 socket 전체 접근이 꼭 필요한 이유가 문서화됐다.</td></tr><tr><td>네트워크</td><td>proxy 또는 TCP endpoint가 공개 인터넷에 노출되지 않는다.</td></tr><tr><td>실패 검증</td><td>허용 작업은 성공하고 금지한 POST·endpoint는 실제로 거부된다.</td></tr><tr><td>재배포</td><td>호스트 교체·재부팅 뒤 GID와 socket 경로를 다시 계산한다.</td></tr></tbody></table></figure>



<p>개인 서버의 전체 메모리와 장애 반경도 함께 점검하려면 <a href="https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/">Docker Compose 메모리 제한과 OOM 가이드</a>를 연결해 보면 된다. 서버 사양 자체가 빠듯하다면 <a href="https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/">1GB·2GB·4GB VPS 사양 선택법</a>에서 컨테이너별 메모리 예산을 먼저 잡는 편이 낫다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">docker 그룹에 사용자를 추가하면 안전한가</h3>



<p>일반 사용자보다 편리하지만 일반 권한은 아니다. Docker 공식 문서는 <code>docker</code> 그룹이 root 수준 권한을 부여한다고 경고한다. 신뢰된 운영 사용자로 제한하고, 서비스 컨테이너에는 필요한 경우에만 숫자 GID를 전달해야 한다.</p>



<h3 class="wp-block-heading">소켓을 :ro로 마운트하면 컨테이너 생성이 막히나</h3>



<p>그렇게 가정하면 안 된다. bind mount의 읽기 전용과 Docker API의 읽기 전용 인가는 다른 문제다. 쓰기 요청을 차단하려면 socket proxy에서 <code>POST=0</code>과 endpoint 허용 목록을 적용하고 실제 거부 응답을 테스트해야 한다.</p>



<h3 class="wp-block-heading">group_add를 넣었는데도 permission denied가 계속되면 무엇을 보나</h3>



<p>컨테이너가 재생성됐는지, 실행 프로세스의 <code>id</code>에 해당 숫자 그룹이 있는지, 마운트된 socket GID가 같은지 확인한다. 그다음 rootless 경로 혼동과 SELinux·AppArmor 감사 로그를 확인한다.</p>



<h3 class="wp-block-heading">Docker-in-Docker가 더 안전한 대안인가</h3>



<p>항상 그렇지 않다. 별도 daemon으로 격리할 수 있지만 저장소·캐시·네트워크·privileged 요구와 운영 복잡성이 생긴다. 호스트 daemon 제어가 필요 없는 CI 빌드라면 rootless builder나 전용 빌드 서비스를 포함해 요구사항별로 비교해야 한다.</p>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://docs.docker.com/engine/install/linux-postinstall/">Docker Engine Linux post-installation</a></li>



<li><a href="https://docs.docker.com/engine/security/">Docker Engine security</a></li>



<li><a href="https://docs.docker.com/engine/security/rootless/">Docker Rootless mode</a></li>



<li><a href="https://docs.docker.com/reference/compose-file/services/#group_add">Docker Compose group_add 명세</a></li>



<li><a href="https://docs.docker.com/reference/cli/docker/container/run/#group-add">docker run 및 socket 전체 접근 설명</a></li>



<li><a href="https://github.com/Tecnativa/docker-socket-proxy">Tecnativa docker-socket-proxy</a></li>



<li><a href="https://github.com/getarcaneapp/arcane/issues/3693">Arcane docker.sock 경로·GID 관련 공개 이슈</a></li>



<li><a href="https://github.com/elie222/rakazo/issues/134">Windows named pipe 대체 경로 관련 공개 이슈</a></li>
</ul>



<p>문서와 공개 이슈 확인 기준일은 2026년 8월 27일이다. 배포판, Docker Engine·Desktop 실행 방식, 보안 모듈과 사용하는 관리 도구에 따라 socket 경로와 필요한 API 범위가 달라질 수 있다.</p>



<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"docker 그룹에 사용자를 추가하면 안전한가","acceptedAnswer":{"@type":"Answer","text":"Docker 그룹은 root 수준 권한을 부여하므로 신뢰된 운영 사용자로 제한하고 서비스에는 필요한 경우에만 GID를 전달해야 한다."}},{"@type":"Question","name":"소켓을 :ro로 마운트하면 컨테이너 생성이 막히나","acceptedAnswer":{"@type":"Answer","text":"bind mount 읽기 전용은 Docker API 인가가 아니다. proxy에서 POST와 endpoint를 제한하고 거부 응답을 검증해야 한다."}},{"@type":"Question","name":"group_add 뒤에도 permission denied가 계속되면 무엇을 보나","acceptedAnswer":{"@type":"Answer","text":"재생성 여부, 프로세스 보조 그룹, socket 숫자 GID, rootless 경로, SELinux와 AppArmor 로그를 순서대로 확인한다."}},{"@type":"Question","name":"Docker-in-Docker가 더 안전한 대안인가","acceptedAnswer":{"@type":"Answer","text":"항상 그렇지 않다. 별도 daemon 격리와 privileged 요구, 저장소와 네트워크 운영 복잡성을 함께 비교해야 한다."}}]}</script>
		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2815"
					data-ulike-nonce="bf529fd681"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2815"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/docker-sock-permission-denied-safe-fix/">docker.sock permission denied 해결: chmod 666 없이 안전하게 고치는 법</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/docker-sock-permission-denied-safe-fix/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AI 에이전트 추적 실무: OpenTelemetry로 지연·토큰·도구 호출 연결하기</title>
		<link>https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/</link>
					<comments>https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Mon, 24 Aug 2026 00:07:08 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[AI 에이전트]]></category>
		<category><![CDATA[LLMOps]]></category>
		<category><![CDATA[OpenTelemetry]]></category>
		<category><![CDATA[트레이싱]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/</guid>

					<description><![CDATA[<p>AI 에이전트의 요청·모델·검색·도구 호출을 OpenTelemetry trace와 span으로 연결하는 방법을 정리했다. 최소 속성, Python 예시, 개인정보·비용·경보 체크리스트를 다룬다.</p>
<p>The post <a href="https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/">AI 에이전트 추적 실무: OpenTelemetry로 지연·토큰·도구 호출 연결하기</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>AI 에이전트 장애를 제대로 추적하려면 모델 호출 로그만 모아서는 부족하다. <strong>사용자 요청 하나를 루트 trace로 만들고, 에이전트 실행·모델 호출·검색·도구 호출·최종 응답을 parent-child span으로 연결해야 한다.</strong> 그래야 느린 구간, 토큰 급증 지점, 실패한 도구와 재시도 원인을 한 화면에서 찾을 수 있다. OpenTelemetry를 공통 전송 계층으로 두면 특정 관측 제품에 종속되지 않고 시작할 수 있다.</p>



<div class="wp-block-group has-border-color has-background" style="border-color:#bfdbfe;border-width:1px;background-color:#eff6ff;padding-top:20px;padding-right:22px;padding-bottom:20px;padding-left:22px"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-3 wp-block-group-is-layout-constrained">


<h2 class="wp-block-heading has-medium-font-size">핵심 요약</h2>



<ul class="wp-block-list">
<li>첫 도입 범위는 <strong>trace_id, 단계, 지연, 상태, 토큰 사용량, 도구 이름</strong>으로 제한한다. 프롬프트와 응답 원문은 기본 수집 대상에서 뺀다.</li>



<li>하나의 사용자 요청 아래에 agent·model·tool·retrieval span을 중첩해야 병목과 실패 전파 경로가 보인다.</li>



<li>운영 대시보드는 평균보다 p95 지연, 오류율, 재시도율, 요청당 토큰, 도구별 실패율을 우선한다.</li>



<li>OpenTelemetry GenAI 의미 규약은 별도 저장소로 이동해 계속 진화 중이므로 속성 이름을 코드 전역에 박지 말고 매핑 계층을 둔다.</li>
</ul>


</div></div>



<h2 class="wp-block-heading">AI 에이전트 추적은 일반 API 추적과 무엇이 다른가</h2>



<p>일반 HTTP API는 요청 하나가 몇 개의 서비스 span으로 끝나는 경우가 많다. AI 에이전트는 한 요청 안에서 모델이 계획을 세우고, 여러 도구를 호출하고, 결과가 부족하면 모델을 다시 부르는 반복 구조를 가진다. 최종 응답은 성공했어도 중간 검색이 세 번 실패했거나 불필요한 모델 재호출로 비용이 커졌을 수 있다.</p>



<p>OpenAI Agents SDK 공식 문서는 기본 trace가 runner, task, turn, agent, generation, function tool, guardrail, handoff span을 포함한다고 설명한다. 특정 SDK를 쓰지 않더라도 이 계층은 실무 설계의 좋은 기준이 된다. 핵심은 로그 줄을 시간순으로 모으는 것이 아니라 <strong>어떤 단계가 어떤 부모 작업에서 파생됐는지</strong> 보존하는 데 있다.</p>



<figure class="wp-block-table"><table><thead><tr><th>질문</th><th>로그만 있을 때</th><th>연결된 trace가 있을 때</th></tr></thead><tbody><tr><td>왜 12초가 걸렸나</td><td>타임스탬프를 수동 대조한다.</td><td>모델·검색·도구 span의 지연을 분해한다.</td></tr><tr><td>왜 토큰이 늘었나</td><td>요청별 합계만 보이기 쉽다.</td><td>모델 재호출과 단계별 토큰을 찾는다.</td></tr><tr><td>어디서 실패했나</td><td>예외 문자열을 검색한다.</td><td>오류 span과 부모 agent 실행을 함께 본다.</td></tr><tr><td>같은 대화인가</td><td>사용자 ID에 의존하기 쉽다.</td><td>가명화한 session/thread 키로 trace를 묶는다.</td></tr></tbody></table></figure>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1050" height="600" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/ai-agent-trace-flow.png" alt="사용자 요청부터 에이전트 모델 도구 최종 응답까지 연결된 트레이스 구조" class="wp-image-2805" style="width:640px;height:auto"/><figcaption class="wp-element-caption">요청·에이전트·모델·도구·응답을 하나의 trace로 연결한 구조<br />출처: OpenTelemetry·OpenAI Agents SDK 공식 문서 기반 구성</figcaption></figure></div>


<h2 class="wp-block-heading">먼저 정할 최소 span 구조</h2>



<p>처음부터 모든 이벤트를 수집하면 비용과 개인정보 위험만 커진다. 아래 다섯 단계로 시작하면 대부분의 운영 질문에 답할 수 있다. 에이전트가 검색을 쓰지 않으면 retrieval span은 생략하고, 여러 도구를 병렬 실행한다면 같은 부모 아래에 형제 span으로 둔다.</p>



<figure class="wp-block-table"><table><thead><tr><th>span</th><th>부모</th><th>최소 기록값</th><th>주요 질문</th></tr></thead><tbody><tr><td>request / workflow</td><td>없음</td><td>trace_id, route, total latency, status</td><td>요청 전체가 성공했는가</td></tr><tr><td>agent run</td><td>request</td><td>agent name, iteration, handoff</td><td>몇 번 계획하고 위임했는가</td></tr><tr><td>model call</td><td>agent run</td><td>provider, model, input/output token, latency</td><td>비용과 지연이 어디서 늘었는가</td></tr><tr><td>retrieval / tool</td><td>agent run</td><td>tool name, duration, status, retry count</td><td>어떤 외부 작업이 실패했는가</td></tr><tr><td>final response</td><td>request</td><td>result status, quality signal</td><td>최종 결과가 기준을 통과했는가</td></tr></tbody></table></figure>



<p>W3C Trace Context의 <code>traceparent</code>를 서비스 경계에서 전달하면 웹 API, 작업 큐, 도구 서버가 같은 분산 trace에 참여할 수 있다. 다만 대화 전체를 하나의 무한히 긴 trace로 만들기보다 <strong>사용자 요청 단위 trace</strong>와 별도의 가명 session key를 함께 쓰는 편이 조회와 보존에 유리하다.</p>



<h2 class="wp-block-heading">속성은 표준·조직·민감정보로 나눠 관리한다</h2>



<p>OpenTelemetry 공식 사이트의 GenAI 의미 규약 페이지는 2026년 8월 현재 관련 규약이 별도 <code>semantic-conventions-genai</code> 저장소로 이동했다고 안내한다. 새 저장소에는 agent, inference, tool, retrieval 등 span 문서와 참조 시나리오가 있다. 아직 변할 수 있는 이름을 애플리케이션 곳곳에 직접 쓰면 업그레이드 비용이 커진다.</p>



<figure class="wp-block-table"><table><thead><tr><th>구분</th><th>예시</th><th>운영 원칙</th></tr></thead><tbody><tr><td>표준 후보</td><td>operation, provider, model, token usage, error type</td><td>공식 규약의 안정성 상태를 확인하고 exporter 앞에서 매핑한다.</td></tr><tr><td>조직 속성</td><td>service tier, feature flag, release, tenant class</td><td>개인 식별값 대신 운영 분류만 넣는다.</td></tr><tr><td>상관관계</td><td>trace_id, span_id, parent span, pseudonymous session</td><td>원본 사용자 ID를 그대로 넣지 않는다.</td></tr><tr><td>본문 데이터</td><td>prompt, response, tool arguments</td><td>기본 비수집, 필요 시 별도 동의·마스킹·짧은 보존을 적용한다.</td></tr></tbody></table></figure>



<p>Langfuse 공식 OpenTelemetry 문서도 GenAI 속성 규약이 진화 중이며 수신 OTel trace를 자체 데이터 모델로 매핑한다고 밝힌다. 또한 baggage는 서비스와 외부 API 경계를 따라 전파되므로 비밀번호, API 키, 개인정보를 넣지 말라고 경고한다. 검색 필터 편의를 위해 민감값을 baggage에 넣는 설계는 피해야 한다.</p>



<h2 class="wp-block-heading">Python에서 최소 추적을 붙이는 순서</h2>



<p>다음 코드는 특정 LLM 프레임워크 자동 계측에 기대지 않고 구조를 이해하기 위한 최소 예시다. OpenTelemetry Python 공식 문서의 <code>TracerProvider</code>, <code>BatchSpanProcessor</code>, current span 구조를 따른다. <code>app.*</code> 속성은 이 글의 조직 예시이며 공식 GenAI 속성으로 오해하면 안 된다.</p>



<pre class="wp-block-code"><code>from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

provider = TracerProvider()
provider.add_span_processor(
    BatchSpanProcessor(OTLPSpanExporter())
)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(&quot;agent-service&quot;)

with tracer.start_as_current_span(&quot;agent.request&quot;) as root:
    root.set_attribute(&quot;app.route&quot;, &quot;support-agent&quot;)

    with tracer.start_as_current_span(&quot;agent.model_call&quot;) as model_span:
        model_span.set_attribute(&quot;app.model&quot;, selected_model)
        result = call_model(messages)
        model_span.set_attribute(&quot;app.input_tokens&quot;, result.input_tokens)
        model_span.set_attribute(&quot;app.output_tokens&quot;, result.output_tokens)

    with tracer.start_as_current_span(&quot;agent.tool_call&quot;) as tool_span:
        tool_span.set_attribute(&quot;app.tool&quot;, &quot;knowledge_search&quot;)
        docs = search_knowledge(result.query)</code></pre>



<ol class="wp-block-list">
<li><strong>개발 환경에서 console exporter로 구조를 먼저 확인한다.</strong> 부모·자식 관계가 끊기지 않는지 본다.</li>



<li><strong>OTLP exporter를 Collector 또는 관측 백엔드에 연결한다.</strong> 애플리케이션이 각 제품의 전용 전송 코드를 직접 갖지 않게 한다.</li>



<li><strong>모델·도구 wrapper 한 곳에서 속성을 정규화한다.</strong> 프레임워크가 바뀌어도 대시보드 키를 유지한다.</li>



<li><strong>오류와 재시도를 이벤트 또는 span 상태로 남긴다.</strong> 최종 성공만 기록하면 숨은 실패 비용을 놓친다.</li>



<li><strong>샘플링과 보존 기간을 부하 테스트로 결정한다.</strong> trace 자체가 서비스 병목이 되지 않는지 확인한다.</li>
</ol>



<h2 class="wp-block-heading">운영 대시보드는 다섯 지표부터 만든다</h2>



<p>대시보드에 모든 속성을 올리기보다 장애와 비용 결정을 직접 바꾸는 지표를 먼저 둔다. 아래 경보선은 제품 공식값이 아니라 초기 운영을 위한 예시다. 서비스의 정상 기준선을 수집한 뒤 조정해야 한다.</p>



<figure class="wp-block-table"><table><thead><tr><th>지표</th><th>보는 이유</th><th>초기 점검 조건 예시</th></tr></thead><tbody><tr><td>요청 p95 지연</td><td>느린 소수 요청이 사용자 경험을 좌우한다.</td><td>기준선 대비 2배가 15분 지속</td></tr><tr><td>모델 호출 횟수/요청</td><td>루프와 불필요한 재계획을 찾는다.</td><td>상한 초과 요청 비율 증가</td></tr><tr><td>입력·출력 토큰/요청</td><td>비용 급증과 컨텍스트 팽창을 찾는다.</td><td>배포 전후 중앙값·p95 비교</td></tr><tr><td>도구별 오류·재시도율</td><td>외부 API와 검색 장애를 분리한다.</td><td>특정 도구 오류율이 기준선 초과</td></tr><tr><td>완료율·품질 신호</td><td>빠르지만 실패한 응답을 걸러낸다.</td><td>status OK와 평가 통과를 함께 집계</td></tr></tbody></table></figure>



<p>토큰 단가를 연결할 때는 모델과 컨텍스트 구간, 캐시 읽기·쓰기, Batch 여부에 따라 가격표가 달라질 수 있다. 따라서 span에는 계산된 비용만 남기기보다 provider, model, 입력·출력·캐시 토큰을 보존하고 비용 계산기를 별도 버전으로 관리하는 편이 감사와 재계산에 유리하다.</p>



<h2 class="wp-block-heading">개인정보와 비용 때문에 실패하는 지점</h2>



<ul class="wp-block-list">
<li><strong>프롬프트 원문 기본 수집:</strong> 고객 정보, 소스코드, API 키가 trace 백엔드로 복제될 수 있다. 메타데이터 우선 원칙을 적용한다.</li>



<li><strong>모든 span 100% 장기 보존:</strong> 트래픽과 도구 호출 수가 늘면 저장·인덱싱 비용이 빠르게 커진다. 정상 요청은 head sampling, 오류·고지연은 tail sampling을 검토한다.</li>



<li><strong>비동기 경계의 context 손실:</strong> 큐 worker와 병렬 도구 실행에서 부모 context를 전달하지 않으면 trace가 여러 조각으로 갈라진다.</li>



<li><strong>속성의 무제한 cardinality:</strong> 원문 URL, 사용자 ID, 임의 오류 메시지를 인덱스 필드로 쓰면 조회 비용이 커진다. 정규화한 코드와 제한된 분류를 쓴다.</li>



<li><strong>관측 백엔드 실패의 서비스 전파:</strong> exporter는 batch와 짧은 timeout을 쓰고, 추적 전송 실패 때문에 사용자 요청까지 실패하지 않게 분리한다.</li>
</ul>



<p>OpenAI Agents SDK 문서는 추적이 기본 활성화될 수 있고, 전역 환경변수·코드·개별 실행 설정으로 끌 수 있다고 안내한다. 또한 Zero Data Retention 정책을 쓰는 조직에는 해당 trace 기능을 사용할 수 없다고 명시한다. 사용하는 SDK의 기본값과 데이터 정책을 배포 전에 반드시 확인해야 한다.</p>



<h2 class="wp-block-heading">도입 단계별 체크리스트</h2>



<figure class="wp-block-table"><table><thead><tr><th>단계</th><th>완료 조건</th><th>중단 조건</th></tr></thead><tbody><tr><td>1. 로컬 구조</td><td>요청→agent→model/tool 계층이 보인다.</td><td>부모 context가 자주 끊긴다.</td></tr><tr><td>2. 스테이징 OTLP</td><td>Collector 수신과 exporter 재시도가 확인된다.</td><td>전송이 응답 지연을 유의미하게 늘린다.</td></tr><tr><td>3. 민감정보 점검</td><td>샘플 trace에 원문·키·개인정보가 없다.</td><td>마스킹 이전 데이터가 남는다.</td></tr><tr><td>4. 제한 배포</td><td>p95·오류·토큰·도구율 대시보드가 동작한다.</td><td>cardinality와 저장량을 예측할 수 없다.</td></tr><tr><td>5. 운영 확대</td><td>장애 한 건을 trace로 재현해 원인을 찾는다.</td><td>수집은 되지만 실제 운영 질문에 답하지 못한다.</td></tr></tbody></table></figure>



<p>이미 개념과 제품 선택부터 정리해야 한다면 <a href="https://blog.kwt.co.kr/ai-agent-observability-guide/">AI 에이전트 관측성 가이드</a>와 <a href="https://blog.kwt.co.kr/ai-agent-observability-tools-comparison/">Langfuse·LangSmith·Phoenix·OpenTelemetry 비교</a>를 먼저 보는 편이 낫다. 비용 분석까지 확장하려면 <a href="https://blog.kwt.co.kr/ai-agent-cost-tracking-guide/">AI 에이전트 비용 추적 가이드</a>를 함께 연결하면 된다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">로그와 trace를 둘 다 남겨야 하나</h3>



<p>둘의 역할이 다르다. trace는 요청의 단계와 부모·자식 관계, 지연을 보여주고 로그는 상세 사건과 디버그 문맥을 제공한다. 로그에 trace_id와 span_id를 넣어 상호 이동할 수 있게 만드는 구성이 실용적이다.</p>



<h3 class="wp-block-heading">프롬프트와 응답을 저장하지 않으면 디버깅이 불가능하지 않나</h3>



<p>대부분의 운영 장애는 모델명, 지연, 토큰, 도구 입력의 분류, 상태, 오류 코드만으로도 1차 진단이 가능하다. 원문이 꼭 필요한 평가 환경은 별도 동의, 마스킹, 접근 제어, 짧은 보존 기간을 적용해 분리한다.</p>



<h3 class="wp-block-heading">OpenTelemetry만 설치하면 AI 비용도 자동으로 계산되나</h3>



<p>그렇지 않다. OpenTelemetry는 신호와 context를 수집·전송하는 기반이다. 모델별 단가와 캐시·컨텍스트 구간을 반영한 비용 계산 로직 또는 이를 지원하는 백엔드가 별도로 필요하다.</p>



<h3 class="wp-block-heading">trace는 요청마다 하나가 좋은가, 대화마다 하나가 좋은가</h3>



<p>일반적으로 사용자 요청마다 trace를 만들고 가명 session 또는 thread 키로 여러 trace를 묶는 편이 낫다. 대화 전체를 하나의 장기 trace로 만들면 크기, 시간 제한, 조회가 복잡해진다.</p>



<h3 class="wp-block-heading">가장 먼저 경보로 만들 지표는 무엇인가</h3>



<p>오류율과 요청 p95 지연을 먼저 두고, 모델 호출 횟수와 요청당 토큰을 추가하는 순서가 현실적이다. 도구가 핵심인 서비스라면 도구별 오류·재시도율도 첫 단계에 포함한다.</p>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://github.com/open-telemetry/semantic-conventions-genai">OpenTelemetry GenAI Semantic Conventions 저장소</a></li>



<li><a href="https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-agent-spans.md">OpenTelemetry GenAI Agent Spans</a></li>



<li><a href="https://opentelemetry.io/docs/languages/python/instrumentation/">OpenTelemetry Python Instrumentation</a></li>



<li><a href="https://openai.github.io/openai-agents-python/tracing/">OpenAI Agents SDK Tracing</a></li>



<li><a href="https://langfuse.com/docs/opentelemetry/get-started">Langfuse OpenTelemetry 문서</a></li>



<li><a href="https://www.w3.org/TR/trace-context/">W3C Trace Context</a></li>
</ul>



<p>문서 확인 기준일은 2026년 8월 24일이다. OpenTelemetry GenAI 의미 규약은 진화 중이므로 실제 적용 전 저장소의 최신 상태와 사용하는 SDK·백엔드의 지원 범위를 다시 확인해야 한다.</p>



<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"로그와 trace를 둘 다 남겨야 하나","acceptedAnswer":{"@type":"Answer","text":"trace는 요청 단계와 관계·지연을, 로그는 상세 사건을 담당한다. 로그에 trace_id와 span_id를 넣어 함께 쓰는 편이 좋다."}},{"@type":"Question","name":"프롬프트와 응답을 저장하지 않으면 디버깅이 불가능하지 않나","acceptedAnswer":{"@type":"Answer","text":"메타데이터만으로 1차 진단이 가능하다. 원문은 별도 동의·마스킹·접근 제어·짧은 보존 기간을 적용한 환경에서만 수집한다."}},{"@type":"Question","name":"OpenTelemetry만 설치하면 AI 비용도 자동으로 계산되나","acceptedAnswer":{"@type":"Answer","text":"아니다. 모델별 단가와 캐시·컨텍스트 구간을 반영한 비용 계산 로직이나 백엔드가 별도로 필요하다."}},{"@type":"Question","name":"trace는 요청마다 하나가 좋은가, 대화마다 하나가 좋은가","acceptedAnswer":{"@type":"Answer","text":"요청마다 trace를 만들고 가명 session 또는 thread 키로 여러 trace를 묶는 방식이 일반적으로 관리하기 쉽다."}},{"@type":"Question","name":"가장 먼저 경보로 만들 지표는 무엇인가","acceptedAnswer":{"@type":"Answer","text":"오류율과 요청 p95 지연을 우선하고 모델 호출 횟수, 요청당 토큰, 도구 오류·재시도율을 추가한다."}}]}</script>
		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2806"
					data-ulike-nonce="8fe6bc40fc"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2806"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/">AI 에이전트 추적 실무: OpenTelemetry로 지연·토큰·도구 호출 연결하기</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/ai-agent-tracing-opentelemetry-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Docker 메모리 제한 가이드: Compose로 OOM 장애 막는 법</title>
		<link>https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/</link>
					<comments>https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 00:07:37 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Docker Compose]]></category>
		<category><![CDATA[OOM]]></category>
		<category><![CDATA[홈서버]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/</guid>

					<description><![CDATA[<p>Docker Compose에서 mem_limit·mem_reservation·restart·healthcheck를 조합해 OOM 장애 반경을 줄이는 방법과 2GB·4GB VPS 메모리 예산, 점검 명령을 정리했다.</p>
<p>The post <a href="https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/">Docker 메모리 제한 가이드: Compose로 OOM 장애 막는 법</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Docker 컨테이너의 메모리를 제한하지 않으면 한 서비스의 누수나 순간 부하가 호스트 전체의 OOM 장애로 번질 수 있다. 개인 VPS와 홈서버에서는 <strong>서비스별 hard limit를 먼저 두고, 호스트 여유 메모리를 남긴 뒤, OOMKilled와 재시작 횟수를 함께 관측하는 구성</strong>이 가장 현실적이다. restart만 설정하거나 swap만 늘리는 방식은 원인을 해결하지 못한다.</p>



<div class="wp-block-group has-border-color has-background" style="border-color:#bfdbfe;border-width:1px;background-color:#eff6ff;padding-top:20px;padding-right:22px;padding-bottom:20px;padding-left:22px"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-4 wp-block-group-is-layout-constrained">


<h2 class="wp-block-heading has-medium-font-size">핵심 요약</h2>



<ul class="wp-block-list">
<li>Docker 컨테이너는 기본적으로 호스트가 허용하는 만큼 자원을 사용할 수 있으므로 운영 서버에서는 메모리 경계를 명시하는 편이 안전하다.</li>



<li><code>mem_limit</code>는 hard limit, <code>mem_reservation</code>은 경합 때 작동하는 soft limit다. reservation은 초과 방지를 보장하지 않는다.</li>



<li>plain Docker Compose의 <code>healthcheck</code>는 상태를 표시하지만 unhealthy 컨테이너를 자동 재시작하지 않는다. 재시작은 프로세스 종료와 함께 설계해야 한다.</li>



<li>2GB·4GB 소형 서버에서는 모든 컨테이너 hard limit 합계를 RAM과 같게 잡지 말고 OS·Docker·파일 캐시·배포 피크용 여유를 남긴다.</li>
</ul>


</div></div>



<h2 class="wp-block-heading">메모리 제한이 없으면 왜 호스트까지 흔들릴까</h2>



<p>Docker 공식 문서에 따르면 컨테이너에는 기본 자원 제한이 없으며 호스트 커널 스케줄러가 허용하는 만큼 메모리와 CPU를 사용할 수 있다. Linux가 중요한 시스템 기능을 유지할 메모리를 확보하지 못하면 OOM 처리를 시작하고 프로세스를 종료한다. 컨테이너 프로세스가 먼저 종료될 가능성이 높지만 Docker 데몬이나 같은 호스트의 다른 서비스도 영향권에 들어간다.</p>



<p>문제는 평균 사용량이 아니라 피크의 합이다. 평소 250MB인 웹 앱이 배포 중 700MB를 쓰고, 같은 시각 데이터베이스 백업과 로그 압축이 겹치면 2GB VPS는 짧은 순간에도 한계에 닿는다. 따라서 “평소에는 괜찮다”보다 <strong>동시에 발생할 수 있는 최대 작업</strong>을 기준으로 경계를 잡아야 한다.</p>



<figure class="wp-block-table"><table><thead><tr><th>신호</th><th>의미</th><th>먼저 확인할 것</th></tr></thead><tbody><tr><td><code>OOMKilled=true</code></td><td>커널이 컨테이너 프로세스를 메모리 부족으로 종료했을 가능성이 크다.</td><td>limit, 직전 RSS, 호스트 available 메모리</td></tr><tr><td>재시작 횟수 증가</td><td>프로세스 종료 후 restart 정책이 반복 실행 중이다.</td><td>종료 코드, 애플리케이션 로그, OOM 여부</td></tr><tr><td>swap 지속 사용</td><td>RAM 압박을 디스크 I/O로 미루고 있다.</td><td>응답 지연, major page fault, 스왑 설정</td></tr><tr><td>호스트 SSH 지연</td><td>컨테이너 밖의 시스템 여유도 부족하다.</td><td>OS·Docker·파일 캐시용 미할당 공간</td></tr></tbody></table></figure>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1050" height="600" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/docker-memory-defense-flow.png" alt="Docker 메모리 제한 복구 정책 호스트 관측의 3단계 방어선" class="wp-image-2802" style="width:640px;height:auto"/><figcaption class="wp-element-caption">컨테이너 제한·복구 정책·호스트 관측의 3단계 방어선<br />출처: Docker 공식 문서 기반 구성</figcaption></figure></div>


<h2 class="wp-block-heading">Docker Compose에서 hard limit와 soft reservation을 함께 둔다</h2>



<p>아래 예시는 2GB VPS에서 웹 앱과 데이터베이스를 함께 운영할 때의 <strong>출발용 구성</strong>이다. 512M과 768M은 Docker가 제시한 보편 권장값이 아니라, 나머지 메모리를 호스트와 배포 피크에 남기기 위한 예시다. 실제 값은 <code>docker stats</code>와 서비스 부하 테스트로 조정해야 한다.</p>



<pre class="wp-block-code"><code>services:
  app:
    image: example/app:latest
    mem_limit: 512m
    mem_reservation: 256m
    pids_limit: 200
    restart: unless-stopped
    healthcheck:
      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-f&quot;, &quot;http://localhost:8080/health&quot;]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s

  db:
    image: postgres:18
    mem_limit: 768m
    mem_reservation: 512m
    restart: unless-stopped</code></pre>



<ul class="wp-block-list">
<li><strong>mem_limit</strong>: 컨테이너가 할당할 수 있는 메모리 상한이다. 상한을 너무 낮추면 정상적인 피크도 OOM으로 처리된다.</li>



<li><strong>mem_reservation</strong>: 호스트에 경합이 생길 때 적용되는 soft limit다. hard limit보다 작게 두며 초과를 완전히 막는 장치로 보면 안 된다.</li>



<li><strong>pids_limit</strong>: 프로세스·스레드 폭증이 호스트를 압박하는 범위를 줄인다. 메모리 제한과 함께 두면 장애 반경을 줄이기 쉽다.</li>



<li><strong>restart</strong>: 종료된 프로세스를 다시 띄우는 정책이다. 메모리 누수의 원인을 고치거나 상태를 정상으로 만드는 기능은 아니다.</li>
</ul>



<p>Compose의 <code>deploy.resources.limits.memory</code>와 <code>reservations.memory</code>도 공식 Deploy Specification에 정의돼 있다. 같은 파일에서 서비스 수준의 <code>mem_limit</code>·<code>mem_reservation</code>을 함께 사용한다면 값이 서로 일치해야 한다. 배포 환경이 Docker Compose인지 Swarm인지도 구분해야 한다.</p>



<h2 class="wp-block-heading">2GB·4GB VPS는 컨테이너 합계보다 여유 공간이 중요하다</h2>



<p>소형 서버의 시작점은 컨테이너별 평균값을 더하는 방식이 아니라, hard limit 합계와 호스트 여유를 동시에 보는 방식이다. 아래 비율은 공식 최소 요구 사항이 아니라 개인 서비스의 보수적인 초기 운영 휴리스틱이다.</p>



<figure class="wp-block-table"><table><thead><tr><th>호스트 RAM</th><th>컨테이너 hard limit 합계 시작점</th><th>호스트·피크 여유</th><th>적합한 상황</th></tr></thead><tbody><tr><td>2GB</td><td>약 1.2~1.5GB</td><td>약 25~40%</td><td>웹 앱+소형 DB, 경량 WordPress</td></tr><tr><td>4GB</td><td>약 2.6~3.2GB</td><td>약 20~35%</td><td>여러 앱, 앱+DB+모니터링</td></tr><tr><td>8GB</td><td>약 5.5~6.5GB</td><td>약 20~30%</td><td>빌드·크롤링·검색 작업이 섞인 서버</td></tr></tbody></table></figure>



<p>가장 위험한 구성은 모든 컨테이너 limit의 합계를 호스트 RAM과 같게 두는 것이다. Docker 데몬, 커널, SSH, 파일 캐시, 로그, 백업, 이미지 pull과 압축 해제도 메모리를 사용한다. 자세한 서버 사양 출발점은 <a href="https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/">개인 서비스 VPS 사양 선택법</a>과 함께 보면 판단하기 쉽다.</p>



<h2 class="wp-block-heading">swap은 완충 장치이지 메모리 증설이 아니다</h2>



<p><code>memswap_limit</code>는 메모리와 swap의 합계 한도를 조정한다. 공식 문서 기준으로 memory와 같은 값으로 설정하면 컨테이너의 swap 사용을 막고, memory만 설정한 채 memswap_limit를 비워 두면 호스트에 swap이 있을 때 memory 값만큼의 swap을 추가로 사용할 수 있다. 예를 들어 memory가 300M이면 합계 600M까지 가능할 수 있다.</p>



<p>swap은 OOM까지 시간을 벌 수 있지만 반복적인 디스크 교환은 지연을 키운다. 데이터베이스나 응답 시간에 민감한 API에서 swap 사용량이 계속 증가한다면 “안 죽었다”가 아니라 “느리게 장애가 진행 중이다”라고 해석하는 편이 안전하다. swap을 끄기 전에 실제 working set과 순간 피크를 확인해야 한다.</p>



<h2 class="wp-block-heading">restart와 healthcheck를 과신하면 안 된다</h2>



<p>Docker의 restart policy는 컨테이너가 종료됐을 때 동작한다. 공식 문서상 정책은 컨테이너가 최소 10초 동안 정상적으로 시작된 뒤 적용되며, 수동으로 중지한 컨테이너에는 데몬 재시작 또는 수동 재시작 전까지 정책이 무시된다. <code>unless-stopped</code>는 개인 서버의 일반적인 상시 서비스에 편리하지만 무한 재시작 루프를 정상화하지는 못한다.</p>



<p>또한 plain Docker Compose에서 healthcheck는 healthy·unhealthy 상태를 기록할 뿐 unhealthy만으로 컨테이너를 재시작하지 않는다. 애플리케이션이 복구 불가능한 상태에서 명확히 종료하도록 만들거나, 별도의 감시·오케스트레이션 정책을 설계해야 한다. AI 서비스의 추적·알림 설계는 <a href="https://blog.kwt.co.kr/ai-agent-observability-tools-comparison/">AI 에이전트 관측 도구 비교</a>의 기준도 참고할 수 있다.</p>



<h2 class="wp-block-heading">OOM이 발생했을 때 10분 안에 확인할 순서</h2>



<ol class="wp-block-list">
<li><code>docker inspect &lt;container&gt; --format {{.State.OOMKilled}}</code>로 OOM 종료 여부를 확인한다.</li>



<li><code>docker stats --no-stream</code>으로 현재 사용량과 설정된 limit를 함께 기록한다.</li>



<li><code>docker inspect</code>에서 종료 코드, 재시작 횟수, 메모리 설정을 확인한다.</li>



<li>애플리케이션 로그와 커널 로그에서 종료 직전의 배포·백업·요청 급증 시점을 맞춘다.</li>



<li>limit만 즉시 올리지 말고 누수, 캐시 상한, 작업 동시성, DB 버퍼 설정을 먼저 분리한다.</li>



<li>재현 부하에서 working set과 피크를 측정한 뒤 reservation과 limit를 단계적으로 조정한다.</li>
</ol>



<pre class="wp-block-code"><code>docker inspect app --format &#x27;{{.State.OOMKilled}} {{.State.ExitCode}} {{.RestartCount}}&#x27;
docker stats --no-stream
docker inspect app --format &#x27;{{.HostConfig.Memory}} {{.HostConfig.MemoryReservation}}&#x27;</code></pre>



<p>로컬 LLM이나 임베딩 서비스는 모델 파일 외에도 KV 캐시와 런타임 버퍼가 커질 수 있다. 이런 워크로드라면 <a href="https://blog.kwt.co.kr/local-llm-memory-ram-vram-guide/">로컬 LLM 메모리 계산법</a>으로 컨테이너 limit 이전에 전체 메모리 예산부터 계산하는 편이 낫다.</p>



<h2 class="wp-block-heading">배포 전 체크리스트</h2>



<ul class="wp-block-list">
<li>각 서비스에 hard limit가 있으며 정상 피크보다 낮게 잡히지 않았는가</li>



<li>reservation이 hard limit보다 작고 실제 steady-state 사용량과 맞는가</li>



<li>모든 hard limit 합계 외에 OS·Docker·캐시·배포용 여유가 남는가</li>



<li>restart 횟수와 OOMKilled를 모니터링하거나 정기 확인하는가</li>



<li>healthcheck 실패가 실제 복구 동작으로 이어지는지 별도로 검증했는가</li>



<li>swap 사용량 증가와 지연을 함께 보고 있는가</li>



<li>백업·빌드·로그 압축이 같은 시간대에 겹치지 않는가</li>
</ul>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">mem_limit만 설정하면 OOM 장애가 사라질까?</h3>



<p>아니다. 호스트 전체 장애의 반경은 줄일 수 있지만 limit가 너무 낮으면 컨테이너 내부 OOM이 더 자주 발생한다. 정상 피크 측정, 호스트 여유, 재시작 원인 기록을 함께 운영해야 한다.</p>



<h3 class="wp-block-heading">mem_reservation과 mem_limit의 차이는 무엇인가?</h3>



<p>reservation은 메모리 경합 때 쓰는 soft limit이고 limit는 할당 상한인 hard limit다. reservation은 컨테이너가 그 값을 넘지 않는다고 보장하지 않는다.</p>



<h3 class="wp-block-heading">healthcheck가 unhealthy면 Docker가 자동으로 재시작할까?</h3>



<p>plain Docker Compose에서는 그렇지 않다. healthcheck는 상태를 표시하며 restart policy는 기본적으로 프로세스 종료에 반응한다. 종료 전략이나 별도 감시 계층이 필요하다.</p>



<h3 class="wp-block-heading">2GB VPS에서 Docker를 몇 개까지 실행할 수 있을까?</h3>



<p>개수만으로 정할 수 없다. 경량 프록시 여러 개보다 DB 하나가 더 많은 메모리를 쓸 수 있다. 각 서비스 working set, 동시 피크, hard limit 합계와 호스트 여유로 판단해야 한다.</p>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://docs.docker.com/engine/containers/resource_constraints/" target="_blank" rel="noopener">Docker Docs: Resource constraints</a></li>



<li><a href="https://docs.docker.com/reference/compose-file/services/" target="_blank" rel="noopener">Docker Docs: Compose services</a></li>



<li><a href="https://docs.docker.com/reference/compose-file/deploy/" target="_blank" rel="noopener">Docker Docs: Compose Deploy Specification</a></li>



<li><a href="https://docs.docker.com/engine/containers/start-containers-automatically/" target="_blank" rel="noopener">Docker Docs: Start containers automatically</a></li>
</ul>



<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"mem_limit만 설정하면 OOM 장애가 사라질까?","acceptedAnswer":{"@type":"Answer","text":"호스트 전체 장애의 반경은 줄일 수 있지만 limit가 너무 낮으면 컨테이너 내부 OOM이 발생한다. 정상 피크와 호스트 여유를 함께 측정해야 한다."}},{"@type":"Question","name":"mem_reservation과 mem_limit의 차이는 무엇인가?","acceptedAnswer":{"@type":"Answer","text":"reservation은 메모리 경합 때 쓰는 soft limit이고 limit는 할당 상한인 hard limit다."}},{"@type":"Question","name":"healthcheck가 unhealthy면 Docker가 자동으로 재시작할까?","acceptedAnswer":{"@type":"Answer","text":"plain Docker Compose에서는 healthcheck만으로 자동 재시작하지 않는다. 프로세스 종료 전략이나 별도 감시 계층이 필요하다."}},{"@type":"Question","name":"2GB VPS에서 Docker를 몇 개까지 실행할 수 있을까?","acceptedAnswer":{"@type":"Answer","text":"컨테이너 개수가 아니라 각 서비스 working set, 동시 피크, hard limit 합계와 호스트 여유로 판단해야 한다."}}]}</script>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2803"
					data-ulike-nonce="27541dc89d"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2803"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/">Docker 메모리 제한 가이드: Compose로 OOM 장애 막는 법</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/docker-compose-memory-limit-oom-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>개인 서비스 VPS 사양 선택법: 1GB·2GB·4GB 비용과 운영 기준</title>
		<link>https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/</link>
					<comments>https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Sat, 22 Aug 2026 00:06:55 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[VPS]]></category>
		<category><![CDATA[클라우드 비용]]></category>
		<category><![CDATA[홈서버]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/</guid>

					<description><![CDATA[<p>개인 WordPress와 Docker 서비스에 맞는 VPS 메모리를 1GB·2GB·4GB로 나눠 비교했다. 월 비용, OOM·스왑·디스크 신호, 보안·백업 체크리스트를 정리했다.</p>
<p>The post <a href="https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/">개인 서비스 VPS 사양 선택법: 1GB·2GB·4GB 비용과 운영 기준</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>개인 서비스용 VPS는 처음부터 큰 사양을 사기보다 <strong>2GB에서 시작해 메모리와 디스크 지표를 보고 4GB로 올리는 방식</strong>이 가장 안전하다. 정적 사이트나 단일 경량 앱은 1GB도 가능하지만, WordPress·데이터베이스·Docker를 한 서버에 함께 두면 2GB를 실용적인 출발점으로 보는 편이 낫다. 여러 앱, 빌드 작업, 검색·벡터 DB까지 묶는다면 4GB 이상을 검토해야 한다.</p>



<div class="wp-block-group has-border-color has-background" style="border-color:#bfdbfe;border-width:1px;background-color:#eff6ff;padding-top:20px;padding-right:22px;padding-bottom:20px;padding-left:22px"><div class="wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-5 wp-block-group-is-layout-constrained">
<h2 class="wp-block-heading has-medium-font-size">핵심 요약</h2>



<ul class="wp-block-list">
<li><strong>1GB</strong>: 정적 사이트, 리버스 프록시, 단일 경량 앱처럼 역할이 분명할 때만 고른다.</li>



<li><strong>2GB</strong>: 개인 WordPress, 소형 API, 2~3개 경량 Docker 서비스의 현실적인 시작점이다.</li>



<li><strong>4GB</strong>: 앱과 DB를 함께 운영하거나 빌드·크롤링처럼 순간 메모리 사용량이 큰 작업에 유리하다.</li>



<li>사양은 평균 사용량이 아니라 <strong>피크 메모리, OOM 기록, 디스크 증가량, 복구 시간</strong>으로 결정한다.</li>
</ul>
</div></div>



<h2 class="wp-block-heading">VPS 사양은 CPU보다 메모리부터 정한다</h2>



<p>개인 서비스에서 처음 부딪히는 한계는 대개 CPU 코어 수보다 메모리다. 웹 서버만 실행할 때는 작아 보여도 데이터베이스 버퍼, PHP·Node.js 런타임, Docker 데몬, 로그 수집기, 배포 중 빌드 프로세스가 겹치면 피크가 빠르게 커진다. 메모리가 모자라면 Linux OOM Killer가 프로세스를 종료하거나 스왑 때문에 응답 시간이 급격히 늘 수 있다.</p>



<p>아래 표는 공급자의 최소 요구 사항이 아니라 <strong>작게 시작하기 위한 운영 추정치</strong>다. 플러그인 수, 동시 접속, 캐시, 데이터 크기, 빌드 방식에 따라 결과가 달라지므로 배포 뒤 실제 지표로 조정해야 한다.</p>



<figure class="wp-block-table"><table><thead><tr><th>메모리</th><th>적합한 시작 범위</th><th>주의할 실패 조건</th><th>판단</th></tr></thead><tbody><tr><td>1GB</td><td>정적 사이트, 프록시, 단일 경량 프로세스</td><td>서버 내 빌드, DB 동시 운영, 무거운 플러그인</td><td>역할을 한정할 때만</td></tr><tr><td>2GB</td><td>개인 WordPress, 소형 API, 경량 컨테이너 2~3개</td><td>배포와 백업이 겹치는 시간대의 피크</td><td>기본 출발점</td></tr><tr><td>4GB</td><td>앱+DB, 여러 Docker 서비스, 소형 모니터링</td><td>검색 엔진·벡터 DB·대규모 빌드 추가</td><td>운영 여유가 필요할 때</td></tr><tr><td>8GB 이상</td><td>여러 앱, CI 빌드, 검색·관측 스택</td><td>단일 장애 영역과 백업 비용 증가</td><td>서비스 분리도 함께 검토</td></tr></tbody></table><figcaption class="wp-element-caption">실제 필요량은 애플리케이션과 트래픽을 측정해 결정해야 한다.</figcaption></figure>



<h2 class="wp-block-heading">1GB·2GB·4GB 월 비용은 얼마나 차이 날까</h2>



<p>2026년 8월 22일 공식 가격표를 확인하면 공인 IPv4가 포함된 Linux 기준 AWS Lightsail은 1GB 7달러, 2GB 12달러, 4GB 24달러, 8GB 44달러다. DigitalOcean Basic Droplet은 1GB 6달러, 2GB 12달러, 4GB 24달러, 8GB 48달러다. 지역, 세금, 백업, 추가 디스크, 초과 트래픽은 별도일 수 있다.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1035" height="585" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/vps-monthly-price-comparison.png" alt="AWS Lightsail과 DigitalOcean VPS 메모리별 월 정가 비교" class="wp-image-2799" style="width:640px;height:auto"/><figcaption class="wp-element-caption">1GB·2GB·4GB·8GB VPS 월 정가 비교<br />출처: AWS Lightsail·DigitalOcean 공식 가격표 (2026-08-22 확인)</figcaption></figure></div>


<p>2GB에서 4GB로 올리면 두 예시 모두 월 12달러가 늘어난다. 3년 동안 같은 사양을 유지한다는 단순 가정에서는 432달러 차이다. 그래서 여유 사양을 무조건 선구매하기보다, 2GB에서 관측한 뒤 업그레이드하는 편이 작은 서비스의 비용 통제에 유리하다. 반대로 장애 한 번의 복구 비용이 월 12달러보다 크다면 4GB의 여유가 더 합리적이다.</p>



<h2 class="wp-block-heading">서비스 유형별로 고르는 현실적인 기준</h2>



<h3 class="wp-block-heading">정적 사이트와 리버스 프록시</h3>



<p>Nginx·Caddy 같은 프록시와 정적 파일 제공만 담당한다면 1GB로 시작할 수 있다. 다만 같은 서버에서 이미지 변환, Node 빌드, 데이터베이스까지 실행하면 이 전제가 깨진다. 배포 산출물을 외부 CI에서 만들어 서버에는 완성 파일만 전달하는 구조가 1GB에 더 잘 맞는다.</p>



<h3 class="wp-block-heading">WordPress와 소형 웹 애플리케이션</h3>



<p>웹 서버, PHP, 데이터베이스가 한 인스턴스에 들어가는 개인 WordPress라면 2GB를 출발점으로 삼을 만하다. 페이지 캐시가 잘 작동하고 트래픽이 작으면 충분할 수 있지만, 백업 압축과 플러그인 업데이트가 겹칠 때 피크를 확인해야 한다. WordPress는 PHP를 실행할 수 있는 웹 서버를 요구하지만 공식 문서가 모든 사이트에 공통인 RAM 용량을 정하지는 않는다.</p>



<h3 class="wp-block-heading">Docker 여러 개와 데이터베이스</h3>



<p>API, DB, Redis, 프록시, 모니터링을 한 VPS에 모으면 4GB 쪽이 운영하기 편하다. Docker는 기본적으로 컨테이너 메모리를 자동 제한하지 않으므로 <code>--memory</code>나 Compose의 자원 제한을 명시해야 한 컨테이너가 서버 전체를 압박하는 상황을 줄일 수 있다. 스왑은 순간 피크의 안전장치일 뿐 지속적인 메모리 부족을 해결하는 증설 대체재가 아니다.</p>



<h2 class="wp-block-heading">업그레이드 신호는 네 가지로 확인한다</h2>



<ol class="wp-block-list">
<li><strong>피크 메모리</strong>: 평균이 아니라 배포·백업·트래픽 피크 시간의 사용량을 본다.</li>



<li><strong>OOM 기록</strong>: <code>journalctl -k</code>와 애플리케이션 로그에서 강제 종료 흔적을 찾는다.</li>



<li><strong>스왑 대기</strong>: 스왑 사용이 계속 늘고 응답 지연이 함께 발생하면 메모리를 올리거나 프로세스를 분리한다.</li>



<li><strong>디스크 증가량</strong>: 로그, DB, Docker 이미지가 차지하는 공간과 백업 보존 기간을 계산한다.</li>
</ol>



<p>간단한 시작 명령은 <code>free -h</code>, <code>docker stats</code>, <code>df -h</code>, <code>journalctl -k</code>다. 7일 이상 평일과 주말, 배포 시점을 모두 포함해 본 뒤 판단하는 편이 낫다. 평균 메모리만 보고 증설하면 OOM을 놓치고, 순간 피크만 보고 증설하면 비용을 낭비할 수 있다.</p>



<h2 class="wp-block-heading">비용보다 먼저 확인할 운영·보안 체크리스트</h2>



<ul class="wp-block-list">
<li>SSH 비밀번호 로그인을 끄고 키 기반 로그인과 방화벽을 설정한다.</li>



<li>운영 데이터는 Docker 이미지가 아니라 볼륨에 분리하고 별도 위치에 백업한다.</li>



<li>백업 파일 생성뿐 아니라 새 인스턴스에서 복구되는지 주기적으로 확인한다.</li>



<li>자동 보안 업데이트의 적용 범위와 재부팅 정책을 정한다.</li>



<li>메모리, 디스크, HTTP 상태, 인증서 만료 알림을 서버 밖에서 받는다.</li>



<li>수직 증설 전에 앱·DB·빌드 작업을 서로 분리할 가치가 있는지 비교한다.</li>
</ul>



<p>AI 에이전트 서버를 직접 구성하려면 <a href="https://blog.kwt.co.kr/openclaw-install-guide-mac-mini-ai-agent-server/">맥미니 OpenClaw 설치 가이드</a>를 함께 볼 수 있다. 외부 LLM 호출의 비용과 장애를 한곳에서 관리하려면 <a href="https://blog.kwt.co.kr/ai-gateway-cloudflare-litellm-guide/">Cloudflare AI Gateway와 LiteLLM 비교</a>, 운영 지표 설계가 필요하면 <a href="https://blog.kwt.co.kr/ai-agent-observability-tools-comparison/">AI 에이전트 관측 도구 비교</a>가 이어진다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">개인 WordPress는 1GB VPS로 충분할까?</h3>



<p>캐시가 잘 작동하고 플러그인이 가벼우며 트래픽이 작다면 가능하다. 그러나 DB, PHP, 백업 압축이 같은 서버에서 겹치므로 2GB가 운영 여유를 확보하기 쉽다. 1GB를 쓴다면 OOM 기록과 스왑 대기를 반드시 확인해야 한다.</p>



<h3 class="wp-block-heading">처음부터 4GB를 사는 편이 안전하지 않을까?</h3>



<p>장애 비용이 크거나 여러 서비스를 한 번에 올린다면 4GB가 합리적이다. 단일 개인 앱이라면 2GB에서 측정한 뒤 올리는 편이 3년 누적 비용을 줄일 수 있다. 공급자가 지원하는 스냅샷과 사양 변경 절차도 미리 확인해야 한다.</p>



<h3 class="wp-block-heading">스왑을 크게 만들면 RAM을 늘리지 않아도 될까?</h3>



<p>아니다. 스왑은 짧은 피크에서 즉시 종료되는 상황을 줄일 수 있지만 디스크 접근은 RAM보다 느리다. 지속적으로 스왑을 쓰고 지연이 발생하면 메모리를 늘리거나 서비스를 분리해야 한다.</p>



<h3 class="wp-block-heading">VPS 비용 비교에서 빠뜨리기 쉬운 항목은 무엇일까?</h3>



<p>세금, 자동 백업, 스냅샷, 추가 블록 스토리지, 공인 IPv4, 초과 트래픽, 외부 모니터링 비용이다. 월 인스턴스 가격만 비교하지 말고 복구 가능한 백업까지 포함한 총비용을 계산해야 한다.</p>



<h2 class="wp-block-heading">참고 자료</h2>



<ul class="wp-block-list">
<li><a href="https://aws.amazon.com/lightsail/pricing/" target="_blank" rel="noreferrer noopener">AWS Lightsail Pricing</a></li>



<li><a href="https://www.digitalocean.com/pricing/droplets" target="_blank" rel="noreferrer noopener">DigitalOcean Droplet Pricing</a></li>



<li><a href="https://docs.docker.com/engine/containers/resource_constraints/" target="_blank" rel="noreferrer noopener">Docker Docs: Resource constraints</a></li>



<li><a href="https://docs.docker.com/engine/storage/volumes/" target="_blank" rel="noreferrer noopener">Docker Docs: Volumes</a></li>



<li><a href="https://developer.wordpress.org/advanced-administration/server/web-server/" target="_blank" rel="noreferrer noopener">WordPress Developer Resources: Web servers</a></li>
</ul>



<p><em>가격 확인일: 2026년 8월 22일. 공급자 가격, 환율, 세금, 제공 사양은 이후 바뀔 수 있다.</em></p>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2800"
					data-ulike-nonce="c4a795643a"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2800"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/">개인 서비스 VPS 사양 선택법: 1GB·2GB·4GB 비용과 운영 기준</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/vps-sizing-guide-1gb-2gb-4gb/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DDR4에서 DDR5로 업그레이드할 가치가 있을까? 비용·성능·교체 기준</title>
		<link>https://blog.kwt.co.kr/ddr4-to-ddr5-upgrade-guide-2026/</link>
					<comments>https://blog.kwt.co.kr/ddr4-to-ddr5-upgrade-guide-2026/#respond</comments>
		
		<dc:creator><![CDATA[시간 조절자]]></dc:creator>
		<pubDate>Thu, 20 Aug 2026 00:29:35 +0000</pubDate>
				<category><![CDATA[기술]]></category>
		<category><![CDATA[DDR4]]></category>
		<category><![CDATA[DDR5]]></category>
		<category><![CDATA[PC 메모리]]></category>
		<category><![CDATA[RAM 업그레이드]]></category>
		<guid isPermaLink="false">https://blog.kwt.co.kr/ddr4-to-ddr5-upgrade-guide-2026/</guid>

					<description><![CDATA[<p>DDR4에서 DDR5로 바꿀 때 RAM 가격만 보면 안 된다. 게임·개발·영상 작업별 성능 차이와 메인보드·CPU 교체비, 플랫폼 호환성, 2-DIMM 구성 기준을 정리했다.</p>
<p>The post <a href="https://blog.kwt.co.kr/ddr4-to-ddr5-upgrade-guide-2026/">DDR4에서 DDR5로 업그레이드할 가치가 있을까? 비용·성능·교체 기준</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>DDR4 시스템을 쓰고 있다는 이유만으로 DDR5로 즉시 바꿀 필요는 없다. <strong>CPU와 메인보드까지 교체할 시점이라면 DDR5가 맞지만, 게임·사무용 PC에서 메모리만 바꾸기 위해 플랫폼 전체를 교체하는 것은 비용 대비 효과가 작다.</strong> DDR5의 장점은 모든 작업에서 같은 성능 향상을 내는 것이 아니라 높은 메모리 대역폭을 활용하는 일부 작업과 앞으로의 플랫폼 호환성에 있다.</p>



<div class="wp-block-group summary-box has-border-color has-background" style="border-color:#dbeafe;border-width:1px;background-color:#eff6ff;margin-top:24px;margin-bottom:24px;padding-top:18px;padding-right:20px;padding-bottom:18px;padding-left:20px"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h3 class="wp-block-heading">핵심 요약</h3>



<ul class="wp-block-list">
<li>DDR4와 DDR5는 슬롯 구조와 전기적 규격이 달라 서로 꽂아 쓸 수 없다.</li>



<li>기존 DDR4 PC에서 DDR5를 사용하려면 최소 메인보드, 경우에 따라 CPU까지 교체해야 한다.</li>



<li>Tom’s Hardware 테스트에서는 좋은 DDR4와 DDR5의 게임 차이가 약 2%였지만 Lightroom 28%, 압축 작업 46%처럼 작업별 편차가 컸다.</li>



<li>새 PC를 조립하거나 AM5·Core Ultra 데스크톱 플랫폼으로 이동한다면 DDR5를 선택하는 편이 합리적이다.</li>



<li>업그레이드 전 메인보드 메모리 지원 목록(QVL), 최대 용량, DIMM 개수별 지원 속도를 확인해야 한다.</li>
</ul>
</div></div>



<h2 class="wp-block-heading">DDR4에서 DDR5로 바꾸면 무엇이 달라질까</h2>



<p>DDR5는 DDR4보다 높은 전송률과 더 큰 모듈 용량으로 확장하기 유리하다. 그러나 숫자가 높다고 모든 프로그램이 그 대역폭을 사용하는 것은 아니다. CPU 캐시와 GPU가 병목인 작업은 메모리를 바꿔도 차이가 작고, 대용량 데이터를 연속 처리하거나 압축·과학 계산을 수행하는 작업은 차이가 커질 수 있다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>비교 항목</th><th>DDR4 유지가 유리한 경우</th><th>DDR5 전환이 유리한 경우</th></tr></thead><tbody><tr><td>PC 상태</td><td>현재 CPU·메인보드 성능이 충분함</td><td>CPU·메인보드도 교체할 예정</td></tr><tr><td>주요 작업</td><td>웹·문서·일반 게임·가벼운 개발</td><td>압축·대규모 데이터·일부 제작 작업</td></tr><tr><td>예산</td><td>그래픽카드·SSD·용량 증설이 우선</td><td>새 플랫폼 비용을 이미 편성함</td></tr><tr><td>확장성</td><td>현재 용량으로 2~3년 충분함</td><td>64GB 이상 또는 향후 재사용을 고려함</td></tr></tbody></table></figure>



<p>DDR5는 지연시간이 무조건 짧은 규격도 아니다. 초기 DDR5나 느슨한 타이밍의 제품은 잘 튜닝된 DDR4보다 지연시간이 길 수 있다. 따라서 DDR5-6000처럼 전송률만 볼 것이 아니라 CL 타이밍, CPU 메모리 컨트롤러, 메인보드 안정성을 함께 봐야 한다.</p>



<h2 class="wp-block-heading">실제 성능 차이는 2%에서 46%까지 벌어진다</h2>



<p>Tom’s Hardware의 DDR4·DDR5 비교에서 좋은 DDR4와 DDR5의 게임 성능 차이는 약 2%였다. Microsoft Office는 테스트한 최고·최저 구성 사이에서도 약 4%, Adobe Premiere는 약 3%였다. 반면 Adobe Lightroom은 28%, 특정 압축 작업은 46% 차이가 났다.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1035" height="600" src="https://blog.kwt.co.kr/wp-content/uploads/2026/08/ddr4-ddr5-performance-by-workload.png" alt="DDR4와 DDR5의 작업별 성능 차이" class="wp-image-2794" style="width:500px;height:auto"/><figcaption class="wp-element-caption">DDR5 성능 차이는 작업에 따라 크게 달라진다<br>출처: Tom’s Hardware DDR5 vs DDR4 테스트</figcaption></figure></div>


<p>다만 이 수치를 “DDR5가 항상 46% 빠르다”는 의미로 해석하면 안 된다. 게임은 DDR4-3200 C15와 DDR5-6400 C36, Lightroom은 DDR4-4000 C16과 DDR5-6400 C36, 압축은 DDR4-4000 C16과 DDR5-4800 C40처럼 항목별 비교 구성이 다르다. CPU·메모리 속도·타이밍·소프트웨어 버전에 따라 결과도 달라진다. 이 데이터가 보여주는 핵심은 평균값 하나가 아니라 <strong>작업별 편차가 매우 크다</strong>는 점이다.</p>



<h2 class="wp-block-heading">DDR5 업그레이드 비용은 RAM 가격만 보면 안 된다</h2>



<p>DDR4와 DDR5는 물리적으로 호환되지 않는다. DDR4 메인보드에 DDR5를 꽂거나 반대로 사용할 수 없다. 같은 CPU 세대가 DDR4·DDR5를 모두 지원하더라도 메인보드는 둘 중 하나의 규격만 지원하는 경우가 일반적이다.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>확인할 비용</th><th>이유</th></tr></thead><tbody><tr><td>DDR5 메모리</td><td>필요 용량과 속도, 2개 구성 여부를 결정해야 함</td></tr><tr><td>메인보드</td><td>DDR5 슬롯과 해당 CPU 소켓을 동시에 지원해야 함</td></tr><tr><td>CPU</td><td>현재 CPU가 새 DDR5 보드와 호환되지 않을 수 있음</td></tr><tr><td>CPU 쿨러</td><td>소켓 변경 시 브래킷 또는 쿨러 교체가 필요할 수 있음</td></tr><tr><td>재설치·작업 시간</td><td>BIOS 설정, 안정화 테스트, 암호화 키 확인 등이 필요함</td></tr></tbody></table></figure>



<p>그래서 “DDR4 32GB를 DDR5 32GB로 바꾸면 얼마나 빨라질까”보다 “플랫폼 전체 교체 비용을 지불할 만큼 현재 CPU가 부족한가”를 먼저 물어야 한다. 현재 PC가 GPU 병목인 게임용이라면 같은 예산을 그래픽카드에 쓰는 편이 체감이 클 수 있다. 메모리 부족으로 스왑이 발생한다면 DDR 세대 변경보다 DDR4 용량을 16GB에서 32GB 또는 64GB로 늘리는 편이 더 효과적일 수 있다.</p>



<h2 class="wp-block-heading">새 플랫폼이라면 DDR5를 선택하는 것이 맞다</h2>



<p>새 PC를 조립하거나 CPU·메인보드를 함께 바꿀 예정이라면 DDR5가 기본 선택이다. AMD Ryzen 7 9700X 공식 사양은 시스템 메모리 유형을 DDR5로 명시한다. 같은 페이지에서 2개 DIMM 구성은 DDR5-5600, 4개 DIMM 구성은 DDR5-3600까지로 표기돼 있다. 고용량을 위해 슬롯 네 개를 모두 채우면 공식 지원 속도가 내려갈 수 있다는 뜻이다.</p>



<p>Intel도 Core Ultra 200S 데스크톱 플랫폼에서 DDR5를 사용한다. 반면 일부 이전 Intel 플랫폼은 CPU가 DDR4와 DDR5를 모두 지원했지만 실제 사용할 규격은 메인보드가 결정했다. CPU 이름만 보고 메모리를 주문하지 말고, 메인보드 모델의 메모리 규격과 QVL을 확인해야 한다.</p>



<div class="wp-block-group has-border-color has-background" style="border-color:#fde68a;border-width:1px;background-color:#fffbeb;padding-top:16px;padding-right:18px;padding-bottom:16px;padding-left:18px"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<p><strong>실무 팁:</strong> 고클럭 DDR5를 안정적으로 쓰려면 처음부터 2개 DIMM으로 필요한 용량을 맞추는 편이 유리하다. 16GB 4개보다 32GB 2개가 메모리 컨트롤러 부담과 향후 증설 측면에서 나을 수 있다. 단, 최종 선택은 CPU·메인보드 QVL과 공식 지원표를 기준으로 해야 한다.</p>
</div></div>



<h2 class="wp-block-heading">사용 목적별 결론</h2>



<h3 class="wp-block-heading">게임용 PC</h3>



<p>현재 DDR4 시스템의 CPU가 충분하고 그래픽카드 사용률이 높은 게임을 한다면 유지해도 된다. 메모리 세대만 바꾸기 위해 메인보드와 CPU까지 교체하는 것은 비효율적이다. CPU 병목이 뚜렷해 플랫폼을 교체할 때 DDR5로 넘어가는 것이 자연스럽다.</p>



<h3 class="wp-block-heading">개발·Docker·가상머신</h3>



<p>전송률보다 총용량 부족이 먼저 문제 되는 경우가 많다. 빌드, IDE, 브라우저, 컨테이너를 동시에 띄웠을 때 메모리가 부족하다면 DDR4 64GB 증설이 플랫폼 교체보다 경제적일 수 있다. 새 PC를 구성한다면 32GB 2개처럼 2-DIMM 구성을 우선 검토한다. 구체적인 용량 판단은 <a href="https://blog.kwt.co.kr/ai-development-ram-guide-2026/">AI 개발용 RAM 32GB·64GB·96GB·128GB 가이드</a>에서 확인할 수 있다.</p>



<h3 class="wp-block-heading">로컬 LLM·대용량 데이터</h3>



<p>로컬 LLM은 모델 파일과 KV 캐시가 메모리에 들어가는지가 우선이다. DDR5가 빨라도 필요한 모델이 메모리에 들어가지 않으면 실행할 수 없다. 세대보다 용량을 먼저 계산하고, 그다음 대역폭을 판단해야 한다. 모델별 계산은 <a href="https://blog.kwt.co.kr/local-llm-memory-ram-vram-guide/">로컬 LLM 메모리 계산법</a>을 참고하면 된다.</p>



<h3 class="wp-block-heading">영상·사진·압축 작업</h3>



<p>Lightroom, 압축, 과학 계산처럼 메모리 대역폭 영향을 크게 받는 작업은 DDR5 전환 효과를 확인할 가치가 있다. 다만 프로그램마다 차이가 크므로 자신의 앱과 CPU를 사용한 벤치마크를 찾아야 한다. Premiere처럼 차이가 작게 나타난 작업도 있기 때문이다.</p>



<h2 class="wp-block-heading">업그레이드 전 체크리스트</h2>



<ol class="wp-block-list">
<li><strong>현재 병목 확인:</strong> 작업 중 메모리 사용량, 스왑, CPU·GPU 사용률을 확인한다.</li>



<li><strong>메인보드 규격 확인:</strong> DDR4·DDR5 중 어떤 슬롯인지, 최대 용량과 QVL을 확인한다.</li>



<li><strong>전체 교체비 계산:</strong> RAM뿐 아니라 메인보드·CPU·쿨러 비용을 합산한다.</li>



<li><strong>2-DIMM 우선 검토:</strong> 목표 용량을 가능한 한 두 개 모듈로 구성하고 공식 지원 속도를 확인한다.</li>



<li><strong>가격 추이 확인:</strong> 급등기에는 플랫폼을 서둘러 바꾸지 말고 제품별 가격과 재고를 비교한다.</li>
</ol>



<p>현재 가격 흐름은 <a href="https://blog.kwt.co.kr/ram-price-history-chart-sites/">램 가격 변동 그래프 보는 곳</a>에서 확인할 수 있고, 구매 시점 판단은 <a href="https://blog.kwt.co.kr/ddr5-ram-buying-timing-2026/">DDR5 구매 타이밍 체크리스트</a>에 정리돼 있다.</p>



<h2 class="wp-block-heading">FAQ</h2>



<h3 class="wp-block-heading">DDR4 메인보드에 DDR5를 꽂을 수 있나?</h3>



<p>꽂을 수 없다. 노치 위치와 전기적 규격이 달라 물리적으로 호환되지 않는다. 억지로 장착하면 부품이 손상될 수 있다.</p>



<h3 class="wp-block-heading">DDR5로 바꾸면 게임 프레임이 크게 오르나?</h3>



<p>항상 그렇지는 않다. 테스트 환경에 따라 다르지만 좋은 DDR4와 DDR5 사이의 차이가 몇 퍼센트에 그치는 게임도 많다. GPU 병목이라면 체감 차이는 더 작을 수 있다.</p>



<h3 class="wp-block-heading">DDR4 용량을 늘리는 것과 DDR5로 바꾸는 것 중 무엇이 우선인가?</h3>



<p>현재 메모리가 부족해 스왑이 발생한다면 용량 증설이 우선이다. DDR4 16GB에서 32GB로 늘리는 변화가, 용량은 그대로 두고 DDR5로 플랫폼을 바꾸는 것보다 체감이 클 수 있다.</p>



<h3 class="wp-block-heading">DDR5 4개를 꽂으면 더 빠른가?</h3>



<p>대개 그렇지 않다. 4-DIMM 구성은 메모리 컨트롤러 부담이 커져 지원 속도가 낮아질 수 있다. 고클럭과 안정성을 우선한다면 2-DIMM 구성을 먼저 검토해야 한다.</p>



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



<p><strong>기존 DDR4 PC가 충분히 빠르다면 유지하고, CPU·메인보드 교체 시점에 DDR5로 넘어가는 것이 가장 합리적이다.</strong> DDR5는 미래 플랫폼과 고대역폭 작업에 유리하지만, 게임과 일반 사무에서는 플랫폼 전체 교체비를 정당화할 만큼 차이가 크지 않을 수 있다. 세대 이름보다 현재 병목, 필요한 용량, 전체 교체비를 기준으로 결정해야 한다.</p>



<h2 class="wp-block-heading">참고자료</h2>



<ul class="wp-block-list">
<li><a href="https://www.tomshardware.com/features/ddr5-vs-ddr4-is-it-time-to-upgrade-your-ram" target="_blank" rel="noopener noreferrer">Tom’s Hardware, DDR5 vs DDR4: Is It Time To Upgrade Your RAM?</a></li>



<li><a href="https://www.amd.com/en/products/processors/desktops/ryzen/9000-series/amd-ryzen-7-9700x.html" target="_blank" rel="noopener noreferrer">AMD Ryzen 7 9700X 공식 사양</a></li>



<li><a href="https://www.intel.com/content/www/us/en/products/sku/241067/intel-core-ultra-7-processor-265k-30m-cache-up-to-5-50-ghz/specifications.html" target="_blank" rel="noopener noreferrer">Intel Core Ultra 7 265K 공식 사양</a></li>



<li><a href="https://www.crucial.com/articles/about-memory/difference-between-ddr4-and-ddr5" target="_blank" rel="noopener noreferrer">Crucial, DDR4와 DDR5 차이</a></li>
</ul>

		<div class="wpulike wpulike-robeen " ><div class="wp_ulike_general_class wp_ulike_is_not_liked"><button type="button"
					aria-label="Like Button"
					data-ulike-id="2795"
					data-ulike-nonce="12d8e84456"
					data-ulike-type="post"
					data-ulike-template="wpulike-robeen"
					data-ulike-display-likers=""
					data-ulike-likers-style="popover"
					class="wp_ulike_btn wp_ulike_put_image wp_post_btn_2795"></button><span class="count-box wp_ulike_counter_up" data-ulike-counter-value="0"></span>			</div></div>
	<p>The post <a href="https://blog.kwt.co.kr/ddr4-to-ddr5-upgrade-guide-2026/">DDR4에서 DDR5로 업그레이드할 가치가 있을까? 비용·성능·교체 기준</a> appeared first on <a href="https://blog.kwt.co.kr"></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.kwt.co.kr/ddr4-to-ddr5-upgrade-guide-2026/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
