코드 리뷰 요청하기: PR 전 자가 검토부터 피드백 반영까지
한 줄 요약
PR을 올리기 전 Claude Code로 스스로 코드를 검토하고, 동료 피드백을 받은 후 수정하는 전체 리뷰 사이클을 체계화한다.
대상 독자
- 팀 프로젝트에서 PR을 처음 올려보는 대학생
- 동료 리뷰 피드백을 어떻게 반영해야 할지 막막한 개발 입문자
- TypeScript strict 타입 에러를 코드 리뷰 전에 미리 잡고 싶은 학생
- "코드 리뷰가 무서워서 PR을 미루는" 경험이 있는 팀원
핵심 워크플로우
전체 리뷰 사이클
[개발 완료]
↓
requesting-code-review → 자가 검토 (버그·타입 에러·스타일)
↓
[GitHub PR 생성]
↓
동료 리뷰어 피드백 수신
↓
receiving-code-review → 피드백 분류 및 수정 계획
↓
[수정 커밋 + PR 업데이트]
↓
[머지 승인]단계 1 — PR 전 자가 검토 (requesting-code-review)
코드 작성이 끝나면 GitHub에 바로 올리지 말고 먼저 requesting-code-review 스킬을 실행한다. 이 스킬은 "리뷰어 시각"으로 코드를 재검토해 실수를 미리 잡아준다.
claude
> /skill requesting-code-review
> 다음 파일들을 리뷰해줘. PR 올리기 전 자가 검토야.
> - app/notices/page.tsx
> - app/api/notices/route.ts
> - components/NoticeCard.tsx
> 체크 기준:
> 1. TypeScript strict 위반 (any 타입, 타입 단언 남용)
> 2. Supabase 쿼리 N+1 문제
> 3. 에러 핸들링 누락
> 4. 접근성 (aria 속성)
> 5. 모바일 반응형 레이아웃requesting-code-review 스킬이 생성하는 자가 검토 보고서 예시:
## 자가 검토 결과
### 🔴 Critical (머지 전 필수 수정)
- `route.ts:42` — `const data = await supabase.from('notices').select('*')` 에서
에러 처리 없음. `if (error) throw error` 추가 필요.
- `NoticeCard.tsx:15` — `props.author as string` 타입 단언 제거,
타입을 `string | null`로 명시적으로 처리할 것.
### 🟡 Warning (권장 수정)
- `page.tsx:8` — 공지 목록 로딩 중 skeleton UI 없음 (UX 개선 권장)
- `route.ts:60` — 페이지네이션 파라미터 유효성 검사 없음
### 🟢 Info (선택 개선)
- `NoticeCard.tsx` — `<img>` 태그 대신 Next.js `<Image>` 사용 권장단계 2 — TypeScript strict 에러 수정 패턴
requesting-code-review에서 타입 에러가 발견되면 다음 패턴으로 수정한다.
패턴 A: any 타입 제거
> route.ts의 `any` 타입을 모두 제거하고 올바른 타입을 추론해줘.
> Supabase 응답 타입은 Database 타입 파일에서 import해서 사용해.패턴 B: 타입 단언(as) 제거
> NoticeCard.tsx에서 `as string` 단언을 제거하고
> null 처리를 포함한 타입 안전 코드로 바꿔줘.
> 예: author?.name ?? '익명'패턴 C: 유니온 타입 처리
> Supabase의 select 결과가 null일 수 있는 경우를 모두 찾아서
> 옵셔널 체이닝(?.)과 nullish 병합(??)으로 처리해줘.단계 3 — GitHub PR 작성 체크리스트
자가 검토가 완료되면 PR을 생성한다. Claude Code로 PR 설명문을 자동 생성할 수 있다.
> 방금 작업한 내용을 기반으로 GitHub PR 설명문을 작성해줘.
> 포함 항목:
> - 변경 사항 요약 (3줄 이내)
> - 스크린샷 삽입 위치 안내
> - 테스트 방법 (로컬 실행 명령어)
> - 리뷰어가 집중해서 봐야 할 파일/함수생성된 PR 설명문 예시:
## 변경 사항
- 공지 목록 페이지 SSR 구현 (Supabase 서버 컴포넌트)
- 공지 CRUD API 라우트 추가 (GET/POST/DELETE)
- NoticeCard 컴포넌트 + 스켈레톤 로딩 UI
## 테스트 방법
1. `pnpm dev` 실행
2. `/notices` 접속 → 공지 목록 확인
3. 로그인 후 `/notices/new` → 글쓰기 테스트
## 리뷰 포인트
- `app/api/notices/route.ts:40-65` — Supabase RLS와 서버 인증 로직
- `components/NoticeCard.tsx` — TypeScript 타입 처리 방식단계 4 — 피드백 수신 및 분류 (receiving-code-review)
동료 리뷰어의 피드백이 달리면 receiving-code-review 스킬로 분류하고 수정 계획을 수립한다.
> /skill receiving-code-review
> 아래 리뷰 피드백들을 분석하고 수정 계획을 만들어줘.
>
> 피드백 1 (김팀원): "route.ts에서 인증 체크를 미들웨어로 분리하는 게 좋을 것 같아요"
> 피드백 2 (이팀원): "NoticeCard의 날짜 포맷이 일관성 없어요. date-fns 쓰는 건 어때요?"
> 피드백 3 (박팀원): "페이지네이션 파라미터에 음수 넣으면 에러 나요"receiving-code-review 스킬이 생성하는 수정 계획:
## 피드백 처리 계획
### 즉시 수정 (Blocking)
1. 페이지네이션 음수 파라미터 → Zod 스키마로 유효성 검사 추가
파일: app/api/notices/route.ts, 예상 소요: 30분
### 이번 PR에 포함 (Non-blocking, 동의)
2. 날짜 포맷 통일 → date-fns 설치 + formatRelative 적용
파일: components/NoticeCard.tsx, 예상 소요: 20분
### 다음 PR로 이관 (범위 초과)
3. 인증 미들웨어 분리 → 별도 이슈 생성 권장
이유: 미들웨어 리팩토링은 이번 PR 범위를 초과함실전 시나리오
상황: 동아리 공지 게시판 프로젝트에서 공지 CRUD 기능 PR을 올리는 상황
시나리오 A: PR 전 자가 검토
# 개발 완료 후 자가 검토 실행
claude
> /skill requesting-code-review
> 공지 API 라우트 파일을 검토해줘.
> 파일: app/api/notices/route.tsClaude Code가 발견한 문제:
// 문제 발견: Supabase 에러 처리 누락
// 수정 전
export async function GET(request: Request) {
const { data } = await supabase
.from('notices')
.select('*')
.order('created_at', { ascending: false });
return Response.json(data);
}
// 수정 후 (Claude Code 제안)
export async function GET(request: Request) {
const { data, error } = await supabase
.from('notices')
.select('*')
.order('created_at', { ascending: false });
if (error) {
console.error('공지 목록 조회 실패:', error.message);
return Response.json({ error: '데이터를 불러올 수 없습니다' }, { status: 500 });
}
return Response.json(data ?? []);
}시나리오 B: 동료 리뷰 피드백 반영
# 동료 피드백 처리
> /skill receiving-code-review
> 팀원이 이런 피드백을 남겼어:
> "Zod로 request body 유효성 검사 추가해줘.
> title이 빈 문자열이거나 200자 초과면 에러 반환해야 해."
>
> POST 핸들러에 Zod 스키마를 추가해줘.Claude Code가 생성한 수정 코드:
import { z } from 'zod';
// 공지 생성 요청 스키마
const createNoticeSchema = z.object({
title: z.string().min(1, '제목을 입력해주세요').max(200, '제목은 200자 이내여야 합니다'),
content: z.string().min(1, '내용을 입력해주세요'),
isPinned: z.boolean().default(false),
});
export async function POST(request: Request) {
const body = await request.json();
const parsed = createNoticeSchema.safeParse(body);
if (!parsed.success) {
return Response.json(
{ error: '입력값이 올바르지 않습니다', details: parsed.error.flatten() },
{ status: 400 }
);
}
const { data, error } = await supabase
.from('notices')
.insert(parsed.data)
.select()
.single();
if (error) {
return Response.json({ error: '공지 등록에 실패했습니다' }, { status: 500 });
}
return Response.json(data, { status: 201 });
}시나리오 C: TypeScript 에러 일괄 수정
# tsc 검사 후 에러 목록을 붙여넣고 일괄 수정 요청
> tsc --noEmit 결과를 분석하고 에러를 모두 수정해줘:
>
> error TS2322: Type 'string | null' is not assignable to type 'string'
> at components/NoticeCard.tsx:23:15
>
> error TS7006: Parameter 'e' implicitly has an 'any' type
> at app/notices/new/page.tsx:45:34
>
> error TS2339: Property 'author' does not exist on type 'Notice'
> at components/NoticeCard.tsx:31:22추천 스킬 조합
| 상황 | 스킬 | 용도 |
|---|---|---|
| PR 전 자가 점검 | requesting-code-review | 버그·타입 에러 미리 발견 |
| 동료 피드백 처리 | receiving-code-review | 피드백 분류 및 수정 계획 |
| 수정 후 검증 | verification-before-completion | 수정 내용 부작용 확인 |
| 회귀 방지 | test-driven-development | 리뷰 수정 후 테스트 추가 |
| 타입 에러 수정 | systematic-debugging | tsc 에러 체계적 해결 |
주의사항
리뷰어 입장에서 지켜야 할 체크리스트
PR을 리뷰할 때 다음 항목을 순서대로 확인한다:
- TypeScript strict 준수:
any타입,as단언 남용 여부 - 에러 핸들링: Supabase 에러, fetch 실패, null 케이스 처리
- 보안: 인증 없이 접근 가능한 API 엔드포인트
- 성능: N+1 쿼리, 불필요한 re-render, 대용량 번들
- UX: 로딩 상태, 빈 상태(empty state), 에러 메시지 표시
자주 하는 실수
피드백 전부 즉시 수정하려는 충동: 피드백을 Blocking / Non-blocking / 다음 PR로 분류한 다음 이번 PR 범위를 초과하는 수정은 새 이슈로 이관한다.
자가 검토 없이 PR 오픈: requesting-code-review 없이 PR을 올리면 사소한 실수로 리뷰 라운드가 늘어나 팀 전체 속도가 느려진다.
PR 크기 너무 크게: 하나의 PR에 3개 이상의 기능을 넣으면 리뷰어가 집중하기 어렵다. 기능 단위로 PR을 분리한다.
리뷰 코멘트 무시: "나중에 고치면 되지"는 기술 부채를 만든다. receiving-code-review 스킬로 처리 계획을 명시하고 이슈 번호를 남긴다.
CI 실패 무시:
pnpm build또는tsc --noEmit실패 상태로 PR을 열지 않는다. 자가 검토 단계에서 반드시 로컬 빌드를 먼저 통과시킨다.
팁
- PR 설명문 템플릿 등록:
.github/pull_request_template.md에 Claude Code가 생성한 템플릿을 저장해두면 팀 전체가 일관된 PR을 작성할 수 있다. - 리뷰 피드백은 텍스트로 복사: GitHub PR 코멘트를 Claude Code 세션에 그대로 붙여넣으면 receiving-code-review 스킬이 자동으로 분류해준다.
| 항목 | 내용 |
|---|---|
| 원본 URL | https://docs.anthropic.com/en/docs/claude-code |
| 라이선스 | CC BY 4.0 |
| 해설 작성일 | 2026-04-12 |
| 작성자 | Claude-Code-Study 프로젝트 |