들어가며
안녕하세요. LINE Plus에서 Global E-Commerce Platform 개발을 맡고 있는 윤석 범입니다.
AI로 개발할 때 결과물의 품질은 AI의 코드 생성 능력보다 얼마나 정확한 맥락 위에서 작업하는지에 달려 있습니다. 그런데 MSA(Microservices Architecture) 환경에서는 이 맥락이 여러 저장소와 서비스에 흩어져 있습니다. 하나의 기능이 여러 서비스에 나뉘어 구현돼 있어 단일 저장소의 코드만으로는 전체 비즈니스 흐름과 의도를 파악하기 어렵습니다.
이 문제는 요구사항을 받아 스펙을 정리할 때 특히 드러납니다. 요청을 개발 가능한 수준으로 구체화하려면 조건과 예외, 데이터 기준, 영향 범위를 정의하고 기존 정책·인터페이스와 충돌하지 않는지 확인해야 하는데, 그 근거가 여러 서비스와 문서에 흩어져 있는 데다 무엇이 최신 기준인지 판단하기도 어렵습니다. AI가 낡은 문서를 참조하거나 부족한 맥락을 추론으로 메우면 실제 구현과 다른 전제가 스펙에 섞여 들어가고, 잘못 정리된 스펙은 이후 개발과 검토의 기준이 되기 때문에 뒤늦게 발견하면 스펙 정리부터 개발까지 다시 해야 합니다.
그래서 저희는 매번 흩어진 정보를 AI에 주입하는 대신, 코드를 근거로 삼는 SSOT( Single Source of Truth, 단일 진실 공급원)를 만들었습니다. 코드에서 비즈니스 정책을 추출해 지식 문서로 정리하고, 코드가 바뀌면 문서도 따라 최신화되는 구조입니다. 이렇게 지식이 한곳으로 모이면서 AI가 추론으로 빈칸을 메우는 일이 줄었고, 영향받는 서비스를 추적하거나 도메인 문의에 답할 때도 하나의 SSOT에서 답을 얻게 됐습니다.
이 글에서는 이 지식 문서를 LLM Wiki로 만들고 유지한 방법과, 실제 개발에 활용한 과정을 공유하려 합니다.
LLM Wiki란 무엇인가
LLM Wiki는 Andrej Karpathy가 제안한 개념으로, 질문을 받을 때마다 원본을 매번 다시 읽는 대신, LLM(Large Language Model)이 원본을 한 번 읽어 지속적으로 관리되는 위키로 정리해 두고, 이후 질문은 그 위키에서 답하게 하자는 것입니다. 핵심은 위키를 관리하는 주체가 사람이 아니라 LLM이라는 점입니다.
저희는 이 개념을 코드 중심으로 구현했습니다. LLM이 코드와 문서에서 비즈니스 정책을 추출해 도메인 지식 문서를 만들고, 코드가 바뀌면 그 변경을 반영해 다시 최신화합니다. 사람은 이 과정에서 모호한 지점을 확정하고 변경분을 리뷰하는 검증자 역할을 맡습니다.
코드를 근거로 raw와 knowledge를 쌓는다
이 개념에서 출발해 저희가 구축한 SSOT의 구조는 한 문장으로 요약할 수 있습니다. 코드에서 현재 동작 기준의 스펙을 추출해 raw로 원본 맥락과 함께 보존하고, 이를 LLM이 읽어 사람과 AI가 함께 참조할 수 있는 지식 문서(knowledge)로 정리하는 것입니다. 즉 SSOT는 raw와 knowledge 두 개의 층으로 이루어지고, 이 두 층의 근거가 되는 것이 코드입니다.
먼저 코드입니다. 코드는 시스템이 현재 어떻게 동작하는지 확인할 수 있는 가장 강한 근거입니다. 문서는 작성된 뒤 시간이 지나면 실제 구현과 어긋날 수 있지만, 코드는 현재 서비스에 반영된 동작을 직접 보여 줍니다. 그래서 저희는 이 코드를 분석해 비즈니스 정책과 스펙으로 정리하는 데서 시작했습니다.
다만 코드는 '무엇이 동작하는지'는 보여 주지만, '왜 그렇게 결정됐는지'까지 설명해 주지는 않습니다. 어떤 정책이 왜 그 값으로 정해졌는지, 어떤 범위를 왜 제외했는지 같은 결정의 배경은 코드 주석이나 Confluence, Slack, 회의 메모 어딘가에 흩어져 있는 경우가 많습니다. 그래서 코드에서 확인한 사실과 함께, 이 판단의 배경이 되는 원본 맥락을 raw에 모아 보존했습니다.
knowledge는 이렇게 모인 raw를 LLM이 읽어 정리한 지식 문서입니다. 사람이 평소에 읽고, AI가 요구사항 분석이나 스펙 정리 과정에서 참조하는 문서가 이 knowledge입니다. raw가 원본 근거를 그대로 보존하는 영역이라면, knowledge는 그 원본을 지금 기준의 도메인 문서로 재구성한 영역입니다.
전체 흐름 한눈에 보기
앞서 본 SSOT가 코드로부터 실제로 만들어지고 유지되는 흐름은 크게 두 단계로 나뉩니다. 처음 한 번 baseline을 만드는 단계와, 이후 코드가 바뀔 때마다 갱신하는 단계입니다.
baseline 생성 단계에서는 소스 코드와 설정에서 현재 동작 기준의 baseline 스펙을 역추출하고, 이를 raw에 원본 근거로 보존한 뒤 knowledge 문서로 정리합니다.
이후 knowledge 최신화 단계에서는 각 서비스 저장소에 PR(pull request)가 병합될 때마다 변경분을 자동으로 수집합니다. 수집한 변경분은 raw에는 덮어쓰지 않고 변경 이력으로 누적하고, knowledge에는 현시점에 유효한 최신 정보만 남도록 반영합니다.
여기에 더해, 문서가 계속 신뢰 가능한 상태로 유지되도록 주기적으로 검증합니다. raw와 knowledge의 연결이 끊기지 않았는지, 오래된 정보가 남아 있지 않은지, 검색 색인이 최신 문서를 가리키는지 점검합니다.
이 모든 과정은 세 종류의 장치가 맞물려 동작합니다. 코드에서 스펙을 추출하는 스킬, raw를 knowledge에 반영하고 점검하는 워크플로우, 그리고 이 과정을 PR마다 자동으로 실행하는 GitHub Actions입니다. 아래에서 각각의 역할을 차례로 살펴보겠습니다.
스킬 — 코드에서 스펙을 뽑아낸다
스킬은 코드에서 비즈니스 스펙을 역추출하는 도구입니다. 처음 문서화할 때 쓰는 것과, 이후 변경분을 반영할 때 쓰는 것 두 가지가 있습니다.
소스 전체에서 baseline 스펙을 만든다
하나는 모듈을 처음 문서화할 때 쓰는 스킬로, 소스 코드와 설정 전체를 분석해 baseline 스펙을 만듭니다. 이때 소스의 어느 부분에서 어떤 사실을 뽑는지는 대체로 다음과 같습니다.
- 데이터 기준: DTO·Entity 같은 곳에서 필드명과 타입, 필수 여부, 허용값
- 정책·예외: Validator나 예외 처리에서 허용·불허 조건과 예외 상황
- 처리 흐름: Service·UseCase에서 처리 단계와 분기, 입출력
- 설정: YAML·Config에서 처리 한도와 환경별 차이
- 연동 관계: 노출된 API와 주고받는 메시지로 드러나는 다른 서비스와의 연결
- 결정 배경: 코드 주석에 남은, 정책 값이나 예외 분기가 그렇게 정해진 이유
핵심은 클래스나 메서드 구조를 그대로 옮기는 게 아니라, 요구사항 분석과 개발 판단에 실제로 필요한 정책·데이터·흐름·예외로 바꿔 적는다는 점입니다. 다만 API 엔드포인트, Kafka 토픽, DB 컬렉션, enum 값 같은 식별자만은 예외입니다. 이 값들은 다른 서비스나 코드와 연결되는 지점이라 한 글자만 달라져도 추적이 어긋나므로, 번역하거나 줄이지 않고 원문 그대로 옮깁니다.
이렇게 추출·정리한 스펙은 곧바로 확정되지 않습니다. 먼저 스스로 검토하는 단계를 거칩니다. 구현 설명이 남아 있지는 않은지, 코드에 근거가 없는 내용을 지어내지는 않았는지, 식별자가 원문과 일치하는지를 점검합니다.
그런 다음에도 코드만으로는 판단이 안 서는 지점이 남습니다. 어떤 값이 왜 그렇게 정해졌는지, 예외적인 분기가 의도된 것인지 같은 부분입니다. 이런 모호한 지점은 사람에게 하나씩 물어 확인하고, 그 답을 반영한 뒤에야 baseline 스펙으로 확정됩니다. 즉 추출과 정리는 스킬이 하되, 마지막 판단은 사람이 채워 넣는 구조입니다.
PR 단위로 변경 스펙을 만든다
다른 하나는 이미 만들어진 스펙에 변경분을 반영할 때 쓰는 스킬입니다. baseline 생성이 소스 전체를 분석한다면, 이 스킬은 하나의 PR이 무엇을 바꿨는지에만 집중합니다. 그래서 입력도 PR 단위로 모읍니다. PR의 제목·본문·리뷰 코멘트와 diff를 한데 모은 변경 기록에, 이번에 바뀐 소스 파일 전체와 그 파일이 참조하는 주변 코드까지 함께 입력받습니다. diff만으로는 맥락이 부족할 때 변경 파일의 전후 구조나 연결된 정의를 같이 봐야 하기 때문입니다.
이렇게 모은 입력에서 전체를 다시 쓰는 것이 아니라 변경분만 가려냅니다. 기존 raw 스펙과 대조해 이번 PR로 무엇이 추가되고 수정되고 삭제됐는지를 찾고, '이전에는 이랬는데 이번에 이렇게 바뀌었다'는 형태로 정리합니다. 추출 방식과 원칙은 baseline 생성 스킬과 같습니다. 구현 자체가 아니라 비즈니스 관점으로 적되, 식별자는 원문 그대로 옮깁니다.
이 스킬은 세 종류의 문서를 만듭니다.
- 변경 스펙: PR 작업 내용. ingest가 knowledge에 반영할 원본이 됩니다.
- 분석 리포트: 추출 근거와 참조한 파일, 반영 대상 문서. ingest가 knowledge를 갱신할 때 참조합니다.
- 리뷰 피드백 정리: AI가 작업한 PR에 사람이 남긴 리뷰 코멘트 중 개발 가이드에 반영할 내용. 이후 개발 과정에서 참조합니다.
워크플로우 — raw를 knowledge에 반영하고(ingest), 점검한다(lint)
스킬이 만든 스펙은 곧바로 knowledge가 되지 않고 먼저 raw에 쌓입니다. 이 raw를 지식 문서에 반영하는 일이 ingest, 그렇게 만든 지식 문서가 시간이 지나도 원본과 어긋나지 않는지 점검하는 일이 lint입니다.
ingest — raw를 knowledge에 반영한다
ingest는 raw를 보고 knowledge를 만듭니다. 다만 raw를 그대로 옮기지는 않습니다. knowledge는 사람과 AI가 위키 문서를 찾아보듯 평소에 스펙과 정책을 참조하는 문서입니다. 그래서 참조에 필요한 비즈니스 정책, 핵심 수치와 한도, 모듈 간 관계와 흐름을 요약해 담고, 상세한 원본은 필요할 때 raw에서 확인합니다.
raw와 knowledge는 담기는 모양이 다릅니다. raw는 잘게 쌓입니다. 모듈 단위로 나뉘어 있고, baseline 스펙과 이후 PR 단위 변경 스펙이 따로 있어, 기존 원본을 수정하지 않고 변경 이력(changelog)으로 누적합니다. 그래서 '예전엔 어땠고 언제 왜 바뀌었는지'가 원본과 이력에 그대로 남습니다. 반면 knowledge는 도메인 단위로 크게 묶여, 현시점에 유효한 최신 내용만 유지합니다.
여기서 중요한 건 이 knowledge 문서 하나가 사람과 AI 양쪽을 동시에 만족시켜야 한다는 점입니다. 문서를 사람용과 AI용으로 따로 만들면 결국 한쪽 만 낡아 가기 때문에, 같은 Markdown(md) 문서 하나에서 양쪽을 다 풀어냅니다.
AI 쪽에서는 문서를 쉽게 탐색하고, 이 문서가 맞는지 빠르게 판단할 수 있게 합니다. Markdown 맨 앞에는 이게 어떤 성격의 문서인지, 어떤 원본에서 나왔는지 같은 메타데이터(frontmatter)와 한 줄 요약(TLDR)을 붙입니다.
---
title: 주문 상태 집계 (Order Status Aggregator)
doc_type: knowledge_summary
tags: ["#entity/order-aggregator", "#concept/aggregation", "#status/current"]
sources: [raw/order/order-status-aggregator-spec.md, raw/order/order-aggregation-window-spec.md]
last_updated: 2026-05-20
---
::: info TLDR
Order Status Aggregator는 주문 상태 변경 이벤트를 수신해 판매자·기간 단위로 집계하고,
확정된 결과를 요약 API와 결과 토픽(order.status.aggregate.result)으로 내보내는 집계 시스템이다.
:::
AI는 이 정보를 보고 어떤 문서인지 빠르게 파악합니다. doc_type으로 문서 성격을 구분하고, tags로 주제를 좁히고, last_updated로 최신 여부를 봅니다. sources에 적힌 원본을 따라가면 raw까지 내려가 근거를 확인할 수도 있습니다. 그리고 맨 앞 TLDR 한 줄로 이 문서가 지금 찾는 내용인지 가려냅니다.
같은 Markdown 파일을 사람이 읽기 좋은 HTML로 변환해 정적 사이트(Knowledge Wiki)로 배포합니다.
이렇게 사람이 보는 문서와 AI가 참조하는 문서가 같은 파일에서 나옵니다.
knowledge 문서를 탐색할 때는 index.md로 빠르게 찾아 들어가고, raw 기준으로 찾아야 할 때는 검색 색인(semantic-analysis)을 씁니다. index.md는 도메인별로 각 문서의 링크와 한 줄 요약(TLDR)을 모아두고, 검색 색인은 raw를 기준으로 별칭·검색 의도·서비스 간 연결을 함께 남깁니다. 변경 이력은 log.md에 기록합니다.
lint — 어긋난 곳을 찾아 되돌린다
ingest는 이렇게 knowledge 문서 하나에서 여러 산출물을 함께 갱신합니다. 그런데 이 중 한 곳이라도 빠지면 문서는 조금씩 어긋납니다. lint는 이런 문제를 주기적으로 점검하고 보정합니다. 크게 나누면 다음과 같습니다.
| 검사 영역 | 검출 대상 |
|---|---|
| 링크·정합성 | 고아 페이지, 끊긴 참조, 페이지 간 모순 |
| 식별자 무결성 | raw 원본과 어긋나는 식별자 |
| 최신성 | raw 변경이 반영되지 않은 knowledge |
| 문서 규칙 | 필수 메타데이터 누락, 문서 유형별 태그 위반, index.md 요약과 본문 불일치 |
| 산출물 동기화 | knowledge 변경이 반영되지 않은 HTML·검색 색인 |
이 중 가장 중요한 것은 식별자 무결성(Identifier integrity)입니다. raw에 있는 식별자를 knowledge와 비교합니다. 읽기 좋게 다듬는 과정에서 원문 식별자가 변형되면, 사람이 보기에는 자연스러워도 시스템 기준으로는 다른 의미가 됩니다. 원본에 없는 식별자가 추론으로 추가되는 경우도 마찬가지입니다.
lint에서 발견한 문제는 ingest를 다시 실행해 바로잡습니다. raw는 원본 근거와 변경 이력을 보존하는 영역이므로 직접 수정하지 않고, knowledge가 raw와 어긋난 경우 knowledge를 다시 정리합니다. ingest가 raw를 바탕으로 지식을 쌓는 과정이라면, lint는 그 결과가 원본 근거에서 벗어나지 않았는지 확인하고 다시 맞추는 검증 단계입니다.
GitHub Actions — PR을 트리거로 자동화한다
지금까지 설명한 각 단계를 매번 사람이 직접 실행해야 한다면, 언젠가는 놓치게 됩니다. 그래서 이들을 GitHub Actions에 연결해, PR 병합을 트리거로 자동화했습니다.
트리거에서 시작해 Action이 이어받고, 사람은 스펙 PR 리뷰만 담당합니다.
[트리거] 각 저장소의 소스 코드 PR 병합
│
[Action ①] 변경 감지 → pr-spec-extractor로 변경 스펙 추출 → [spec sync] PR 생성
│
[사람] 스펙 PR 리뷰 · 병합
│
[Action ②] ingest 실행
[Action ③] 주기적인 lint 검증
이렇게 만든 지식을 어떻게 활용하나
여기까지가 코드에서 지식 문서를 만들고, 코드가 바뀔 때마다 최신 상태로 유지하는 과정이었습니다. 이제 이 SSOT를 어떻게 활용하는지 살펴보겠습니다. 활용 방식은 크게 둘입니다. AI가 개발 워크플로우에서 참조하거나, 사람이 직접 조회해 읽습니다.
SSOT 기반 스펙 주도 개발
스펙 주도 개발(Spec-Driven Development)이란 AI 기반 코딩에서 코드 작성 전에 스펙을 먼저 구체화하고, 그 스 펙을 기준으로 구현과 검증을 진행하는 방식입니다. 스펙을 한 번 작성하고 끝내는 것이 아니라, 요구사항 정의부터 구현, 검증, 리뷰, PR까지 모든 단계가 스펙을 기준으로 이어집니다.
가장 중요한 단계는 초기에 요구사항을 개발 가능한 스펙으로 구체화하는 과정입니다. 스펙이 어긋나면 이후 계획, 구현, 검증도 같은 잘못된 전제를 따라가기 때문입니다. 그래서 저희는 이 단계에서 앞서 만든 SSOT를 기준으로 삼았습니다. 흩어진 정보를 AI가 추론으로 메우지 않도록 기존 정책, 인터페이스, 이벤트 흐름, 예외 조건을 SSOT에서 확인하고 스펙에 반영합니다. SSOT는 이런 스펙 구체화를 중심으로, 개발 전후의 영향도 분석에도 활용됩니다.
먼저 이슈 티켓이 등록되면 요구사항을 기준으로 '사전 영향도 분석'을 합니다. 직접 수정 대상, 영향받는 모듈, 충돌 가능한 기존 정책, 그리고 스펙 확정 전 결정해야 할 확인 사항을 티켓 코멘트로 남깁니다. 영향도 분석은 요약된 knowledge만으로는 부족하기 때문에 검색 색인(semantic-analysis)을 활용하여 raw 원본을 기준으로 확인합니다.
다음 '스펙 구체화 및 구현' 단계에서는 사전 영향도 분석 결과를 바탕으로 스펙을 확정하고, 개발 가이드와 컨벤션을 참조해 일관된 품질로 코드를 작성합니다. PR에는 구체화한 전체 스펙이 아니라 코드로 확인할 수 없는 'ADR(Architecture Decision Record)만 첨부'합니다. 이후 이 변경이 raw로 수집될 때, 코드에서 추출한 사실에 이 보조 맥락이 더해져 다음 개발의 기준이 됩니다.
마지막은 '사후 영향도 분석'입니다. PR이 생성되면 실제로 변경된 소스를 기준으로 영향받는 모듈을 체크합니다. 이때 보는 건 서비스 경계를 넘 나드는 연결점입니다. 다른 서비스가 호출하는 API 엔드포인트, Kafka 토픽의 발행 조건이나 메시지 형태, DB 스키마 등의 변경으로 영향받는 서비스를 추적합니다.
사람이 함께 보고 검증하는 Knowledge Wiki
여기까지가 AI가 SSOT를 기준으로 개발하고, 그 결과가 다시 SSOT에 쌓이는 과정이었습니다. 하지만 SSOT가 AI만을 위한 데이터로 남아 있으면 사람이 검토하고 활용하기 어렵습니다. 그래서 앞서 소개한 대로 knowledge md를 HTML로 변환해, 사람이 읽기 좋은 Knowledge Wiki로 제공합니다. 기존 위키처럼 도메인이나 모듈별로 찾아볼 수 있고, 각 모듈의 역할, 주요 정책, 입력과 출력, 관련 문서를 확인할 수 있습니다. 필요한 경우 로컬 LLM을 통해 자연어로 질문하며 내용을 탐색할 수도 있습니다. 이 문서는 코드와 PR 변경 흐름에 맞춰 함께 최신화됩니다. 그 결과 사람과 AI가 서로 다른 문서를 보며 판단하는 것이 아니라, 같은 knowledge를 기준으로 현재 유효한 정보를 함께 확인할 수 있습니다.
MSA 환경에서는 하나의 기능이 여러 서비스에 걸쳐 동작하고, 서비스 간 관계도 각 서비스의 코드와 문서에 흩어져 있어 개별 서비스만으로는 전체 흐름을 파악하기 어렵습니다. 그래서 각 서비스의 역할, 입출력, 의존 관계, 관련 정책을 함께 엮어 전체 파이프라인 흐름을 한눈에 볼 수 있도록 정리했습니다. 이를 통해 코드만으로는 추적하기 어려운 서비스 간 연결이 드러나고, 전체 구조를 더 빠르게 파악할 수 있습니다. 새로 합류한 동료가 도메인과 서비스 구조를 이해하는 온보딩 자료로도 활용됩니다.
마치며
지금까지 흩어진 도메인 지식을 코드 기준으로 정리하고, 코드 변화에 맞춰 자동으로 최신화하며, 활용하는 과정을 살펴봤습니다. 이렇게 하나로 모인 지식 덕분에 AI는 MSA 환경에서도 전체 그림을 보고 개발할 수 있고, 사람은 업무 문의나 정책 확인이 필요할 때 문서를 찾아다니는 대신 자연어로 질의해 바로 확인할 수 있습니다.
다만 문서를 유지하는 과정이 전부 자동은 아닙니다. baseline을 만들 때는 코드만으로 판단이 서지 않는 지점을 사람이 답해 줘야 하고, PR마다 올라오는 스펙 변경도 아직은 사람이 리뷰해 확정합니다. 추출 결과를 얼마나 믿을 수 있는지 확인하는 단계이기 때문입니다.
이 수동 단계는 점차 줄어들 것으로 기대합니다. 스펙 리뷰는 신뢰가 쌓이는 대로 자동화할 계획이고, baseline에서 사람이 답해야 했던 빈틈도 SSOT 기반 워크플로우로 개발하면 스펙과 ADR이 코드와 함께 남기 때문에 사라질 것입니다.
앞으로는 Slack 봇이나 AI 에이전트와 연동해 질문에 자동으로 답하거나 관련 문서를 찾아 주는 등 활용처도 늘려 가려 합니 다.
비슷한 고민을 하는 분들께 이 글이 도움이 되기를 바라며, 이만 마치겠습니다.









