본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 02. 00:51

PR을 열기 전 AI를 활용한 셀프 리뷰 — branchdiff를 이용한 실용적인 워크플로우

요약

PR을 열기 전 branchdiff를 활용하여 AI 기반의 셀프 리뷰를 수행하는 효율적인 워크플로우를 소개합니다. 로컬 환경에서 AI를 통해 코드의 결함을 미리 파악함으로써 리뷰어의 부담을 줄이고 깔끔한 PR을 유지하는 방법을 다룹니다.

핵심 포인트

  • PR 오픈 전 AI 셀프 리뷰를 통해 코드 품질 선제적 확보
  • branchdiff를 활용한 로컬 기반의 안전한 AI 코드 분석
  • 리뷰어의 주의력을 핵심 로직에 집중시키기 위한 워크플로우
  • 불필요한 커밋 노이즈를 줄이고 깔끔한 히스토리 유지

그 순간을 알고 계실 겁니다. 브랜치를 푸시하고 PR(Pull Request)을 열자마자 바로 눈에 띄는 것들 말이죠 — 환불 경로에서의 정의되지 않은 반환값(undefined return), 콘솔에 로그로 남겨진 토큰, 그리고 6주 전에 임시로 작성하려 했던 TODO 주석 같은 것들 말입니다. 리뷰어는 4시간 후에 이를 발견하고, 당신은 마치 다른 사람이 그 코드를 작성한 것처럼 "잘 찾아내셨네요, 지금 수정하겠습니다"라고 답하곤 합니다.

대부분의 Pull Request에서 첫 번째 리뷰어는 작성자 본인이었어야 합니다. 당신이 받게 될 코멘트의 절반 — 누락된 null 체크, 테스트되지 않은 에러 분기(error branch), 추출 가능한 중복 로직, 이제는 사용되지 않는 임포트(import) 등 — 은 한 번만 더 주의 깊게 읽었더라면 스스로 잡아낼 수 있었던 것들입니다. 당신이 그 읽기 과정을 건너뛰는 이유는 이틀 동안 계속 코드에 매달려 있었기에 뇌가 문장을 알아서 완성해 버리기 때문입니다. 페이지에 적힌 내용이 아니라, 당신이 쓰려고 의도했던 내용을 보게 되는 것이죠.

이 포스트는 PR을 열기 _전_에 구조화된 AI 지원 셀프 리뷰(AI-assisted self-review)를 통해 그 간극을 메우는 방법에 관한 것입니다. 인간 리뷰어를 건너뛰기 위함이 아닙니다. 명백한 문제들은 이미 해결하고, 테스트의 빈틈은 이미 채우고, PR 설명(description)까지 이미 작성된 상태로 리뷰에 임하기 위함입니다. 그래야 리뷰어의 주의력이 실제로 두 번째 눈(second pair of eyes)이 필요한 부분에 집중될 수 있습니다.

사용할 도구는 branchdiff입니다. 이는 localhost에서 diff를 실행하고, 모든 것을 ~/.branchdiff/에 저장하며, 명시적인 branchdiff agent 커맨드 API를 통해 AI 접점을 제어하는 로컬 브라우저 앱입니다. 당신이 푸시하기로 결정하기 전까지는 아무것도 당신의 컴퓨터를 떠나지 않습니다.

왜 "PR 전"이 적절한 타이밍인가

Self-Review: Before vs. After Opening the PR

만약 PR(Pull Request)을 연 후에 리뷰를 한다면, 모든 AI 수정 사항은 노이즈가 됩니다. 강제 푸시(force-push), 리뷰어를 위한 재검토, 감사 추적(audit trail)에 남는 또 다른 커밋 등이 발생합니다. 만약 당신이 버그를 발견했을 때 팀원이 이미 리뷰를 진행 중이라면, 당신은 부주의해 보일 수 있습니다. 원래의 푸시(push)에 포함되었어야 할 패치(patch)가 이후의 모든 작업 흐름에 방해 요소가 됩니다.

