LabHub

블로그

코드 리뷰와 Merge 파이프라인의 현대 — PR·Merge Queue·Stacked PRs·Monorepo·AI Review·Trunk-Based·Husky·Semgrep 심층 가이드 (2025)

한국어English日本語

코드 리뷰는 우리 직업의 절반이다 — 왜 거의 안 얘기하나

엔지니어가 하루에 PR 3~5개를 리뷰한다고 치자. 주 5일, 연 50주면 연간 1,000개에 달한다. 새로운 기능을 만드는 시간보다 남의 코드를 읽고 판단하고 제안하는 시간이 더 많을 수도 있다. 그런데 우리는 코드 리뷰에 대해 놀라울 정도로 적게 말한다. "리뷰 받는 게 무서워서 PR 크기를 키운다", "승인 못 받고 2주 묵힌다", "리뷰어가 못 찾은 버그로 장애 남", "AI 리뷰가 자동 스팸" 같은 일이 매일 일어난다.

2025년 그 풍경이 격변하고 있다. Cursor·Copilot Review·CodeRabbit·Greptile 같은 AI 리뷰어가 "1차 리뷰는 기계가" 시대를 열었고, Graphite·Sapling·Jujutsu가 Stacked PRs를 주류 워크플로로 끌어올렸으며, Merge Queue가 GitHub 기본 기능이 되었다. Monorepo 도구(Nx·Turborepo·Moon·Bazel·Buck2)도 세대 교체됐다. Trunk-based Development가 "이상"에서 "기본"으로 움직였다.

이 글은 그 2025년 코드 리뷰와 Merge 파이프라인을 낱낱이 본다.

이 글은 앞선 Platform EngineeringObservability 글의 연장선이다. 플랫폼이 "셀프 서비스 제공"이라면, 코드 리뷰는 "코드 변경의 품질 게이트"다.

1부. PR의 사회학 — 블로커가 되지 않는 법

1.1 리뷰가 괴로운 진짜 이유

1.2 좋은 PR의 4요소

  1. 작은 단위 — 400줄 이하 권장 (연구상 결함 탐지 효율 최대 지점)
  2. 한 가지 변경 — 리팩토링과 기능을 섞지 말기
  3. 맥락을 본문에 — "무엇을, 왜, 어떻게 테스트했는가"
  4. Self-review 먼저 — 열자마자 작성자가 먼저 코멘트 달기

1.3 좋은 리뷰어의 4원칙 (Google Code Review Guide 요약)

1.4 Conventional Comments

블로킹 의도와 강도를 접두사로 표시해 감정을 제거.

praise: 테스트 케이스 꼼꼼해요
nitpick: 이름이 더 명확할 수 있음 - userId → userIdentifier
suggestion: 이 부분을 util로 빼면 재사용이 쉬울 것 같습니다
issue: 이 상태에서 race condition 가능 - TOCTOU
thought: 나중에 A/B 테스트가 필요할까요?
question: 이 리트라이 횟수가 3인 이유가 있나요?

2부. Code Owner와 Reviewer Assignment

2.1 CODEOWNERS 파일

