
저는 몇 년 동안 대부분 혼자 개발을 했습니다
최근에도 혼자서 개발하고 앱 출시까지 하면서 코드리뷰에 대한 갈망이 더 커져갔습니다
그래서 Claude를 이용해 PR 생성부터 코드리뷰까지 해주는 워크플로우를 만들게 되었습니다
최종 완성된 흐름
워크플로우 순서는 아래와 같습니다
개발자가 git push
│
├─ [즉시] 린트 + 타입 체크 실행
│ 오류 있으면 → push 차단
│ 통과하면 → push 진행
│
└─ [push 후 백그라운드] Claude 실행
│
├─ PR이 없으면 → PR 자동 생성 (제목/내용도 Claude가 요약해서 작성)
│
└─ 코드리뷰 진행
│
├─ CRITICAL → 무조건 수정해야하는 이슈 + /merge 댓글 차단
├─ MINOR → 개선 권장 댓글 + /merge 입력시 머지 가능
└─ APPROVED → 자동으로 main에 rebase merge + 브랜치 삭제
1차 시도
클로드 코드에게 해당 워크플로우 내용을 던졌더니, Github Actions에서 앤트로픽 API를 호출하는 로직을 추천했습니다
Push -> Github Actions 실행 -> Github Actions 가상서버 내에서 앤트로픽 API 호출 -> PR 생성 및 리뷰
근데 저는 추가로 앤트로픽 API까지 결제하는건 부담이 되는 상태였습니다
또한, 이해가 가지 않았습니다. 굳이 가상서버 내에서 호출을 해야 하나?
어차피 git branch를 따서 작업을 한 거니까 내 작업에 대한 context는 명확히 확보가 되어있으니
코드를 push 할 때 클로드 코드한테 지금까지 이 branch에서 작업한 내용을 바탕으로 코드 리뷰를 진행하고 PR에 리뷰 댓글만 추가하면 끝나는 건데?라는 생각이 들어서
클로드 코드한테 위에 생각한 내용을 그대로 전달했더니 다른 방식의 코드를 제안하기 시작했습니다
2차 시도
git에는 특정 동작 전후에 자동으로 실행되는 스크립트를 끼워 넣을 수 있는 hook을 제공합니다
여기서 pre-push라고 git push 직전에 실행하는 hook을 사용했습니다
내부 핵심 코드만 보겠습니다
branch 확인
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
if [ "$BRANCH" = "main" ] || [ -z "$BRANCH" ]; then
exit 0
fi
첫 번째로 branch를 확인합니다
main에 직접 push 하는 경우는 코드리뷰를 건너뜁니다
Lint 및 Type check
echo "🔍 린트 및 타입 체크를 실행합니다..."
pnpm --filter=web lint --fix 2>/dev/null
if ! pnpm --filter=web lint; then
echo "❌ 린트 오류가 있습니다. 수정 후 다시 push 해주세요."
exit 1
fi
if ! pnpm --filter=web typecheck; then
echo "❌ 타입 오류가 있습니다. 수정 후 다시 push 해주세요."
exit 1
fi
그다음 린트 및 타입 체크를 합니다
처음에는 이 과정을 개발자가 이미 체크 후 push 했다를 전제로 진행했으나,
코드리뷰를 실제로 진행하는 과정에서 클로드가 제안을 하더라고요
그래서 이 과정을 추가하게 되었습니다 더블 체크 한다는 느낌으로!
자동으로 고칠 수 있는 오류는 먼저 수정하고 그럼에도 불구하고 오류가 있으면 push를 중단합니다
Github 사용자명 조회
GH_USER=$(gh api user --jq .login 2>/dev/null || echo "")
현재 로그인한 사용자 정보를 가져옵니다
이 과정도 마지막에 추가하게 되었는데,
앞서 조건에서 심각한 오류가 아닌 권장, 제안 리뷰일 경우 /merge라는 댓글을 달면 해당 PR을 종료하게 조건을 걸었습니다
근데 이게 공개 레포일 경우 다른 사람이 악의적으로 /merge 댓글을 달 우려가 있더라고요
그래서 PR을 만든 사람을 자동으로 담당자로 지정되게 설정하고
이걸 체크해 해당 사용자가 /merge 댓글을 단 것만 통과하게 추가해 놨습니다
백그라운드 Claude 실행
(sleep 3 && export PATH="$HOME/.local/bin:$PATH" && \. "$NVM_DIR/nvm.sh" && claude -p "
...긴 프롬프트...
" --allowedTools "Bash" \
&& osascript -e "display notification \"코드리뷰가 완료되었습니다.\" ..." \
|| osascript -e "display notification \"Claude 코드리뷰 실행에 실패했습니다.\" ...") &
exit 0
push는 push대로 진행되고 코드리뷰 과정은 백그라운드에서 진행되는 로직입니다
사실 이 부분은 왜 굳이 백그라운드로 진행되어야 하지? 하는 의문이 있었습니다
pre-push hook 시작 -> 클로드 실행 -> 완료 후 push를 진행하나,
pre-push hook 시작 -> 클로드 진행 백그라운드로 던짐 exit 0 -> push 진행
뭔 차이지? 전자일 경우 터미널에서 2~3분을 기다려야 할 수 있다인데,
어차피 코드리뷰 달리기까지도 기다려야 하는 것이 아닌가? 란 의문이 들었습니다
근데 실무 관점에서 보면 후자가 맞더라고요
저희 모두 PR을 먼저 작성하고 동료들이 해당 PR의 리뷰를 달아주기를 기다리잖아요?
우리는 그동안 다른 작업을 먼저 하고 있고요
그리고 이게 규모가 작으니까 터미널에서 2~3분 기다리는 거지 규모가 크면 더 오래 걸리겠구나 싶고
(사실 하나의 브랜치의 작업 규모가 너무 큰 것도 문제 이긴 합니다)
무언가 프로세스가 순차적으로 끝나길 기다리는 것보단,
서로의 의존성을 낮춰서 code push라는 작업은 이것만 수행, 코드리뷰는 코드리뷰만 진행하는 게 맞는 것 같다는 생각이 들었습니다
그래서 백그라운드에서 진행되게 해 놨습니다
(여기서 한 가지 3초를 기다리는 것도 규모에 따라 달라지기에 변경해야 할 것 같습니다)
프롬프트
claude -p "
브랜치 '${BRANCH}'에 push가 발생했습니다. 아래 워크플로우를 순서대로 실행해주세요.
## 1단계 — PR 존재 여부 확인
gh pr list --head \"${BRANCH}\" --base main --state open --json number,title
## 2단계 — PR 생성 (PR이 없을 때만)
git diff origin/main...HEAD
gh pr create --title \"...\" --body \"...\" --assignee \"${GH_USER}\"
## 3단계 — 코드리뷰
...
## 4단계 — 리뷰 결과를 GitHub PR에 반영
...
" --allowedTools "Bash"
클로드는 프롬프트를 받아서 스스로 판단하며 실행하게 됩니다
1. PR이 있는지 확인
2. 없으면 diff를 분석해서 PR 제목 및 내용을 작성하고 신규 생성
3. 코드를 리뷰해서 CRITICAL / MINOR / APPROVED 판정
4. 판정에 따라 Github에 리뷰 댓글을 달거나, 자동 merge
PR merge 처리에 대한 Github Actions 워크플로우도 작성했습니다
name: PR 머지 처리
on:
issue_comment:
types: [created]
jobs:
merge-on-comment:
if: |
github.event.issue.pull_request != null &&
contains(github.event.comment.body, '/merge')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Assignee 권한 확인
id: auth
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
COMMENTER: ${{ github.event.comment.user.login }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
IS_ASSIGNEE=$(gh api "repos/$REPO/issues/$PR_NUMBER/assignees" \
--jq "[.[] | select(.login == \"$COMMENTER\")] | length")
if [ "$IS_ASSIGNEE" -eq 0 ]; then
gh pr comment $PR_NUMBER --body "❌ PR assignee만 \`/merge\`를 사용할 수 있습니다."
exit 1
fi
- name: CRITICAL 리뷰 여부 확인
id: check
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
PR_NUMBER=${{ github.event.issue.number }}
# Claude가 CRITICAL request-changes 리뷰를 남긴 적 있는지 확인
# → CRITICAL이 해결되지 않은 상태면 /merge 댓글이 있어도 머지 차단
HAS_CRITICAL=$(gh api "repos/$REPO/pulls/$PR_NUMBER/reviews" \
--jq '[.[] | select(
(.body | test("<!-- claude-review -->")) and
(.state == "CHANGES_REQUESTED")
)] | length')
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
if [ "$HAS_CRITICAL" -gt 0 ]; then
echo "blocked=true" >> $GITHUB_OUTPUT
else
echo "blocked=false" >> $GITHUB_OUTPUT
fi
# CRITICAL 이슈가 남아있으면 머지 거부
- name: CRITICAL 이슈로 머지 거부
if: steps.check.outputs.blocked == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr comment ${{ steps.check.outputs.pr_number }} --body \
"🚨 **머지 불가** — CRITICAL 코드리뷰 이슈가 아직 해결되지 않았습니다. 수정 후 다시 push 해주세요."
# CRITICAL 없으면 rebase merge 진행
- name: Rebase merge 실행
if: steps.check.outputs.blocked == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr merge ${{ steps.check.outputs.pr_number }} \
--rebase --delete-branch --yes
최종 결과



