이제 클로드코드에 "이슈 231 개발" 한 줄만 입력합니다. 그러면 브랜치 생성, 테스트 먼저 쓰기, 구현, PR, 머지, 이슈 종료까지 한 흐름으로 끝납니다. 이 글은 그 한 줄을 만든 dev-issue 스킬 이야기입니다.

혼자서 여러 SaaS 제품을 만들다 보면 코드보다 절차가 더 많이 반복됩니다. 이슈 하나를 처리할 때마다 같은 순서를 밟고, 같은 당부를 AI에게 다시 말해야 했습니다. 그 반복을 스킬로 옮기고 나서 저는 이슈의 내용에만 집중하게 됐습니다.

이슈 하나에 매번 밟던 절차

제 저장소는 feature → dev → main 순서로 코드가 흘러갑니다. 이슈 하나를 처리하는 절차는 늘 같았습니다.

  1. 이슈 요구사항을 읽고 범위를 정한다.
  2. dev를 최신으로 받고 feature 브랜치를 만든다.
  3. 관련 파일을 미리 훑어보고 설계한다.
  4. 테스트를 먼저 쓰고(TDD) 구현한다.
  5. 정적 분석과 테스트로 검증한다.
  6. PR을 만들고 dev에 Squash merge 한다.
  7. 작업 내역을 이슈에 코멘트로 남기고 이슈를 닫는다.
  8. 다 쓴 브랜치와 워크트리를 정리하고 dev를 다시 최신화한다.

문제는 이 순서를 매번 채팅으로 지시해야 했다는 점입니다. 어느 날은 테스트를 나중에 쓰고, 어느 날은 이슈 코멘트를 빠뜨립니다. 채팅으로 한 당부는 세션이 끝나면 사라지기 때문입니다. 절차가 사람의 기억에 기대는 한 결과도 들쭉날쭉했습니다.

작은 스킬부터 만들었다

처음부터 큰 스킬 하나를 만들지 않았습니다. 절차를 구간별로 잘라, 한 가지 일만 하는 작은 스킬 세 개를 먼저 만들었습니다.

스킬

맡은 구간

하는 일

start-issue

시작

이슈 요구사항 파악, dev 최신화, feature 브랜치 생성, 관련 파일 미리 탐색

end-issue

종료

작업 내역을 이슈 코멘트로 남기고 이슈를 닫은 뒤 커밋

prune-branch

정리

병합이 끝난 로컬·원격 브랜치를 PR 상태까지 확인해 정리

작게 나눈 이유는 두 가지입니다. 하나는 따로 써도 쓸모가 있다는 점입니다. 브랜치만 정리하고 싶을 때는 prune-branch만 부르면 됩니다. 다른 하나는 고치기 쉽다는 점입니다. 어느 단계가 잘못되면 그 스킬 하나만 손보면 됩니다.

작은 스킬을 엮어 dev-issue를 만들었다

작은 스킬이 각각 안정된 뒤, 이를 엮어 상위 스킬 두 개를 만들었습니다. finish-issue는 PR부터 정리까지 뒷마무리를 맡습니다. dev-issue는 start-issue로 시작해 설계, TDD 구현, 검증을 거친 뒤 finish-issue로 이어지는 전체 사이클입니다.

강조한 세 칸이 먼저 만든 작은 스킬입니다. 상위 스킬은 새 절차를 만들지 않고, 이미 검증된 작은 스킬을 순서대로 부릅니다.

그래서 쓰는 방법도 세 가지가 됩니다. 이슈 하나를 처음부터 끝까지 맡길 때는 dev-issue를 씁니다. 구현은 직접 하고 뒷마무리만 맡길 때는 finish-issue를 씁니다. 특정 단계만 필요할 때는 작은 스킬을 하나만 부릅니다.

저장소의 사정을 스킬에 적는다

스킬의 진짜 가치는 일반적인 절차가 아니라 내 저장소만의 사정을 담는 데 있습니다. 대표적인 예가 브랜치 정리입니다.

저는 feature → dev를 Squash merge로 합칩니다. Squash merge는 feature의 커밋들을 새 커밋 하나로 만들어 dev에 올립니다. 그래서 feature 브랜치의 커밋은 dev 이력에 그대로 남지 않습니다. 이 때문에 흔히 쓰는 git branch --merged로는 병합된 브랜치를 가려낼 수 없습니다.

