본문 바로가기
AI/자동화

Git MR 자동 코드 리뷰 파이프라인 구축

by Machine-Geon 2026. 4. 15.
반응형

Claude Code CLI + GitLab CI를 활용한 MR 자동 리뷰 시스템


전체 흐름

MR 생성 → GitLab CI 트리거 → git diff 추출 → Claude CLI -p → MR 노트 등록

설계 결정 사항

API key vs CLI 구독

Anthropic API key(토큰 과금) 방식도 가능하지만, CI에서 MR마다 전체 diff를 전송하면 비용이 예측하기 어렵다.

Claude Pro/Max 구독의 CLI를 사용하면 구독 한도 내에서 추가 비용 없이 사용 가능하다.

CLAUDE_CODE_OAUTH_TOKEN으로 구독 인증, claude -p non-interactive 모드로 호출

세션 관리 (--resume 고려)

OpenClaw 등에서는 claude -p --resume sessionId로 세션을 유지하며 컨텍스트를 이어가는 방식을 사용한다.

코드 리뷰는 MR 단위로 독립적인 요청이므로 세션 유지가 불필요하다.

→ 매 MR마다 새 프로세스로 실행, --resume 미사용


최초 구축 가이드

1. Node.js 및 Claude Code CLI 설치

Runner 머신(Rocky Linux 9)에 설치한다.

dnf module enable nodejs:20 -y && dnf install nodejs -y
npm install -g @anthropic-ai/claude-code

claude 실행 후 브라우저 OAuth 로그인 (Claude Pro/Max 구독 사용)

2. OAuth 토큰 추출

cat ~/.claude/.credentials.json

claudeAiOauthToken.accessToken 값 복사

3. GitLab CI Variables 등록

프로젝트 → Settings > CI/CD > Variables

Key 설명 Masked
CLAUDE_CODE_OAUTH_TOKEN 2번에서 복사한 accessToken
GITLAB_TOKEN Personal Access Token, api scope

4. Shell Executor Runner 등록

프로젝트 → Settings > CI/CD > Runners → New project runner

태그: mr-code-review-runner

Runner 머신에서 등록:

gitlab-runner register \
  --url https://gitlab.example.com \
  --token <발급받은토큰> \
  --executor shell \
  --non-interactive

gitlab-runner start

5. 프롬프트 파일 작성

프로젝트 루트에 .claude-review-prompt.txt 생성

You are a code reviewer for the Felice project (Kafka monitoring platform), built with Java and Spring Boot.
Review the following git diff and provide feedback in Korean.

[Felice 특화]
- ~~~이 변경된 경우
  반드시 상단에 "⚠️ 프론트엔드 팀 전달 필요: [변경 내용 요약]" 형태로 경고

[JPA]
- N+1 쿼리 가능성
- 카르테시안 곱 (복수 컬렉션 fetch join 동시 사용)
- FetchType.EAGER 남용
- 영속성 컨텍스트 범위 밖 지연 로딩

[보안]
- SQL 인젝션, XSS 가능성
- 민감정보 하드코딩 (비밀번호, API 키 등)
- 인증/인가 누락

[예외 처리]
- 예외 삼키기 (catch 블록이 비어있거나 로그만 찍는 경우)
- NPE 가능성
- 부적절한 예외 타입 사용

[성능]
- 컬렉션 루프 안에서 무거운 연산 또는 DB 호출

[동시성]
- 공유 자원 동기화 누락
- Thread-safe하지 않은 자료구조 사용 (예: HashMap → ConcurrentHashMap)

[메모리]
- 순환참조
- Stream/Connection/리스너 등 자원 미닫기 (메모리 릭)

[가독성/유지보수]
- SRP 위반 (메서드/클래스 책임 과다)
- 매직넘버/매직스트링
- 코드 중복
- 복잡한 로직에 주석 없음
- 컨벤션 위반 (Java, Spring Boot 기준)

[테스트]
- 변경된 로직에 테스트 코드 누락