만약 PR을 열기 전에 리뷰를 한다면, AI의 출력물은 개인적인 작업 공간이 됩니다. 당신은 중요한 사항에 대해서만 조치를 취하고, 수정 사항을 자신의 히스토리에 커밋합니다(종종 푸시하기 전에 스쿼시(squash)할 fixup! 커밋 형태로). 이렇게 하면 첫 번째 푸시부터 훨씬 깔끔한 PR이 올라갑니다. 리뷰어들은 당신의 의식의 흐름에 따른 수정 사항이 아니라, 당신의 실제 작업물을 보게 됩니다.

더 미묘한 이점도 있습니다. 바로 거절을 통해 배운다는 점입니다.

http://localhost:5391에서 브라우저 탭이 열립니다. 두 개의 이름이 지정된 참조(named refs)를 비교하고 있기 때문에, 이는 **지속적인 세션 (persistent session)**입니다. 즉, 당신(또는 AI)이 여기에 남긴 댓글은 어느 한쪽 브랜치에 새로운 커밋이 추가되어도 유지됩니다. 리뷰 기록을 잃지 않고 여러 차례의 수정 과정을 반복할 수 있습니다. 만약 새로 시작하고 싶다면, --new 옵션이 현재 세션을 아카이브하고 깨끗한 새 세션을 생성합니다. 아카이브된 세션은 branchdiff review threads --session <id>를 통해 여전히 조회할 수 있습니다.

Diff(차이점)는 분할 뷰(split view) 또는 통합 뷰(unified view)로 렌더링되며, 150개 이상의 언어에 대한 구문 강조(syntax highlighting), 변경된 파일 사이드바, 그리고 키보드 단축키(j/k는 다음/이전 파일, n/p는 다음/이전 덩어리(hunk))를 제공합니다.

2단계 — AI 리뷰 실행

Claude Code를 사용한다면, 스킬(skills)을 한 번만 설치하면 됩니다:

branchdiff skill add        # .claude/skills/branchdiff-{review,resolve}를 추가합니다

그 다음 Claude Code 세션에서 다음을 실행합니다:

/branchdiff-review main feature/payments

이 스킬은 branchdiff agent diff를 호출하여 전체 Diff를 읽은 다음, branchdiff agent comment --file <path> --line <n> --body "[tag] ..."를 통해 인라인 댓글(inline comments)을 게시합니다. 각 댓글에는 심각도 태그(severity tag)가 포함됩니다:

Comment Tag Taxonomy

태그의미일반적인 조치
[must-fix]버그, 보안 문제, 깨진 계약 (broken contract)푸시하기 전에 수정
...

다른 AI를 사용하는 경우, README에 동일한 branchdiff agent 명령 인터페이스를 구동할 수 있는 복사-붙여넣기용 프롬프트가 포함되어 있습니다. 또는 컨텍스트를 직접 파이프(pipe)로 전달할 수도 있습니다:

branchdiff review context | claude -p "review for security and breaking changes"
branchdiff review run --exec "claude" --mode review

v1.5.0에서의 두 가지 개선 사항 덕분에 이 단계가 눈에 띄게 더 좋아졌습니다:

  • 건설적인 어조 (Constructive tone). 이 기술은 판단이 아닌 문제점을 먼저 제시합니다. 즉, "이것은 틀렸습니다"라고 말하는 대신 "amount === 0일 때 undefined를 반환합니다"라고 말합니다. 협력적인 언어를 사용하는 것입니다. AI의 코멘트가 비난이 아닌 관찰로 읽힐 때, 엔지니어들은 실제로 버그를 수정합니다.
  • N번째 리뷰 인지 (Nth-time review awareness). 코멘트를 남기기 전에, 이 기술은 해결되었거나(resolved) 기각된(dismissed) 스레드를 읽습니다. 해결된 스레드는 다시 제기되지 않으며, 기각된 스레드는 새로운 증거가 있는 경우에만 다시 표시됩니다. 동일한 피드백을 다시 논쟁할 필요 없이, 의미 있는 커밋이 있을 때마다 /branchdiff-review를 실행할 수 있습니다.

Step 3 — 읽기, 분류, 결정 (read, triage, decide)

브라우저를 엽니다. 각 AI 코멘트는 diff의 특정 라인에 고정되어 있으며, 거터(gutter)에 태그가 표시되고 본문은 인라인(inline)으로 나타납니다. 각 스레드에는 네 가지 옵션이 있습니다:

