PR 리뷰 사이클을 줄이기 위한 self-review 커맨드
- AI
- Command
배경
AI를 개발 전반에 활용하며
AI를 개발 전반에 활용하면서, 더 효율적인 개발을 위해 두 가지 질문을 반복하게 되었다.
구현 속도 자체는 점점 빨라지고 있다. 하지만 그 앞뒤를 감싸는 과정들은 여전히 사람의 시간을 꽤 잡아먹는다고 느꼈다. 앞단에는 다른 팀과 소통하며 기획을 확정짓는 단계가 주를 이루는데, 이 단계도 단축할 여지가 없진 않지만 개발팀이 직접 통제할 수 있는 뒷단에 우선 집중하기로 했다.
뒷단에서의 과정은?
기획이 확정된 후, 실제 개발에서 배포까지의 흐름을 정리하면 다음과 같다.
구현 → PR 작성 → PR 리뷰 → 리뷰 반영 → 승인 → merge이 중 merge 승인을 제외한 나머지 각 단계는 모두 단축할 수 있다고 생각한다. 그리고 그 안에서 가장 시간을 아낄 수 있는 단계가 바로 PR 리뷰와 리뷰 반영이라 판단했다.
왜 PR 리뷰에서 시간이 오래걸릴까?
리뷰에 시간이 많이 걸리는 데에는 구조적인 이유가 있다고 본다. 리뷰어는 작성자만큼 맥락을 알고 있지 않기 때문에, 코드를 이해하는 것 자체에 시간이 필요하다. 여기에 “왜 이렇게 작성했는가”까지 추적하는 과정이 더해지면서 리뷰 속도는 자연스럽게 느려진다.
또한 리뷰는 비동기적으로 이루어진다. 리뷰 요청 → 코멘트 → 반영 → 재요청의 사이클 사이마다 대기가 발생하고, 이 대기가 누적되면서 전체 개발 리드타임이 길어진다.
그렇다면, 어떻게 시간을 아낄 수 있을까?
코드 맥락을 전달하는 것도 중요하지만, 그 자체로는 리뷰 비용을 근본적으로 줄이기에는 한계가 있다. PR을 올리기 전에 리뷰어가 지적할 만한 문제를 얼마나 미리 제거할 수 있는가가 핵심이라 생각했다.
이를 해결하고자 만든 것이 /self-review 커맨드다. Claude Code의 커스텀 슬래시 커맨드 기능을 활용했다. PR을 올리기 전 AI에게 먼저 리뷰를 받고 반영하면, 실제 리뷰어가 남길 코멘트 중 적어도 한두 개는 사전에 막을 수 있다. 무엇보다, 그 지점을 놓쳤을 때 발생할 수 있는 이슈 자체를 방지할 수 있다.
진행 과정
1. 역할 정의
가장 먼저 이 커맨드의 역할부터 정의했다. 어떤 맥락에서 왜 필요한지, 그리고 무엇을 목표로 하는지를 명확히 하는 데 초점을 맞췄다. 역할이 불분명하면 이후에 붙는 규칙이나 출력 형식도 흔들리기 때문에, 출발점을 분명히 잡는 것이 중요하다고 판단했다.
# /self-review — PR 작성 전 셀프 리뷰
- 현재 브랜치에서 작업한 내용을 바탕으로,
- PR을 올리기 전에 스스로 시니어 개발자 관점에서 검토합니다.
- "내가 리뷰어라면 이 PR에서 무엇을 지적할까?"를 미리 점검해 PR 품질을 높이는 것이 목적입니다.2. 페르소나 설정
다음으로는 리뷰를 수행할 페르소나를 설정했다.
## 리뷰 페르소나
- 10년차 이상 시니어 개발자 기준으로 판단.
- 스타일보다 설계, 엣지케이스, 유지보수성, 보안, 성능을 우선
- 칭찬이나 잘된 점은 한 줄로만 요약하고,
- **부족한 부분과 개선이 필요한 부분에 비중을 두어** 작성
- "동작은 한다"가 아니라 "프로덕션에서 버틸 수 있는가, 다음 사람이 유지보수할 수 있는가" 기준으로 검토개인적으로 “10년차 이상 시니어 개발자”라는 표현을 자주 사용한다. 이 키워드를 포함했을 때와 그렇지 않을 때, 리뷰의 깊이와 관점에서 분명한 차이가 발생했기 때문이다. 단순한 코드 수준의 피드백을 넘어서, 설계와 운영 관점까지 확장된 리뷰를 유도하는 데 효과적이었다.
"프로덕션에서 버틸 수 있는가, 다음 사람이 유지보수할 수 있는가"
해당 기준은 빠르게 구현이 이루어지는 환경일수록 놓치기 쉽다. 단순히 기능이 동작하는지에 머무르지 않고, 트래픽 상황에서도 안정적으로 동작하는지, 이후의 변경과 확장을 견딜 수 있는 구조인지까지 함께 점검하도록 만든다.
3. Pn 룰
AI에게 여러 번 리뷰를 요청하면서 가장 크게 느낀 점은 우선순위가 없는 피드백은 오히려 판단을 어렵게 만든다는 것이었다. 어떤 수정이 지금 반드시 필요한지, 무엇을 나중으로 미뤄도 되는지 구분하기 어려웠고, 그 과정에서 불필요하게 시간을 쓰거나 중요한 문제를 놓치기도 했다.
이 문제를 해결하기 위해 뱅크샐러드의 Pn 룰을 셀프 리뷰에 그대로 도입했다. 라벨을 적용한 이후, 리뷰를 처리하는 방식이 명확하게 달라졌다.
## Pn 룰
각 발견 사항은 아래 라벨을 코멘트 앞에 붙여서 작성한다.
- `P1` — 꼭 수정해야 합니다: PR 올리기 전 반드시 수정해야 하는 수준 (서비스 오류, 보안 취약점 등)
- `P2` — 적극적으로 고려하세요: 리뷰어가 Request changes를 낼 가능성이 높은 수준
- `P3` — 웬만하면 반영하세요: 리뷰어가 Comment를 남길 가능성이 있는 수준
- `P4` — 반영해도 좋고 넘어가도 좋습니다: Approve 이후 가볍게 언급될 수 있는 수준
- `P5` — 그냥 사소한 의견입니다: 취향 차이거나 향후 개선 여지 정도의 수준P1 / P2
P1 / P2는 즉시 수정이 필요한 항목으로 분류해 집중적으로 검토하고, 영향 범위까지 추가로 확인하게 됐다. 실제로는 핵심 로직에서의 오류나 잠재적인 장애 가능성처럼, 그대로 두면 문제로 이어질 수 있는 경우가 대부분이었다.
P4 / P5
P4 / P5는 전체 설계 관점에서의 개선 여지를 짚어주는 경우가 많았다. 파일 분리, 코드 구조, 스타일과 같은 리팩토링 성격의 제안들이었고, 우선순위를 낮춰 부담 없이 검토하거나 이후 작업으로 넘기는 기준으로 활용할 수 있었다.
결과적으로 “무엇을 지금 해결해야 하는가”와 “무엇을 나중에 다뤄도 되는가”가 분리되면서, 리뷰를 훨씬 빠르고 안정적으로 처리할 수 있게 됐다.
4. 점검 항목
## 점검 항목
1. **설계/아키텍처** — 책임 분리, 기존 코드베이스 패턴과의 일관성, 불필요한 추상화/과설계
2. **정확성** — 로직 버그, 엣지 케이스(null, 빈 배열, 동시성, 경계값), 예외 처리 누락
3. **보안** — 인증/인가 누락, 입력 검증, 민감 정보 노출, OWASP Top 10 관점
4. **성능** — 불필요한 연산/쿼리, N+1, 과도한 렌더링·재계산
5. **테스트** — 변경 범위 대비 테스트 커버리지 누락, 테스트가 실제로 버그를 잡아낼 수 있는지
6. **가독성/유지보수성** — 네이밍, 함수 길이/책임, 중복 코드
7. **일관성** — 기존 코드베이스 컨벤션/구조와의 정합성
8. **PR 설명 준비** — 변경 이유/영향 범위/테스트 방법을 PR body에 담을 수 있는지점검 항목은 프론트엔드 개발에서 중요하다고 판단한 기준들을 정리한 것이다. 큰 기능 개발뿐 아니라, 작은 리팩토링이나 내부 개선 작업에서도 일관되게 적용할 수 있도록 범용적인 기준으로 구성했다.
성능
성능 항목을 별도로 명시한 이유는, 프론트엔드에서 특히 자주 놓치는 두 가지 지점이 있기 때문이다.
첫 번째는 네트워크 비용이다. 불필요한 API 호출, 중복 요청, 비효율적인 데이터 페칭 구조는 기능적으로는 문제없이 동작하더라도 전체 응답 속도와 사용자 경험에 직접적인 영향을 준다. 캐싱 전략이 없거나, 동일한 데이터를 여러 번 가져오는 구조는 코드만 봐서는 쉽게 드러나지 않는 경우가 많다.
다른 하나는 렌더링 비용이다. 리스트 렌더링이나 상태 변경 시 발생하는 불필요한 리렌더링, 과도한 재계산은 기능적으로는 정상처럼 보이지만 사용자가 체감하는 속도와 직결된다. 일반적인 코드 리뷰에서도 잘 드러나지 않는 경우가 많아, 의식적으로 점검할 필요가 있다고 판단했다.
테스트
테스트 항목은 의도적으로 범위를 제한했다. 커버리지 누락 여부와 테스트의 실효성까지만 점검하고, 테스트 코드를 작성하거나 실행하는 단계는 포함하지 않았다.
테스트의 깊이와 방식은 상황에 따라 달라지기 때문에, 이를 셀프 리뷰 단계에서 모두 처리하려 하면 오히려 검토와 구현 모두가 흐려질 수 있다고 판단했다. 대신 테스트 작성과 실행은 별도의 단계로 분리했다.
AI 기반으로 빠르게 구현하는 과정에서는 설계 단계에서 고려했던 테스트 케이스가 누락되거나, 기존 코드와의 결합 과정에서 성능이나 일관성 문제가 발생하기 쉽다. 이 점검 항목들은 그러한 지점을 체계적으로 드러내고, 최종적으로 기존 코드베이스와의 정합성을 유지하는 것을 목표로 했다.
5. 실행 절차
마지막으로 실제 검토를 수행하는 절차를 정리했다. 핵심은 베이스 브랜치와의 diff를 기준으로 변경 사항을 파악하고, 그 위에 앞서 정의한 기준들을 일관되게 적용하는 것이다.
## 실행 절차
1. 베이스 브랜치 결정:
- `$ARGUMENTS`에 브랜치명이 있으면 사용 (예: `/self-review develop`)
- 없으면 `git remote show origin` 또는 `git symbolic-ref refs/remotes/origin/HEAD`로 기본 브랜치(main) 자동 감지
2. 브랜치 변경 내용 확보:
- `git log <베이스>..<현재브랜치> --oneline` 으로 커밋 목록 확인
- `git diff <베이스>...<현재브랜치>` 로 전체 diff 확보
3. diff만으로 맥락이 부족하면 관련 파일을 직접 읽어 기존 코드와의 일관성/영향 범위 확인
4. 위 점검 항목 8개 기준으로 변경된 파일을 분석
- 보안 의심 지점은 OWASP 체크리스트 관점으로 한 번 더 검증
- 재사용성/효율성은 중복/단순화 여지 관점으로 추가 점검
5. 발견 사항을 P1~P5로 분류해 아래 형식으로 보고:
```
## 셀프 리뷰 — <현재 브랜치명>
### 요약
- 한 줄 평가 + 이 상태로 PR을 올렸을 때 리뷰어 반응 예상 (Request changes / Comment / Approve 중 어느 쪽에 가까운지)
### [P1] PR 올리기 전 반드시 수정
- `path/file.ts:42` — 문제 설명 및 개선 제안
### [P2] 적극적으로 고려하세요
- ...
### [P3] 웬만하면 반영하세요
- ...
### [P4] 반영해도 좋고 넘어가도 좋습니다
- ...
### [P5] 사소한 의견
- ...
### 잘된 점
- (간단히 1~3줄)
```단순히 변경된 코드를 나열하는 것이 아니라, diff를 출발점으로 맥락을 보완하고, 점검 항목을 통해 검토 범위를 고정한 뒤, Pn 라벨로 우선순위를 정리하는 흐름을 만든 셈이다.
이 과정을 거치면서 리뷰의 기준과 결과가 모두 구조화되고, PR을 올리기 전 한 번 더 품질을 끌어올릴 수 있도록 했다.
실제 적용 예시
어떤 작업에서의 예시인지?
과거 작업했던 프로젝트의 특정 브랜치에서 커맨드를 사용해보았다. 강의실 내 투표(Poll)와 Q&A 기능을 별도 도메인 폴더로 분리하는 리팩토링 브랜치였는데, 그 안에 "투표 실패 시 선택 상태가 롤백되지 않는" 버그를 수정하는 커밋도 함께 섞여 있었다.
전체 리뷰 요약

