AI/ML
우리 팀 코드 스타일을 아는 AI 만들기: RAG와 Vector DB 활용기
김재민Ballack(발락) / 파트너웹개발팀여기어때
2025년 11월 5일
원문에서 보기 ↗안녕하세요. 여기어때컴퍼니 프론트엔드 개발자 발락입니다.
최근 저희 조직에서는 AI와 LLM 활용 역량 강화를 적극 독려하고 있으며, 각 팀에서 업무 효율화를 위한 다양한 시도들이 이뤄지고 있습니다. 저 역시 평소 개발 생산성 향상에 관심이 많아, 반복적이고 귀찮은 작업들을 자동화하여 비즈니스 문제 해결에만 온전히 집중할 수 있는 환경을 만들고자 노력해왔습니다. 👨💻
개발 생산성과 안정성, 두 마리 토끼를 잡고 싶다
프론트엔드 개발을 하다 보면 누구나 공감하실 텐데요. 매일같이 쏟아지는 기능 개발 요구사항과 긴급한 버그 수정으로 바쁘게 돌아가다 보니, “나중에 해야지” 하고 미루는 작업들이 점점 늘어갑니다.
- 테스트 코드 작성 — “기능은 잘 돌아가니까 나중에…”
- 코드 리뷰 — “일단 approve 하고 나중에 자세히…”
- 컴포넌트 문서화 — “일단 개발부터 하고 스토리북은 나중에…”
- TypeScript 타입 정의 — “any로 일단 넘어가고 나중에 제대로…”
- 리팩토링 — “동작하는 코드를 왜 건드려? 나중에 시간 날 때…”
이런 작업들을 계속 미루다 보면 개발 생산성은 점점 떨어지고 , 무엇보다 QA 단계에서 발견되는 버그로 인한 커뮤니케이션 비용이 증가하게 됩니다. 특히 테스트 코드가 없으면 리팩토링한 후, 기존 로직대로 정상 동작하는지를 보장할 수 없어 그 동안 과감한 결단을 내리기 어려웠습니다.
우리 팀 코딩 스타일을 아는 AI가 있다면?
열심히 코딩하고 있던 어느 날, 팀장님께서 저에게 이런 질문을 하셨습니다.
“우리 팀의 코딩 스타일과 패턴을 학습한 AI가 있다면, 테스트 코드도 자동으로 생성하고, 코드 리뷰도 꼼꼼하게 해줄 수 있지 않을까요?”
짧은 미팅을 진행하면서 굉장히 재밌겠다는 생각을 했고, 바로 업무에 적용하기 위한 작업을 시작했습니다.
RAG + Vector DB로 찾은 해결책
위의 질문을 해결하기 위해 저희는 RAG(Retrieval-Augmented Generation) 기술과 Vector DB를 활용하기로 했습니다. 팀 코드베이스를 벡터화하여 DB에 저장하고, 이를 기반으로 RAG를 진행해 AI가 저희 팀의 코드 스타일을 이해하도록 만든 것이죠.
결과적으로 저희 팀은 Diffy 라는 자동 코드 리뷰 시스템과 @pwb/testgen이라는 테스트 코드 자동 생성 npm 패키지를 개발했습니다. (이외에도 더 멋지고 편한 AI 기반 기능을 개발하고 있습니다.) 이번 글에서는 이 과정에서 파트너웹개발팀의 Vector DB를 어떻게 구축했는지 공유드리려 합니다.🚀