수정하기 (Fix it) — 에디터에서 변경 사항을 적용한 다음, 스레드를 해결합니다 (branchdiff agent resolve <id> --summary "added null guard"를 입력하거나 UI에서 _Resolve_를 클릭). 요약(summary)은 선택 사항이지만 작성할 가치가 있습니다. 향후의 리뷰 단계와 미래의 리뷰어들이 무엇이 왜 수행되었는지 확인할 수 있기 때문입니다.

자동 수정하기 (Auto-fix it) — Claude Code를 사용 중이라면, /branchdiff-resolve가 열려 있는 코멘트를 읽고 기계적인 수정(이름 변경, 함수 추출, null 체크, 누락된 테스트 스텁 추가 등)을 적용한 뒤 요약과 함께 스레드를 해결합니다. 커밋하기 전에 반드시 diff를 읽으세요 — AI가 가끔 사용자의 의도보다 제안을 더 문자 그대로 받아들여 적용할 때가 있습니다.

기각하기 (Dismiss it) — 코멘트가 틀렸거나, 범위를 벗어났거나, 이미 상위 단계(upstream)에서 처리된 경우입니다. branchdiff agent dismiss <id> --reason "..."를 통해 이유를 기록합니다. 이 이유는 N번째 리뷰 인지(nth-time awareness) 기능에서 활용되어, 다음 패스에서 동일한 지점이 다시 제기되지 않도록 합니다.

답장하기 (Reply to it)[question] 태그의 경우, branchdiff agent reply <id> --body "..."를 통해 스레드 내에서 답변할 수 있습니다. AI가 불분명한 동작을 지적했을 때, 다음 리뷰어를 위해 근거를 기록해 두고 싶을 때 유용합니다.

기각 사유(dismissal reason)를 기록하는 것은 구축해야 할 가장 중요한 습관입니다. 이는 여러 번의 검토 과정 동안 AI가 정직함을 유지하도록 하며, 리뷰어가 "왜 이 코드가 이렇게 되어 있나요?"라고 물었을 때 근거로 제시할 수 있는 기록(paper trail)을 남겨줍니다.

단계 3.5 — 긴 diff를 다루기 쉽게 만드는 리뷰 도구 활용하기

동료의 40개 파일 규모의 PR(Pull Request)을 관리 가능하게 만드는 기능들은 여러분의 브랜치에서도 동일한 효과를 발휘합니다:

조회 카운터(Viewed counter) + stale 감지. 파일을 살펴볼 때마다 조회됨(eye icon 또는 우클릭)으로 표시하세요. 사이드바에 12 / 24 viewed와 같이 표시됩니다. 조회됨으로 표시했지만 나중에 변경된 파일은 황색 점과 함께 stale(오래된/유효하지 않은) 상태로 전환됩니다. stale 상태는 diff 시그니처의 FNV-1a 해시를 통해 감지되므로, 내용 변경이 없는 rebase(리베이스)는 여러분이 설정한 표시를 무효화하지 않습니다.

사이드바 필터(Sidebar filters). Commented(댓글 있음), Uncommented(댓글 없음), Viewed(조회됨), Unviewed(조회되지 않음), Stale(stale), Collapsed(접힘), Expanded(펼쳐짐), Staged(스테이지됨), Unstaged(스테이지되지 않음) 등 9개의 필터 칩이 검색창과 함께 배치되어 있습니다. 수정 작업을 마친 후 두 번째 검토를 진행할 때: _Filter(필터) → Stale(stale)_을 선택하면 정확히 어떤 파일을 다시 읽어야 하는지 보여줍니다.

모두 접기 / 모두 펼치기(Collapse all / Expand all). 상세히 살펴보기 전에 빠르게 전체적인 흐름을 파악할 수 있습니다. 열려 있는 댓글이 있는 파일은 강제로 펼쳐지므로, 스레드가 접힌 diff 뒤에 숨겨지는 일이 없습니다.

Staged / unstaged 토글. 첫 번째 커밋을 하기 전 작업 트리(working tree)를 검토할 때, 툴바에서 git diff --stagedgit diff 사이를 전환할 수 있습니다. 파일 행에는 S(staged) 및 U(unstaged)와 같은 인라인 상태 배지가 표시됩니다.

