블로그

Private 환경을 위한 DeepWiki 대안을 직접 설계한 이유

Public Repo만 지원하는 DeepWiki를 사내 레거시 환경에서 쓸 수 없어서 직접 만들었습니다. 코드베이스만 보는 것이 아니라 DB, GitHub, Jira, Confluence를 교차 검증해야 진짜 비즈니스 맥락을 잡을 수 있다는 게 핵심이었습니다.

AI Agent레거시 분석MCPFilesystem MCPGitHub MCPConfluence MCPMSSQLKafkaMermaidDeepWiki
LocalWiki — 코드베이스 자동 문서화 시스템
로컬 Private 레포를 분석하여 AI가 구조적 위키를 자동 생성하는 시스템
local-wiki.vercel.app

참고: 이 글은 실제 회사 프로젝트에서 설계한 내용을 개념 수준에서 재구성했습니다. 내부 코드와 데이터는 포함되지 않습니다.

왜 만들게 됐나

팀에 합류했을 때 가장 막막했던 건 코드 자체가 아니었습니다. 코드는 있었는데 그 코드가 왜 생겼는지를 아무도 알려줄 수 없는 상황이 문제였습니다.

  • Confluence 문서는 있는데 현재 코드와 맞지 않는 내용이 섞여 있었습니다
  • 초기 설계를 담당했던 분들은 이미 팀을 떠난 상태였습니다
  • Jira PR은 남아 있는데 코드 변경과 비즈니스 맥락이 연결이 안 됐습니다
  • 핵심 비즈니스 로직이 Stored Procedure 안에 있어서, 코드만 봐서는 실제 분기 조건을 알 수 없었습니다

특정 기능의 전체 흐름을 파악하려면, API가 어떤 Kafka 토픽으로 이어지고, 어떤 컨슈머가 처리하며, 마지막에 어떤 SP와 테이블을 건드리는지까지 직접 추적해야 했습니다. 이게 반복됐습니다. 사람이 바뀔 때마다, 기능을 새로 맡을 때마다.

DeepWiki를 쓰면 되지 않나 싶었는데 안 됐습니다. 분석 대상이 공개 레포가 아니라 사내 비공개 레포였고, 비즈니스 로직 상당 부분이 DB SP 안에 있었고, 변경 배경은 Jira와 Confluence에 흩어져 있었으니까요.

그래서 직접 만들기로 했습니다. 코드만 요약하는 도구가 아니라, DB, GitHub, Jira, Confluence를 함께 읽고 교차 검증해서 비즈니스 맥락을 복원하는 방향으로.


코드만 보면 알 수 없는 것들

코드베이스만 분석하면 다음 정도는 파악됩니다.

- 이 API가 어떤 파라미터를 받는지
- 이 함수가 어떤 클래스를 호출하는지
- 어떤 Kafka topic 이름이 코드에 등장하는지

하지만 코드만으로는 확인이 안 되는 게 있습니다.

- 이 Kafka 토픽에 어떤 비즈니스 이벤트가 담기는지
- 이 SP가 왜 이런 분기 조건을 가지는지
- 몇 년 전 특정 로직이 왜 변경됐는지
- 예외 처리가 어떤 운영 정책에서 나온 것인지

이 간극을 메우려면 여러 소스를 함께 봐야 합니다. 코드 + GitHub PR + Jira + Confluence + DB SP.

특히 SP 기반으로 비즈니스 로직을 운영하는 회사에서는 이 문제가 더 심합니다. 코드는 생각보다 쓸모가 없습니다. 코드에는 exec sp_CalculateSettlement @date = ? 한 줄만 있고, 실제 정산 로직, 분기 조건, 예외 처리는 전부 SP 안에 있습니다. 코드를 아무리 정독해도 비즈니스 흐름이 안 보이는 건 당연합니다. 이런 구조에서는 DB를 어떻게 읽을 것인지가 해결돼야 도구가 의미를 가집니다.


설계 원칙: 근거가 있는 문서

가장 중요하게 잡은 기준은 하나였습니다. 문서에 남는 주장마다 출처를 함께 기록한다.

"이 API는 정산 배치를 트리거합니다"라는 문장이 있다면, 그게 코드에서 확인한 사실인지, Confluence 정책 문서에서 온 건지, 여러 단서를 조합한 추론인지 구분해야 합니다. 그래야 읽는 사람이 어디까지를 사실로 보고, 어디부터를 추가 확인이 필요한 해석으로 볼지 판단할 수 있습니다.

타입 근거 사용 방식
code/config 실제 코드와 설정 파일 구현 사실 확인
wiki Confluence 설계·정책 문서 설계 의도와 운영 배경 확인
github PR, 커밋, 리뷰 코멘트 변경 시점과 변경 이유 추적
db 테이블, SP 정의, 의존성 DB 내부 로직 확인
inferred 여러 근거를 조합한 해석 확정 표현을 피하고 검토 대상으로 표시

탐색 순서가 있는 MCP 아키텍처

