Tips & Tricks (업데이트: 2026. 6. 2.)

Claude Code로 팀 코드 리뷰 흐름 만들기

Claude Code로 위험 기반 PR 리뷰를 만들고 PR 템플릿, CI 게이트, CODEOWNERS까지 연결합니다.

Claude Code로 팀 코드 리뷰 흐름 만들기

Claude Code를 코드 리뷰에 쓰는 목적은 사람 리뷰어를 대체하는 것이 아닙니다. 목적은 PR의 위험을 먼저 정리하고, 빠진 테스트와 위험한 변경을 드러내며, 사람이 아키텍처와 비즈니스 판단에 집중하도록 만드는 것입니다.

팀에서 쓰려면 즉흥적으로 “이 PR 리뷰해줘”라고 묻는 것만으로는 부족합니다. PR 템플릿, CLAUDE.md 리뷰 규칙, diff 크기 검사, GitHub Actions, CODEOWNERS, 고정 리뷰 프롬프트를 하나의 흐름으로 묶어야 합니다. 공식 문서는 Claude Code common workflows, GitHub pull request 문서, CODEOWNERS, GitHub Actions workflow syntax, OWASP Code Review Guide를 참고하세요.

리뷰 구조

위험 기반 리뷰는 모든 줄을 같은 강도로 보지 않는 방식입니다. 인증, 권한, 결제, 데이터 마이그레이션, 성능, 테스트 누락에 더 많은 시간을 씁니다. diff scope는 이번 PR에서 실제로 바뀐 범위입니다. CI gate는 조건을 만족하지 않는 PR을 자동으로 막거나 경고하는 검사입니다. hallucinated finding은 diff에 근거가 없는데도 AI가 그럴듯하게 만든 지적입니다.

flowchart LR
  A["PR template"] --> B["Diff size gate"]
  B --> C["Claude Code review"]
  C --> D["Code owner review"]
  D --> E["CI tests and merge"]
  C --> F["Questions before fixes"]

가장 중요한 원칙은 Claude Code가 리뷰 중 조용히 코드를 고치지 않게 하는 것입니다. 의도, 데이터 계약, 권한 정책이 불명확하면 버그라고 단정하지 말고 질문해야 합니다.

실제 사용 사례

첫째, 인증과 권한 변경입니다. 로그인, 세션, 역할, 관리자 화면, API key를 만지는 PR에서는 권한 누락, 권한 상승, secret 노출, 감사 로그 누락을 Claude Code가 먼저 확인하게 합니다. 비즈니스 규칙이 맞는지는 사람이 판단합니다. 보안 흐름은 보안 감사 자동화와 함께 보세요.

둘째, 성능 민감 변경입니다. 검색, 목록, 캐시, 이미지 처리, 배치 작업은 N+1 쿼리, 반복 렌더링, 캐시 키 충돌, 큰 payload가 숨어 있을 수 있습니다. 좋은 리뷰는 “어떤 입력 크기에서 느려지는지”와 “어떻게 측정할지”를 말해야 합니다.

셋째, 테스트와 데이터 마이그레이션입니다. schema, migration, seed, validation, backfill 변경은 롤백, 기존 데이터, nullable 필드, unique 제약, 실패 후 재실행을 봐야 합니다. Claude Code가 빠진 테스트와 위험 케이스를 먼저 정리하고, 데이터 담당자가 최종 판단합니다.

넷째, 너무 큰 PR입니다. diff가 800에서 1000줄을 넘으면 리뷰 품질이 떨어집니다. CI는 크기를 감지하고, Claude Code는 기능, migration, UI, 테스트 단위로 나누는 방법을 제안할 수 있습니다.

PR 템플릿

.github/pull_request_template.md를 만듭니다.

## Change summary
- What changed:
- Why it changed:
- User-visible impact:

## Risk review
- [ ] Security impact checked
- [ ] Performance impact checked
- [ ] Test coverage added or explained
- [ ] Data migration or rollback plan checked
- [ ] No secrets, tokens, or personal data included

## Claude Code review request
Please review this PR by diff scope only.

Focus on:
- Security: auth, authorization, injection, secret leakage
- Performance: N+1 queries, cache keys, unnecessary work
- Tests: missing unit, integration, and migration tests
- Data: schema changes, rollback, backfill safety

For each finding, include:
- file and line
- why it matters
- evidence from the diff
- suggested fix or question for the author

diff scope only라는 문구가 중요합니다. 저장소 전체에 대한 일반론이 아니라 이번 PR에 있는 증거로 리뷰하게 만듭니다.

CLAUDE.md 규칙

CLAUDE.md에 팀의 리뷰 기준을 적습니다. 이 파일은 Claude Code가 참고하는 프로젝트 메모입니다. 더 넓은 운영은 CLAUDE.md 베스트 프랙티스를 참고하세요.

## Code review rules

Review only the current diff unless the user asks for wider context.

Severity:
- Must fix: security bug, data loss, broken build, failed test, migration risk
- Should fix: likely production bug, missing important test, measurable performance issue
- Nice to have: naming, small cleanup, optional refactor

Evidence rule:
- Every finding must cite a file and line.
- If the evidence is uncertain, ask a question instead of asserting a bug.
- Do not invent dependencies, routes, database columns, or team policies.

Security checks:
- Authentication and authorization
- SQL or command injection
- XSS and unsafe HTML
- Secret leakage
- Missing audit log for privileged actions