# /auth/** 는 security 팀이 필수 리뷰
/auth/**                        @org/security
/packages/payments/**           @org/payments-team
/infrastructure/terraform/**    @org/platform
*.md                            @org/docs

2.2 자동 리뷰어 선정 도구

2.3 리뷰 부하 평형

3부. Merge Queue — 2024~2025 기본값

3.1 문제

3.2 Merge Queue가 하는 일

  1. 머지 요청을 큐에 담음
  2. 큐 헤드에서 "현재 main + 이 PR"을 시뮬레이션 빌드
  3. 통과하면 실제 머지
  4. 실패하면 작성자에게 돌려보냄

Google·Facebook이 내부적으로 10년 넘게 써온 방식. 2023년 GitHub 네이티브, 2024년 기본 권장.

3.3 도구들

3.4 Batched Merge

대형 모노레포는 한 번에 여러 PR을 배치. 실패하면 이분 탐색(bisect)으로 원인 PR 골라내기. Meta·Google 수준에서만 필요.

4부. Stacked PRs — 대형 변경을 작게 쪼개는 법

4.1 문제

4.2 해결

변경을 여러 PR로 쌓아서(stack) 각각 작게. 앞 PR이 머지되면 다음 PR이 자동으로 main에 rebase.

main ← PR1 (스키마 추가)PR2 (API 추가)PR3 (UI 추가)

각 PR을 독립적으로 리뷰. 다만 스택 관리가 수동이면 rebase 지옥.

4.3 도구들

4.4 Jujutsu가 주목받는 이유

5부. Monorepo vs Polyrepo — 2025년 결론

5.1 언제 Monorepo가 이기나

5.2 언제 Polyrepo가 이기나

5.3 실전 합의

Google/Meta는 10만명 monorepo. 스타트업은 "작게 시작 → 크기 커지면 monorepo로 병합"이 흔함. 2024~2025 트렌드는 "서비스는 monorepo, 오픈소스 라이브러리만 별도 레포".

5.4 Monorepo 필수 조건

  1. 빠른 빌드 캐시 (Remote Cache)
  2. Affected Detection — 변경된 프로젝트만 빌드/테스트
  3. Merge Queue — 대용량 PR 병렬 머지
  4. Code Owner 자동 라우팅
  5. 규모별 Git 관리 — Git partial clone, Git LFS, VFS

6부. 모노레포 빌드 도구 — Nx·Turborepo·Moon·Bazel·Buck2·Pants·Lerna 종말

6.1 JavaScript/TypeScript 중심

6.2 언어 중립

6.3 선택 트리

6.4 Remote Cache

모든 도구의 공통 승부처. Turborepo/Nx는 Vercel/Nx Cloud, Bazel은 BuildBuddy/Remote Build Execution, Buck2는 자체 프로토콜. 팀에서 5분 걸리던 CI가 30초로 줄어든 사례는 대부분 Remote Cache 덕분.

7부. AI 코드 리뷰 — 2024~2025 폭발

7.1 AI가 잘하는 것

7.2 AI가 못하는 것

7.3 도구들

7.4 AI 리뷰 도입 실무 팁

8부. Trunk-based Development

8.1 정의

8.2 왜 이기나

8.3 Git Flow의 사망

8.4 Feature Flag 기반 개발

9부. Git 기술 — Rebase·Squash·Linear History

9.1 Merge vs Rebase 논쟁

9.2 팀별 정책

9.3 공용 브랜치에서 force-push 금지

git rebasegit push --force는 팀 공용 브랜치에서 재앙. --force-with-lease로 방어. 최근 GitHub은 Protected Branch에서 force-push 기본 차단.

9.4 Conventional Commits

feat(auth): add passkey support
fix(payments): handle stripe timeout
refactor(db): extract repository interface
chore: bump deps
docs: update README

10부. Pre-commit·Pre-push 훅 — 로컬에서 CI 빠르게

10.1 Hook 매니저

10.2 필수 훅 세트

repos:
  - repo: local
    hooks:
      - id: lint
        name: eslint
        entry: pnpm lint --fix
        language: system
      - id: typecheck
        entry: pnpm typecheck
        language: system
      - id: test
        entry: pnpm test:affected
        language: system
      - id: secrets
        entry: gitleaks protect --staged
        language: system

10.3 훅이 싫어지는 이유와 해결

11부. 정적 분석 — Semgrep·SonarQube·CodeQL·ESLint

11.1 Semgrep

11.2 SonarQube / SonarCloud

11.3 GitHub CodeQL

11.4 ESLint·Biome·Oxlint

11.5 보안 특화

12부. CI 속도 — PR 머지가 10분 이하여야 하는 이유

12.1 Compound effect

12.2 개선 전략

12.3 Flaky Test

13부. 실전 — 팀 크기별 코드 리뷰 파이프라인

13.1 5명 팀

13.2 50명 팀

13.3 500명+

14부. 체크리스트 12 · 안티패턴 10

✅ 체크리스트 12

  1. 평균 PR 크기가 400줄 이하인가?
  2. PR 머지까지 P50 24시간 이하인가?
  3. CODEOWNERS가 최신이고 작동하는가?
  4. Merge Queue가 붙어 있어 semantic conflict가 차단되는가?
  5. Stacked PRs가 팀 일반 워크플로인가?
  6. Conventional Commits가 적용되는가?
  7. pre-commit/pre-push 훅이 빠르고(10초 이내) 유용한가?
  8. Biome/Oxlint 같은 빠른 linter로 전환했는가?
  9. CI가 평균 10분 이하에 끝나는가?
  10. Flaky test 탐지/격리 시스템이 있는가?
  11. AI 리뷰어 스팸 비율이 5% 이하인가?
  12. Trunk-based + Feature Flag가 표준인가?

⚠️ 안티패턴 10

  1. 1,000줄 PR을 "검토"했다고 서명
  2. PR 제목·본문 비어 있음
  3. Long-lived feature branch 1개월 이상
  4. --no-verify로 훅 습관적 우회
  5. AI 리뷰 승인만 받고 머지
  6. Merge Queue 없이 동시 머지 → silent conflict
  7. Flaky test를 if (retryCount < 3)로 덮음
  8. CODEOWNERS 미관리 → 자동 리뷰어가 유령 계정
  9. 팀 전체의 리뷰가 한 시니어에게 집중
  10. Rebase/Squash 정책이 팀 내 불일치 → 이력 혼란

다음 글 예고 — "엔지니어링 블로그의 시대: 기술 글쓰기·RFC·ADR·Design Doc·블로그 운영·커뮤니케이션" — 글을 잘 쓰는 엔지니어가 이기는 이유

코드 리뷰를 얘기했다면 다음은 기술 글쓰기다. RFC, ADR, Design Doc, 사내 위키, 외부 블로그. 글 잘 쓰는 엔지니어는 영향 반경이 10배다.

코드는 결국 사람들 사이에서 살아남는다. 다음 글에서 그 생존 전략을 본다.

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다