16. Pull Request 심화 — 코드 리뷰와 협업
- Pull Request(PR)가 무엇이고 왜 협업의 핵심인지 이해한다
- PR을 열고, 리뷰하고, 병합하는 전체 흐름을 익힌다
- 협업자(collaborator)를 추가하고 보호 브랜치를 설정한다
- 이슈(Issue)로 작업을 추적한다
16.1 Pull Request란 무엇인가?
지금까지는 내 변경을 그냥 git push로 main에 바로 올렸습니다. 하지만 팀에서는 그렇게 하지 않습니다. "내 브랜치의 변경을 main에 합쳐도 될까요? 검토해주세요"라고 요청하고, 동료가 확인(리뷰)한 뒤 합칩니다. 이 요청이 Pull Request(PR)입니다.
flowchart TD
F["🌿 내 feature 브랜치"]
PR["📬 PR 생성<br/>리뷰 요청"]
R["👀 동료가 코드 검토<br/>+ 코멘트"]
M["✅ 승인 → main에 병합"]
F --> PR --> R --> M
classDef branch fill:#dbeafe,stroke:#2563eb,color:#1e40af
classDef pr fill:#fef3c7,stroke:#d97706,color:#92400e
classDef review fill:#f3e8ff,stroke:#9333ea,color:#6b21a8
classDef merge fill:#dcfce7,stroke:#16a34a,color:#166534
class F branch
class PR pr
class R review
class M merge
PR이 주는 이점
- 코드 리뷰: 합치기 전에 동료가 버그·개선점을 발견
- 토론 기록: 왜 이렇게 바꿨는지 대화가 영구 보존
- 품질 게이트: CI(13장)가 자동으로 테스트를 돌려 검증
- 지식 공유: 다른 사람의 코드를 보며 팀 전체가 성장
16.2 PR 전체 흐름 (Step by Step)
가장 일반적인 PR 워크플로우입니다.
# 1. main 최신화 git switch main git pull # 2. 작업용 브랜치 생성 git switch -c feature/add-login # 3. 작업하고 커밋 echo "login code" > login.js git add login.js git commit -m "Add login feature" # 4. 원격에 브랜치 push git push -u origin feature/add-login
- GitHub에서 PR 생성: push 후 GitHub 저장소에 가면 "Compare & pull request" 버튼이 뜹니다. 또는 12장의
gh pr create로 터미널에서 바로 만들 수 있습니다.
- PR 작성: 제목, 설명(무엇을·왜 바꿨는지), 리뷰어 지정.
- 리뷰 → 수정 → 승인 → 병합
- 정리: 병합 후 브랜치 삭제.
git switch main git pull git branch -d feature/add-login
16.3 PR 리뷰하기
리뷰어는 PR 페이지의 Files changed 탭에서 변경을 줄 단위로 봅니다.
- 특정 줄에 마우스를 올려 + 를 누르면 그 줄에 코멘트를 남길 수 있습니다.
- 리뷰를 마치며 세 가지 중 하나를 선택합니다.
| 리뷰 결정 | 의미 |
|---|---|
| Comment | 의견만 남김 (승인/거부 아님) |
| Approve | 승인 (병합해도 좋음) |
| Request changes | 수정 요청 (이대로는 병합 불가) |
터미널에서도 가능합니다(12장).
gh pr review 42 --approve gh pr review 42 --request-changes --body "테스트 추가 부탁드려요"
작성자가 코멘트에 따라 추가 커밋을 push하면, PR에 자동으로 반영됩니다. PR은 "브랜치"를 가리키므로, 그 브랜치에 커밋이 쌓이면 PR도 함께 갱신됩니다.
16.4 PR 병합 방식 3가지
병합할 때 GitHub은 세 가지 방식을 제공합니다. (8·9장의 개념과 연결됩니다.)
| 방식 | 결과 | 언제 |
|---|---|---|
| Create a merge commit | 병합 커밋 생성, 모든 커밋 보존 | 작업 이력을 그대로 남기고 싶을 때 |
| Squash and merge | 브랜치의 모든 커밋을 하나로 합쳐 병합 | 자잘한 커밋을 깔끔히 정리할 때 (가장 흔함) |
| Rebase and merge | 커밋들을 main 위에 직선으로 재배치 | 병합 커밋 없이 직선 이력을 원할 때 |
gh pr merge 42 --squash --delete-branch
16.5 협업자(Collaborator) 추가하기
개인 저장소에 다른 사람이 직접 push하려면 협업자로 초대해야 합니다.
- 저장소 → Settings → Collaborators
- Add people으로 GitHub 사용자명/이메일 입력
- 초대받은 사람이 이메일/알림에서 수락
협업자가 되면 그 사람도 브랜치를 push하고 PR을 열 수 있습니다. (포크 없이 직접 기여 — 12장의 포크 방식과 대비됩니다. → 17장)
16.6 보호 브랜치(Protected Branch) 설정
기본적으로는 승인 없이도 main에 병합이 가능합니다. 하지만 중요한 브랜치(main)는 규칙으로 보호해야 사고를 막습니다.
- 저장소 → Settings → Branches → Add branch ruleset (또는 Branch protection rule)
- 대상 브랜치:
main - 주요 옵션:
| 규칙 | 효과 |
|---|---|
| Require a pull request before merging | main 직접 push 금지, PR 필수 |
| Require approvals | 병합 전 N명의 승인 필요 |
| Require status checks to pass | CI(테스트) 통과해야 병합 가능 |
| Require conversation resolution | 모든 리뷰 코멘트 해결 후 병합 |
이 설정 후에는 승인 없는 PR은 병합 버튼이 비활성화됩니다. 즉 누군가 한 명은 반드시 코드를 봐야 main에 들어갑니다.
16.7 이슈(Issue)로 작업 추적하기
이슈는 "할 일·버그·아이디어"를 기록하고 토론하는 공간입니다. 코드를 담지 않는 일종의 게시판입니다.
- Issues 탭 → New issue
- 제목 + 설명(재현 절차, 기대 동작 등) 작성
- Labels(bug, enhancement...), Assignees(담당자), Milestone(목표 시점) 지정
# 터미널에서 (12장) gh issue create --title "로그인 버튼 작동 안 함" --label bug --assignee "@me" gh issue list --state open
PR과 이슈 연결하기
커밋 메시지나 PR 설명에 특정 키워드를 쓰면, PR이 병합될 때 이슈가 자동으로 닫힙니다.
Fixes #17 Closes #23 Resolves #5
예: PR 설명에 Fixes #17이라고 쓰면, 그 PR이 main에 병합되는 순간 17번 이슈가 자동으로 Close됩니다. 작업과 추적이 깔끔하게 연결됩니다.
16.8 공개 저장소에서 배우기
유명 오픈소스 저장소의 PR을 구경하는 것은 최고의 학습법입니다. 실제 개발자들이 어떻게 변경을 설명하고, 리뷰하고, 토론하는지 그대로 볼 수 있습니다. 관심 있는 프로젝트의 Pull requests 탭과 Issues 탭을 둘러보세요. 좋은 PR 설명과 리뷰 문화를 자연스럽게 익히게 됩니다.
16.9 이 장에서 배운 것 (요약)
- PR = "내 브랜치를 main에 합쳐달라"는 리뷰 요청 (GitLab은 MR)
- 흐름: 브랜치 push → PR 생성 → 리뷰/코멘트 → 승인 → 병합 → 브랜치 정리
- 리뷰 결정: Comment / Approve / Request changes
- 병합 방식: merge commit / squash(인기) / rebase
- 협업자 추가로 직접 기여 권한 부여
- 보호 브랜치로 PR·승인·CI 통과를 강제 (main 보호)
- 이슈로 작업 추적,
Fixes #번호로 PR과 자동 연결
✍️ 확인 문제
- "Pull Request"라는 이름이 붙은 이유는?
- 자잘한 커밋을 main에 하나로 깔끔하게 넣는 병합 방식은?
- main에 승인 없이는 병합 못 하게 하려면 무엇을 설정하나요?
다음 장에서는 권한이 없는 남의 저장소에 기여하는 방법, 포크(Fork)와 오픈소스 기여를 배웁니다. → 17_포크와오픈소스기여.md