AI는 보통 git branch --merged로 정리하려고 합니다. 그래서 prune-branch에 이렇게 적어 두었습니다. 브랜치를 지우기 전에 그 브랜치의 PR이 실제로 머지됐는지 확인하라. 이 한 줄 덕분에 AI가 이 함정에 빠지지 않습니다.

이런 규칙은 채팅으로 말하면 다음 세션에 사라집니다. 스킬에 적어 두면 매번 같은 판단을 합니다.

스킬 혼자서는 부족하다

스킬은 절차를 정해 줄 뿐, 결과가 맞는지는 다른 장치가 확인합니다. dev-issue가 믿을 만해진 것은 아래 장치들이 함께 돌기 때문입니다.

장치

역할

CLAUDE.md 계층

모든 프로젝트 공통 규칙은 사용자 수준, 프로젝트 고유 규칙은 프로젝트 수준에 둔다

훅 (PreToolUse·PostToolUse)

코드가 바뀔 때마다 테스트가 자동으로 돈다

GitHub Actions + 셀프호스티드 러너

PR마다 PHPUnit과 PHPStan을 돌린다. 조직 단위로 등록한 Docker 러너 3대가 처리한다

git worktree

여러 클로드코드 세션이 서로 다른 이슈를 동시에 진행한다

셀프호스티드 러너는 사연이 있습니다. 개발 초창기에 GitHub 무료 플랜의 월 2,000분을 넘겨 CI가 멈췄습니다. 이슈 사이클이 빨라지자 PR도 그만큼 늘었기 때문입니다. 그래서 집의 Ubuntu 서버에 러너를 직접 올렸습니다.

worktree도 같은 흐름입니다. 세션 여러 개가 동시에 이슈를 처리하니 정리할 워크트리도 늘었습니다. 그래서 finish-issue가 브랜치와 함께 워크트리까지 정리하도록 했습니다.

직접 만들어 보려는 분께

이슈 사이클 스킬을 만들며 정리된 순서입니다.

  1. 절차를 글로 먼저 적는다. 내가 이슈 하나를 어떻게 처리하는지 번호를 붙여 적어 봅니다. 적을 수 없는 절차는 스킬로도 만들 수 없습니다.
  2. 한 구간씩 작은 스킬로 만든다. 시작, 종료, 정리처럼 경계가 분명한 구간부터 시작합니다. 각각 따로 불러 보며 다듬습니다.
  3. 저장소의 사정을 적는다. Squash merge처럼 일반적인 방법이 통하지 않는 지점이 반드시 있습니다. AI가 한 번 틀린 곳이 곧 스킬에 적을 곳입니다.
  4. 작은 스킬을 엮어 상위 스킬을 만든다. 작은 스킬이 각각 안정된 뒤에 엮어야 상위 스킬도 안정됩니다.
  5. 검증은 스킬 밖에 둔다. 테스트와 정적 분석은 훅과 CI가 맡게 합니다. 스킬에 "테스트를 잘 돌려라"라고 적는 것보다 확실합니다.

스킬은 사용자 수준(~/.claude/skills/)에 둘 수도, 프로젝트 수준(.claude/skills/)에 둘 수도 있습니다. 저는 이슈 사이클 스킬을 사용자 수준에 두고 모든 제품에서 같이 씁니다. 이슈 처리 방식은 제품이 달라도 같기 때문입니다.

돌아보며

dev-issue가 바꾼 것은 속도보다 일관성입니다. 이슈마다 같은 순서로, 같은 기준으로 처리됩니다. 테스트를 건너뛰거나 이슈 코멘트를 빠뜨리는 날이 없어졌습니다.

그렇다고 모든 것을 맡기지는 않습니다. 이슈를 어떻게 쓸지, 범위를 어디까지 잡을지는 여전히 제가 정합니다. 스킬은 정해진 일을 정해진 순서로 해낼 뿐, 무엇을 할지는 정하지 못합니다. 좋은 이슈가 좋은 결과를 만듭니다.

돌이켜보면 스킬을 만드는 일은 결국 내 일하는 방식을 글로 옮기는 일이었습니다. 26년 동안 몸에 밴 절차를 처음으로 문서로 꺼내 본 셈입니다. 혼자 일하더라도, 그 절차를 AI와 나눠 가지면 팀처럼 일할 수 있습니다.