[출력 형식]
- 문제가 없으면 "✅ 특이사항 없음" 한 줄만 출력
- 문제가 있으면 아래 형식으로만 출력, 칭찬이나 요약 없이 문제점만 나열

  ⚠️ [WARN] 파일명:라인 - 문제 설명
  ℹ️ [INFO] 파일명:라인 - 문제 설명

6. .gitlab-ci.yml 수정

workflow rules에 MR 이벤트 추가:

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: always
    # ... 기존 rules

stages에 review 추가:

stages:
  - build
  - deploy
  - clean
  - sync
  - review

clean 잡 수정 (MR 파이프라인 충돌 방지):

clean:local:docker:images:
  stage: clean
  needs:
    - job: build:docker:image:and:push:local
      optional: true  # 추가

mr-code-review 잡 추가:

mr-code-review:
  stage: review
  tags:
    - mr-code-review-runner
  before_script: []
  variables:
    GIT_DEPTH: 0
  only:
    - merge_requests
  script:
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
    - DIFF=$(git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD)
    - PROMPT=$(cat .claude-review-prompt.txt)
    - REVIEW=$(echo "$DIFF" | claude -p "$PROMPT")
    - |
      curl --request POST \
        "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" \
        --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
        --header "Content-Type: application/json" \
        --data "{\"body\": $(echo "$REVIEW" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}"
  allow_failure: true

다른 프로젝트에 추가하는 방법

Runner는 여러 프로젝트에서 공유할 수 있다. 이미 등록된 Runner를 그대로 활용하면 된다.

1. Runner 공유

프로젝트 → Settings > CI/CD > Runners

기존 mr-code-review-runner를 다른 프로젝트에 할당하거나, Runner 관리자가 프로젝트에 추가한다. Runner 머신에 Claude CLI가 이미 설치되어 있으므로 별도 설치 불필요.

2. CI Variables 등록

Key 설명 Masked
CLAUDE_CODE_OAUTH_TOKEN 공용 계정 accessToken
GITLAB_TOKEN 본인 Personal Access Token, api scope

3. 프롬프트 및 CI 설정 추가

프로젝트 루트에 .claude-review-prompt.txt 추가 (프로젝트 특성에 맞게 수정)

.gitlab-ci.yml에 workflow rules, stages, mr-code-review 잡 추가. 잡의 tagsmr-code-review-runner로 지정.


트러블슈팅

Docker executor에서 claude: not found

기존 Runner가 Docker executor라 컨테이너 안에 Claude CLI 없음 → claude: not found

컨테이너 안에서 설치는 가능하나, OAuth 토큰이 없어 구독 인증 불가.

→ Shell executor Runner를 별도 등록해서 로컬에 설치된 Claude CLI 직접 사용

fatal: no merge base (GIT_DEPTH: 1)

기본 설정 GIT_DEPTH: 1로 shallow clone 시 타겟 브랜치와 머지 베이스를 찾지 못함.

mr-code-review 잡에 GIT_DEPTH: 0 설정으로 full clone

clean 잡이 MR 파이프라인을 블록

clean 잡이 needs: build:docker:image:and:push:local인데 MR 파이프라인엔 해당 잡이 없어 파이프라인 실패.

needs.optional: true 추가


동작 시점

  • MR 생성 시 자동 실행
  • MR 브랜치에 추가 커밋 push 시 자동 실행
  • 일반 브랜치 push, 머지 실행 시에는 동작하지 않음
  • allow_failure: true — 리뷰 잡 실패해도 MR 블록 안 됨

주의사항

  • CLAUDE_CODE_OAUTH_TOKEN은 만료될 수 있어 주기적으로 갱신 필요
  • 공용 계정 사용 시 구독 한도를 팀이 함께 소진. 사용량 증가 시 팀/엔터프라이즈 구독 전환 고려
  • 외부 코드 전송이 우려되는 경우 AWS Bedrock 또는 GCP Vertex AI 경유 검토
  • 스크린샷 등에 토큰 노출 시 즉시 Runner 삭제 후 재발급
반응형