|
1 | | -# code-review |
| 1 | +# AI Code Reviewer |
2 | 2 |
|
3 | | -Kotlin과 Spring Boot 기반으로 만든 자동 코드 리뷰 서비스로, PR에 포함된 변경 내용을 분석하여 LLM을 통해 리뷰 코멘트를 생성하고 GitHub에 자동으로 남긴다. 리뷰 생성 실패 시 재시도까지 관리하여 일관된 코드 리뷰 자동화를 제공한다. |
4 | | - |
5 | | ---- |
| 3 | +Kotlin, Spring Boot, Google Gemini 기반의 AI 코드 리뷰 어시스턴트입니다. GitHub 앱으로 동작하여 Pull Request에 대한 요약과 상세 리뷰를 자동으로 제공합니다. |
6 | 4 |
|
7 | 5 | ## 프로젝트 개요 |
8 | 6 |
|
9 | | -이 프로젝트는 GitHub Pull Request 이벤트(Webhook)를 받아 변경된 파일의 diff를 분석한 뒤, Google GenAI를 활용해 리뷰 코멘트를 생성하고 GitHub API를 통해 자동으로 리뷰를 남기는 시스템이다. 리뷰 생성 과정에서 발생할 수 있는 요청 한도 초과(429)·서버 오류(503) 같은 상황은 내부 재시도 큐에서 관리하여 안정적으로 처리한다. |
10 | | - |
11 | | ---- |
12 | | - |
13 | | -## CodeReview 프로세스 |
14 | | - |
15 | | -1. **PR 발생 → Webhook 수신** |
16 | | - GitHub Webhook이 PR 이벤트 정보를 서버로 전달한다. |
17 | | - |
18 | | -2. **Diff 수집 및 분석** |
19 | | - PR의 변경 파일을 조회하고 파일 단위로 diff snippet을 분리한다. |
| 7 | +이 프로젝트는 Github Pull Request(PR)의 코드 변경 사항을 분석하고, Google Gemini API를 통해 리뷰 코멘트를 생성하여, Github에 게시해줍니다. |
| 8 | +기본적으로 PR 생성 시 변경 사항을 요약해주고, `review-bot` 라벨을 통해 요청 시 상세 리뷰를 수행합니다. |
20 | 9 |
|
21 | | -3. **리뷰 생성 요청(LLM 호출)** |
22 | | - 파일별 diff snippet을 기반으로 프롬프트를 구성해 Google GenAI 모델에 리뷰 생성을 요청한다. |
| 10 | +## 주요 기능 |
23 | 11 |
|
24 | | -4. **GitHub에 리뷰 코멘트 등록** |
25 | | - 생성된 리뷰 코멘트를 GitHub Pull Request에 자동으로 작성한다. |
| 12 | +- **PR 변경점 자동 요약**: PR이 열리면 전체 변경 사항을 요약하여 PR에 코멘트로 남겨줍니다. |
| 13 | +- **요청 기반 상세 리뷰**: PR에 `review-bot` 라벨을 추가하면, 파일별로 상세 코드 리뷰를 진행하고 **파일 코멘트**를 작성합니다. |
| 14 | +- **안정적인 비동기 처리**: Kotlin Coroutine과 Channel을 사용한 내부 작업 큐를 통해 리뷰 요청을 순차적으로 처리하여, GitHub API와 LLM API의 Rate Limit에 대응합니다. |
| 15 | +- **지능적인 Diff 분석**: `import` 구문 변경이나 파일 삭제, 공백 등 의미 없는 변경 사항은 필터링하여 핵심 로직에만 집중합니다. |
| 16 | +- **고품질 리뷰 프롬프트**: '시니어 테크 리드' 페르소나를 적용한 정교한 시스템 프롬프트를 통해 깊이 있고 일관된 품질의 리뷰를 생성합니다. |
| 17 | +- **GitHub 앱 기반 인증**: 안전한 GitHub 앱 인증(JWT) 방식을 사용하여 각 리포지토리에 대한 작업을 수행합니다. |
26 | 18 |
|
27 | | -5. **오류 발생 시 재시도 큐로 이동** |
28 | | - - 모델 응답 지연, 429/503 등 재시도가 필요한 오류는 재시도 큐에 적재 |
29 | | - - 일정 간격으로 스케줄러가 큐를 실행하여 재리뷰 시도 |
30 | | - - 최대 재시도 횟수 초과 시 실패 로그만 남기고 종료 |
| 19 | +## 동작 방식 |
31 | 20 |
|
32 | | -이 구조를 통해 PR 하나의 리뷰가 파일 단위로 병렬 처리되고, 장애 상황에서도 안정적으로 완료될 수 있도록 설계되어 있다. |
| 21 | +1. **Webhook 수신 (`CodeReviewController`)** |
| 22 | + - GitHub로부터 `pull_request` 이벤트를 수신합니다. |
| 23 | + - `X-Hub-Signature-256` 헤더를 통해 요청이 유효한지 검증합니다. |
33 | 24 |
|
34 | | ---- |
| 25 | +2. **이벤트 라우팅 (`CodeReviewFacade`)** |
| 26 | + - **PR `opened` 액션**: `CodeSummaryService`를 호출하여 PR 요약 생성을 시작합니다. |
| 27 | + - **`labeled` 액션 (`review-bot` 라벨)**: `ReviewJobQueue`에 상세 리뷰 작업을 추가합니다. |
35 | 28 |
|
36 | | -## 사용 기술 스택 |
| 29 | +3. **PR 요약 생성 (`CodeSummaryService`)** |
| 30 | + - `GithubDiffClient`를 통해 PR의 diff 내용을 가져옵니다. |
| 31 | + - 전체 diff를 기반으로 요약 프롬프트를 구성하여 Gemini 모델을 호출합니다. |
| 32 | + - 생성된 요약 텍스트를 `GithubReviewClient`를 통해 PR에 일반 코멘트로 등록합니다. |
37 | 33 |
|
38 | | -- **언어 및 런타임** |
39 | | - Kotlin 1.9, JVM 21 |
| 34 | +4. **상세 코드 리뷰 (`ReviewJobQueue` & `CodeReviewService`)** |
| 35 | + - 백그라운드 워커가 큐에서 리뷰 작업을 가져옵니다. |
| 36 | + - `GithubDiffUtils`가 diff 텍스트를 파일 단위로 파싱하고, 리뷰가 불필요한 변경(import 등)을 필터링합니다. |
| 37 | + - `CodeReviewService`는 각 코드 변경 청크(chunk)에 대해 Gemini 모델을 호출하여 리뷰를 생성합니다. |
| 38 | + - `Semaphore`를 사용하여 LLM API 동시 요청 수를 제어합니다. |
| 39 | + - API 호출 후 일정 시간(`delay`)을 두어 Rate Limit을 준수합니다. |
| 40 | + - `GithubReviewClient`가 생성된 리뷰를 PR의 해당 코드 라인에 코멘트로 등록합니다. |
40 | 41 |
|
41 | | -- **프레임워크** |
42 | | - Spring Boot 3.5(Web + WebFlux), Kotlin Coroutine, Reactor |
| 42 | +## 인증 방식 |
43 | 43 |
|
44 | | -- **AI 모델** |
45 | | - Google GenAI Java SDK(LLM 기반 리뷰 생성) |
| 44 | +- **GitHub Webhook Secret**: Webhook 페이로드의 무결성을 검증하기 위해 사용됩니다. |
| 45 | +- **GitHub App Authentication**: |
| 46 | + - 리뷰 코멘트 작성 등 리포지토리에 대한 작업을 수행하기 위해 GitHub 앱으로 인증합니다. |
| 47 | + - `GithubAppTokenProvider`가 앱의 Private Key로 JWT를 생성하고, 이를 일시적인 Installation Token으로 교환하여 API 요청에 사용합니다. |
| 48 | +- **GitHub PAT (Personal Access Token)**: |
| 49 | + - `GithubDiffClient`에서 PR의 diff 정보를 가져오는 등 간단한 읽기 전용 작업에 사용됩니다. 현재는 App 인증과 별도로 관리되고 있습니다. |
46 | 50 |
|
47 | | -- **데이터 처리** |
48 | | - Jackson Kotlin Module, Reactor Extensions |
| 51 | +## 기술 스택 |
49 | 52 |
|
50 | | -- **인증/보안** |
51 | | - GitHub App 인증(JWT + Installation Token), JJWT 기반 서명 처리 |
52 | | - |
53 | | -- **CI/CD 및 배포** |
54 | | - GitHub Actions(self-hosted runner), Docker Buildx, Docker Hub, EC2 |
55 | | - |
56 | | ---- |
| 53 | +- **언어 및 프레임워크**: Kotlin 1.9, Spring Boot 3 (Web + WebFlux), Coroutine |
| 54 | +- **AI 모델**: Google Gemini (google-genai Java SDK) |
| 55 | +- **인증/보안**: GitHub Apps (JWT), JJWT |
| 56 | +- **데이터 처리**: Jackson Kotlin Module |
| 57 | +- **CI/CD 및 배포**: GitHub Actions, Docker (Buildx), EC2 |
57 | 58 |
|
58 | 59 | ## 배포 프로세스 |
59 | 60 |
|
60 | | -1. **Build Job** |
61 | | - - self-hosted Runner에서 Gradle 빌드 |
62 | | - - JAR 파일 생성 후 아티팩트 업로드 |
63 | | - |
64 | | -2. **Dockerize Job** |
65 | | - - 다운로드한 JAR을 기반으로 Docker 이미지를 빌드 |
66 | | - - Buildx를 사용해 `linux/amd64` 와 `linux/arm64` 멀티 아키텍처 이미지 생성 |
67 | | - - Docker Hub로 push |
68 | | - |
69 | | -3. **Deploy Job** |
70 | | - - SSH로 EC2에 연결 |
71 | | - - 환경변수를 전달하고 `code-review-deploy.sh` 실행 |
72 | | - - 기존 컨테이너 중지 후 최신 이미지로 재배포 |
73 | | - - 자동 재시작 설정으로 운영 환경 안정성 확보 |
74 | | - |
75 | | -이 파이프라인을 통해 PR → LLM 리뷰 생성 → GitHub 코멘트 작성 → 장애 시 재시도 → 자동화된 Docker 배포까지 전 과정이 자동으로 이어진다. |
| 61 | +<img width="1024" height="523" alt="Image" src="https://github.com/user-attachments/assets/cec29ab5-c2b1-49f3-a6c5-131c419c2660" /> |
76 | 62 |
|
77 | 63 | ## 사용 API Document |
78 | 64 |
|
79 | 65 | - [Google GenAI](https://github.com/google-gemini/cookbook) |
80 | 66 | - [Github Webhook](http://docs.github.com/webhooks) |
81 | 67 | - [Get Pull Request Diff](https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request) |
82 | | -- [Pull Request Comment](https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#create-a-review-comment-for-a-pull-request) |
| 68 | +- [Pull Request Comment](https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#create-a-review-comment-for-a-pull-request) |
0 commit comments