Stacked PR로 대형 기능을 잘게 나눠 리뷰받기
Stacked PR을 활용한 PR 분할 전략과 실전 워크플로를 정리했습니다. 대형 기능을 작은 단위로 쪼개 코드 리뷰 품질을 높이고, 자동 rebase로 스택을 관리하는 방법까지 다룹니다.
대형 기능을 하나의 거대한 PR로 올리면 리뷰어는 수백 줄에서 수천 줄을 한 번에 마주하게 됩니다. 리뷰가 늦어지고, 지적이 쌓이면 재작업 범위도 커지며, 결국 대충 승인하는 악순환이 반복됩니다. Stacked PR은 이런 문제를 구조적으로 해결하는 접근입니다. 하나의 기능을 논리적으로 연결된 여러 개의 작은 PR로 쌓아 올려, 각 단계를 독립적으로 리뷰받는 방식입니다. 이 글에서는 PR 분할의 기준과 스택을 유지하는 실전 워크플로, 그리고 자동 rebase로 겪는 고통을 줄이는 방법을 정리합니다.
Stacked PR이란 무엇인가
Stacked PR은 base 브랜치 위에 첫 번째 PR을 만들고, 그 브랜치를 다시 base로 삼아 다음 PR을 쌓는 방식입니다. 예를 들어 결제 기능을 구현한다면 데이터 모델, API 엔드포인트, UI 연동을 각각 별도의 PR로 나누되 순서대로 의존하도록 연결합니다. 리뷰어는 각 PR에서 변경된 실제 diff만 보게 되므로 맥락 파악이 쉬워집니다.
기존의 단일 브랜치 방식과 비교하면 다음과 같은 차이가 있습니다.
- 각 PR이 하나의 관심사만 다루므로 diff가 작고 리뷰 집중도가 높아집니다.
- 선행 PR이 머지되기 전에도 후속 작업을 병행할 수 있어 개발 흐름이 끊기지 않습니다.
- 특정 단계에서 문제가 발견되면 해당 PR만 되돌리면 되어 롤백 범위가 명확합니다.
- 리뷰어를 단계별로 다르게 지정해 도메인 전문가에게 적절한 부분을 맡길 수 있습니다.
PR을 어떤 기준으로 나눌 것인가
PR 분할의 핵심은 줄 수가 아니라 '리뷰 단위'입니다. 각 PR은 그 자체로 이해 가능하고, 이상적으로는 독립적으로 빌드와 테스트가 통과해야 합니다. 무작정 파일 개수로 자르면 오히려 맥락이 끊겨 리뷰가 더 어려워집니다.
- 리팩터링과 기능 추가는 반드시 분리해 어떤 변경이 동작을 바꾸는지 명확히 합니다.
- 의존성 방향을 따라 하위 계층부터 상위 계층 순서로 스택을 쌓습니다.
- 한 PR에는 하나의 논리적 변경만 담아 리뷰어가 승인 여부를 단번에 판단하게 합니다.
- 순수한 이동이나 이름 변경은 로직 변경과 섞지 않고 별도 PR로 처리합니다.
- 각 PR의 설명에 스택 내 위치와 선행 PR 링크를 남겨 맥락을 공유합니다.
좋은 PR 분할의 기준은 '리뷰어가 5분 안에 승인 여부를 결정할 수 있는가'이다. 줄 수를 줄이는 것이 목적이 아니라, 판단의 단위를 명확히 하는 것이 목적이다.
스택 유지의 진짜 난관: 자동 rebase
Stacked PR의 가장 큰 실무적 부담은 스택 관리입니다. 스택 하단의 PR에서 리뷰 피드백을 반영하면, 그 위에 쌓인 모든 PR을 다시 rebase해야 합니다. 5단계 스택에서 두 번째 PR을 수정하면 세 번째부터 다섯 번째까지 순차적으로 rebase가 필요합니다. 이 과정을 수동으로 하면 충돌 해결과 force push가 반복되며 실수가 발생하기 쉽습니다.
자동 rebase를 도입하면 이 부담을 크게 줄일 수 있습니다. 스택을 하나의 단위로 인식하고 하단 변경을 상단으로 전파하는 도구를 활용하는 것이 실용적입니다.
- 하단 PR을 수정하면 상단 PR들이 자동으로 rebase되어 수동 작업을 줄입니다.
- 선행 PR이 머지되면 후속 PR의 base가 자동으로 갱신되도록 설정합니다.
- 충돌이 발생한 지점만 알림으로 받아 필요한 부분만 손보게 합니다.
- force push 이후에도 진행 중이던 리뷰 코멘트가 유지되도록 관리합니다.
DevCowork에서 Stacked PR 관리하기
DevCowork은 스택 전체를 하나의 화면에서 시각화하고, 하단 PR 수정 시 상단 PR을 자동 rebase해주는 기능을 제공합니다. 각 PR의 의존 관계와 머지 순서를 그래프로 확인할 수 있고, 선행 PR이 머지되면 후속 PR의 base 갱신을 자동으로 처리합니다. PR 분할부터 자동 rebase, 단계별 리뷰어 지정까지 코드 리뷰 흐름을 하나의 워크플로로 묶어, 대형 기능을 잘게 나눠 리뷰받는 부담을 줄이는 데 초점을 맞췄습니다.