처음부터 DB를 넓게 조회하면 안 됩니다. 레거시 DB에는 테이블과 SP가 수백 개씩 있고, 운영 정책상 무작정 조회할 수 없습니다.

그래서 먼저 코드와 GitHub 히스토리에서 후보를 좁히고, 거기서 나온 테이블명과 SP명만 MSSQL에 확인하는 순서로 설계했습니다.

Filesystem MCPLocal Search(API, Consumer, SQL 호출부) GitHub MCPPR, Commit, CODEOWNERS(변경 맥락) 조회 대상 확정Table, SP 후보(불필요한 DB 탐색 방지) MSSQL MCPTargeted Query(SP 정의, 의존성 확인) Jira & Confluence MCP정책, 이슈, 운영 문서(비즈니스 배경) Code Sonar근거 대조 후 문서 생성

Filesystem MCP: 범위를 먼저 좁힌다

첫 단계는 로컬 워크스페이스 검색입니다. API path, Kafka topic명, Consumer 클래스, Repository 호출부, SQL mapper를 먼저 찾습니다. 정답을 바로 내는 게 아니라 조회 범위를 줄이는 게 목적입니다. RankingConsumer에서 특정 topic명과 SP 호출 흔적을 찾으면, 그 이름을 다음 단계의 탐색 키로 넘깁니다.

GitHub MCP: 왜 바뀌었는지

PR 제목과 본문, 리뷰 코멘트, 커밋 메시지, CODEOWNERS를 확인합니다. PR 설명이 잘 남아 있으면 비즈니스 맥락을 빠르게 잡을 수 있었고, 설명이 빈약한 경우엔 Jira나 Confluence를 병행해서 봐야 했습니다.

Jira & Confluence MCP: 정책과 의도

기획 의도, 정책 문서, QA 이슈, 운영 장애 리포트를 여기서 확인합니다. 다만 오래된 Confluence 문서가 최신 코드와 항상 일치하진 않았습니다. 설계 당시의 의도와 의사결정 배경으로는 유효하지만, 구현 사실은 반드시 코드와 DB에서 다시 검증해야 했습니다.

MSSQL MCP: SP 안의 비즈니스 로직

레거시 시스템에서 핵심 비즈니스 로직이 SP 안에 남아 있는 경우가 많았습니다. 애플리케이션 코드에서는 SP 호출만 보이고, 실제 분기 조건이나 데이터 변환 규칙은 DB를 직접 봐야 알 수 있었습니다. 앞 단계에서 식별한 SP명과 테이블명만 대상으로 한정해서 조회했습니다.

CREATE PROCEDURE CalculateAdBid
    @adId INT,
    @slotId INT
AS
BEGIN
    -- 실제 업무 규칙과 예외 처리가 이 안에 남아 있는 경우가 있었습니다.
END

정적 분석 엔진: LLM 없이 다이어그램을 만드는 이유

초기 버전에서는 코드를 LLM에 그대로 넘기고 다이어그램을 생성했는데, 문제가 있었습니다. 모델마다 결과가 달랐고, 같은 모델도 실행할 때마다 구조가 조금씩 달라졌습니다. 비용이 비싼 모델을 써야 그나마 일관성이 유지됐습니다.

그래서 방향을 바꿨습니다. 아키텍처 다이어그램은 LLM이 만들지 않고, 정적 분석 엔진이 코드를 직접 파싱해서 생성하도록 했습니다.

코드 파일들
    → ASTAnalyzer (tree-sitter로 클래스, 함수, import 추출)
    → CallGraph (Node/Edge 의존성 그래프 구성)
    → MermaidGen (degree 기반 top-N 필터링 → 다이어그램 생성)

tree-sitter를 쓰면 Python, TypeScript, Go, Java, Rust, Ruby, C#, PHP 등 8개 언어를 IDE나 언어 서버 없이 파싱할 수 있습니다. 어느 환경에서도 의존성 없이 바로 실행됩니다.

이렇게 하면 두 가지가 해결됩니다.

첫째, 다이어그램 품질이 모델 성능과 무관해집니다. 구조는 코드에서 직접 추출하기 때문에 어떤 LLM을 쓰든 동일합니다.

둘째, LLM이 글을 쓸 때 환각이 줄어듭니다. 각 페이지를 생성할 때 해당 파일들의 클래스, 함수, import, 의존성 요약을 프롬프트에 미리 넣어줍니다. "무엇에 대해 써야 하는지"를 코드 팩트로 못박으니, 모델이 없는 내용을 만들어낼 여지가 줄어듭니다. 저렴한 모델을 써도 문서 품질이 일정하게 유지되는 건 이 덕분입니다.

셋째, 다이어그램이 스파게티가 되지 않습니다. 코드베이스에 파일이 수백 개 있으면 그냥 CallGraph를 그리면 선이 수백 개 교차하는 읽을 수 없는 다이어그램이 나옵니다. MermaidGen에서 degree 기반 top-N 필터링을 적용해서, 연결이 많은 핵심 컴포넌트 위주로만 남깁니다. 디렉토리별 cluster 다이어그램으로 분류해서 전체 구조 다이어그램과 모듈별 다이어그램을 분리해 생성합니다. 실제로 읽을 수 있는 다이어그램이어야 문서로서 의미가 있습니다.


