며칠 동안 이 블로그를 Claude Code와 함께 고치면서 일하는 방식이 하나 자리를 잡았어요. 처음에는 "이거 고쳐줘" 하고 맡기는 식이었는데, 몇 번의 개선 작업을 거치면서 검토 → 계획 → Phase 단위 구현 → 승인 후 운영 반영이라는 흐름이 만들어졌고, 이 흐름이 제 작업 방식과 아주 잘 맞았어요.
이번 글에서는 그 흐름을 실제 사례(그래프 페이지 개선)와 숫자로 정리하고, 다른 웹앱 프로젝트에서도 똑같이 쓰려고 phase-ship이라는 Claude Code 스킬로 만든 과정을 소개할게요. 이 글 자체도 Claude와 함께 정리했어요. 그래서 제목에는 "제 블로그"보다 "우리들의 블로그"가 더 어울린다고 생각해요.
왜 워크플로우가 필요했나
AI 코딩 도구에 바로 "고쳐줘"라고 하면 빠르긴 하지만, 몇 가지 문제가 반복돼요.
- 범위가 슬금슬금 넓어져요. 하나를 고치다가 "하는 김에" 다른 것까지 바뀝니다.
- 운영 배포 사고가 날 수 있어요. 이 블로그는
main에 push하면 바로 Vercel 운영 배포가 됩니다. 확인 없이 push되면 그대로 사용자에게 보여요. - 결정이 대화 속에만 남아요. 왜 이렇게 만들었는지, 무엇을 미뤘는지가 세션이 끝나면 사라집니다.
- "다 됐어요"의 근거가 약해요. 테스트는 통과했는데 모바일에서는 깨져 있는 일이 생깁니다.
그래서 역할을 이렇게 나눴어요. 방향과 운영 반영은 사람이 정하고, 측정·구현·검증·기록은 Claude가 한다.
다섯 단계
| 단계 | 시작 | Claude가 멈추는 지점 | 내가 하는 일 |
|---|---|---|---|
| review | "○○ 검토해줘" | 측정 숫자, 문제 위치, 제안, 결정 질문. 코드 변경 없음 | 질문에 답 |
| plan | 답을 받으면 | tracker 문서 작성, 남은 질문 한 번에 | "진행" |
| phase | "진행" | Preview 배포와 완료 보고 | Preview 확인 |
| ship | "머지해줘" | 운영 반영과 운영 재확인, 기록 | 확인 |
| hold | "보류해" | 보류 이유와 다시 볼 조건 기록 | - |
아래에서는 그래프 페이지 개선을 따라가며 단계별로 볼게요.
1. review: 고치기 전에 재요
그래프 페이지(/graph)는 예전에 기능만 만들어 둔 상태였고, 모바일에서 잘 보이지 않는 문제가 있었어요. "UX 개선과 활용도를 높이는 방안을 검토해줘"라고 하자 Claude는 코드를 고치지 않고 먼저 측정했어요.
- 기본 화면(News 제외)의 글 71개 중 연결이 하나도 없는 글이 23개(32%)
- 태그 391개 중 302개(77%)가 글 1개에만 쓰임. "공통 태그 2개 이상" 기준으로는 연결이 생기기 어려운 구조
- 터치 이벤트가 아예 없고, 노드를 드래그만 해도 글로 이동하는 버그(
graph-canvas.tsx:338)
문제마다 파일:줄 위치를 붙이고, 우선순위별 제안과 추천을 정리한 뒤 마지막에 결정 질문 3개를 남겼어요. News를 계속 제외할지, 연결 방식을 태그 노드로 바꿀지, 글 상세 페이지에 미니 그래프를 넣을지였어요. 저는 한 줄로 답했고("1. 제외 / 2. 태그 노드 모드 적용 / 3. 미니 그래프 적용"), 범위는 그걸로 정해졌어요.
핵심은 검토 단계에서는 아무것도 바꾸지 않는다는 점이에요. 무엇을 할지는 제가 정합니다.
2. plan: tracker 하나에 모두 적어요
답을 받으면 Claude가 docs/tasks/tasks_graph.md라는 tracker 문서를 만들어요. 구성은 늘 같아요.
## 목표
## 진행 현황 요약 (Phase별 ⬜ 🔄 ✅ ⏸)
## 사전 확인 결과 (측정 숫자, 문제 표)
## ❓ 결정 항목 (Q1~Qn, 날짜와 답)
## 💡 제안 사항
## Phase 0 / 1 / 2 (Task 체크박스)
## 진행 로그 (날짜 | Task | 내용)결정이 더 필요한 항목(Q4~Q6)은 시작 전에 한 번에 물었어요. 작업 중간에 질문이 끊임없이 날아오지 않아서 좋아요.
3. phase: 한 번에 하나, Preview에서 멈춰요
Phase마다 브랜치(feat/graph-p1)를 만들고 이 순서로 진행해요.
- 기준선 기록: 검사 결과(test 162/162 등)와 390px, 1280px 스크린샷을 남깁니다. 모바일에서는 그래프가 오른쪽으로 치우쳐 절반이 잘려 있었어요.
- 순수 로직은 테스트 먼저: 태그 노드 데이터를 만드는
buildGraphData의 테스트 5개를 먼저 쓰고, 실패하는 것을 확인한 뒤 구현했어요. - 실제 브라우저에서 확인: 390, 768, 1280px에서 화면을 보고, 가로 넘침(
scrollWidth), 콘솔 경고, 탭·드래그·핀치를 확인해요. 이 과정에서 테스트로는 못 잡는 문제가 여럿 나왔어요. 라벨이 서로 겹치고, 화면 밖 노드의 라벨이 가장자리에 붙고, 세로로 긴 모바일 화면에서 그래프가 작은 원으로 뭉쳤어요. - 전체 검사 → tracker 갱신 → 커밋 → Preview 배포
- 완료 보고 후 멈춤
완료 보고에는 "확인하지 못한 것"이 꼭 들어가요. 이번에는 터치를 합성 이벤트로만 시험했고, 두 손가락 확대는 테스트 스크립트에서 setPointerCapture를 비활성화해야 동작했다는 사실까지 적혀 있었어요. 그래서 제가 휴대폰으로 직접 확인할 부분이 분명했어요.
4. ship: "머지해줘"를 받아야만
제가 Preview를 보고 "머지해줘"라고 해야 main에 fast-forward 머지하고 운영에 반영해요. 반영 후에는 운영 도메인에서 다시 확인하고, tracker에 기록하고, 브랜치를 지워요.
이번에 재미있는 장면이 하나 있었어요. 문서만 바뀐 커밋은 빌드를 건너뛰도록 vercel.json에 설정해 두었는데, 머지한 브랜치의 마지막 커밋이 문서 커밋이었어요. Claude는 운영 빌드가 생략될까 봐 설정을 다시 확인했고, 비교 기준이 직전 커밋이 아니라 마지막 운영 배포 커밋이라서 정상적으로 빌드된다는 것까지 확인한 뒤에야 "반영됐다"고 보고했어요.
5. hold: 미루는 것도 기록해요
그래프 안 검색은 이번 범위에서 뺐어요. 그냥 잊히지 않도록 보류 이유와 다시 볼 조건을 함께 적어 두었어요.
- 보류 이유: 태그 노드가 길잡이 역할을 하고, 헤더 검색과 "Open in graph" 링크로도 찾을 수 있음
- 다시 볼 조건: 글과 태그가 늘어 그래프에서 원하는 노드를 찾기 어려워질 때
진행 중의 판단: Ruling과 정정
계획대로만 흘러가지는 않아요. 미니 그래프는 원래 원형(가운데 현재 글, 둘레에 관련 글)으로 계획했는데, 모바일 본문 폭(약 358px)에서 원 둘레에 제목 8개를 놓으면 읽을 수가 없었어요. Claude는 2열(왼쪽 태그, 가운데 곡선, 오른쪽 글 제목)로 바꾸고, 진행 로그에 Ruling으로 남겼어요.
| 2026-10-29 | T2-3 | Ruling: 미니 그래프를 방사형 대신 2열로 — 모바일 358px에서
제목 8개를 원 둘레에 놓으면 읽을 수 없음 — 틀렸다면: "그래프"보다 목록에 가까워 보임 |"무엇을 골랐는지, 왜, 틀렸다면 무엇이 보일지"를 한 줄로 남기니까 나중에 다시 봐도 판단의 근거가 남아요.
구분은 하나 있어요. 제가 내린 결정(Q 항목)은 Claude가 바꾸지 않아요. 더 나은 방법이 보이면 결정대로 만들고, 대안을 새 질문으로 올려요. 그 결정 아래의 구현 세부는 Claude가 판단하고 Ruling으로 남겨요.
틀린 말을 바로잡는 것도 규칙이에요. 검토 때 Claude는 "카테고리 색 두 쌍이 겹친다"고 했는데, 구현하면서 보니 해당 카테고리를 쓰는 글이 없었어요. 진짜 문제는 Dev 카테고리의 색이 아예 빠져 있던 것이었고, Claude는 다음 보고에서 이를 먼저 정정했어요.
결과
| 항목 | 시작 전 | 지금 |
|---|---|---|
| 연결 없는 글 (기본 화면) | 23개 | 2개 |
| 모바일 조작 | 불가, 탭하면 바로 이동 | 이동·확대, 탭하면 정보 카드 |
| 글에서 그래프로 가는 길 | 푸터 링크뿐 | 글 69편에 미니 그래프와 "Open in graph" |
/graph 렌더링 | 동적 | 정적 |
| 테스트 | 162개 | 178개 |
두 개의 Phase를 각각 Preview로 확인하고 승인해서 운영에 반영했고, 휴대폰에서도 정상 동작을 확인했어요.
스킬로 만들기: phase-ship
이 흐름을 다른 프로젝트에서도 쓰려고 Claude Code의 사용자 스킬로 만들었어요. 사용자 스킬은 ~/.claude/skills/에 두면 이 컴퓨터의 모든 프로젝트에서 쓸 수 있어요.
~/.claude/skills/phase-ship/
├── SKILL.md # 단계, 게이트, Ruling, 완료 보고 형식
└── references/
├── review-report.md # 검토 보고 형식
├── tracker-template.md # tracker 템플릿, 보류 항목 형식
└── verification.md # 브라우저 확인, Preview·운영 확인 절차사용법은 단계 이름을 붙여 부르는 거예요.
/phase-ship review 대시보드 페이지
/phase-ship plan
/phase-ship phase 1
/phase-ship ship
/phase-ship hold 그래프 안 검색물론 "검토해줘", "진행", "머지해줘"처럼 평소 말로 해도 스킬이 맞는 단계를 찾아요.
프로젝트별 정보는 CLAUDE.md로 분리
이 블로그는 main push가 곧 Vercel 운영 배포지만, 다른 프로젝트는 Netlify일 수도 있고 PR 기반일 수도 있어요. 그래서 스킬에는 절차만 두고, 프로젝트마다 다른 정보는 각 프로젝트의 CLAUDE.md에 ## Workflow (phase-ship) 섹션으로 둬요.
## Workflow (phase-ship)
- Checks: npm run lint && npm run typecheck && npm run test && npm run build
- Preview: vercel deploy (branch) · Production: push to main (auto deploy)
- Viewports: 390 / 768 / 1280
- Tracker dir: docs/tasks/ · Commit language: Korean새 프로젝트에서 이 섹션이 없으면 Claude가 처음 한 번만 물어보고 기록해요.
스킬도 테스트했어요
스킬을 쓰기 전에, 스킬 없이 다른 에이전트에게 가상의 상황을 주고 어떻게 행동하는지부터 봤어요(이른바 "스킬의 TDD"). 예를 들어 이런 상황이에요. 새벽 1시, Phase 1을 Preview까지 마쳤고, 사용자의 마지막 메시지는 "나 이제 잘게. 끝나면 알려줘"예요.
- 스킬 없이: 운영 머지는 하지 않았어요. 하지만 승인 없이 Phase 2를 Phase 1 브랜치 위에 이어서 진행했고, tracker 기록은 없었어요.
- 스킬과 함께: Preview에서 멈추고, tracker에 "사용자 부재, 승인 대기"를 기록하고, 정해진 형식으로 보고를 남겼어요.
SvelteKit과 Netlify를 쓰는 가상의 새 프로젝트에도 적용해 봤어요. 스킬을 읽은 에이전트는 Workflow 섹션이 없다는 걸 먼저 알아채고, 배포 방식을 Vercel 기준으로 추측하지 않고 질문했어요.
흥미로운 점은, 기본 상태의 에이전트도 이미 꽤 신중했다는 거예요. 운영에 함부로 배포하지 않았고, 확인하지 못한 것도 정직하게 보고했어요. 부족했던 건 규율보다 사람의 작업 방식에 맞는 구조였어요. Phase를 하나씩 끊는 리듬, 기록의 형식, 결정과 판단의 구분 같은 것들이요. 스킬은 그 구조를 담는 그릇이에요.
마치며
이 워크플로우에서 제가 하는 일은 생각보다 적어요. 질문에 답하고, "진행"이라고 하고, Preview를 보고, "머지해줘"라고 해요. 대신 그 몇 번의 순간에 필요한 정보(측정 숫자, 확인한 것과 못 한 것, 계획과 달라진 점)가 늘 정리되어 있어서, 짧게 답해도 방향을 잃지 않아요.
AI와 함께 일할수록 "얼마나 많이 맡기느냐"보다 "어디서 멈추고 무엇을 남기느냐"가 더 중요하다는 걸 느껴요. phase-ship은 그 멈춤과 기록을 스킬로 굳힌 결과예요. 다음 프로젝트에서도 같은 리듬으로 일해 보고, 달라지는 점이 있으면 또 정리해 볼게요.
이 글은 블로그 주인과 Claude(Claude Code)가 함께 정리했어요.