Data checks:
- Migration rollback path
- Backfill failure behavior
- Existing nullable and unique constraints
- PII handling and retention

증거 규칙은 AI 리뷰의 품질을 크게 올립니다. 파일과 줄, 이유가 없는 지적은 질문으로 낮추는 것이 좋습니다.

Diff Gate 스크립트

scripts/review-diff-gate.mjs로 저장합니다.

#!/usr/bin/env node
import { execSync } from "node:child_process";

const baseRef = process.env.BASE_REF || "origin/main";
const maxFiles = Number(process.env.MAX_REVIEW_FILES || 25);
const maxLines = Number(process.env.MAX_REVIEW_LINES || 800);

function git(command) {
  return execSync(command, { encoding: "utf8" }).trim();
}

const files = git(`git diff --name-only ${baseRef}...HEAD`)
  .split(/\r?\n/)
  .filter(Boolean);

const numstat = git(`git diff --numstat ${baseRef}...HEAD`);
const changedLines = numstat
  .split(/\r?\n/)
  .filter(Boolean)
  .reduce((total, line) => {
    const [added, deleted] = line.split(/\s+/);
    return total + (Number(added) || 0) + (Number(deleted) || 0);
  }, 0);

const riskyPatterns = [
  /^src\/auth\//,
  /^src\/billing\//,
  /^db\/migrations\//,
  /^infra\//,
  /^\.github\/workflows\//,
];

const riskyFiles = files.filter((file) =>
  riskyPatterns.some((pattern) => pattern.test(file))
);

let failed = false;

if (files.length > maxFiles) {
  console.error(`Too many files changed: ${files.length} > ${maxFiles}`);
  failed = true;
}

if (changedLines > maxLines) {
  console.error(`Too many changed lines: ${changedLines} > ${maxLines}`);
  failed = true;
}

if (riskyFiles.length > 0) {
  console.log("Risk-sensitive files changed:");
  for (const file of riskyFiles) console.log(`- ${file}`);
}

if (failed) {
  console.error("Split the PR or add a reviewer-approved exception.");
  process.exit(1);
}

console.log(`Review gate passed: ${files.length} files, ${changedLines} lines.`);

로컬 실행:

BASE_REF=origin/main MAX_REVIEW_FILES=25 MAX_REVIEW_LINES=800 node scripts/review-diff-gate.mjs

GitHub Actions와 CODEOWNERS

.github/workflows/review-gate.yml에 같은 검사를 둡니다.

name: review-gate

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  diff-gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: "22"

      - name: Run diff size gate
        env:
          BASE_REF: origin/${{ github.base_ref }}
          MAX_REVIEW_FILES: "25"
          MAX_REVIEW_LINES: "800"
        run: node scripts/review-diff-gate.mjs

위험한 영역은 .github/CODEOWNERS로 담당자에게 보냅니다.

# .github/CODEOWNERS
/src/auth/ @example-org/security
/src/billing/ @example-org/payments
/db/migrations/ @example-org/backend-leads
/.github/workflows/ @example-org/platform
/infra/ @example-org/platform

CI 설계는 CI/CD 설정 가이드, PR 품질 운영은 PR 품질 개선을 함께 보면 좋습니다.

리뷰 프롬프트

Review the current PR diff against main.

Rules:
1. Stay inside the diff scope unless a referenced file is required.
2. Do not rewrite code silently.
3. For each finding, include file, line, severity, evidence, and suggested action.
4. If business intent or data contract is unclear, ask a question instead of guessing.
5. Ignore style-only preferences unless they break CLAUDE.md or project conventions.

Focus areas:
- Security: auth, authorization, injection, XSS, secrets, audit logs
- Performance: N+1 queries, cache invalidation, repeated rendering, large payloads
- Tests: missing coverage for changed behavior, migrations, and edge cases
- Data migration: rollback, backfill, nullable fields, unique constraints
- CI and ownership: required checks, CODEOWNERS, risky paths

Output:
## Must fix
## Should fix
## Questions
## No issue found in

함정과 검증 메모

첫 번째 함정은 리뷰와 수정을 한 번에 맡기는 것입니다. 발견의 타당성을 확인하기 전에 diff가 더 커집니다. 먼저 리뷰하고, 사람이 고칠 항목을 고른 뒤, 테스트를 실행하세요.

두 번째 함정은 근거 없는 지적을 받아들이는 것입니다. 파일, 줄, 변경된 동작을 설명하지 못하면 질문으로 취급합니다.

세 번째 함정은 migration을 가볍게 보는 것입니다. 테스트가 통과해도 운영 데이터가 안전하다는 뜻은 아닙니다. 기존 NULL, 중복값, 락 시간, rollback 한계, backfill 재시도를 확인하세요.

이 글의 예시는 작은 저장소 흐름으로 확인했습니다. Node 스크립트는 Git과 Node 22만 필요하고, GitHub Actions는 같은 스크립트를 실행합니다. 팀에 도입할 때는 위험 경로, 담당자, 테스트 명령을 바꾼 뒤 한 PR에서 먼저 시험하세요. 다음 단계는 커밋 전 리뷰 게이트 체크리스트를 보며 표준화하면 됩니다.

#Claude Code #code review #quality assurance #team development #best practices
무료

무료 PDF: Claude Code 치트시트

이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.

개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.

Masa

작성자 소개

Masa

Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.