전체 파일 보기(Full-file view) + 미니맵(minimap). 툴바의 _Full-file view_를 사용하면 모든 헌크(hunk)가 배치된 상태로 VS Code 스타일의 전체 파일 렌더링이 열립니다. 우측의 미니맵은 추가, 삭제 및 수정된 영역을 표시합니다. 이를 통해 1,000줄짜리 파일을 한눈에 스캔하고 변경 사항으로 즉시 클릭하여 이동할 수 있습니다. 헌크 보기(hunk view)에서 전체 파일 보기(full-file view)로 전환하더라도 인라인 댓글은 고정된 상태를 유지합니다. 마크다운(Markdown) 파일은 양쪽 모두를 포맷팅된 마크다운으로 렌더링하는 Preview(미리보기) 토글(v1.5.0) 기능이 제공됩니다.

커밋 상세 페이지 (Commit detail page). 히스토리 사이드바에서 커밋을 클릭하면 전체 SHA, 부모 링크(parent links), +N / -N 카운트가 포함된 파일 목록, 그리고 동일한 디프(diff) 뷰가 포함된 /commit/:hash 페이지가 열립니다. 뒤로 가기 버튼을 누르면 현재 위치가 유지됩니다.

4단계 — 위험 요소에 집중한 검토 (focused passes)

일반적인 검토(generalist review)는 광범위한 범위를 포착합니다. 반면, 아래의 네 가지 사전 구축된 워크플로우(workflows)는 더 좁고 깊은 유형의 문제를 포착합니다.

보안 감사 (Security audit) — 인젝션(Injection: SQL, 커맨드, XSS, 템플릿, NoSQL, 프롬프트), 비밀 정보 유출(secret leaks), 취약한 암호화(weak crypto), 권한 부여 오류(broken authorisation), 역직렬화 함정(deserialisation traps), 경로 탐색(path traversal), SSRF, 그리고 의존성 위험(dependency risk)만을 탐색합니다. 스타일 검토는 완전히 건너뜁니다. 200줄짜리 인증(auth) 디프의 경우, 50개의 모호한 코멘트 대신 5개의 정밀한 코멘트를 생성합니다.

테스트 커버리지 공백 (Test coverage gaps) — 모든 새로운 함수, 분기(branch), 또는 에러 경로(error path)에 대해 테스트 디렉토리를 확인하고, 커버되지 않은 경로를 스텁(stub) it(...) 제안과 함께 표시합니다. 우선순위: 에러 분기 → 새로운 공개 API (public API) → 엣지 케이스 (edge cases) → 해피 패스 (happy path).

파괴적 변경 사항 검토 (Breaking-change review) — 모든 변경 사항을 파괴적(breaking) 또는 비파괴적(non-breaking)으로 분류합니다. 파괴적 변경의 경우 UPGRADE.md 스니펫(snippet) 초안을 작성하며, 롤백 경로가 없는 스키마 마이그레이션(schema migrations)은 [must-fix]로 표시합니다.

의존성 검토 (Dependency review) — 추가되거나 메이저 버전이 업데이트된 패키지에 대해 유지 관리 상태, 라이선스 호환성, 번들 크기 변화량(bundle-size delta), 퍼스트 파티(first-party) 대안, 그리고 알려진 CVE를 표시합니다.

12개 파일로 구성된 결제(payments) 브랜치에서의 실제 세션

일반 검토 단계(general review pass)를 거친 후 branchdiff agent list --status open의 결과는 다음과 같을 수 있습니다.

[must-fix]   src/billing/charge.ts:84      Refund path returns undefined when amount === 0
[must-fix]   src/api/webhooks.ts:42        Missing signature verification before parsing body
[suggestion] src/utils/format.ts:12        Replace toFixed(2) with Intl.NumberFormat for i18n
...

Sample Self-Review Session — Comment Breakdown

두 개의 [must-fix] 항목, 세 개의 개선 사항, 무시해도 될 만한 사소한 지적(nit) 하나, 그리고 답변해야 할 질문 하나. 20분간의 정리 작업. 당신이 푸시하는 PR(Pull Request)은 점심 식사 전에 푸시했을 PR보다 실질적으로 더 나은 상태가 됩니다.

AI의 일반적인 코멘트는 종종 변경 사항을 두세 문장으로 요약해 주는데

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0