본문으로 바로가기
728x90
반응형
SMALL

로컬 LLM 기반 AI Code Reviewer 구축기 - 단순 코드 리뷰를 넘어 아키텍처 리뷰까지

들어가며

최근 AI 기반 코드 리뷰 도구들이 빠르게 발전하고 있다.

GitHub Copilot, Cursor, Claude Code 같은 도구들은 코드 작성뿐만 아니라 코드 리뷰까지 지원하고 있다.

하지만 실제 프로젝트에서 사용해보니 한 가지 아쉬운 점이 있었다.

"이 변경사항이 현재 프로젝트 아키텍처에 적합한가?"

라는 질문에는 의외로 답변 품질이 높지 않았다.

특히 프로젝트의 설계 원칙이나 레이어 규칙을 모르는 상태에서 PR Diff만 보고 리뷰하기 때문에 종종 일반론적인 피드백이 나왔다.

그래서 직접 GitHub Pull Request 이벤트를 기반으로 동작하는 AI Code Reviewer를 만들어보기로 했다.

목표는 단순했다.

  • PR 생성 시 자동 리뷰
  • 코드 품질 리뷰
  • 프로젝트 아키텍처 리뷰
  • 로컬 LLM 기반 운영
  • GitHub Comment 자동 작성

시스템 아키텍처

전체 구조는 다음과 같다.

GitHub PR 생성

      │

      ▼

Webhook 수신

      │

      ▼

PR Diff 수집

      │

      ▼

Review Context 생성

      │
      ├── Diff
      ├── 변경 파일 전체 코드
      ├── AGENTS.md
      └── Package Tree

      ▼

Local LLM

      │
      ├── Code Review
      └── Architecture Review

      ▼

Review Merge

      ▼

GitHub Comment 작성

기술 스택은 다음과 같다.

  • Spring Boot 3
  • Spring AI
  • Ollama
  • Qwen3 30B
  • GitHub Webhook
  • GitHub REST API

왜 Diff만으로는 부족했을까?

처음 구현은 매우 단순했다.

GitHub Webhook으로 PR 생성 이벤트를 수신한 후 Diff를 그대로 LLM에게 전달했다.

PR Diff
   ↓
LLM
   ↓
Review

코드 리뷰 품질은 꽤 괜찮았다.

예를 들어

  • Null 처리 누락
  • 예외 처리 부족
  • 테스트 코드 필요
  • 성능 문제

등은 잘 찾아냈다.

하지만 아키텍처 리뷰는 이상했다.

예를 들면

PullRequestReviewService

내부에 새로운 책임이 추가되었는데도

전반적으로 구조가 양호합니다.

같은 답변이 나왔다.

곰곰이 생각해보니 이유는 명확했다.

LLM은 현재 변경된 몇 줄만 보고 있었다.

즉,

  • 이 클래스가 원래 어떤 역할인지
  • 같은 패키지에 어떤 클래스가 있는지
  • 프로젝트 설계 원칙이 무엇인지

전혀 모르는 상태였다.


코드 리뷰와 아키텍처 리뷰를 분리하다

이 문제를 해결하기 위해 리뷰를 두 종류로 나누었다.

Code Review

입력

PR Diff

검토

  • 버그 가능성
  • 예외 처리
  • 성능
  • 가독성
  • 테스트 필요성

Architecture Review

입력

PR Diff
+ 변경 파일 전체 코드
+ Package Tree
+ AGENTS.md

검토

  • 계층 분리
  • 책임 분산
  • Service 비대화
  • 외부 API 호출 위치
  • 테스트 가능성
  • 프로젝트 규칙 위반 여부

AGENTS.md 도입

가장 효과가 좋았던 개선은 AGENTS.md였다.

프로젝트 루트에 다음과 같은 규칙 파일을 추가했다.

# Architecture Rules

- Controller는 HTTP 처리만 담당한다.
- Service는 유스케이스 조율만 담당한다.
- 외부 API 호출은 Client 계층에 둔다.
- Prompt 생성은 PromptBuilder에 둔다.

리뷰 시 이 파일을 읽어서 프롬프트에 포함한다.

[PROJECT_RULES]
AGENTS.md

[PR_DIFF]
...

[CHANGED_FILE_SOURCE]
...

[PACKAGE_TREE]
...

이후부터는 단순한 코드 품질 리뷰가 아니라

"현재 프로젝트 규칙을 위반하는지"

를 판단하기 시작했다.


변경 파일 전체 코드 수집

아키텍처 리뷰에서 가장 중요한 컨텍스트였다.

Diff만 보면

+ private final GithubClient githubClient;

정도만 보인다.

하지만 전체 클래스를 보면

PullRequestReviewService
 ├─ Diff 조회
 ├─ LLM 호출
 ├─ Comment 작성
 └─ Prompt 생성

처럼 책임 과다 문제를 발견할 수 있다.

GitHub API를 이용해 변경 파일의 최신 코드를 수집하도록 개선했다.


프로젝트 규칙을 모르는 AI는 좋은 리뷰어가 아니다

이번 프로젝트에서 얻은 가장 큰 교훈이다.

AI는 똑똑하지만 프로젝트를 모른다.

프로젝트가

Controller
  ↓
Service
  ↓
Client

구조를 따르는지,

DDD를 사용하는지,

Hexagonal Architecture를 사용하는지,

알 수 없다.

그래서 좋은 AI 리뷰를 만들기 위해서는

"좋은 모델"

보다

"좋은 컨텍스트"

가 훨씬 중요했다.


앞으로 개선할 내용

현재는 다음 단계까지 구현했다.

  • GitHub Webhook
  • PR Diff 수집
  • Local LLM 연동
  • Code Review
  • Architecture Review
  • GitHub Comment 작성

앞으로는 다음 기능을 추가할 예정이다.

RAG 기반 프로젝트 컨텍스트 검색

PR Diff
   ↓
Vector Search
   ↓
관련 코드 검색
   ↓
LLM

테스트 결과 기반 리뷰

Gradle Test
    ↓
실패 테스트
    ↓
LLM

프로젝트 히스토리 기반 리뷰

과거 PR
과거 버그
과거 설계 결정

을 참고하는 리뷰 환경 구축


마치며

AI 코드 리뷰어를 만들면서 느낀 점은 하나였다.

AI 리뷰 품질은 모델 크기로 결정되지 않는다.

얼마나 많은 프로젝트 컨텍스트를 제공하느냐가 더 중요하다.

Diff만 보는 리뷰어와

프로젝트 규칙, 전체 코드, 패키지 구조를 이해하는 리뷰어는 전혀 다른 결과를 만든다.

이번 프로젝트는 단순히 LLM을 붙이는 것이 아니라,

"프로젝트를 이해하는 AI 리뷰어"를 만드는 과정이었다.

728x90
반응형
LIST