그 결과 위와 같이 클로드가 코드를 단계별로 잘 분석해서 리뷰를 해주게 됩니다!
해당 PR에 몇 번을 Push해도 이전 리뷰와 분석해서 수정사항이 잘 반영되었는지 확인하고, 한번 더 체킹 해줍니다
만약 승인이 바로 될 경우에는

리뷰 댓글과 함께 바로 코드를 merge 하고 브랜치를 삭제합니다
이 과정이 순차적으로, 자동으로 이루어집니다
개인적으로 너ㅓㅓㅓ무 만족스럽습니다
프롬프트는 사용하면서 조금씩 수정을 거쳐갈 예정입니다
요즘 제 로그트립 프로젝트 내에서 자동화할 포인트가 뭐가 있을지 찾는게 소소한 즐거움이 아닐까 싶습니다
(바이브 코딩 말고)
다음에도 클로드 코드를 이용해 무언갈 해본 경험기로 돌아오겠습니다
'Project > 로그트립' 카테고리의 다른 글
| TanStack Query를 Next.js 캐싱 전략으로 바꾸기 (1) | 2026.03.08 |
|---|---|
| React Native + Next.js (WebView)간에 Supabase SSR Cookie 설정 (0) | 2026.03.04 |
| 하이브리드 앱 구축 및 출시 회고 | React Native + Next.js + Supabase 조합 (0) | 2026.03.04 |
댓글