-
내 코드 위키를 남의 코딩 에이전트가 쓰게 하려면 — SKILL.md 한 장으론 부족하다IT 2026. 6. 5. 22:00
코드를 읽어 위키를 LLM이 생성하는 시스템을 혼자 굴릴 때는 한 가지 트릭으로 충분했다. "이 위키를 이렇게 써라"라는 운영 규칙을
SKILL.md한 파일에 모아 두고, 그게 모든 위키 세션의 system prompt에 자동으로 끼워 넣어지게 하는 것이다. AI 에이전트는 매 세션이 새로 시작이라 위키 사용법을 매번 추측하는데, 그 한 파일이 추측을 contract로 대체해 줬다.그런데 이 위키를 나 혼자가 아니라 외부의 수많은 사람에게 배포하기로 하면서 질문이 생겼다. 딥 위키를 나눠 줄 때 그 SKILL.md도 같이 배포해야 하나? 그리고 그것만으로 충분한가? 직관적으로는 "규칙 파일을 같이 주면 남의 에이전트도 똑같이 일관되게 쓰겠지"였다. 하지만 그 직관은 내 기계에서만 성립하던 전제 위에 서 있었다.
결론부터 적으면 이렇다. 계약 파일(SKILL.md)은 같이 배포해야 하지만, 그것만으로는 작동하지 않는다. 남의 에이전트는 (1) 그 계약을 받아 적용하는 통로가 나와 다르고, (2) 애초에 위키 본문에 접근할 길이 없다. 이 글은 그 두 결함을 짚고, 딥위키 커뮤니티가 이미 어떻게 풀었는지(스포일러: 파일이 아니라 MCP 서버다)를 따라가며 "배포 가능한 위키"의 구조를 정리한다.
1. 혼자 쓸 때 성립했던 세 전제 — 그리고 배포에서 깨지는 지점
SKILL.md 한 장으로 충분했던 건, 사실 내 환경에 보이지 않는 전제 세 개가 깔려 있었기 때문이다.
- 전제 ① — 계약이 자동으로 들어온다. 내 챗 모달은 위키 질문이 들어오면 system prompt 맨 앞에 SKILL.md를 무조건 prepend했다. 에이전트가 "이 스킬을 쓸까?"를 결정할 필요가 없었다.
- 전제 ② — 위키 본문에 접근할 검색기가 이미 있다. 내 기계엔 Qdrant RAG가 위키를 인덱싱해 두었고, 질문마다 관련 청크를 꺼내 줬다. SKILL.md의 규칙들("RAG 첫 청크에 묶이지 마라", "tier=llm 청크는 신뢰를 낮춰 표시하라")은 그 검색기가 있다는 걸 당연히 전제했다.
- 전제 ③ — 위키를 볼 뷰어가 있다. 로컬 SPA가 떠 있어서 사람도, 링크도 위키 페이지를 열 수 있었다.
남에게 파일 하나를 건넨다고 이 셋 중 어느 것도 따라가지 않는다. 상대는 Claude Code가 아니라 Cursor나 Copilot, Codex를 쓸 수 있고(전제 ① 붕괴), 내 Qdrant 인덱스도 로컬 SPA도 그의 기계엔 없다(전제 ②③ 붕괴). 그 상태에서 SKILL.md만 받은 에이전트는 "file:line을 인용하라"는 규칙은 알지만 인용할 위키 본문 자체가 손에 없다. 계약서는 있는데 계약이 가리키는 대상이 없는 셈이다.
2. 커뮤니티는 이미 답을 정했다 — 파일이 아니라 MCP 엔드포인트
"코드 위키를 코딩 에이전트가 쓰게 한다"는 문제는 나만의 것이 아니다. 이 분야를 사실상 정의한 건 Cognition(자율 코딩 에이전트 Devin을 만든 팀)의 DeepWiki다. GitHub 저장소를 통째로 구조화된 위키로 바꿔 주는 서비스인데, 흥미로운 건 "코딩 에이전트가 이걸 어떻게 쓰느냐"에 대한 그들의 답이다. 문서 페이지를 다운로드시키는 게 아니라 — MCP(Model Context Protocol) 서버를 띄웠다. 에이전트가 코딩 도구 안에서 위키를 직접 질의하도록.
그 DeepWiki MCP 서버가 노출하는 도구는 단 세 개다.
read_wiki_structure— 그 저장소 위키의 목차(어떤 페이지·주제가 있는지). 에이전트가 먼저 지형을 파악한다.read_wiki_contents— 특정 페이지의 본문 전체. 자동 코드 리뷰·요약에 쓴다.ask_question— 자연어 질문을 던지면 코드에 grounding된 답을 받는다.
로그인도 인증도 없이 공개 저장소면 바로 붙는다(
mcp.deepwiki.com). 실제 사용 사례도 또렷하다 — Andrej Karpathy는 DeepWiki MCP를 자기 코딩 에이전트에 물려서, 외부 라이브러리가 특정 학습 기능을 어떻게 구현했는지 위키로 파악하고 핵심 로직만 뽑아 의존성 없는 독립 모듈로 다시 썼다. 수천 줄의 라이브러리 소스를 직접 안 읽고. 그리고 사내·비공개 저장소를 위한 자가 호스팅 버전도 커뮤니티에 있다 —deepwiki-open,OpenDeepWiki같은. 코드를 외부 서버로 보내지 않고 같은 위키 경험을 띄운다.다이어그램 설명. 왼쪽은 내가 처음 떠올린 "SKILL.md를 같이 준다"는 배포다 — 계약은 전달되지만, 그 계약이 가리키는 위키 본문에 닿을 통로가 남의 기계엔 없다. 규칙은 작동할 대상을 못 찾고 빈 참조로 떠 버린다. 오른쪽이 커뮤니티가 수렴한 방식이다. 위키를 "문서"가 아니라 질의 가능한 엔드포인트(MCP 서버)로 배포한다. 에이전트는 목차를 받고(
read_wiki_structure), 본문을 열고(read_wiki_contents), 자연어로 묻는다(ask_question). 위키를 "배포한다"는 건 파일을 건네는 게 아니라 에이전트가 닿을 수 있는 표면을 띄우는 것이라는 발상의 전환이다.3. 그래서 SKILL.md만으론 부족하다 — 접근 층과 계약 층
여기서 위키 배포가 두 개의 분리된 층으로 쪼개진다.
- 접근 층 (access) — 에이전트가 위키를 읽을 수단. 곧 MCP 서버다. 이게 없으면 아무 규칙도 적용할 대상이 없다.
- 계약 층 (contract) — 읽은 걸 어떻게 쓸지의 규칙. 곧 SKILL.md다. 이게 없으면 에이전트가 위키를 막 쓴다(첫 청크만 보거나, 추측을 사실로 단언하거나).
둘은 어느 하나로 다른 하나를 대체할 수 없다. 계약만 주면 읽을 게 없고, 접근만 주면 규율 없이 쓴다. 그런데 내 SKILL.md의 규칙들은 한술 더 떠 접근 층의 구체적 형태까지 전제하고 있었다. "tier=llm 청크는 신뢰를 낮춰 표시하라"는 규칙은, 응답에
tier라는 메타가 실려 온다는 가정 위에 선다. 내 Qdrant 인덱스는 그걸 페이로드로 달아 줬지만, 남의 에이전트가 본문 텍스트만 받으면tier는 어디에도 없다. 규칙이 빈 참조가 된다.여기서 grounding(그라운딩, 근거 대기)이라는 말이 계속 나올 것인데, 이건 메타 정보의 이름이 아니라 하나의 원칙의 이름이다. grounding은 LLM이 내놓는 주장을 "검증 가능한 출처에 묶는 것"을 뜻한다 — 위키의 모든 서술 문장이 허공의 추측이 아니라 실제 코드의 어느 줄에서 나왔는지를 가리키게 만드는 것이다. 비유하자면 주장을 땅(코드)에 말뚝 박아 고정하는(ground) 일이다. 그래서 grounding은 "근거에 묶는다"는 행위·원칙이고, 그 묶음은 두 군데에 나뉘어 실린다 — 본문 산문 안에 인라인으로 박힌 anchor, 그리고 본문이 스스로는 못 드러내는 신뢰 등급을 담는 메타 필드(
tier)다.anchor(file:line) — 주장을 코드에 묶는 "말뚝". 그런데 이건 본문 산문 안에 인라인으로 박혀 있다(예: "handle_chat—stage_b.py:148"). 그래서 별도 메타 필드가 아니라 본문(body)에 그대로 실려 온다.tier— 이 문장이 코드에서 결정적으로 추출된 것인지(derived), LLM이 추정한 것인지(llm-enriched)의 신뢰 등급. 본문이 스스로는 못 드러내는 건 이것뿐이다 — 그래서 따로 메타로 빼서 실어야 하는 건 사실상tier하나다.
그래서 배포의 핵심은 "MCP가 본문 +
tier를 함께 반환하는 것"으로 좁혀진다.file:line좌표는 본문에 이미 들어 있으니body로 충분하고, 본문이 못 드러내는 신뢰 등급만tier로 따로 붙이면 된다. 그러면 계약 규칙 둘 — "좌표를 인용하라"(본문 anchor로 충족), "추정이면 신뢰를 낮춰라"(tier로 충족) — 이 모두 적용할 데이터를 갖는다.# mcp_server.py — read_wiki_contents가 본문과 함께 신뢰 등급(tier)을 반환한다 # (Cognition DeepWiki MCP의 read_wiki_contents를 우리 위키 스키마에 맞춰 미러링) @mcp.tool() def read_wiki_contents(repo: str, page: str) -> dict: """위키 한 페이지의 본문 + tier(신뢰 등급)를 반환한다. file:line anchor는 본문 산문 안에 이미 인라인으로 적혀 있어 body로 따라온다. 본문이 스스로 못 드러내는 건 'tier'(결정적 추출인지 LLM 추정인지)뿐 — 그래서 따로 빼서 실어야 하는 메타는 그것 하나다. """ md = _load_page(repo, page) # wiki-output/<repo>/<page>.md fm = _parse_frontmatter(md) # frontmatter: tier, repo_url ... return { "repo": repo, "page": page, "tier": fm["tier"], # derived | llm-enriched | human-pinned ... "body": _strip_frontmatter(md), # file:line anchor가 본문에 그대로 들어 있다 }코드 설명. 반환값은
body와tier둘뿐이다.file:line좌표(anchor)는 본문 산문에 이미 박혀 있으니body에 자연히 딸려 오고, 따로 빼야 할 건 본문이 못 드러내는 신뢰 등급tier하나다. 그러면 남의 에이전트가 내 Qdrant·SPA를 한 줄도 안 갖고도, SKILL.md의 규칙("좌표를 인용하라"는 본문에서, "추정이면 신뢰를 낮춰라"는tier에서) 둘 다 적용할 재료를 손에 쥔다. 접근 층(MCP)이 계약 층(SKILL.md)이 필요로 하는 데이터를 실어 보내는 순간, 두 층이 맞물려 돌아간다. 즉 SKILL.md는 같이 배포하되, 그것이 전제하는tier가 MCP 응답에 따라붙도록 함께 묶어야 한다.4. 계약을 어떤 파일에 담아 배포하나 — 이식성 함정
접근 층을 MCP로 풀었다면, 남은 건 계약 층을 "어느 파일 형식으로" 배포하느냐다. 여기에 내가 빠질 뻔한 함정이 있었다. 나는 "SKILL.md가 모든 세션의 system prompt에 자동 prepend된다"고 알고 있었는데, 그건 내 Claude Code 설정과 내 챗 모달의 동작이지 보편 사실이 아니었다. 2026년 현재 에이전트 instruction 파일은 형식마다 로딩 방식과 지원 도구가 제각각이다.
다이어그램 설명. 네 형식의 성격이 다 다르다.
CLAUDE.md는 매 세션 자동 로딩(always-on)이지만 Claude Code 전용이다 — 내가 의존하던 "자동 prepend"가 사실 이 칸이었다..cursorrules는 Cursor 전용 legacy.SKILL.md는 거의 모든 도구에서 돌지만 trigger 기반(on-demand) — 관련 요청이 와야 활성화되지, 무조건 prepend되는 게 아니다. 그리고AGENTS.md는 저장소 루트에 두면 매 턴 자동으로 들어가는 크로스툴 always-on 표준으로, 2025년 12월 Linux Foundation의 Agentic AI Foundation에 MCP와 나란히 편입돼 사실상 표준화 경쟁에서 이겼다(Claude Code의 네이티브 지원은 아직 feature request 단계). 결론: 남이 어떤 도구를 쓸지 모르는 배포 상황에서 "SKILL.md만 주면 자동으로 적용된다"는 건 성립하지 않는다.그래서 배포용 계약은 하나의 진본(source of truth)을 두고, 도구별 파일은 그걸 참조만 하게 짠다. 같은 13개 규칙을 CLAUDE.md·SKILL.md·.cursorrules에 네 벌 복붙하는 건 동기화 지옥이다. 크로스툴 always-on인 AGENTS.md를 진본으로 삼는 게 2026년의 합의에 가깝다.
# AGENTS.md — 크로스툴 진본 (모든 에이전트가 매 턴 읽는 한 곳) ## 이 코드 위키를 쓰는 법 - 코드 질문은 먼저 `read_wiki_structure`로 목차를 받고, 관련 페이지를 `read_wiki_contents`로 연다. - 답에 코드를 인용하면 본문에 적힌 `file:line`을 그대로 박는다. - `tier`가 `llm-enriched`면 "추정"이라고 표시한다. - 위키와 실제 코드가 어긋나면 코드를 우선한다. 전체 규칙(13개)과 그 근거 → SKILL.md / docs/adr/ 참조.코드 설명. AGENTS.md엔 위키 사용의 핵심 규칙 몇 줄과 MCP 도구 호출 순서만 둔다. 그러면 Cursor·Copilot·Codex 사용자는 별도 설정 없이 이 한 파일로 동일한 사용 패턴을 얻는다. 깊은 규칙 전문(13개)과 결정 근거는 SKILL.md와 ADR로 미루고 AGENTS.md는 "여기 더 있다"고 가리키기만 한다 — always-on 파일이 너무 길면 매 턴 토큰을 잡아먹기 때문이다. 즉 AGENTS.md(얇은 always-on 진본) + SKILL.md(두꺼운 on-demand 상세) + MCP(접근)의 역할 분담이다.
5. 배포 가능한 deep-wiki의 최소 구성
처음 질문 — "SKILL.md도 같이 배포해야 하나? 그것만으로 충분한가?" — 에 이제 정확히 답할 수 있다. 같이 배포한다. 하지만 그것만으론 부족하다. 혼자 쓰던 위키를 남의 코딩 에이전트가 잘 쓰게 하려면 세 가지가 함께 가야 한다.
- ① 접근 층 — MCP 서버. 위키를 파일이 아니라 질의 가능한 엔드포인트로 노출한다(
read_wiki_structure/read_wiki_contents/ask_question). 공개 저장소면 호스팅, 비공개면 자가 호스팅(deepwiki-open류). 이게 빠지면 계약은 빈 참조다. - ② 계약 층 — 이식 가능한 instruction 파일. AGENTS.md를 얇은 진본으로 두고, SKILL.md가 상세를 받친다. "내 Claude Code가 자동 prepend해 준다"는 전제를 버리고, 남이 어떤 도구를 쓰든 닿는 형식으로 배포한다.
- ③ grounding이 응답에 따라붙게. 계약 규칙이 전제하는 신뢰 등급(
tier)을 MCP 응답에 실어, 규칙이 적용할 데이터를 함께 공급한다(file:lineanchor는 본문에 이미 들어 있어body로 따라온다). 내 RAG·뷰어를 안 가진 상대에게도 규칙이 작동하도록.
이 셋의 관계가 핵심이다 — 셋은 더하기가 아니라 곱하기다. 접근만 있고 계약이 없으면 에이전트가 위키를 막 쓰고, 계약만 있고 접근이 없으면 규칙이 헛돈다. 그리고 둘이 다 있어도 grounding 메타가 응답에 안 실리면 계약의 절반(신뢰·인용 규칙)이 죽는다. 딥위키 커뮤니티가 "예쁜 문서 사이트"를 넘어 MCP 서버로 수렴한 건, 바로 이 세 층을 한 표면에서 동시에 제공하기 때문이다.
6. 계약과 MCP를 따로 배포하나? — 한 서버에 같이 싣는다
여기서 자연스러운 의문이 든다. "그럼 MCP 서버는 호스팅하고, SKILL.md·AGENTS.md는 GitHub에 따로 올려서 두 군데서 배포해야 하나?" 그렇게 나눠 둘 수도 있지만, 더 깔끔한 답이 있다. MCP 서버가 계약을 직접 실어 나를 수 있다. 접근과 계약을 한 연결로 묶는 것이다.
MCP 프로토콜에는 서버가 클라이언트와 처음 연결(handshake)할 때 돌려주는
instructions라는 필드가 있다. "이 서버를 이렇게 써라"라는 사용 설명서를 문자열로 담는 자리인데, 많은 클라이언트가 이 문자열을 받아 LLM의 system prompt 앞에 그대로 끼워 넣는다(tool 스키마나 사용자 메시지보다 먼저). 즉 SKILL.md의 핵심 계약을 이instructions에 실으면, 에이전트가 MCP 서버에 붙는 순간 계약이 자동으로 따라온다 — 별도 파일을 내려받게 할 필요 없이.# mcp_server.py — 서버가 handshake 때 계약(SKILL.md 핵심)을 함께 건넨다 mcp = FastMCP( name="deep-wiki", # MCP 스펙의 instructions 필드. 클라이언트가 이 문자열을 system prompt에 주입한다. # → MCP에 연결하는 순간 계약이 따라오므로, 계약 파일을 따로 배포할 필요가 없다. instructions=Path("SKILL.md").read_text(encoding="utf-8"), ) # instructions가 특히 값진 건 'tool 설명만 봐선 안 보이는 도구 간 의존성'을 적을 때다: # "코드를 인용하기 전 read_wiki_contents를 먼저 호출하고, # 본문에 적힌 file:line을 답에 그대로 박아라. tier=llm-enriched면 추정으로 표시."코드 설명. 이렇게 하면 접근(MCP 도구)과 계약(
instructions)이 한 서버, 한 연결로 동시에 배포된다. 사용자는 MCP 엔드포인트 하나만 등록하면 위키를 읽을 수단과 쓰는 규칙을 같이 받는다.마무리 — 문서를 잘 쓰는 문제가 아니라, 표면을 주는 문제
혼자 쓰는 위키와 배포하는 위키의 차이는 "문서를 얼마나 잘 쓰느냐"가 아니었다. 내 SKILL.md는 그대로 좋은 계약서였다. 문제는 그 계약서가 내 기계에만 있던 통로(자동 prepend)와 검색기(RAG)와 뷰어 위에 조용히 얹혀 있었다는 것이다. 남에게 줄 때 그 받침대가 따라가지 않으니 계약서만 덩그러니 남았다.
그래서 배포의 본질은 문서가 아니라 에이전트가 닿을 수 있는 표면을 주는 것이다. 위키를 질의 가능한 MCP 엔드포인트로 띄우고(접근), 도구를 안 가리는 형식으로 계약을 싣고(이식성), 규칙이 먹을 메타를 응답에 함께 흘려보낸다(grounding). SKILL.md는 이 구조에서 여전히 필요하다 — 다만 그것은 접근 위에 얹는 계약이지, 접근 그 자체가 아니다. "위키를 배포한다"는 말을 "파일을 건넨다"가 아니라 "표면을 띄운다"로 바꿔 읽는 순간, 무엇을 더 만들어야 하는지가 분명해진다.
참고
- Cognition — The DeepWiki MCP Server: cognition.ai/blog/deepwiki-mcp-server
- Devin Docs — DeepWiki MCP: docs.devin.ai/work-with-devin/deepwiki-mcp
- 자가 호스팅 오픈소스 — deepwiki-open: github.com/AsyncFuncAI/deepwiki-open
- 크로스툴 표준 — AGENTS.md: agents.md
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
에이전트 루프의 파수꾼, 검증(Verification) — 행동의 결과를 평가하고 멈추는 법 (0) 2026.06.07 에이전트 루프의 실행력, 행동(Action) — 생각에서 변화로 나아가는 도구 호출 (0) 2026.06.07 에이전트 루프의 나침반, 계획(Planning) — 복잡함을 나눌 때 시작되는 문제 해결 (0) 2026.06.06 에이전트 루프의 첫 단추, 관찰(Observation) — 세상의 상태를 맥락으로 번역하기 (0) 2026.06.06 에이전트의 다섯 가지 본질 — 루프·도구·맥락·정지·신뢰 (0) 2026.06.06 생성된 위키 문서에서 틀린 줄을 발견했다 — 고치지 말고, 입력을 바꿔라 (0) 2026.06.05 같은 사실도 신뢰 레벨이 다르다 — 코드 위키의 Trust Gradient (0) 2026.06.04 불필요한 껍데기 걸러내기 — vulture를 이용한 데드 코드 탐지 및 지식 정제 (0) 2026.06.04 코드의 어두운 구석을 드러내기 — radon을 통한 순환 복잡도 지표 수집 (0) 2026.06.04 LSP를 메모리 안으로 — jedi를 통한 초고속 함수 단위 CALLS 그래프 구축 (0) 2026.06.03