RAG로 팀 코드베이스를 프롬프트에 제공하기
핵심 개념
RAG(Retrieval-Augmented Generation) LLM에 프롬프트를 보낼 때, 관련된 정보를 먼저 검색(Retrieval)해서 컨텍스트로 함께 제공하는 방식입니다. “GPT야, 우리 팀 코드 스타일은 이런 거야” 하고 참고 자료를 같이 건네주는 것과 같죠.
Vector Embedding 코드를 숫자의 배열(벡터)로 변환하는 과정입니다. 비슷한 의미나 기능을 가진 코드들은 벡터 공간에서 가까운 위치에 놓이게 됩니다.
유사도 검색(Similarity Search) 사용자가 “유저 정보를 가져오는 함수”를 요청하면, 벡터 공간에서 이와 가장 유사한 코드 조각들을 찾아내는 과정입니다. 두 문자열을 벡터로 만들었다면, 벡터 간의 유사함 정도를 수치로 계산할 수 있습니다. 가장 유명한 방식으로는 두 벡터간 코사인 값을 구하는 방식인 코사인 유사도가 있습니다. 예를 들어 getUserInfo()와 fetchUserData()는 벡터 공간에서 가까운 위치에 있어 높은 유사도를 가질 확률이 큽니다.
왜 파인 튜닝이 아닌 RAG를 선택했나?
처음에는 팀 코드로 모델을 직접 파인 튜닝(fine tuning)하는 방법을 고려했습니다. 하지만 회사의 보안 정책상 내부 코드를 외부 LLM에 학습 데이터로 제공하는 것은 불가능했죠. 그리고 파인 튜닝을 하려면 언어 모델을 학습시키는 데 드는 비용과 리소스 문제도 있었습니다.
Microsoft Research의 2024년 연구에 따르면 RAG는 파인튜닝과 유사한 정확도를 달성했으며, 일부 모델에서는 RAG가 더 우수한 성능을 보였습니다(Vicuna: RAG 79% vs 파인튜닝 72%)[1]. 특히 Fully correct(답변이 완전히 정확한 정도)에서 모든 모델이 RAG 적용 시 16–28%p 향상되어 RAG의 실질적 효과가 입증되었습니다[1].
이렇게 관련 연구를 보고 RAG 만으로도 파인 튜닝만큼의 효과를 낼 수 있다고 판단했고, 다음과 같은 추가 장점도 있기 때문에 RAG 시스템을 구축하기로 결정했습니다.:
- 회사 코드를 외부 LLM에 학습시키지 않고도 활용 가능
- 실시간으로 최신 코드 반영 가능
- 추가 학습 비용이 들지 않음
- 필요시 특정 코드 제외/포함 여부를 유연하게 조정 가능
ts-morph로 빠르게 코드 청킹하기
청킹(Chunking)은 코드를 나눠서 저장한다는 것을 의미하고, Vector DB를 구축하는데에 핵심 단계 중 하나입니다.
왜 청킹이 필요할까요? 너무 긴 코드는 필연적으로 많은 컨텍스트를 가질 수 밖에 없는데, 이를 통째로 임베딩하면 벡터에 여러 컨텍스트가 섞이게 되어 검색 정확도가 떨어지기 때문입니다. 그래서 적절한 크기로 나누고, 청크 안의 코드가 동일한 컨텍스트를 가진다면 더 정확한 유사도 검색이 가능해집니다.
코드베이스를 벡터화하기 위해 여러 청킹 전략을 시도해보았고, 마지막 전략을 최종 채택했습니다:
❌ 정규표현식으로 함수 단위 자르기 → 복잡한 코드에서 부정확
❌ tiktoken으로 토큰 단위 청킹 → 문법 구조 무시하고 강제 분리
❌ langchain의 텍스트 스플리터 → 청킹 시 각 토큰의 의미를 분석하기 때문에 시간이 오래 걸림
✅ ts-morph로 AST 분석 → TypeScript 컴파일러와 같은 방식으로 구문 분석 수행, rule base 기반이라 성능 좋음
// ts-morph를 활용한 청킹 전략
import { Node, Project } from 'ts-morph';
const project = new Project({ useInMemoryFileSystem: true });
const sourceFile = project.createSourceFile('path/to/temp.tsx', code);
// 함수, 함수 표현식, 화살표 함수, 클래스, 인터페이스, 타입 등을 개별 청크로 분리
sourceFile.getFunctions().forEach((fn) => processNode(fn)); // function
sourceFile.getClasses().forEach((cls) => processNode(cls)); // class
// 다른 타입도 동일한 방식으로 작업 수행
function processNode(node: Node): void { /* 재귀적으로 실행되면서 청크 생성 */}
긴 함수는 내부 로직 블록 단위로 재귀적으로 청킹하여, 너무 큰 청크가 생기지 않도록 했습니다. 그리고 JS의 import 구문은 그 자체로는 RAG에 도움이 안되는데 비해 타 코드와 유사도가 높게 나오기 때문에, Vector DB에 저장하지 않았습니다.

Vector DB
Vector DB로는 ChromaDB를 선택했습니다:
- 오픈소스이고 사용법이 간단함
- 강력한 메타데이터 필터링 지원
- 로컬 개발과 프로덕션 환경 모두 쉽게 구축
하나의 Git 레포지토리 = 하나의 ChromaDB 컬렉션 구조로 설계하여, 프로젝트별로 독립적인 벡터 공간을 유지했습니다.
임베딩 모델과 배치 처리
저희 회사는 Google Cloud Platform을 활용하여 ML 관련 업무를 수행하고, Gemini 사용을 지원하고 있습니다. 따라서 임베딩 모델도 Gemini embedding 모델(gemini-embedding-001)을 사용했습니다. 768차원 모델로 세밀한 의미 차이를 구분할 수 있으면서도 비용 효율적이었습니다.
그리고 전체 코드베이스에 대해 임베딩 시 성능 최적화를 위해 500개 단위로 VectorDB에 적재하는 배치 처리를 적용했습니다:
async function batchStoreChunks(allChunks: CodeChunk[]) {
const BATCH_SIZE = 500;
for (let i = 0; i < allChunks.length; i += BATCH_SIZE) {
const batch = allChunks.slice(i, i + BATCH_SIZE);
// 배치 단위로 임베딩 생성 및 저장
await processAndStore(batch);
console.log(`✅ ${Math.min(i + BATCH_SIZE, allChunks.length)}/${allChunks.length} 완료`);
}
}
이 최적화로 약 10,000개 청크 처리 시간을 기존 45분에서 8분으로 단축했습니다.
자동 업데이트 파이프라인
한 번 구축하고 끝이 아니라, 코드가 업데이트될 때마다 Vector DB도 최신 상태를 유지해야 합니다. 이를 위해 CI/CD 파이프라인에 자동 업데이트 프로세스를 구축했습니다:
update-embedding:
image: node:22
stage: build
script:
- yarn add -D @pwb/testgen -W
- npx embedding-by-diff
rules:
- if: '$CI_COMMIT_BRANCH == "dev"'
when: always
dev 브랜치에 push 시 자동으로 변경된 파일들만 찾아서 Vector DB를 업데이트합니다.
실제 활용: 코드 리뷰 자동화와 테스트 코드 생성
Vector DB가 잘 구축되었다면, RAG 과정은 아래 다이어그램처럼 진행됩니다.

