Skip to content

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

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

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

엔지니어가 하루에 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,000줄 PR은 누구도 제대로 못 봄
  • 맥락이 부족 — 왜 이 변경이 필요한지 본문에 안 적혀 있음
  • 감정이 실린다 — "이렇게 하면 안 됩니다"는 공격처럼 읽힘
  • 비동기 핑퐁 — 한 번 주고받기에 24시간씩 → 1주일 묵힘

1.2 좋은 PR의 4요소

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

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

  • 원저자의 의도를 이해하고 평가 — 완벽보다 "전보다 나은가"
  • 원칙 기반 코멘트 — "I prefer"가 아니라 "이 코드베이스 규칙상"
  • 질문으로 시작 — 단정 대신 "이게 의도한 건가요?"
  • Blocking vs Nit 구분nit:, question:, blocking: 접두사

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
  • GitHub·GitLab 기본 지원
  • Branch protection과 결합해 "필수 승인자 자동 요청"

2.2 자동 리뷰어 선정 도구

  • Pullrequest rotation — GitHub 팀 기반 라운드로빈
  • ReviewBot, Toast — 커스텀 알고리즘(경험·현재 부하 고려)
  • Graphite Merge — 리뷰어 추천
  • 내부 툴: "코드 변경된 파일의 최근 커밋자"를 자동 제안 (Facebook mention_bot 원조)

2.3 리뷰 부하 평형

  • 한 시니어에 리뷰가 몰리면 그 시니어가 생산 병목
  • 분산: Pair reviewer 강제, 주니어 1 + 시니어 1
  • 대시보드로 "열린 리뷰 수" 가시화

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

3.1 문제

  • PR A와 B가 각각 main 기반으로 CI 통과
  • A가 먼저 머지
  • B는 사실 새 main에서 깨질 수 있음(silent semantic conflict)
  • → 머지 후에야 CI 실패 발견

3.2 Merge Queue가 하는 일

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

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

3.3 도구들

  • GitHub Merge Queue (2023 GA) — 기본 선택
  • Mergify — Python 규칙 기반, 복잡한 정책 가능
  • Aviator — stacked PR + merge queue
  • Graphite — 통합 제품(Stacked PR + Merge + Code Review)
  • Bors NG / Trainium — OSS 대안

3.4 Batched Merge

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

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

4.1 문제

  • 큰 기능을 만들다 보면 한 번에 2,000줄이 쌓임
  • 리뷰어가 못 봄 → 대충 승인 → 버그

4.2 해결

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

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

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

4.3 도구들

  • Graphite (gt) — 업계에서 가장 많이 사용. TypeScript/Python 생태계 지배적
  • Sapling (Meta 2022 OSS) — Mercurial 기반, Meta 내부 도구
  • Jujutsu (jj) (Google 2023 OSS) — Git 호환, 차세대 후보로 주목
  • Spr (Facebook 과거 툴) — CLI
  • ghstack (PyTorch 팀)
  • git-branchless — 개인용

4.4 Jujutsu가 주목받는 이유

  • Git 레포와 호환되며 위에 덮어 씀
  • "first-class conflict" — merge conflict가 commit 상태로 남음
  • 거대한 revset 쿼리 (jj log -r 'ancestors(@)')
  • operation log로 undo 완벽
  • 2025년 Google 사내 주력화 계획, 외부 관심 폭발

5부. Monorepo vs Polyrepo — 2025년 결론

5.1 언제 Monorepo가 이기나

  • 내부 의존성이 강한 여러 서비스/라이브러리
  • 동시 변경(스키마 + API + 클라이언트)이 흔함
  • 표준 도구 통일이 중요한 조직 규모

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 중심

  • Nx — Nx Cloud, Graph UI, 플러그인 풍부
  • Turborepo (Vercel) — 빠름, 간단, pnpm + Next.js 팀 특화
  • Moon (Rust) — 언어 중립 지향, Turbo 경쟁
  • Lerna — 공식 deprecated 후 Nx 팀이 인수해서 유지

6.2 언어 중립

  • Bazel — Google, 최고 성능·최고 학습 비용
  • Buck2 (Meta 2023 OSS, Rust) — Bazel보다 빠르게
  • Pants (Twitter) — Python 프로젝트에 특히 적합
  • Please — 소형팀
  • Earthly — Dockerfile 유사 DSL로 재현 가능 빌드