작업 브랜치에서의 전반적인 평가는 "구조 변경 자체는 깔끔하지만, 핵심 버그 수정 패턴이 다른 컴포넌트에는 반영되지 않았다"는 내용이었다.
투표 다이얼로그에서 고친 낙관적 업데이트 롤백 로직이 구조가 거의 동일한 Q&A 다이얼로그에는 적용되지 않았다는 점, 그리고 그 버그 수정 자체에 대한 회귀 테스트가 빠져 있다는 점을 짚었고, 이 상태로 PR을 올리면 리뷰어가 Request changes를 결정할 가능성이 높다고 판단했다.
우선 순위에 따른 리뷰

P2로 분류된 항목이 가장 인상적이었다. 투표 다이얼로그에서 고친 버그와 정확히 같은 패턴이 Q&A 다이얼로그에는 그대로 남아 있다는 걸 코드 비교만으로 짚어냈다. 두 컴포넌트를 나란히 놓고 보지 않으면 놓치기 쉬운 지점인데, diff 전체를 한 번에 훑는 과정에서 자연스럽게 드러났다.
P3/P4에서는 이미 다른 곳에 정의돼 있는 타입을 컴포넌트에서 다시 선언하고 캐스팅까지 추가한 부분, 파일을 옮기면서 로그 prefix가 옛 위치 이름으로 남은 부분처럼, 혼자 보면 그냥 지나치기 쉬운 디테일들을 짚어줬다.
잘된 점

