| name | create-pr |
| description | 현재 브랜치를 기반으로 GitHub Pull Request를 생성하는 스킬. 변경 내역(커밋과 diff)을 분석해 "어떤 파일·클래스·함수가 어떻게 바뀌었는지"가 한눈에 보이는 구체적인 PR 본문을 작성한다. 본문은 업계 베스트 프랙티스(요약 → 배경 → 주요 변경 → 테스트 → 관련 이슈)를 따르는 **고정 형식**으로 통일한다. 사용자가 "PR 만들어줘", "pull request 생성해줘", "PR 올려", "지금 브랜치로 PR 띄워줘", "create pr", "open pr" 등을 말하거나, 작업이 끝났으니 PR을 만들어 달라는 맥락이 보일 때 이 스킬을 사용한다. 단순 커밋 생성 요청에는 사용하지 않는다.
|
Pull Request 생성
현재 브랜치의 변경 내역을 분석해 GitHub PR을 만든다. 본문은 아래의 고정 5섹션 템플릿을
사용하며, 핵심 가치는 "본문만 봐도 무엇이 왜 어떻게 바뀌었는지 이해할 수 있게 쓰는 것"이다.
고정 PR 본문 템플릿
모든 PR은 다음 5개 섹션 + 푸터를 항상 같은 순서로 사용한다. 섹션을 추가하거나 빼지 않는다.
각 섹션이 비게 될 것 같으면 정보를 더 캐서 채운다 (커밋·diff·이슈를 다시 읽기).
## 요약
<이 PR이 한 일을 2-3문장으로 서술. 추상적 단어("개선", "리팩토링") 대신
무엇을 만들었는지 구체적으로.>
## 배경
<왜 이 변경이 필요했는지. 해결하려는 문제, 사용자 요구, 기술 부채 등.
버그 수정이면 증상이 아니라 근본 원인을 적는다.>
## 주요 변경
- `대상명`: 무엇을 어떻게 바꿨는지
- `대상명`: 무엇을 어떻게 바꿨는지
- ...
## 테스트
- [x] 자동 검증된 항목 (테스트 클래스/메서드 명시)
- [ ] 사용자가 직접 확인해야 하는 항목
Closes #<이슈번호>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
연관된 이슈가 없으면 Closes #N 줄을 생략한다. 이슈가 있는데 자동 종료가 적절치 않으면
Refs #N 으로 바꾼다. 그 외 섹션은 모두 유지한다.
본문은 항상 한국어로 작성한다 (저장소가 어떤 언어를 쓰든 무관).
사전 점검
다음 조건이 충족되지 않으면 진행 전에 사용자에게 알리고 확인을 받는다:
- 현재 디렉터리가 git 저장소인지 (
git rev-parse --git-dir)
gh CLI가 인증되어 있는지 (gh auth status)
- main/develop 같은 베이스 브랜치 위가 아닌지 (베이스 브랜치 위면 새 브랜치를 만들지 물어본다)
- 커밋되지 않은 변경 사항이 있는지 — 있으면 사용자에게 PR에 포함할지 별도 작업인지 확인
워크플로우
1단계: 컨텍스트 수집 (병렬 실행)
다음 명령을 하나의 메시지에서 병렬로 실행한다:
git status — 워킹 트리 상태
git rev-parse --abbrev-ref HEAD — 현재 브랜치
gh repo view --json defaultBranchRef -q .defaultBranchRef.name — 기본 베이스 브랜치
(CLAUDE.md에서 메인 브랜치를 명시하고 있으면 그쪽을 우선)
git log <base>..HEAD --pretty=format:'%h%n%B%n---' — 본문 포함 전체 커밋 메시지
git diff <base>...HEAD --stat — 변경 파일 통계
git diff <base>...HEAD — 전체 diff (큰 PR이면 파일별로 나눠 읽는다)
gh pr view --json number,url 2>/dev/null — 현재 브랜치의 기존 PR 존재 여부
2단계: 변경 내역 분석
커밋 메시지와 diff를 함께 보고 다음을 추출한다. 모든 커밋을 훑는다 — 마지막 커밋만
보면 PR 전체 의도를 놓친다.
- 신규 추가된 클래스/컴포넌트/함수/파일 — 이름과 한 줄 책임
- 수정된 기존 코드 — 무엇을 어떻게 바꿨는지 (단순 리팩토링인지, 동작이 바뀐 건지)
- 삭제된 코드 — 무엇이 사라졌는지, 왜 필요 없어졌는지
- 설정/스키마/마이그레이션 — DB 스키마, 환경 변수, CI 변경 등 파급력 있는 변경
- 연관 Issue — 브랜치 이름(예:
feature/207-xxx → #207), 커밋 메시지, "Closes #N" 표기
- 변경 동기 — 이슈 본문, 커밋 본문, 브랜치 명에서 "왜"의 단서를 모은다.
단서가 부족하면 사용자에게 묻는다 (배경 섹션을 채우려면 반드시 필요).
큰 diff는 영역별로 묶어 읽는다 (예: 백엔드/프론트엔드, 도메인 모듈별).
3단계: PR 제목 작성
- 70자 이내
- Conventional Commits 접두사 사용 (
feat:, fix:, refactor:, chore:, docs:,
test:, perf:, style:, build:, ci: 중 선택)
- 추상어 대신 핵심 변경을 한 줄에 담는다
- 가장 최신 커밋 제목을 그대로 쓰지 말고 PR 전체를 대표하는 제목을 새로 짓는다
예시:
- ❌
feat: 세션 기능 추가
- ✅
feat: Redis 기반 활성 세션 매니저 및 세션 교체 이벤트 DTO 구현
4단계: 각 섹션 작성 가이드
## 요약
2-3문장으로 PR이 한 일을 서술한다. 커밋 로그 복사 X. 큰 그림을 짧게.
- ❌ "여러 변경사항을 적용했습니다."
- ✅ "STOMP CONNECT 시 같은 사용자의 기존 세션을 감지해 교체 이벤트를 발행하고, 교체된
세션의 disconnect 시 유예 기간을 스킵하도록 처리한다. 통합 테스트 3건으로 모든
교체 시나리오를 커버한다."
## 배경
왜 이 변경이 필요한지를 적는다. 이슈 본문, 커밋 본문, 브랜치 이름에서 단서를 찾는다.
- 새 기능: 어떤 사용자 요구·제품 결정에서 출발했는지
- 버그 수정: 증상 → 근본 원인 → 수정 접근 (왜 이 방식인지)
- 리팩토링: 기존 구조의 어떤 문제가 있었고, 새 구조가 어떻게 그것을 해결하는지
- 의존성/설정: 왜 지금 바꿔야 했는지
단서가 부족해 추측으로 채워야 할 것 같으면 추측하지 말고 사용자에게 직접 묻는다.
"이 변경의 배경을 한두 문장으로 알려주시겠어요?" 라고 물어 본 뒤 작성한다.
## 주요 변경
이 섹션이 PR 본문의 심장이다. 다음 규칙을 지킨다:
- 이름을 명시한다: 수정된 클래스·함수·파일·컴포넌트 이름을 백틱으로 감싸 적는다
- 무엇을 + 어떻게를 한 줄에 담는다 (동사 + 대상 + 방식)
- 모호한 동사 금지: "개선", "리팩토링", "정리" 단독 사용 X
- 부수 변경도 별도 항목으로 (버그 수정, 타입 추가, 의존성 업데이트 등)
- 5~10개 항목이 적정. 너무 많으면 영역별로 묶거나 핵심만 남긴다
나쁜 예 vs 좋은 예:
❌
- 세션 관리 기능 추가
- 관련 테스트 작성
✅
- `ActiveSessionManager` 신규 생성: Redis GET/SET/DEL 기반 활성 세션 CRUD (TTL 24시간, Lua 스크립트 원자적 삭제)
- `SessionReplacedEventMessage` 신규 생성: `RoomEventMessage` 다형성 직렬화 지원 (`SESSION_REPLACED` 타입)
- `RoomEventMessage`의 `@JsonSubTypes`에 `SESSION_REPLACED` 항목 추가
- `ActiveSessionManagerTest` 통합 테스트 9건 추가 (Testcontainers Redis 사용)
## 테스트
체크박스 형식 사용. 이미 검증한 항목은 [x], 사용자가 직접 확인해야 하는 항목(브라우저
동작·운영 환경 등)은 [ ]로 둔다. 가짜로 모두 체크하지 않는다.
- 테스트 코드를 추가했다면 어떤 클래스·메서드를 어떤 케이스로 작성했는지 명시
- 자동 테스트로 검증 불가능한 항목 (UI, 외부 서비스, 권한)은
[ ]로 두고 사용자가
머지 전에 확인하도록 둔다
- 항목이 5개 이상 늘어나면 비슷한 것을 묶어 줄인다
예시:
- [x] `ActiveSessionManagerTest` — 세션 등록/조회/갱신/삭제 (9개 케이스)
- [x] 같은 방에서 새 탭으로 접속 → SESSION_REPLACED 이벤트 전송 (통합 테스트)
- [ ] 운영 환경에서 다른 탭 접속 시 기존 탭에 오버레이 표시 확인
Closes #N
브랜치명·커밋·이슈 검색으로 연관 이슈를 찾는다. 자동 종료가 부적절하면 Refs #N으로
바꾼다. 연관 이슈가 없으면 줄 자체를 생략한다.
푸터
🤖 Generated with [Claude Code](https://claude.com/claude-code) 한 줄을 항상 마지막에 둔다.
5단계: 사용자 확인
작성한 제목과 본문을 사용자에게 보여주고 확인을 받는다. 사용자가 곧바로 "만들어줘"라고
지시했거나 auto/자율 모드라면 한 번 보여주고 바로 진행해도 좋다. 큰 PR이거나 ## 배경 을
추측으로 채워야 했다면 반드시 확인한다.
6단계: PR 생성
순서:
- 원격 추적 브랜치가 없으면
git push -u origin <branch> 로 푸시. 이미 있으면 git push
로 최신화.
- 동일 브랜치에 PR이 이미 있으면 새로 만들지 말고
gh pr edit <번호> --body "..."
또는 --title "..." 로 갱신할지 사용자에게 묻는다.
- PR 생성은 반드시 HEREDOC으로 본문을 전달한다. 한 줄 문자열이나
\n 이스케이프는
포맷이 깨진다.
gh pr create --base <base-branch> --title "feat: 무엇을 했는지 구체적으로" --body "$(cat <<'EOF'
## 요약
<2-3문장>
## 배경
<왜 이 변경이 필요했는지>
## 주요 변경
- `대상명`: 무엇을 어떻게 바꿨는지
- `대상명`: 무엇을 어떻게 바꿨는지
## 테스트
- [x] 자동 검증된 항목
- [ ] 사용자가 직접 확인할 항목
Closes #123
🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"
7단계: 결과 보고
PR이 생성되면 URL을 사용자에게 보여준다. gh pr create 출력의 마지막 줄이 URL이다.
안전 수칙
git push --force 또는 --force-with-lease는 사용자가 명시적으로 요청하지 않는 한 쓰지 않는다.
- main/develop 같은 보호 브랜치에 직접 푸시하지 않는다 — PR은 현재 작업 브랜치에서만 생성한다.
--no-verify 같이 hook을 우회하는 옵션은 사용자가 명시적으로 요청하지 않는 한 쓰지 않는다.
- 시크릿(.env, credentials 등)이 diff에 포함되어 있으면 PR 생성 전에 사용자에게 경고한다.
- PR 본문에 추측을 쓰지 않는다. diff·커밋에서 실제로 확인한 것만 적는다. 모르는 부분은
사용자에게 묻거나 항목에서 뺀다.
흔한 실수와 회피
- ❌ 마지막 커밋 메시지만 보고 작성 → ✅
<base>..HEAD 전체 커밋과 diff를 본다
- ❌ "기능 추가, 테스트 작성, 버그 수정" 같은 추상적 bullet → ✅ 클래스/함수 이름이 들어간 구체적 bullet
- ❌
## 배경을 추측으로 채움 → ✅ 단서가 부족하면 사용자에게 묻는다
- ❌ 모든 테스트 항목을
[x]로 체크 → ✅ 실제 검증 여부를 정확히 표기
- ❌
gh pr create --body "줄1\n줄2" 사용 → ✅ HEREDOC 사용
- ❌ 베이스 브랜치를 잘못 추정 (
main인데 master로) → ✅ gh repo view로 확인
- ❌ 5개 섹션 중 일부를 생략 → ✅ 정보를 더 캐서 모든 섹션을 채운다