6.3 선택 트리

  • pure JS/TS monorepo, ≤ 50 패키지 → Turborepo
  • JS/TS + UI 팀 + 플러그인 필요 → Nx
  • 언어가 여럿(JS/Go/Rust), 중형 → Moon
  • 초대형, 빌드 엔지니어링 투자 가능 → Bazel 또는 Buck2
  • Python 중심 → Pants

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가 잘하는 것

  • Null safety, off-by-one, 미사용 변수 같은 정적 분석 범주
  • "이 함수 이름이 모호함" 같은 스타일
  • 반복되는 패턴 인식 ("이 코드베이스에서는 X를 쓰는데 Y를 썼습니다")
  • 테스트 케이스 제안
  • 유닛 테스트 커버리지 예상

7.2 AI가 못하는 것

  • 아키텍처 수준 판단
  • 비즈니스 맥락 ("이 변경이 고객에게 의미 있는가")
  • 팀 암묵적 관행
  • 보안 컨텍스트(외부 입력이 어디까지 신뢰되는가)

7.3 도구들

  • CodeRabbit — PR에 자동 요약 + 코멘트, 무료 오픈소스 모드
  • Greptile — 코드베이스 전체 RAG 기반 context-aware 리뷰
  • Ellipsis — "PR 설명 자동 생성"이 특히 강함
  • Cursor BugBot — Cursor 사용자용
  • Copilot Review (GitHub 2024~) — Copilot Enterprise
  • Qodo (Codium) — Python/JS 테스트 자동 생성 강점
  • Sourcery — Python 리팩토링
  • Graphite AI — 스택된 PR에 대한 리뷰

7.4 AI 리뷰 도입 실무 팁

  • 일주일 PR에 자동 코멘트만 → 팀이 가치 있는 코멘트 비율을 측정
  • 스팸 비율 5% 넘으면 조정 필요 (false positive가 리뷰 문화를 오염시킴)
  • AI 승인 권한은 주지 않기 — 인간 리뷰 필수
  • PR 요약(summary)만 AI로 쓰는 조직도 많음(가장 안전한 시작점)

8부. Trunk-based Development

8.1 정의

  • 모든 엔지니어가 main 근처에서(수시간 내 수명) 작업
  • Long-lived feature branch 금지
  • 기능을 feature flag로 숨김 (LaunchDarkly/Statsig)
  • main은 항상 deployable

8.2 왜 이기나

  • Merge conflict가 적어짐
  • 배포 주기가 짧아짐 → MTTR 감소
  • 지속 통합이 의미 있어짐
  • DORA 지표 elite 수준의 필수 조건

8.3 Git Flow의 사망

  • nvie/gitflow(2010)가 2020년 작성자에 의해 사실상 deprecated 선언
  • GitLab Flow, GitHub Flow가 더 단순한 대안
  • 여전히 엔터프라이즈 금융권은 release branch 유지

8.4 Feature Flag 기반 개발

  • "배포 = 릴리스"가 분리됨
  • A/B 테스트·Gradual Rollout·Kill Switch 하나로
  • 관리 안 된 flag가 flag debt — 6개월 이상된 flag 정리 의식

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

9.1 Merge vs Rebase 논쟁

  • Merge commit — 이력 보존, 시간 흐름 그대로
  • Rebase — 선형적, bisect에 친화적
  • Squash and Merge — PR 하나를 commit 하나로

9.2 팀별 정책

  • Linus Torvalds/Linux 커널: rebase 권장, linear
  • GitHub 기본: Squash and Merge (가장 단순)
  • Google: linear history, rebase 전제
  • Meta: Mercurial → Sapling, rebase 네이티브

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
  • 자동 changelog 생성
  • semantic-release로 버전 bump
  • 팀 규율과 도구 생태계 결합

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

10.1 Hook 매니저

  • Husky — JS 생태계 표준, Node 전용
  • lefthook — Go 바이너리, 언어 중립, 빠름
  • pre-commit (Python) — 언어 중립, 전세계 사용
  • Soft-serve, cog — 새 실험

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 훅이 싫어지는 이유와 해결

  • 느려서 --no-verify로 우회 → 훅이 10초 안에 끝나야
  • pnpm test:affected 같은 변경 파일 전용
  • staged 파일만 format: lint-staged
  • 빌드/테스트는 pre-push에만, commit에는 format/lint만

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