잘된 점은 한두 줄로만 짚어주었고, 이미 반영한 변경의 의미와 효과를 다시 정리해주면서, 놓치고 지나갈 수 있는 개선 지점까지 명확하게 인지할 수 있었다. 단순히 잘된 점을 나열하는 것이 아니라, 어떤 문제가 어떻게 해결되었는지를 구조화해준다는 점에서 의미가 있었다.
이 덕분에 PR 설명을 작성할 때도 도움이 됐다. 무엇을 변경했는지를 넘어서, 왜 이 변경이 필요했고 어떤 문제를 해결했는지를 보다 분명하게 정리할 수 있었기 때문이다.
마무리
이렇게 셀프 리뷰를 거쳐 수정 사항을 반영하고 나면, 그다음은 PR 생성 커맨드로 이어진다. /self-review는 단독으로 끝나는 도구가 아니라, "구현 → 셀프 리뷰 → 반영 → PR 작성"으로 이어지는 흐름의 한 단계로 설계한 것이다.
이 과정을 도입하면서 PR을 올리는 시점의 완성도가 눈에 띄게 달라졌다. 리뷰어가 처음 코드를 마주했을 때 지적할 수 있는 주요 문제들이 미리 정리된 상태가 되기 때문에, 리뷰에 소요되는 시간과 왕복 횟수도 자연스럽게 줄어든다.
특히 리뷰의 성격 자체가 달라졌다. 이전에는 로직 오류나 누락된 케이스처럼 필수 수정 사항이 중심이었다면, 적용 이후에는 구조 개선이나 설계에 대한 논의가 더 많이 오가는 형태로 바뀌었다. 불필요한 코멘트가 줄어들고, 정말 필요한 피드백에 집중할 수 있게 된 것이다.
결과적으로 PR 리뷰를 병목으로 만들던 요소를 구현 단계에서 상당 부분 흡수할 수 있었다. 물론 사람의 리뷰를 완전히 대체하는 것이 목적은 아니다. 다만 리뷰 이전 단계에서 품질을 한 번 끌어올리는 것만으로도, 전체 개발 흐름은 훨씬 매끄러워졌다.