본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 04. 11:18

코드를 공유하지 않고 AI 코드 리뷰어를 구축하려 시도한 경험 — 성공적인 방법은 무엇인가

요약

기업의 기밀 코드 유출을 방지하기 위해 외부 클라우드에 데이터를 전송하지 않고 로컬 환경에서 작동하는 AI 코드 리뷰어 구축 경험을 공유합니다. 로컬 LLM과 LangChain을 활용한 초기 시도의 실패 원인을 분석하고, 구조화된 JSON 출력을 활용한 성공적인 통합 패턴을 제시합니다.

핵심 포인트

  • 기밀 코드 보호를 위해 로컬 LLM 또는 신뢰할 수 있는 엔드포인트 필요
  • 단순 모델 사용보다 구조화된 출력(JSON) 강제가 핵심
  • LangChain 등 무거운 프레임워크보다 가벼운 API 래퍼가 효율적일 수 있음
  • 모델의 환각 현상을 제어하기 위한 통합 패턴 설계의 중요성

몇 주 전, 저는 800줄 이상의 변경 사항이 포함된 풀 리퀘스트 (Pull Request)를 마주하고 있었습니다. 팀은 빠르게 움직이고 있었고, 저는 스타일, 잠재적인 버그, 그리고 보안 문제에 대해 빠르게 검토(Sanity check)를 하고 싶었습니다. 저의 첫 번째 본능은 무엇이었을까요? 바로 ChatGPT에게 물어보는 것이었습니다. 하지만 곧 편집증적인 걱정이 밀려왔습니다. 기업의 기밀 코드를 블랙박스에 붙여넣게 되는 것이니까요. 저희 법무팀이 기절할지도 모를 일이었습니다. 그래서 저는 민감한 데이터를 제3자에게 전송하지 않고도 AI 기반의 코드 리뷰를 실행할 수 있는 방법을 찾아 나섰습니다.

이 과정이 순탄했다고 거짓말하지는 않겠습니다. 로컬 LLM (Large Language Models)과 씨름하고, Python 스크립트를 다루려 애쓰다가, 결국 실제로 작동하는 패턴을 찾아냈습니다. 이 글은 제가 그때 미리 발견했더라면 좋았을 내용입니다.

문제점: 개인정보 보호와 편의성은 공존하기 어렵다

저희 팀은 인라인 제안을 위해 GitHub Copilot을 사용하지만, 이는 코드 스니펫 (Code snippets)을 Microsoft의 클라우드로 전송합니다. 저희의 내부 도구와 고객 대상 코드에 대해서는 이는 절대 허용될 수 없는 일입니다. 저는 다음과 같은 기능을 갖춘 리뷰 봇이 필요했습니다:

  • 어떤 크기의 디프 (Diff)라도 수용할 수 있을 것
  • 구조화된 피드백 (줄 번호가 포함된 이슈, 심각도, 제안 사항)을 반환할 것
  • 저희의 인프라 내에서 완전히 실행되거나 신뢰할 수 있는 엔드포인트 (Endpoint)를 통해 실행될 것

GPU를 위한 Kubernetes 클러스터를 직접 유지 관리하고 싶지는 않았지만, 그렇다고 또 다른 엔터프라이즈 계약을 체결하고 싶지도 않았습니다.

실패했던 시도들 (처참하게)

시도 1: LM Studio + Ollama

Ollama를 통해 Llama 3 8B를 다운로드했습니다. 제 노트북에서 실행되었습니다. 디프 (Diff)를 입력하고 리뷰를 요청하는 Python 스크립트를 작성했습니다. 결과는 어땠을까요? 끔찍했습니다. 모델은 줄 번호를 환각 (Hallucinate)하고, 프롬프트 (Prompt)를 무시하며, 때로는 실행 가능한 피드백 없이 그저 "훌륭한 코드입니다!"라며 횡설수설하기도 했습니다. 게다가 API를 수동으로 처리하고 텍스트 응답을 파싱 (Parse)해야 했습니다. 재현성도 없었습니다.

시도 2: LangChain + 로컬 LLM

LangChain이 당연한 정답처럼 보였습니다. 프롬프트 템플릿 (Prompt template)과 로컬 모델을 사용하여 체인 (Chain)을 설정했습니다. 설정은 투박했고, 의존성 (Dependencies)은 무거웠으며, 구조화된 출력 파서 (Structured output parser)는 계속해서 오류를 일으켰습니다. 마침내 작동했을 때는 리뷰당 지연 시간 (Latency)이 30초 이상 걸렸습니다. 실시간 PR 체크용으로는 사용할 수 없는 수준이었습니다.

시도 3: 호스팅된 "엔터프라이즈" API

데이터 프라이버시(Data privacy)를 보장한다고 약속하는 몇몇 제공업체를 평가해 보았습니다. 대부분은 연간 계약, 전용 엔드포인트(Dedicated endpoint), 그리고 최소 지출 금액을 요구했습니다. 개인 개발자나 소규모 팀에게는 과한(Overkill) 요구사항이었습니다.

마침내 성공한 방법: 구조화된 프롬프트를 활용한 간단한 API 래퍼 (Wrapper)

한 걸음 물러나 생각해보니 핵심 문제는 모델이 아니라 통합 패턴(Integration pattern)이었습니다. 저에게는 다음과 같은 것들이 필요했습니다:

  • 범용 API 인터페이스 (백엔드를 쉽게 교체할 수 있도록 OpenAI 호환 방식)
  • 구조화된 JSON 출력 강제 방법 (로컬 모델을 사용하더라도 함수 호출 (Function calling) 기능 활용)
  • 재시도 (Retry) 및 속도 제한 (Rate limiting) 기능 내장
  • 최소한의 의존성 (Minimal dependencies)