11.1 Semgrep

  • 언어 중립 패턴 매칭 (YAML 규칙)
  • Supply-chain, Secrets, Security 규칙 세트
  • Semgrep Cloud Platform (SaaS) — 2023~2024 급성장

11.2 SonarQube / SonarCloud

  • Quality Gate, Technical Debt, Coverage
  • 엔터프라이즈 표준
  • "Clean as You Code" 정책이 최근 권장

11.3 GitHub CodeQL

  • 데이터플로우 기반 취약점 분석
  • OSS 레포 무료, private 조직 유료
  • SQL처럼 쿼리 작성 가능

11.4 ESLint·Biome·Oxlint

  • ESLint — JS/TS 표준, 하지만 느림
  • Biome (2023 Rome fork) — Rust, linter + formatter 통합, 10~50배 빠름
  • Oxlint — Rust, Biome 경쟁, ESLint 규칙 호환
  • dprint — Rust, 언어 중립 포매터

11.5 보안 특화

  • gitleaks — 커밋 전 secret 탐지
  • trufflehog — 깊은 스캔
  • Syft, Grype — SBOM + 취약점
  • Trivy — 컨테이너·IaC 스캔

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

12.1 Compound effect

  • CI 1시간 → 개발자가 context switch
  • 10분 → "다음 태스크 시작 전에 기다림" 가능
  • 5분 이하 → flow 유지

12.2 개선 전략

  • Remote Cache (Nx/Turborepo/Bazel)
  • Parallel Matrix (5 shard로 테스트 분할)
  • Affected-only 빌드
  • Docker layer cache
  • Warm runner (Depot, BuildJet, Namespace, Blacksmith, RunsOn) — GitHub Actions ARM/X86 + NVMe cache
  • Earthly / Docker BuildKit multi-stage

12.3 Flaky Test

  • 최악의 생산성 킬러
  • 재시도 메커니즘 + 격리 추적
  • Trunk.io flaky test detection — 30일 실패율 기반 자동 스킵
  • Test retries는 일시방편, 근본 원인 추적 필수

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

13.1 5명 팀

  • GitHub Flow + Squash and Merge
  • CODEOWNERS 최소, 필수 리뷰어 1명
  • pre-commit hook + ESLint/Prettier
  • CI: GitHub Actions + Turborepo
  • AI 리뷰: CodeRabbit free

13.2 50명 팀

  • Merge Queue 필수
  • AI 리뷰 유료 (CodeRabbit/Greptile)
  • 내부 Runbook: "PR 400줄 이하 권장"
  • 보안 스캔: Semgrep CI + gitleaks
  • 모노레포면 Nx + Remote Cache

13.3 500명+

  • Graphite/Aviator로 stacked PR 표준화
  • Buck2/Bazel Remote Execution
  • CodeQL + SonarQube 엔터프라이즈
  • Trunk-based + Feature Flag 강제
  • 전담 "Dev Productivity" 팀

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배다.

  • Amazon 6-pager 문화 — 왜 파워포인트를 금지했는가
  • Design Doc 템플릿 — Google/Stripe 공개본
  • RFC 프로세스 — Rust·Ember·IETF 비교
  • ADR (Architecture Decision Record)
  • Internal Wiki — Notion·Confluence·Outline·GitBook
  • Engineering Blog 운영 — Stripe·Shopify·Uber·Airbnb 스타일
  • Changelog과 Release Notes
  • Slack/Email 비동기 커뮤니케이션
  • LLM 시대의 글쓰기 — AI를 도구로 쓰면서 목소리 지키기
  • 테크 인플루언서의 경제학 — 글 하나가 커리어를 바꾸는 순간

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

현재 단락 (1/247)

엔지니어가 하루에 PR 3~5개를 리뷰한다고 치자. 주 5일, 연 50주면 **연간 1,000개**에 달한다. 새로운 기능을 만드는 시간보다 **남의 코드를 읽고 판단하고 제안하는...

작성 글자: 0원문 글자: 8,960작성 단락: 0/247