저희는 세 가지 핵심 기능을 구현했고, 이외에도 더 많은 AI 기반 업무 효율 개선 프로젝트를 진행하고 있습니다.:
1. Diffy — 자동 코드 리뷰 시스템
GitLab Merge Request(Github의 Pull Request와 동일)이 생성되면 자동으로 코드를 분석하고, 유사한 기존 코드들을 참고하여 리뷰 코멘트를 생성합니다. 팀 컨벤션 준수 여부, 잠재적 버그, 개선 제안 등을 자동으로 체크합니다. 사람이 놓치기 쉬운 부분까지 꼼꼼하게 체크해주어 실제로 팀에서 반응이 가장 좋았던 기능입니다.
2. @pwb/testgen — 테스트 코드 자동 생성 패키지
기획서 혹은 개발된 코드를 기반으로, 그에 대응하는 테스트 코드를 자동으로 작성해주는 npm 패키지를 사내에 배포했습니다. 이 패키지 덕분에 쉽게 통합 테스트 케이스 127개를 채울 수 있었고 , 최근에 진행했던 바텀시트 마이그레이션 작업을 검증하는데 큰 도움 이 되었습니다. 최종 목표는 기획 문서와 디자인 시안을 가지고 작업 전에 먼저 테스트 코드를 생성하는 Test Driven Development가 매끄럽게 이뤄지는 것입니다.
3. 기획 문서 검색
기획 내용이 매우 많은 경우, 기획한지 오래되었거나 기획자가 퇴사한 경우 의도와 방향성을 찾기가 어렵습니다. 저희 팀 코드베이스 뿐만 아니라, 기획서들도 Vector DB에 저장하여 쉽게 검색할 수 있도록 구축했습니다.
(실제 구현한 내용은 다음 편에서 다룰 예정입니다!)
마무리하며
지금까지 팀 코드베이스를 Vector DB로 구축하는 과정을 살펴보았습니다.
핵심 내용 정리
보안 정책을 준수하면서도 팀 코드를 효과적으로 학습시키기 위해 RAG 기술을 활용했고, 오픈소스 Vector DB인 ChromaDB 를 선택하여 간단하면서도 강력한 유사도 검색 시스템을 구축했습니다. ts-morph를 통해 TypeScript AST를 분석하여 함수, 타입, 인터페이스 단위로 정확한 청킹을 수행했고, 긴 함수의 경우 재귀적으로 다시 청킹하는 전략을 적용했습니다.
구현 과정에서 얻은 중요한 인사이트들도 있었는데요. import 문이 유사도 검색에 노이즈가 되는 것을 발견하여 제거했고, 임베딩 후 DB 저장 시 500개 단위의 배치 처리로 대규모 처리 성능을 대폭 개선했습니다. GitLab CI/CD와 연동하여 코드 변경사항이 자동으로 Vector DB에 반영되도록 했고, 이를 기반으로 @pwb/testgen 패키지 와 Diffy 코드 리뷰 시스템을 구축하여 실제 업무에 적용했습니다.
개발자의 생산성, AI와 함께라면 가능합니다
“귀찮아서”, “시간이 없어서” 미뤄왔던 테스트 코드 작성과 꼼꼼한 코드 리뷰가 이제는 AI의 도움으로 자동화되고 있습니다. 특히 팀의 코드베이스를 Vector DB로 구축하여 학습시킨 AI는 단순한 자동 완성을 넘어, 우리 팀만의 스타일을 이해하고 따르는 진정한 ‘팀원’이 되었습니다.
여러분도 RAG와 Vector DB를 활용해 팀만의 AI 어시스턴트를 만들어보시는 건 어떨까요? 반복적인 작업은 AI에게 맡기고, 우리는 더 창의적이고 중요한 문제 해결에 집중할 수 있을 것입니다.
다음 편에서는 구축한 Vector DB를 활용해 실제로 @pwb/testgen의 테스트 코드 생성 과 Diffy의 MR 자동 리뷰를 어떻게 구현했는지 자세히 다루겠습니다. 실제 코드와 함께 더 구체적인 구현 방법을 공유할 예정이니 많은 관심 부탁드립니다.
여러분의 개발 생산성 향상에 조금이나마 도움이 되었기를 바랍니다. 감사합니다! 😊
참고문헌
[1] Balaguer, A., et al. (2024). RAG vs Fine-tuning: Pipelines, Tradeoffs, and a Case Study on Agriculture. arXiv:2401.08406.