저는 정확히 이 역할을 수행하는 가벼운 Python 모듈을 작성했습니다. 이 모듈은 채팅 완성 (Chat completions) 형식을 지원하는 모든 API 엔드포인트에서 작동합니다. 핵심 코드는 다음과 같습니다.

import json
import time
from typing import Optional
...

response_format 필드가 핵심입니다. 프롬프트를 적절히 작성하고 구조화된 출력을 요청한다면, 훨씬 작은 로컬 모델들도 유효한 JSON을 생성할 수 있습니다. (현재 대부분의 OpenAI 호환 로컬 백엔드는 이 기능을 지원합니다.)

저는 내부용으로 설정한 셀프 호스팅(Self-hosted) 엔드포인트를 통해 이를 테스트했습니다. (예를 들어 https://ai.interwestinfo.com/와 같은 API를 가리키도록 설정했지만, 호환 가능한 어떤 제공업체든 사용할 수 있습니다.) 이 코드는 모델이 GPU 클러스터에 있는지 아니면 라즈베리 파이 (Raspberry Pi)에 있는지 상관하지 않습니다.

CLI 도구로 만들기

위의 기능을 파일이나 파이프(Piped)로 전달된 diff를 입력받는 CLI로 래핑했습니다:

$ cat example.diff | python review.py --endpoint https://my-ai-server.com --api-key $KEY --model code-review-7b

출력:

{
  "summary": "Adds authentication middleware",
  "issues": [
...

이제 어떤 diff든 이 도구에 파이프로 전달하여 구조화된 피드백을 받을 수 있으며, 이를 GitHub Action이나 프리 커밋 훅 (Pre-commit hook)에 통합할 수 있습니다.

교훈 및 트레이드오프 (Trade-offs)

  • 모델의 품질이 크기보다 더 중요합니다. 이 특정 작업에서는 잘 튜닝된 8B 모델이 일반적인 70B 모델보다 더 뛰어난 성능을 보입니다. 저는 하드웨어가 아닌 프롬프트 엔지니어링 (Prompt engineering)에 대부분의 노력을 기울였습니다.
  • 구조화된 출력 (Structured output)은 타협할 수 없는 요소입니다. JSON 모드 (JSON mode)가 없다면 자유 형식의 텍스트 (Free text)를 파싱하는 것은 악몽과 같습니다. 항상 response_format이나 함수 호출 (Function calling)을 사용하세요.
  • 프라이버시(Privacy)가 곧 로컬(Local)을 의미하지는 않습니다. 서명된 데이터 처리 합의서 (Data processing agreement)가 포함된 전용 호스팅 엔드포인트 (Hosted endpoint)는 운영 비용(Ops cost) 없이도 자체 하드웨어에서 실행하는 것만큼이나 프라이빗할 수 있습니다. 저는 직접 만지는 것을 좋아해서 llama.cpp를 사용하는 작은 VPS를 결국 사용하게 되었지만, 많은 팀은 그냥 관리형 엔드포인트 (Managed endpoint)를 구매하는 것이 좋습니다.
  • 지연 시간 (Latency)은 실재합니다. 스트리밍 (Streaming)을 사용하더라도 리뷰 시간이 5~20초 정도 걸리는 것은 정상입니다. CI/CD 환경에서는 괜찮지만, 실시간 댓글 달기에는 짜증스러운 수준입니다.
  • 모든 코드를 LLM이 리뷰할 수 있는 것은 아닙니다. 깊은 아키텍처 결함이나 레이스 컨디션 (Race conditions)? AI가 이를 잡아낼 것이라고 기대하지 마세요. 이 도구는 표면적인 스타일과 명백한 버그를 위한 것입니다.

다음에 다시 한다면 다르게 할 점

  • 가능한 가장 단순한 통합부터 시작하겠습니다. response_format이 이미 존재함에도 불구하고 LangChain의 출력 파서 (Output parser)를 작동시키려다 며칠을 허비했습니다.
  • 프롬프트 견고성 (Prompt robustness)을 위해 더 많은 테스트를 작성하겠습니다. 모델마다 "json_object"를 해석하는 방식이 약간씩 다르며, 어떤 모델은 명시적인 스키마 (Schema) 예시를 필요로 합니다.
  • 핵심 라이브러리를 만든 후에 CLI를 구축하겠습니다. 너무 성급하게 과도한 추상화 (Over-abstracted)를 시도했습니다.

저는 여전히 이 작업을 반복하고 있습니다. 다음 단계는 여러 파일에 대한 배치 리뷰 (Batch review)를 추가하고, 반복적인 확인 속도를 높이기 위해 결과를 캐싱 (Caching)하는 것입니다. 전체 저장소는 단 하나의 Python 파일과 Dockerfile로 구성되어 있습니다. 이것은 제품이 아니라, 단지 저의 갈증을 해결해 준 도구일 뿐입니다.

프라이버시에 민감한 환경에서 AI 기반 코드 리뷰를 어떻게 처리하시나요? 로컬 모델을 실행하시나요, 아니면 제공업체를 신뢰하시나요? 여러분에게 무엇이 효과가 있는지(혹은 없는지) 듣고 싶습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0