Agent를 17개로 나눈 이유

처음에는 하나의 Agent가 전체 분석을 담당하는 방식을 시도했습니다. 금방 한계가 왔습니다. 컨텍스트가 커지면서 앞 단계에서 수집한 정보가 뒤에서 무시되기 시작했고, 어느 단계에서 품질이 떨어지는지 추적하기 어려웠습니다.

수집 → 분석 → 작성 → 검증 → 발행 단계로 역할을 쪼갠 이유입니다.

입력 수집filesystem-source-scannerwiki-source-scannergithub-source-scanner 심층 분석bridge-analyzerdb-schema-analystintegration-flow-analystentity-lifecycle-analyst 문서 작성deep-analysis-writerbusiness-workflow-analystcross-repo-tracerenv-matrix-analyst 검증evidence-auditorqa-revieweranalyst-backend 발행wiki-publisheratlassian-adapter
  • bridge-analyzer: 클라이언트부터 Kafka 토픽, 컨슈머, SP 호출까지 이어지는 비즈니스 플로우를 추적합니다
  • db-schema-analyst: 앞 단계에서 식별된 테이블과 SP를 중심으로 DB 스키마와 SP 로직을 분석합니다
  • evidence-auditor: 문서의 각 주장이 근거를 가지고 있는지 확인하고, 사실과 추론을 분리합니다
  • qa-reviewer: Mermaid 문법, 근거 표기, Confluence 발행 형식을 최종 확인합니다

실제로 어떤 문서가 나왔나

여기서 "DB MCP를 쓴다"고 하면 대부분 반응이 비슷합니다. DB에 MCP를 붙인다고? 그거 풀스캔 나는 거 아니야? 운영 DB를 AI가 막 뒤지는 거야?

맞는 우려입니다. 그래서 DB MCP는 쓰임새를 엄격하게 제한했습니다. 특정 SP 이름 또는 특정 테이블 이름을 기준으로만 조회할 수 있습니다. MEMBER 테이블을 SELECT하는 모든 SP를 찾아줘 같은 광범위한 질의는 애초에 안 됩니다.

흐름은 이렇습니다.

  1. 먼저 코드베이스에서 SP 호출부와 테이블명을 추출합니다 (Filesystem MCP 단계)
  2. 그렇게 확보한 구체적인 이름들만 DB MCP에 넘겨서 조회합니다
  3. SP 정의와 의존성이 확인되면, 그 내용을 코드 분석 결과와 연결해 추가 분석합니다

무작위로 DB를 탐색하는 게 아니라, 코드에서 이미 식별된 대상만 검증하는 방식입니다. 이 순서가 지켜지지 않으면 DB MCP는 동작하지 않습니다.


정산 배치 시스템을 이 흐름으로 분석했을 때 나온 결과를 예로 들면, 단순한 코드 요약이 아니라 다음 내용까지 포함된 문서가 생성됐습니다.

  • Batch Job의 Step 실행 순서와 분기 조건 (일집계 → 월집계 → 정산 금액 검증)
  • 환불, 배송 완료 Decider 루프의 반복 처리 로직
  • SP와 테이블의 실제 의존성
  • 스케줄링 조건과 데이터 소스 구성
  • Mermaid로 시각화된 전체 Job 흐름 다이어그램

코드 리뷰 수준의 내용이 명령 한 줄로 나왔습니다. 히스토리가 끊긴 레거시 시스템에서 새 팀원이 온보딩하는 데 수 주가 걸리던 맥락을 빠르게 파악할 수 있게 됐습니다.

코드만 봐서는 알 수 없었던 것들, SP 안의 분기 이유라든가 특정 정산 정책이 왜 그렇게 설계됐는지, DB MCP와 Confluence를 교차 검증하면서 꽤 많은 부분을 복원할 수 있었습니다.


마치며

레거시 시스템의 어려움은 코드의 양보다 맥락의 단절에서 더 크게 옵니다. 코드는 남아 있는데, 그 코드가 왜 생겼는지, 어떤 정책을 반영했는지는 사람이 떠나면 같이 사라집니다.

이 프로젝트를 만들면서 확인한 건, 코드베이스만 분석하는 도구는 결국 절반짜리라는 겁니다. 진짜 비즈니스 맥락은 코드 밖에 있습니다. DB SP 안에, 오래된 Jira 이슈 안에, 형식 없이 남긴 PR 코멘트 안에.

LocalWiki는 그 단서들을 한 곳에 모아서 대조하고, 어디까지가 사실이고 어디부터가 추론인지 구분해서 기록하는 도구입니다. 완전한 복원이 아니라, 흩어진 맥락을 연결하는 보조 수단으로 쓰는 게 맞는 용도입니다.