Split View: 코드 리뷰 완전 가이드: 리뷰를 프로세스로 설계하기
코드 리뷰 완전 가이드: 리뷰를 프로세스로 설계하기
- 들어가며
- 1. 리뷰가 실제로 사는 이유 네 가지
- 2. 승인 기준을 문서화하기
- 3. 변경 크기가 거의 모든 것을 결정한다
- 4. 지연 시간 — 1영업일 규칙과 그 근거
- 5. 무엇을 사람이 보고 무엇을 자동화로 밀어낼 것인가
- 6. 소유권과 승인 규칙
- 7. 코멘트의 등급 — 막는 것과 막지 않는 것
- 8. 합의가 안 될 때의 에스컬레이션
- 9. 리뷰 프로세스를 측정하는 지표와 그 오용
- 퀴즈: 실력을 확인해 보세요
- 마치며
- 참고 자료
- 이어서 읽기
들어가며
이 블로그에는 코드 리뷰를 다룬 글이 이미 있습니다. 코드 리뷰의 대화법과 가르치는 코드 리뷰, 상처 주는 코드 리뷰는 둘 다 말이 어떻게 가서 어떻게 닿는지를 다룹니다. 좋은 글이지만, 그 글들이 다루지 않는 층이 하나 있습니다.
이 글은 리뷰를 대화가 아니라 시스템으로 봅니다. 처리량이 있고, 지연 시간이 있고, 대기열이 있고, 소유권이 있는 프로세스입니다. 같은 팀에서 같은 사람들이 똑같이 친절하게 말해도, 변경 크기가 800줄이고 첫 응답까지 사흘이 걸리면 리뷰는 실패합니다. 반대로 프로세스가 잘 설계되어 있으면 평범한 코멘트도 제 역할을 합니다. 리뷰 품질 문제의 상당 부분은 말투가 아니라 배치의 문제입니다.
기준으로는 Google의 엔지니어링 관행 문서 두 편을 씁니다. 공개된 문서 중 승인 기준과 응답 속도를 가장 구체적으로 규정한 자료이고, 이 글의 인용은 모두 그 원문에서 가져왔습니다.
1. 리뷰가 실제로 사는 이유 네 가지
"리뷰는 버그를 잡기 위한 것"이라는 전제로 프로세스를 짜면 대부분 실패합니다. 결함 발견은 네 가지 목적 중 하나일 뿐이고, 심지어 가장 확실한 것도 아닙니다.
- 결함 발견: 사람이 읽어서 잡을 수 있는 결함은 주로 의도와 구현의 불일치입니다. 널 체크 누락이나 포맷 문제는 도구가 훨씬 잘 잡습니다. 사람이 잘 잡는 것은 "이 함수가 하겠다고 말한 것과 실제로 하는 것이 다르다" 같은 종류입니다.
- 설계 압력: 누군가 읽는다는 사실만으로 작성자의 기준선이 올라갑니다. 리뷰가 실제로 열리기 전에 이미 절반의 효과가 발생합니다.
- 지식 전파: 코드베이스의 어느 부분을 누가 아는지를 넓힙니다. 버스 팩터를 낮추는 가장 저렴한 수단이고, 장기적으로는 결함 발견보다 값이 큽니다.
- 집단 소유권과 기록: "이 결정은 왜 이렇게 됐는가"의 근거가 리뷰 스레드에 남습니다. 6개월 뒤 이 기록은 커밋 메시지보다 자주 읽힙니다.
목적이 다르면 프로세스도 달라집니다. 결함 발견이 목적이면 도메인을 아는 한 명이 깊게 보는 것이 낫고, 지식 전파가 목적이면 잘 모르는 사람이 함께 보는 것이 낫습니다. 두 목적을 한 리뷰에 동시에 얹으면 둘 다 어중간해집니다. 팀이 어느 목적을 사는지 명시하지 않으면 리뷰어마다 다른 기준으로 보게 되고, 그 불일치가 작성자에게는 "사람마다 말이 다르다"로 체감됩니다.
2. 승인 기준을 문서화하기
2-1. 기준이 없으면 리뷰어의 취향이 기준이 된다
리뷰가 가장 크게 무너지는 지점은 승인 기준이 암묵적일 때입니다. 어떤 리뷰어는 완벽을 요구하고 어떤 리뷰어는 대충 넘기면, 작성자는 리뷰어 배정 결과에 따라 통과 여부가 갈리는 경험을 합니다. 이건 공정성 문제이기 이전에 예측 가능성 문제이고, 예측할 수 없는 프로세스는 우회됩니다.
Google의 리뷰어 기준 문서는 이 지점에 한 문장을 제시합니다. "In general, reviewers should favor approving a CL once it is in a state where it definitely improves the overall code health of the system being worked on, even if the CL isn't perfect."
이 문장의 핵심은 두 부분입니다. 판정 대상이 변경 자체의 완성도가 아니라 시스템 전체 코드 건강의 방향이라는 것, 그리고 완벽하지 않아도 승인한다는 것입니다. 기준이 "완벽"이면 승인은 리뷰어의 인내심에 달리고, 기준이 "방향"이면 판정은 재현 가능해집니다.
2-2. 무엇이 근거가 되는가
같은 문서는 의견 충돌의 해결 순서도 정합니다. 기술적 사실과 데이터가 의견과 개인 취향을 이깁니다. 스타일 문제는 스타일 가이드가 권위이고, 가이드에 없으면 개인 취향이 아니라 기존 코드와의 일관성을 따릅니다. 이 순서가 명시되어 있으면 "내 취향으로는"이라는 코멘트가 자연스럽게 줄어듭니다.
2-3. 팀 문서에 넣을 최소 항목
승인 기준 (한 장)
승인한다 시스템의 코드 건강이 분명히 나아지는 방향이면
완벽하지 않아도 승인한다
승인하지 않는다 정확성 결함 / 보안 문제 / 되돌리기 어려운 인터페이스 결정 /
롤백 경로 없음 / 테스트 없이 동작이 바뀜
근거 우선순위 기술적 사실·데이터 > 스타일 가이드 > 기존 코드와의 일관성 > 개인 취향
막지 않는 코멘트 'Nit:' 접두사를 붙이고, 작성자가 넘겨도 된다
이 한 장이 있으면 리뷰 논쟁의 상당수가 문서를 가리키는 것으로 끝납니다. 없으면 매번 처음부터 다시 협상하게 됩니다.
3. 변경 크기가 거의 모든 것을 결정한다
3-1. 크기는 다른 모든 지표의 상류에 있다
리뷰 프로세스에서 손댈 수 있는 변수 중 효과가 가장 큰 것은 리뷰어의 성실성이 아니라 변경 크기입니다. 크기가 커지면 다음이 동시에 나빠집니다.
- 리뷰 착수 지연: 800줄짜리는 "지금은 시간이 없다"의 대상이 됩니다. 대기열에서 가장 오래 머무는 항목은 대개 가장 큰 항목입니다.
- 검토 밀도 저하: 사람이 한 번에 유지할 수 있는 맥락에는 한계가 있습니다. 일정 크기를 넘으면 읽는 속도는 유지되지만 발견율이 떨어집니다. 대형 변경에 "LGTM"만 달리는 현상은 성의 부족이 아니라 용량 초과의 증상입니다.
- 재작업 비용 폭증: 800줄을 다 짠 뒤에 설계 방향이 잘못됐다는 지적을 받으면 되돌릴 것이 너무 많습니다. 그래서 리뷰어가 지적을 삼키게 되고, 결과적으로 리뷰가 형식이 됩니다.
- 충돌과 재베이스: 큰 변경은 오래 열려 있고, 오래 열려 있으면 충돌이 늘고, 충돌을 풀다 보면 다시 커집니다.
3-2. 크기를 줄이는 구체적 방법
- 행동 변경과 구조 변경을 분리한다: 리팩터링과 기능 추가를 한 변경에 섞으면 리뷰어가 진짜 변화를 찾아내지 못합니다. 순수 이동·이름 변경은 별도 변경으로 먼저 보냅니다.
- 인터페이스와 구현을 분리한다: 인터페이스와 계약을 먼저 합의하면 구현 리뷰는 훨씬 빨라집니다. 되돌리기 어려운 결정을 앞으로 당기는 효과도 있습니다.
- 플래그 뒤에서 조각내 넣는다: 완성 전까지 비활성 상태로 병합하면 각 조각이 작게 유지됩니다. Feature Flag와 Progressive Delivery의 방식이 그대로 적용됩니다.
- 생성 코드와 대량 이동은 별도로: 자동 생성물이나 포맷 일괄 적용은 리뷰 대상이 아닌 별도 변경으로 보내고, 커밋 메시지에 재현 명령을 남깁니다.
3-3. 크기 규칙을 운영하는 법
절대 줄 수 상한을 규칙으로 못 박으면 우회가 생깁니다. 대신 크기에 따라 절차를 바꾸는 방식이 잘 작동합니다. 일정 규모를 넘으면 리뷰 요청 전에 설계 합의를 먼저 요구하거나, 분할 계획을 본문에 적게 하는 식입니다. 작성자가 "왜 이렇게 커졌는지"를 한 줄로 설명하게 하는 것만으로도 상당수가 스스로 쪼개집니다.
4. 지연 시간 — 1영업일 규칙과 그 근거
4-1. 규칙
Google의 리뷰 속도 문서는 상한을 명시합니다. "One business day is the maximum time it should take to respond to a code review request (i.e., first thing the next morning)." 그리고 "If you are not in the middle of a focused task, you should do a code review shortly after it comes in"이라고 덧붙입니다.
주의할 것은 이 규칙이 응답 시간에 대한 것이지 승인 시간에 대한 것이 아니라는 점입니다. 같은 문서는 개별 응답의 지연이 전체 소요 시간보다 중요하다고 설명합니다. 리뷰가 여러 번 오가더라도 각 왕복이 빠르면 전체 경험은 좋고, 왕복 한 번에 사흘이 걸리면 두 번만 오가도 일주일이 사라집니다.
4-2. 왜 속도가 그렇게 중요한가
같은 문서는 두 가지 근거를 제시합니다. 하나는 "Most complaints about the code review process are actually resolved by making the process faster"입니다. 리뷰 프로세스에 대한 불만 대부분이 실제로는 속도 문제라는 것입니다. 다른 하나는 파급 효과입니다. "Slow reviews also discourage code cleanups, refactorings, and further improvements to existing CLs."
두 번째가 더 중요합니다. 리뷰가 느리면 비용이 큰 변경만 남습니다. 정리와 리팩터링은 급하지 않으므로 큐에서 밀리고, 밀리는 것을 아는 사람은 애초에 시작하지 않습니다. 그렇게 코드 건강이 서서히 나빠집니다. 리뷰 지연은 리뷰 품질 문제가 아니라 기술 부채 축적 경로입니다. 부채가 쌓이는 경제 구조는 리팩터링의 경제학에 정리되어 있습니다.
4-3. 집중 시간과의 충돌
같은 문서는 집중 작업 중에는 리뷰를 위해 흐름을 끊지 말라고도 말합니다. 이 둘을 동시에 만족시키려면 리뷰를 인터럽트가 아니라 일정으로 다뤄야 합니다.
- 하루 두 번처럼 고정된 리뷰 슬롯을 잡습니다. 무작위로 처리하면 흐름이 끊기고, 슬롯이 없으면 하루 끝까지 밀립니다.
- 대기 중인 리뷰를 팀 단위로 보이게 만듭니다. 개인 알림함에만 있으면 오래된 항목이 조용히 묻힙니다.
- 임계 시간을 넘긴 요청은 자동으로 승격해 다른 리뷰어에게 넘어가게 합니다. 특정인 대기 상태로 방치되는 것이 가장 흔한 지연 원인입니다.
- 시간대가 다른 팀이면 상한을 그 팀 기준으로 다시 씁니다. 1영업일 규칙은 겹치는 근무 시간이 있다는 전제 위에 있습니다.
5. 무엇을 사람이 보고 무엇을 자동화로 밀어낼 것인가
사람의 리뷰 예산은 한정되어 있습니다. 기계가 더 잘하는 것을 사람이 보고 있으면, 사람만 볼 수 있는 것을 볼 시간이 사라집니다.
| 항목 | 담당 | 이유 |
|---|---|---|
| 포맷, 임포트 정렬, 줄 길이 | 자동화 | 논쟁 대상이 아니고 판정이 결정적 |
| 린트 규칙, 미사용 변수 | 자동화 | 규칙으로 표현 가능, 예외는 설정으로 |
| 테스트 실행, 빌드, 타입 검사 | 자동화 | 사람이 확인하면 누락이 생김 |
| 의존성 취약점, 시크릿 유출 | 자동화 | 목록 대조 작업, 사람이 놓침 |
| 변경분 커버리지 하한 | 자동화 | 관문으로 명시 가능 |
| 의도와 구현의 불일치 | 사람 | 요구사항 맥락이 필요 |
| 인터페이스와 이름 | 사람 | 되돌리기 비싸고 판정이 맥락 의존 |
| 실패 처리와 롤백 경로 | 사람 | 운영 지식이 필요 |
| 테스트가 실제 위험을 덮는가 | 사람 | 커버리지 숫자로 대체 불가 |
| 이 변경이 필요한가 | 사람 | 도구가 물을 수 없는 질문 |
원칙은 하나입니다. 한 번이라도 리뷰에서 반복된 지적은 자동화 후보입니다. 같은 코멘트를 세 번 썼다면 그건 사람의 일이 아니라 규칙의 일입니다. 자동화로 옮길 수 없다면 최소한 문서로 옮겨서 매번 협상하지 않게 만듭니다.
AI 리뷰 도구도 이 표의 왼쪽 열을 넓히는 방향으로 봅니다. 다만 자동 제안은 승인이 아니라 코멘트로 취급하는 편이 안전합니다. 판정 책임이 사람에게 남아 있지 않으면 아무도 읽지 않는 승인이 쌓입니다.
6. 소유권과 승인 규칙
6-1. 누가 승인할 수 있는가
소유권 규칙이 없으면 두 가지 실패가 번갈아 나타납니다. 아무나 승인할 수 있으면 도메인을 모르는 사람이 통과시키고, 특정인만 승인할 수 있으면 그 사람이 병목이 되고 휴가 때 팀이 멈춥니다.
실무에서 잘 작동하는 구성은 경로별 소유자 목록을 코드에 두고, 소유자 그룹은 최소 3명 이상으로 유지하는 것입니다. 소유자가 1명인 경로가 남아 있다면 그건 리뷰 규칙 문제가 아니라 버스 팩터 문제입니다.
6-2. 논쟁: 승인 몇 개가 필요한가
여기서 팀마다 답이 갈립니다.
- 1인 승인 쪽: 두 번째 승인의 한계 효용이 낮습니다. 두 명이 필요하면 두 사람의 일정이 겹쳐야 하므로 지연이 늘고, 책임이 분산되어 오히려 각자 덜 꼼꼼히 봅니다.
- 2인 승인 쪽: 결제나 권한처럼 실수 비용이 비대칭적으로 큰 영역에서는 두 번째 눈이 값을 합니다. 규제 요건상 필수인 조직도 있습니다.
- 실제 갈림 축: 되돌리기 비용, 규제 요건, 팀 크기와 도메인 지식 분포, 그리고 현재 지연 시간의 여유.
절충안으로 경로별 차등이 널리 쓰입니다. 대부분의 경로는 1인, 인증·결제·마이그레이션 같은 고위험 경로만 2인으로 두는 방식입니다. 규칙이 코드에 있으면 예외 협상이 줄어듭니다.
6-3. 논쟁: 리뷰가 병합을 막아야 하는가
더 근본적인 논쟁도 있습니다. 트렁크 기반 개발이나 페어 프로그래밍을 하는 팀 중에는 리뷰가 병합을 막지 않아야 한다고 보는 쪽이 있습니다. 페어로 작성하면 이미 두 사람이 본 것이고, 병합 후 리뷰가 오히려 배치 크기를 줄여 통합 빈도를 높인다는 주장입니다.
- 막아야 한다는 쪽: 병합 후 리뷰는 실질적으로 리뷰가 사라지는 경로가 됩니다. 되돌리기 비용이 크고, 지적이 나와도 후속 작업이 우선순위에서 밀립니다.
- 막지 않아야 한다는 쪽: 병합 차단은 대기열을 만들고 대기열은 배치를 키웁니다. 안전은 리뷰가 아니라 테스트·플래그·카나리·빠른 롤백으로 확보하는 편이 낫습니다.
- 실제 갈림 축: 롤백이 얼마나 싼가, 페어링 비율이 얼마나 높은가, 규제 요건이 승인 기록을 요구하는가, 그리고 팀 경험 분포가 얼마나 고른가.
롤백이 몇 분 안에 끝나고 카나리가 있는 팀과, 배포가 월 1회이고 되돌리기가 어려운 팀의 답은 같을 수 없습니다. 어느 쪽을 택하든 그 선택이 어떤 전제 위에 있는지 적어 두는 편이 좋습니다.
7. 코멘트의 등급 — 막는 것과 막지 않는 것
7-1. 등급이 없으면 모든 코멘트가 차단으로 읽힌다
작성자 입장에서 가장 소모적인 상황은 어떤 코멘트를 반드시 반영해야 하는지 모르는 것입니다. 열 개의 코멘트가 같은 무게로 보이면 전부 반영하거나 전부 무시하게 됩니다.
Google 문서는 여기에 간단한 관행을 제시합니다. 반드시 반영할 필요가 없는 다듬기 제안에는 "Nit: " 접두사를 붙여 작성자가 넘길 수 있게 하는 것입니다. 이 관행을 조금 확장해 등급을 명시하면 왕복이 눈에 띄게 줄어듭니다.
Blocking: 반영하지 않으면 승인하지 않음 (정확성·보안·되돌리기 어려운 결정)
Nit: 다듬기 제안, 작성자가 넘겨도 됨
Question: 이해를 위한 질문, 답만 하면 됨
FYI: 이번 변경과 무관한 정보 공유
Later: 별도 이슈로 남길 후속 작업 (여기서 처리하지 않음)
접두사 다섯 개를 도입하는 비용은 거의 없고, 효과는 즉각적입니다. 특히 Later 등급이 있으면 "이왕 여는 김에"로 변경이 부풀어 오르는 현상이 줄어듭니다.
7-2. 논쟁: 코멘트를 단 채 승인하는 것이 건강한가
이것도 팀마다 갈립니다.
- 건강하다는 쪽: 사소한 지적 때문에 하루를 더 기다리게 하는 것은 낭비입니다. 작성자를 신뢰하고 반영은 맡기면 왕복이 사라집니다.
- 건강하지 않다는 쪽: 실제로는 상당수가 반영되지 않고 지나갑니다. 승인이 나간 뒤에는 확인할 사람이 없어서 코멘트가 기록으로만 남습니다.
- 실제 갈림 축: 팀의 후속 반영 이행률, 코멘트 등급 체계의 유무, 그리고 그 변경이 되돌리기 쉬운가.
등급 체계가 있고 이행률이 높으면 코멘트 승인은 잘 작동하고, 등급도 없고 이행 여부를 아무도 보지 않는다면 그건 사실상 무조건 승인입니다. 제도를 도입하기 전에 이행률을 먼저 재 보는 편이 낫습니다.
8. 합의가 안 될 때의 에스컬레이션
리뷰 프로세스에서 가장 자주 빠져 있는 부분이 이것입니다. 대부분의 팀은 합의되는 경우만 가정하고 규칙을 만듭니다.
Google 문서는 원칙을 짧게 제시합니다. "Don't let a CL sit around because the author and the reviewer can't come to an agreement." 교착 자체가 비용이라는 것입니다.
실무 절차로 옮기면 이렇습니다.
1단계 왕복 2회 안에 해결되지 않으면 비동기 코멘트를 중단한다
(텍스트로 세 번 이상 오가는 논쟁은 거의 수렴하지 않는다)
2단계 15분 통화나 대면으로 옮기고, 결론을 리뷰 스레드에 요약해 남긴다
(대화로 옮기되 기록은 리뷰에 남아야 한다)
3단계 그래도 안 되면 판정 근거를 명시한다
기술적 사실·데이터 > 스타일 가이드 > 기존 코드와의 일관성
4단계 판정자가 필요하면 미리 정해 둔 역할이 결정한다
(해당 영역 소유자 → 테크 리드 순서를 문서에 적어 둔다)
5단계 결정을 문서에 반영한다
같은 논쟁이 두 번 일어났다면 그건 가이드가 없는 것이다
핵심은 3단계와 5단계입니다. 근거의 우선순위가 미리 정해져 있으면 논쟁이 취향 대결로 흐르지 않고, 결론을 문서로 되먹이면 같은 논쟁이 반복되지 않습니다. 5단계가 없으면 팀은 매 분기 같은 논쟁을 다시 합니다. 리뷰에서 주장을 설득력 있게 쓰는 방법은 글로 설득하기에 정리되어 있습니다.
9. 리뷰 프로세스를 측정하는 지표와 그 오용
9-1. 볼 값어치가 있는 지표
- 첫 응답까지의 시간: 1영업일 규칙과 직접 대응합니다. 평균이 아니라 상위 백분위로 봅니다. 평균 4시간이어도 상위 10%가 사흘이면 그 사흘이 팀의 체감을 지배합니다.
- 변경 크기 분포: 중앙값과 상위 백분위를 함께 봅니다. 상위 꼬리가 길면 3장의 조치가 필요합니다.
- 왕복 횟수: 3회를 넘는 변경이 늘면 승인 기준이나 코멘트 등급이 불명확하다는 신호입니다.
- 대기열 나이: 열린 지 오래된 항목의 수. 이 값이 오르면 개인이 아니라 배치 규칙을 봐야 합니다.
- 변경 리드 타임과 변경 실패율: DORA는 변경 리드 타임을 "The amount of time it takes for a change to go from committed to version control to deployed in production"으로, 변경 실패율을 "The ratio of deployments that require immediate intervention following a deployment"로 정의합니다. 리뷰 프로세스를 바꿨을 때 이 둘이 어떻게 움직이는지가 최종 판정입니다.
DORA는 속도와 안정성이 상충 관계가 아니라고 말합니다. "DORA's research has repeatedly demonstrated that speed and stability are not tradeoffs." 리뷰를 빠르게 만들었더니 변경 실패율이 올랐다면 절충이 아니라 다른 문제가 있는 것입니다.
9-2. 개인 지표로 쓰는 순간 망가진다
리뷰 지표는 개인 평가에 붙는 순간 전부 왜곡됩니다.
- 작성한 코멘트 수를 재면 의미 없는 코멘트가 늘어납니다.
- 승인 속도를 재면 읽지 않고 승인합니다.
- 리뷰한 변경 수를 재면 작은 것만 골라 봅니다.
- 작성자별 지적 건수를 재면 리뷰가 방어적으로 변하고 솔직한 지적이 사라집니다.
그래서 지표는 사람이 아니라 프로세스에 붙입니다. 첫 응답 시간이 나쁘면 그건 특정인의 게으름이 아니라 배정 규칙과 슬롯 설계의 문제로 봅니다. 변경 크기 꼬리가 길면 작성자를 지적하는 대신 분할 절차를 만듭니다.
또 하나 중요한 것은 결함 발견 수를 리뷰 효과의 대리 지표로 쓰지 않는 것입니다. 1장에서 봤듯 결함 발견은 리뷰의 네 목적 중 하나이고, 지식 전파나 설계 압력은 이 숫자에 전혀 잡히지 않습니다. 지적이 줄었다는 사실은 리뷰가 무력해졌다는 뜻일 수도 있고, 앞단이 좋아졌다는 뜻일 수도 있습니다. 숫자만으로는 구분되지 않습니다.
퀴즈: 실력을 확인해 보세요
퀴즈 1: 리뷰 불만이 계속 나옵니다. 리뷰어 교육과 응답 속도 개선 중 무엇을 먼저 하나?
정답: 속도를 먼저 봅니다. 첫 응답 시간의 상위 백분위와 변경 크기 분포를 측정한 뒤에 교육을 논의합니다.
설명: Google의 리뷰 속도 문서는 리뷰 프로세스에 대한 불만 대부분이 실제로는 속도를 높이는 것으로 해결된다고 말합니다. 말투 문제로 보이는 갈등의 상당수는 사흘을 기다린 뒤 받은 지적이라서 크게 느껴지는 경우입니다. 또한 느린 리뷰는 정리와 리팩터링 같은 급하지 않은 변경을 먼저 포기하게 만들어 코드 건강을 서서히 떨어뜨립니다. 교육이 불필요하다는 뜻은 아니지만 순서가 있습니다.
퀴즈 2: 리뷰어가 "완벽하지 않으니 더 다듬어 달라"며 승인을 미룹니다. 어떤 기준을 적용하나?
정답: 판정 대상은 변경의 완성도가 아니라 시스템 전체 코드 건강의 방향입니다. 분명히 나아지는 방향이면 완벽하지 않아도 승인합니다.
설명: Google 기준 문서는 리뷰어가 시스템의 코드 건강을 분명히 개선하는 상태가 되면 완벽하지 않더라도 승인하는 쪽을 택해야 한다고 명시합니다. 기준이 완벽이면 승인 여부가 리뷰어의 인내심에 달리고 예측 가능성이 사라집니다. 반드시 반영해야 하는 지적과 다듬기 제안을 등급으로 구분하고, 후자에는 넘길 수 있다는 표시를 붙이는 것이 함께 필요합니다.
퀴즈 3: 평균 첫 응답 시간이 4시간인데 팀은 리뷰가 느리다고 말합니다. 무엇을 확인하나?
정답: 평균이 아니라 상위 백분위와 왕복별 지연, 그리고 대기열에 오래 남은 항목의 크기를 확인합니다.
설명: 체감은 평균이 아니라 꼬리가 만듭니다. 평균 4시간이어도 상위 10%가 사흘이면 그 경험이 팀의 인식을 지배하고, 오래 걸린 항목은 대개 가장 큰 변경입니다. 또한 전체 소요 시간보다 개별 응답의 지연이 중요합니다. 왕복 한 번에 사흘이 걸리면 두 번만 오가도 일주일이 사라집니다. 조치는 개인 독려가 아니라 배정 규칙, 리뷰 슬롯, 임계 시간 초과 시 자동 승격 같은 프로세스 쪽입니다.
퀴즈 4: 관리자가 "리뷰 코멘트 수"를 개인 평가 지표로 넣자고 합니다. 어떻게 답하나?
정답: 리뷰 지표는 프로세스에 붙이고 개인 평가에는 붙이지 않습니다. 대신 첫 응답 시간, 변경 크기 분포, 왕복 횟수, 변경 실패율을 팀 지표로 제안합니다.
설명: 코멘트 수를 재면 의미 없는 코멘트가 늘고, 승인 속도를 재면 읽지 않고 승인하며, 리뷰한 변경 수를 재면 작은 것만 골라 보게 됩니다. 게다가 결함 발견은 리뷰의 네 목적 중 하나일 뿐이라 지식 전파나 설계 압력은 어떤 코멘트 수치에도 잡히지 않습니다. 지적이 줄었다는 사실이 리뷰가 무력해졌다는 뜻인지 앞단이 좋아졌다는 뜻인지 숫자만으로는 구분되지 않습니다.
퀴즈 5: 인터페이스 설계를 두고 작성자와 리뷰어가 코멘트로 나흘째 대립 중입니다. 무엇을 하나?
정답: 비동기 논쟁을 중단하고 짧은 통화나 대면으로 옮긴 뒤, 결론을 리뷰 스레드에 요약해 남기고 문서에 반영합니다.
설명: Google 문서는 작성자와 리뷰어가 합의하지 못한다는 이유로 변경이 방치되지 않게 하라고 명시합니다. 교착 자체가 비용이기 때문입니다. 텍스트로 세 번 이상 오가는 논쟁은 거의 수렴하지 않으므로 채널을 바꾸되 기록은 리뷰에 남겨야 합니다. 그래도 결론이 나지 않으면 기술적 사실과 데이터, 스타일 가이드, 기존 코드와의 일관성 순으로 근거의 우선순위를 적용하고, 미리 정해 둔 판정 역할이 결정합니다. 마지막으로 같은 논쟁이 반복되지 않도록 결론을 가이드에 반영합니다.
마치며
코드 리뷰를 개선하려는 시도가 대개 말투에서 시작해 말투에서 끝납니다. 말투는 중요하지만, 같은 사람이 같은 문장을 써도 변경이 800줄이고 응답이 사흘 뒤에 오면 그 리뷰는 실패합니다. 리뷰는 대화이기 전에 대기열이 있는 프로세스입니다.
프로세스로 볼 때 손댈 곳은 분명합니다. 승인 기준을 한 장으로 적어 판정을 재현 가능하게 만들고, 변경 크기를 줄여 상류를 고치고, 첫 응답 시간에 상한을 두고, 기계가 잘하는 일을 사람에게서 걷어내고, 코멘트에 등급을 붙여 무엇이 차단인지 명확히 하고, 교착에는 미리 정해 둔 출구를 둡니다.
그리고 지표는 사람이 아니라 프로세스에 붙입니다. 리뷰가 느린 것은 대개 누군가 게으르기 때문이 아니라 배치가 그렇게 되어 있기 때문입니다. 배치를 고치는 것이 사람을 재촉하는 것보다 언제나 효과가 큽니다.
참고 자료
- The Standard of Code Review — Google Engineering Practices — 완벽하지 않아도 코드 건강이 분명히 개선되면 승인하라는 기준, 기술적 사실과 데이터가 취향에 우선한다는 순서, 스타일 가이드와 기존 코드 일관성의 위치, 다듬기 제안에 붙이는 접두사 관행, 합의 실패로 변경을 방치하지 말라는 문장을 인용했습니다. 2026-08-15 확인.
- Speed of Code Reviews — Google Engineering Practices — 1영업일 응답 상한, 집중 작업 중이 아니면 즉시 리뷰하라는 권고, 불만 대부분이 속도로 해결된다는 문장, 느린 리뷰가 정리와 리팩터링을 위축시킨다는 지적, 개별 응답 지연이 전체 소요 시간보다 중요하다는 설명을 인용했습니다. 2026-08-15 확인.
- DORA — Four keys metrics — 변경 리드 타임과 변경 실패율의 정의, 속도와 안정성이 상충 관계가 아니라는 연구 결과를 인용했습니다. 2026-08-15 확인.
- 리뷰의 네 가지 목적 구분, 코멘트 등급 다섯 종류, 5단계 에스컬레이션 절차, 사람과 자동화의 분담표는 위 자료에 나오는 것이 아니라 이 글에서 정리한 절차입니다.
이어서 읽기
- 이 블로그의 관련 글: 코드 리뷰의 대화법
- 이 블로그의 관련 글: 가르치는 코드 리뷰, 상처 주는 코드 리뷰
- 이 블로그의 관련 글: 글로 설득하기 — 디자인 문서와 RFC가 통과되는 구조
- 이 블로그의 관련 글: 리팩터링의 경제학, 언제 비용이 회수되나
- 관련 도구: 협업 RPG
완전 가이드 시리즈
The Complete Guide to Code Review: Designing Review as a Process
- Introduction
- 1. The Four Reasons Review Actually Exists
- 2. Documenting the Approval Standard
- 3. Change Size Decides Almost Everything
- 4. Latency — the One-Business-Day Rule and Its Rationale
- 5. What Humans Review and What Gets Pushed to Automation
- 6. Ownership and Approval Rules
- 7. Comment Severity — What Blocks and What Does Not
- 8. Escalation When Agreement Fails
- 9. Metrics for the Review Process, and How They Get Misused
- Quiz: Check Your Understanding
- Closing
- References
- Further reading
Introduction
This blog already has posts about code review. The Conversational Craft of Code Review and Reviews That Teach, Reviews That Wound are both about how words travel and how they land. They are good posts, but there is a layer they do not cover.
This post treats review as a system instead of a conversation: something with throughput, latency, a queue and ownership. In the same team, with the same people speaking with the same courtesy, review still fails if the change is 800 lines and the first response takes three days. Conversely, when the process is well designed, even an ordinary comment does its job. A large share of review quality problems are problems of arrangement, not tone.
The reference points are two pages from Google's engineering practices. Among publicly available material they specify the approval standard and the response-time expectation most concretely, and every quotation here comes from those originals.
1. The Four Reasons Review Actually Exists
Building a process on the premise that "review exists to catch bugs" usually fails. Defect discovery is one of four purposes, and it is not even the most reliable one.
- Defect discovery: what a human reader catches is mainly the mismatch between intent and implementation. Missing null checks and formatting issues are caught far better by tooling. What people catch well is "this function does something other than what it says it does."
- Design pressure: the mere fact that someone will read it raises the author's baseline. Half the effect lands before the review is even opened.
- Knowledge spread: it widens who knows which parts of the codebase. It is the cheapest way to lower the bus factor, and over the long run it is worth more than defect discovery.
- Collective ownership and record: the reasoning behind "why is it done this way" is preserved in the review thread. Six months later that record gets read more often than the commit message.
Different purposes imply different processes. If defect discovery is the purpose, one person who knows the domain reading deeply is better; if knowledge spread is the purpose, having someone unfamiliar read along is better. Stacking both onto one review makes both mediocre. If the team never states which purpose it is buying, each reviewer applies a different bar, and the author experiences that inconsistency as "everyone says something different."
2. Documenting the Approval Standard
2-1. Without a standard, the reviewer's taste becomes the standard
Review breaks down hardest when the approval standard is implicit. If one reviewer demands perfection and another waves things through, the author experiences pass or fail as a function of reviewer assignment. That is a predictability problem before it is a fairness problem, and an unpredictable process gets routed around.
Google's reviewer standard page offers one sentence for exactly this: "In general, reviewers should favor approving a CL once it is in a state where it definitely improves the overall code health of the system being worked on, even if the CL isn't perfect."
Two parts of that sentence carry the weight. The object of judgment is the direction of overall system code health, not the polish of the change, and you approve even when it is not perfect. If the bar is perfection, approval depends on reviewer patience; if the bar is direction, the judgment becomes reproducible.
2-2. What counts as grounds
The same page also fixes the order for resolving disagreement. Technical facts and data override opinions and personal preferences. On style, the style guide is the authority, and where the guide is silent, consistency with existing code decides rather than personal taste. Making that order explicit naturally reduces comments of the form "personally I would prefer."
2-3. The minimum to put in the team document
Approval standard (one page)
Approve when the code health of the system clearly improves,
even if the change is not perfect
Do not approve correctness defects / security issues /
hard-to-reverse interface decisions /
no rollback path / behavior changed with no tests
Order of grounds technical facts and data > style guide >
consistency with existing code > personal taste
Non-blocking prefix with "Nit:" — the author may skip it
With this one page, most review arguments end by pointing at the document. Without it, every one is renegotiated from scratch.
3. Change Size Decides Almost Everything
3-1. Size sits upstream of every other metric
Of all the variables you can adjust in a review process, the one with the largest effect is not reviewer diligence — it is change size. As size grows, several things degrade at once.
- Delayed start: an 800-line change becomes the thing there is never time for. The item that sits longest in the queue is usually the largest one.
- Lower inspection density: there is a limit to how much context a person can hold at once. Past a certain size, reading speed holds but discovery rate drops. A large change that gets only "LGTM" is a symptom of exceeded capacity, not laziness.
- Exploding rework cost: being told the design direction is wrong after 800 lines are written means too much to undo. So reviewers swallow the objection, and review becomes ceremony.
- Conflicts and rebases: a big change stays open longer, staying open produces conflicts, and resolving conflicts makes it bigger again.
3-2. Concrete ways to shrink it
- Separate behavior change from structural change: mixing refactoring with a feature hides the real change from the reviewer. Send pure moves and renames as a separate change first.
- Separate interface from implementation: agreeing on the interface and the contract first makes the implementation review far faster, and it pulls hard-to-reverse decisions earlier.
- Land slices behind a flag: merging in an inactive state until completion keeps each slice small. The approach in Feature Flags and Progressive Delivery applies directly.
- Keep generated code and bulk moves separate: send generated output or a formatting sweep as its own non-review change, with the reproducing command in the commit message.
3-3. How to operate a size rule
Hard-coding an absolute line limit invites evasion. What works better is changing the procedure by size: past a threshold, require design agreement before the review request, or require a splitting plan in the description. Just making the author explain in one line why it got this big causes a sizeable share of changes to split themselves.
4. Latency — the One-Business-Day Rule and Its Rationale
4-1. The rule
Google's review speed page states the ceiling explicitly: "One business day is the maximum time it should take to respond to a code review request (i.e., first thing the next morning)." It adds: "If you are not in the middle of a focused task, you should do a code review shortly after it comes in."
Note that this rule is about response time, not approval time. The same page explains that the latency of an individual response matters more than total elapsed time. A review can go several rounds and still feel fine if each round-trip is fast; if one round-trip takes three days, two rounds erase a week.
4-2. Why speed matters this much
The page gives two reasons. One is that "Most complaints about the code review process are actually resolved by making the process faster." The other is the knock-on effect: "Slow reviews also discourage code cleanups, refactorings, and further improvements to existing CLs."
The second matters more. When review is slow, only expensive changes survive. Cleanups and refactorings are never urgent, so they sit in the queue, and people who know they will sit never start them. Code health erodes quietly. Review latency is not a review quality problem, it is a mechanism for accruing technical debt. The economics of that accrual are covered in The Economics of Refactoring.
4-3. The conflict with focus time
The same page also says not to break your flow for a review while you are in focused work. Satisfying both requirements means treating review as scheduled work rather than an interrupt.
- Fix review slots, for example twice a day. Handling them at random breaks flow; having no slot pushes them to the end of the day.
- Make the pending queue visible at team level. Anything that lives only in a personal inbox quietly ages.
- Auto-escalate requests past a threshold to another reviewer. Being parked on one specific person is the most common cause of delay.
- If the team spans time zones, rewrite the ceiling in that team's terms. The one-business-day rule assumes overlapping working hours.
5. What Humans Review and What Gets Pushed to Automation
Human review budget is finite. If people are looking at what machines do better, there is no time left for what only people can see.
| Item | Owner | Reason |
|---|---|---|
| Formatting, import order, line length | Automation | Not debatable, judgment is deterministic |
| Lint rules, unused variables | Automation | Expressible as rules, exceptions via config |
| Test runs, build, type checking | Automation | Human verification leaves gaps |
| Dependency vulnerabilities, leaked secrets | Automation | List matching, humans miss items |
| Delta coverage floor | Automation | Can be stated as an explicit gate |
| Mismatch between intent and implementation | Human | Requires requirements context |
| Interfaces and naming | Human | Expensive to reverse, context-dependent judgment |
| Failure handling and rollback path | Human | Requires operational knowledge |
| Whether the tests cover the real risk | Human | Cannot be replaced by a coverage number |
| Whether this change is needed at all | Human | A question no tool can ask |
There is one principle: any remark repeated even once in review is a candidate for automation. If you have written the same comment three times, it is the job of a rule, not a person. If it cannot be automated, at least move it into a document so it is not renegotiated each time.
AI review tooling belongs in the same frame — it widens the left column. Still, it is safer to treat automated suggestions as comments, not approvals. If the responsibility for judgment does not remain with a person, you accumulate approvals nobody read.
6. Ownership and Approval Rules
6-1. Who is allowed to approve
Without ownership rules, two failures alternate. If anyone can approve, someone without domain knowledge waves things through; if only one person can approve, that person becomes the bottleneck and the team stops when they take leave.
The arrangement that works in practice is a per-path owner list kept in the repository, with every owner group holding at least three people. If a path still has a single owner, that is a bus factor problem, not a review rule problem.
6-2. Contested: how many approvals are required
Teams genuinely differ here.
- The single-approval side: the marginal value of a second approval is low. Requiring two means two calendars have to align, which increases latency, and diffused responsibility means each reviewer reads less carefully.
- The two-approval side: in areas where the cost of a mistake is asymmetric — payments, permissions — the second pair of eyes earns its keep. Some organizations are required to have it by regulation.
- The real axes: reversal cost, regulatory requirements, team size and the distribution of domain knowledge, and how much latency headroom you currently have.
The common compromise is differentiation by path: one approval for most paths, two only for high-risk paths such as authentication, payments and migrations. Encoding the rule in the repository reduces case-by-case negotiation.
6-3. Contested: should review block merge at all
There is a more fundamental argument. Among teams doing trunk-based development or pair programming, some hold that review should not block merge. If it was written in a pair, two people have already read it, and post-merge review keeps batch size down and integration frequency up.
- The blocking side: post-merge review is in practice the path by which review disappears. Reversal is expensive, and when an objection does arrive, the follow-up work loses to other priorities.
- The non-blocking side: blocking merge creates a queue, and a queue grows batches. Safety is better bought with tests, flags, canaries and fast rollback than with a merge gate.
- The real axes: how cheap rollback is, how high the pairing rate is, whether regulation requires an approval record, and how evenly experience is distributed across the team.
A team with minute-scale rollback and a canary cannot have the same answer as a team that ships monthly and cannot easily revert. Whichever you choose, write down the premises the choice rests on.
7. Comment Severity — What Blocks and What Does Not
7-1. Without levels, every comment reads as blocking
The most draining situation for an author is not knowing which comments must be addressed. When ten comments carry equal apparent weight, the author either applies all of them or ignores all of them.
Google's document offers a simple convention here: prefix non-mandatory polish with "Nit: " so the author can skip it. Extending that slightly into explicit levels visibly reduces round-trips.
Blocking: will not approve unless addressed
(correctness, security, hard-to-reverse decisions)
Nit: polish suggestion, the author may skip it
Question: a question for understanding, an answer is enough
FYI: information unrelated to this change
Later: follow-up to file separately, not handled here
Introducing five prefixes costs almost nothing and pays off immediately. In particular, having a Later level reduces the "while we're in here" inflation of change size.
7-2. Contested: is approving with comments healthy
This one splits teams too.
- The healthy side: making someone wait another day over minor remarks is waste. Trust the author and hand the application over, and the round-trip disappears.
- The unhealthy side: in practice a substantial share never gets applied. After approval there is nobody left to check, so comments survive only as a record.
- The real axes: the team's actual follow-through rate, whether a comment severity scheme exists, and whether the change is easy to reverse.
With a severity scheme and a high follow-through rate, approve-with-comments works well; with neither a scheme nor anyone checking whether comments were applied, it is effectively unconditional approval. Measure the follow-through rate before adopting the practice.
8. Escalation When Agreement Fails
This is the part most often missing from a review process. Most teams write rules only for the case where agreement happens.
Google's document states the principle briefly: "Don't let a CL sit around because the author and the reviewer can't come to an agreement." The deadlock itself is the cost.
Translated into a working procedure:
Step 1 If two round-trips do not resolve it, stop commenting asynchronously
(an argument that goes three rounds in text almost never converges)
Step 2 Move to a 15-minute call or a face-to-face,
then summarize the conclusion back into the review thread
(change the channel, but keep the record in the review)
Step 3 If it still stands, state the grounds explicitly
technical facts and data > style guide > consistency with existing code
Step 4 If a decider is needed, a pre-assigned role decides
(write the order in the document: area owner → tech lead)
Step 5 Feed the decision back into the document
if the same argument happened twice, the guide is missing
Steps 3 and 5 are the core. With the order of grounds fixed in advance, the argument does not degenerate into a contest of taste; feeding conclusions back into documentation stops the same argument recurring. Without step 5, a team relitigates the same question every quarter. How to make an argument persuasive in writing is covered in Persuasive Writing for Engineers.
9. Metrics for the Review Process, and How They Get Misused
9-1. Metrics worth watching
- Time to first response: it maps directly onto the one-business-day rule. Watch the upper percentile, not the mean. A four-hour average with a three-day p90 means those three days dominate how the team feels.
- Change size distribution: watch the median and the upper percentile together. A long upper tail calls for the measures in section 3.
- Round-trip count: a rising number of changes going past three rounds signals an unclear approval standard or missing comment levels.
- Queue age: the count of items open a long time. When it rises, look at batching rules rather than individuals.
- Change lead time and change fail rate: DORA defines change lead time as "The amount of time it takes for a change to go from committed to version control to deployed in production" and change fail rate as "The ratio of deployments that require immediate intervention following a deployment." How those two move after a process change is the final verdict.
DORA states that speed and stability are not a trade-off: "DORA's research has repeatedly demonstrated that speed and stability are not tradeoffs." If you made review faster and the change fail rate rose, that is not an inevitable compromise — something else is wrong.
9-2. They break the moment they become individual metrics
Review metrics distort completely once attached to individual performance.
- Comments written produces meaningless comments.
- Approval speed produces approval without reading.
- Changes reviewed produces cherry-picking small ones.
- Objections per author makes review defensive and drives out candid feedback.
So attach metrics to the process, not to people. A bad first-response time is a problem of assignment rules and slot design, not of one person's laziness. A long tail in change size calls for a splitting procedure, not a word with the author.
One more thing matters: do not use defect counts as a proxy for review effectiveness. As section 1 showed, defect discovery is one of four purposes, and knowledge spread and design pressure never appear in that number. Fewer objections might mean review has gone toothless, or it might mean the upstream got better. The number alone cannot tell you which.
Quiz: Check Your Understanding
Quiz 1: Complaints about review keep coming. Reviewer training or faster responses — which first?
Answer: Look at speed first. Measure the upper percentile of first-response time and the change size distribution before discussing training.
Explanation: Google's review speed page states that most complaints about the code review process are actually resolved by making the process faster. A large share of what looks like a tone problem is an objection that feels heavy because it arrived after a three-day wait. Slow review also makes people abandon non-urgent cleanups and refactorings first, eroding code health over time. Training is not useless, but there is an order.
Quiz 2: A reviewer withholds approval, saying "it is not perfect yet, please polish." What standard applies?
Answer: The object of judgment is the direction of overall system code health, not the polish of the change. If it clearly improves things, approve even though it is not perfect.
Explanation: Google's standard page states explicitly that reviewers should favor approving once the change definitely improves the overall code health of the system, even if it is not perfect. If the bar is perfection, approval depends on reviewer patience and predictability disappears. This has to be paired with severity levels that separate must-address objections from polish suggestions, with the latter marked as skippable.
Quiz 3: Average time to first response is four hours, yet the team says review is slow. What do you check?
Answer: Not the mean but the upper percentile, the per-round-trip latency, and the size of items sitting longest in the queue.
Explanation: Perception is made by the tail, not the average. A four-hour average with a three-day p90 means that experience dominates, and the slowest items are usually the largest changes. Individual response latency also matters more than total elapsed time: one three-day round-trip means two rounds erase a week. The fix is on the process side — assignment rules, review slots, automatic escalation past a threshold — not individual nudging.
Quiz 4: A manager proposes using "review comments written" as an individual performance metric. How do you answer?
Answer: Review metrics belong to the process, not to individual performance. Propose first-response time, change size distribution, round-trip count and change fail rate as team metrics instead.
Explanation: Measuring comment counts produces meaningless comments, measuring approval speed produces approval without reading, and measuring changes reviewed produces cherry-picking of small ones. Beyond that, defect discovery is only one of review's four purposes, so knowledge spread and design pressure never show up in any comment count. Whether fewer objections means review went toothless or the upstream improved cannot be distinguished from the number alone.
Quiz 5: Author and reviewer have been deadlocked in comments over an interface design for four days. What do you do?
Answer: Stop the asynchronous argument, move to a short call or a face-to-face, then summarize the conclusion back into the review thread and feed it into the documentation.
Explanation: Google's document states explicitly not to let a change sit around because the author and reviewer cannot agree, because the deadlock itself is the cost. An argument that goes three or more rounds in text almost never converges, so change the channel while keeping the record in the review. If it still does not resolve, apply the order of grounds — technical facts and data, then the style guide, then consistency with existing code — and let a pre-assigned decider decide. Finally, put the conclusion in the guide so the argument does not recur.
Closing
Most attempts to improve code review start with tone and end with tone. Tone matters, but the same person writing the same sentence produces a failed review when the change is 800 lines and the response arrives three days later. Review is a queued process before it is a conversation.
Seen as a process, the places to act are clear. Write the approval standard on one page so judgment becomes reproducible. Shrink change size to fix the upstream. Put a ceiling on first-response time. Take off human hands what machines do better. Attach severity levels to comments so it is obvious what blocks. Give deadlock a pre-agreed exit.
And attach metrics to the process, not to people. Review is usually slow not because someone is lazy but because the arrangement makes it so. Fixing the arrangement always beats hurrying the people.
References
- The Standard of Code Review — Google Engineering Practices — quoted for the standard of approving when code health definitely improves even if the change is not perfect, the precedence of technical facts and data over preference, the position of the style guide and consistency with existing code, the prefix convention for non-mandatory polish, and the instruction not to let a change sit because of disagreement. Checked 2026-08-15.
- Speed of Code Reviews — Google Engineering Practices — quoted for the one-business-day response ceiling, the recommendation to review promptly when not in focused work, the statement that most complaints are resolved by speed, the observation that slow reviews discourage cleanups and refactorings, and the point that individual response latency matters more than total elapsed time. Checked 2026-08-15.
- DORA — Four keys metrics — quoted for the definitions of change lead time and change fail rate, and the finding that speed and stability are not trade-offs. Checked 2026-08-15.
- The four purposes of review, the five comment severity levels, the five-step escalation procedure, and the human-versus-automation split table do not appear in the sources above — they are procedures assembled in this post.
Further reading
- Related post on this blog: The Conversational Craft of Code Review
- Related post on this blog: Reviews That Teach, Reviews That Wound
- Related post on this blog: Persuasive Writing for Engineers — How Design Docs and RFCs Get Approved
- Related post on this blog: The Economics of Refactoring: When It Pays
- Related tool: Collab RPG
Complete Guide Series