jblog
토스가 궁금해 한 Git-Docgen 회고
Frontend

토스가 궁금해 한 Git-Docgen 회고

Git diff를 분석해 자동으로 문서를 생성하는 CLI 라이브러리 Git-Docgen을 만들며 토스 1차 과제를 통과한 이야기. npm 224회 다운로드, 청킹, 캐싱 전략까지.

2025-10-157 min read회고, 토스, npm, openai, cli, typescript

npm 224회나 다운로드해주었다..!

#들어가며

개발을 하다 보면 기록을 해야 하는 순간이 온다. 팀 프로젝트의 경우 PR을 작성해야 하고, 개인 프로젝트에서는 자율이지만 나는 어느 순간부터 커밋 단위별로 내가 알아볼 수 있도록 기록하게 되었다. 그러다 문득 생각이 들었다. 아 Git Diff를 바탕으로 커밋 단위별로 자동으로 문서를 만들어주는 도구를 만들면 어떨까? 딱 명령어 하나로 문서화가 된다면 정말 좋을 것 같았다.

그 때 마침 토스의 Frontend Assistant Platform 공고를 보았다. 진행할 프로젝트에 'LLM을 활용한 자동 문서화 및 수정 플로우'를 발견했고, toss에 지원할 겸 내가 직접 만들어보았다.

#아키텍처 설계

요구사항 정리

레이어설명
GitDiffFetchersimple-git을 이용해 Git 변경 사항을 수집
DiffParserraw diff → 구조화된 AST(JSON)로 파싱 (parse-git-diff)
ChangeAnalyzerAST → 의미 있는 코드 변화 분석 (ts-morph)
DocGeneratorOpenAI API 기반으로 문서 생성
CLI Entry커맨드라인 인터페이스 → 기능 조합 및 실행 제어

빠른 개발을 위한 도구 스택 선택

목적선택이유
번들러tsupesbuild 기반, 빌드 초고속 & TS 지원
테스트VitestVite 호환, 빠르고 ESM 지원
린트 + 포맷ESLint + Prettier일관적 코드 퀄리티 유지
문서 생성TypeDoc + 템플릿주석 활용 + 커스텀 템플릿 가능
배포 자동화ChangesetsPR기반 자동 릴리스 워크플로 지원

번들러로 tsup을 사용한 이유: ts를 지원하는 esbuild 기반이기도 하고 라이브러리 개발에 용이하다고 해서 선택해보았다.

테스트의 경우:

  • 토스에서는 주로 Jest를 쓰고 있지만 최근 Vitest가 많이 채택되고 있어 사용해보았다.
  • Vite와 esbuild 기반이라 속도도 굉장히 빠르고 ESM을 완전히 지원
  • Vite 기반 설정을 재사용할 수 있어서 확장성 측면에서 유리 (alias, plugin 설정을 다시 안 해도 됨)

유닛테스트로 개별함수/모듈별로 격리된 테스트를 진행했다. vi.mock을 사용하여 외부 의존성들을 모킹하였으며, 함수 테스트는 입력에 대한 예상 출력을 지정하여 검증하였다.

#기술적 도전

대규모 Diff 처리 - 청킹

코드 변경 내용이 커지면 문서화했을 때 유실되는 문제를 발견하였다. OpenAI API에 토큰 수 제한이 있기 때문이다. 나는 BPE 알고리즘에서 영감을 얻었다. BPE 알고리즘이란, 가장 빈번한 문자 쌍을 찾아 합치는 방법이다.

# BPE: 가장 빈번한 문자 쌍을 찾아 합치기
text = "low lower newest widest"
pairs = find_most_frequent_pairs(text)  # "lo", "w ", "er" 등
merge_pairs(pairs)  # 빈번한 쌍을 새 토큰으로 합침

결국은 다음과 같이 구조적 분할을 통해 해결하였다:

  1. Git Diff를 파일 단위로 분할
  2. 토큰 수 추정해서 크기 제한
  3. 작은 청크 병합 (파일이 중간에 잘려서 맥락이 파괴되는 것을 막기 위함)
  4. 병합 후 헤더 확인 (파싱 실패 또는 예외 상황 해결하기 위함)

API 비용을 줄이기 위한 방법 - 캐싱

테스트를 하면서도 계속 불필요한 Open API 호출로 내 돈이 날아가는 것을 보고 있을 수만은 없었다. 애초에 같은 Diff인데 AI의 블랙박스 문제 때문에 다른 문서가 생성되는 것이 이상하지 않은가? 그래서 고안해낸 것이 캐싱이었다.

내가 구현한 캐싱:

  • 모델 종류 + 전체 diff 내용 + 설정값 전체를 SHA256으로 해쉬화해서 캐시 키로 사용
  • 캐쉬는 JSON 파일 형태로 관리 (바이너리나 SQLite를 활용하는 방법도 있었겠지만, 캐시 파일을 직접 열어볼 수 있고 디버깅이 편해서 JSON 형태를 활용)

성능 측정의 어려움

나름 위 방법들을 적용하여 비용을 줄였다. 하지만 내가 얼만큼의 성능을 향상시켰는지는 수치로 환산할 수 없었다. 토스의 개발자님께서 이런 경우에는 많은 데이터들이 축적되어야 수치로 표현할 수 있다고 하셨다. 하지만 나는 OpenAI에 돈을 내고 있는 사람으로서 LLM을 직접 개발하지 않는 이상 나 혼자 이 수치를 계산하기에는 어려울 것 같다.

#정리하며,

위 방법으로 만든 Git-Docgen은 npm으로 내가 배포하기도 하였다. 신기하게도 첫 날에만 100회 이상의 다운로드 수를 기록하였다. (심지어 README가 한국어인데!) 무엇보다 내가 원했던 Toss의 1차 과제를 통과하였다!

댓글

댓글을 불러오는 중...