🤔 "AI에게 매번 같은 설명을 하는 것 같다..."
😥 "전에 주의를 준 것을 또 똑같이 했다..."
🫠 "맡길 범위를 넓히고 싶지만, 돌이킬 수 없는 조작을 하지 않을까 불안하다..."
AI와 함께 개발하면서 이런 상황에 자주 부딪힙니다.
AI는 우수하지만, 대화가 바뀔 때마다 이전 내용을 기억하지 못합니다.
개인 개발 중인 커뮤니티 서비스 あじぴた는
약 반년 동안 4,300 커밋의 상당 부분을 Claude Code와 함께 작성했습니다🤖
이 글에서는 AI에게 매번 제로(zero)부터 설명할 필요가 없도록 만들기 위해,
- 문맥을 어디에・어떤 형태로 배치했는지 - 같은 실수를 두 번 하지 않게 기록하는 방법 - 맡길 범위를 넓혀도, 돌이킬 수 없는 조작만은 막는 시스템
을 실제 파일과 함께 작성합니다📝
마지막으로, 이것을 지속하면서 깨달은 '사실 AI만의 이야기는 아니었다'는 점도 적습니다.
AI와 개발하며 처음 느낀 것은 매번 유능한 신입이 첫날 온 것 같은 감각이었습니다.
능력은 높지만, 이 프로젝트에 대해서는 아무것도 모릅니다.
명명 규칙도, 과거에 무엇을 검토해서 버렸는지도, 지난번에 어디서 막혔는지도 모르는 상태입니다.
사람 신입이라면 한 번 가르치면 기억합니다.
AI는 다음 대화에서는 또 첫날입니다😇
그래서 말로 가르치는 것이 아니라, 파일에 남겨두기로 했습니다.
신입이 첫날 읽을 자료를 매번 준비해 두는 이미지를 갖는 것입니다.
그것은 지금까지 자신의 머릿속에만 있던 암묵적 규칙을 모두 언어화하는 작업이기도 했습니다✍️
あじぴた에서는 문맥을 5개의 장소에 배치했습니다.
| 배치 위치 | 내용 | 신입의 경우 |
|---|
| AGENTS.md | 처음 읽어야 할 것・지켜야 할 규칙 | 입사 첫날 전달하는 안내서 |
| ADR | 과거의 판단과 그 이유 | 과거 회의록 |
| 스킬 | 반복적인 작업 절차 | 업무 매뉴얼 |
| 메모리 | 한 번 받은 지적과 그 이유 | 선배가 인계해 주는 사항 |
| 권한과 hooks | 해서는 안 될 조작 | 만지면 안 되는 기계의 열쇠 |
순서대로 소개하겠습니다.
AGENTS.md는 AI가 작업을 시작할 때 가장 먼저 읽는 파일입니다.
Claude Code에서는 CLAUDE.md
부터 읽게 했습니다.
여기서 신경 쓴 부분은, 모두 쓰지 않고・모두 읽게 하지 않는 것이었습니다.
あじぴた에는 사양서・설계서・개발 규약・ADR을 합치면 수십 개의 문서가 있습니다.
매번 전부 읽게 하면, 정작 작업에 쓸 여유가 줄어들기 때문입니다.
그래서 AGENTS.md에는 무엇이 어디에 있는지만 적고, 읽는 순서를 2단계로 나누었습니다.
# 코드를 작성하기 전에
## Step 1 — 반드시 읽을 것 (전 작업 공통)
- `docs/development/rules.md` — 명명・배치・export・스타일링 등의 핵심 규칙
...
반드시 읽어야 할 것은 단 하나입니다. 나머지는, 필요할 때 찾아볼 수 있도록 위치만 표시했습니다🗺️
신입에게
ADR(Architecture Decision Record)은 작성하고 끝내는 것이 아닙니다. 전제 자체가 바뀔 수 있습니다.
아지피타에서는 '외부 API는 Google의 월 $200 무료 크레딧 내에서 운영한다'라는 ADR이 있었습니다.
그런데 Google이 이 크레딧을 폐지하면서, 전제가 성립할 수 없게 되었습니다.
이때 오래된 ADR은 삭제하지 않고 '이 전제는 효력을 상실했다'고 추가하고, 새로운 ADR로 방침을 다시 작성합니다.
삭제해 버리면, 왜 방침이 바뀌었는지 사람도 AI도 추적할 수 없게 되기 때문입니다.
**스킬(Skill)**은 Claude Code에 반복적인 작업 절차를 기억시키는 메커니즘입니다.
/work-on-issue 123
처럼 호출하면, 정해진 절차대로 작업을 진행해 줍니다.
아지피타에서는 13개가 있으며, Issue를 생성한 후 PR이 통과될 때까지의 흐름을 거의 스킬로 연결하고 있습니다🔗
생각해내기(思いつく)
↓ /refine-issue new "한 줄 아이디어" … 대충 이슈만 생성하기
↓ /refine-issue 123 … 착수 전에 배경・수용 조건까지 구체화하기
...
지금은 지시를 한 번 내리면, Issue를 읽는 것부터 구현・PR 작성・리뷰 대응까지, 멈추지 않고 진행하게 할 수도 있습니다.
그에 비하면 명령어를 하나씩 호출하는 이 방식은 조금 돌아가는 것처럼 보일 수 있습니다.
그래도 구분하고 있는 이유는, 모두에게 맡기면 도중에 무슨 일이 일어났는지 파악하기 어려워서 불쾌했기 때문입니다.
마지막에 PR만 나와도 어디서 무엇을 판단했는지 알 수 없습니다🫥
단계별로 구분하면, 구분할 때마다 결과물이 남습니다.
| 단계 | 남는 것 | 내가 확인해야 할 것 |
|---|
/refine-issue | Issue 본문 (배경・수용 조건) | 만들고자 하는 것이 맞는지 |
/work-on-issue | 커밋 | 구현 방향이 벗어나지 않았는지 |
/create-pr | PR 및 수용 조건 대조 결과 | 완료라고 할 근거가 있는지 |
/handle-review | 지적에 대한 답변 | 수정할지 말지 판단이 타당한지 |
이상하다고 생각되면, 그 단계에서 멈춰서 고칠 수 있습니다.
맡기는 양을 줄이고 있는 것이 아니라, 도중에 보이도록 만들고 있다는 느낌입니다👀
나중에 작성할 'PR의 병합(Merge)만은 내가 한다' 역시 같은 생각에서 비롯되었습니다.
특히 효과적인 것은 /refine-issue입니다.
아이디어는 떠오른 순간에 자세히 쓰려고 하면 귀찮아서 안 쓰게 됩니다.
그래서, 떠오르면 한 줄만로 이슈를 생성해 두고, 착수하기 전에 AI와 함께 구체화하도록 했습니다.
구체화할 때는 AI가 코드베이스를 조사한 후 질문해주기 때문에,
배경・수용 조건・관련 Issue까지 다른 Issue와 같은 밀도로 쓸 수 있습니다.
아이디어를 놓치지 않게 된 것이 가장 큰 변화였습니다✨
또 하나, PR을 만들기 전의 **완료 판정(Completion Judgment)**도 절차에 포함했습니다.
AI에게 '수용 조건을 확인해 달라'고 요청하면, 모두 체크하고 끝내는 경우가 있었습니다.
실제로는 충족하지 못한 조건도 모아서 완료 처리되어 버리는 것입니다.
그래서 수용 조건을 1건씩, 3가지로 나누도록 했습니다.
| 분류 | 의미 | 다음 할 일 |
|---|
| A | 충족함 | 근거를 한 줄 추가하여 체크하기 |
| B | 구현이나 검증이 부족함 | PR을 만들지 않고 대응하기 |
| C | 이 PR로는 아무리 해도 충족할 수 없음 | 미달성 기록을 남기고, 다른 Issue로 분리하기 |
포인트는, 체크하는 것은 모두가 A 또는 C가 된 후에라는 순서입니다.
먼저 체크하면, '부족한 것(B)'과 '이 PR 범위 밖의 것(C)' 구분이 사라져 버립니다.
게다가, A에는 근거를 한 줄 추가합니다.
근거가 적히지 않은 조건은 사실 B였다는 경우가 자주 있기 때문입니다🔍
스킬이 '절차'라면, **메모리(Memory)**는 '인수인계(Handover)'입니다.
작업 중에 AI가 틀려서 그것을 지적했을 때,
그 내용을 이유와 함께 파일에 남기도록 하고 있습니다. 현재 31개가 있습니다.
형식은 통일하고 있어서, 무엇을 할지뿐만 아니라, 왜 하는지와 어떻게 사용할지를 반드시 적습니다.
name: feedback_pr_number_added_after_pr_creation
description: docs に「PR #N で対応」と書く一文は、PR を作った後の追加コミットで初めて足す
...
예를 들어, 이런 전달 사항이 있습니다.
문서에 「PR #◯◯로 대응」이라고 쓰고 싶을 때, PR 번호는 PR을 만들기 전까지 결정되지 않습니다.
이전에는 PR #<TBD>
처럼 임시로 적어두고 나중에 교체했습니다.
그러면, 리뷰에서 매번 「실제 번호로 교체해 주세요」라는 지적을 받게 됩니다 😵
5번 같은 지적을 받고 조사한 결과, 원인을 알았습니다.
리뷰는 PR을 만든 시점의 커밋을 보고 있기 때문에, 아무리 빨리 교체해도 지적은 반드시 옵니다.
그래서 메모리에 이렇게 남겼습니다.
무엇을 할 것인가: PR #<TBD>를 쓰지 않는다. 번호 문구는 PR을 만든 후의 추가 커밋에서 처음으로 넣는다 -
이유: 리뷰 대상은 PR을 만든 시점으로 고정되기 때문이다
「TBD라고 쓰지 마라」라는 것만으로는, AI가 비슷하지만 조금 다른 상황에서 같은 실수를 합니다.
왜 안 되는지까지 적어두면, 처음 겪는 상황에서도 올바르게 판단할 수 있게 되었습니다.
메모리는 리포지토리 안에 두고 Git으로 관리합니다.
다른 PC에서 작업해도 동일한 전달 사항이 적용됩니다.
언제/왜 전달 사항이 늘어났는지도 이력에서 추적할 수 있습니다 📚
마지막은, AI에게 무엇을 시키지 않을 것인가입니다.
AI에게 맡기는 범위를 넓힐수록 작업은 빨라집니다.
반면, 돌이킬 수 없는 조작을 당했을 때의 피해도 커집니다.
아지피타(あじぴた)에서는 허가는 넓게, 막는 것은 돌이킬 수 없는 조작만이라는 방침을 취하고 있습니다.
Claude Code의 .claude/settings.json
에서, 작업별로 허용과 금지를 정하고 있습니다.
| 허용 (확인 없이 실행 가능) | 금지 |
|---|
| 테스트・lint・타입 체크 실행 | .env 등의 비밀 정보 파일 수정 |
git add / commit / push | git push --force |
| Issue 조회・생성・댓글, PR 조회・편집 | git reset --hard 같은 작업 폐기 |
| 파일 읽기/쓰기 | PR 병합 (Merge) |
PR의 병합을 금지하고 있는 것은, 실제 운영에 배포할지 여부를 결정하는 것은 사람이라고 생각하기 때문입니다.
구현부터 커밋・PR 생성・리뷰 대응까지는 맡기고, 마지막 판단만 스스로 하고 있습니다 🔑
다만, 설정 파일의 금지는 커맨드의 시작 문자 일치로만 판별할 수 있습니다.
예를 들어 .env에 대한 쓰기는 >에서의 리디렉트나 cp / sed -i 등 여러 가지 작성 방법이 가능합니다.
시작 문자 일치만으로는 모든 것을 막을 수 없습니다.
그래서, 커맨드를 실행하기 직전에 전체 문자열을 검사하는 hook을 넣었습니다.
막는 것:
1. .env*로의 쓰기 (리디렉트 / tee / cp / mv / sed -i 등)
2. .claude/settings*로의 쓰기 (스스로 권한을 넓힐 수 없도록)
...
두 번째는 조금 흥미로운 항목입니다.
AI가 설정 파일을 수정하여, 스스로 자신의 권한을 넓히는 것을 할 수 없게 만들고 있습니다 🔒
이 hook에는 테스트도 작성되어 있습니다.
막아야 할 커맨드가 막힐 뿐만 아니라, 통과해야 할 커맨드도 통과하는 것을 같은 무게로 확인하고 있습니다.
예를 들어 git push origin fix/developer-notes는 develop이라는 글자를 포함하지만, 보호하는 브랜치는 아닙니다.
이것을 실수로 막아버리면, 평소 작업 전체가 멈춥니다.
막는 시스템은, 너무 많이 막으면 쓸모없기 때문입니다.
또 하나, PR을 만드는 커맨드를 감지했을 때, 확인 사항을 AI에게 제시하는 hook도 넣었습니다.
- PR의 방향성 (어떤 브랜치에서 어떤 브랜치로)
- 수용 조건 대조 (③의 A / B / C)를 상기시키는 것
스킬 절차에 적혀 있어도, 작업이 길어지면 빠뜨릴 때가 있습니다.
가장 빼먹고 싶지 않은 순간에, 다시 한번 눈앞에 제시하기 위한 장치입니다 👀
여기까지는 AI에게 작업을 맡기기 위한 구조였습니다.
마지막으로, AI가 검토하는 이야기가 있습니다.
혼자 개발하다 보면, 리뷰를 해줄 사람이 없습니다.
그래서 모든 PR에 GitHub Copilot의 리뷰가 자동으로 들어가도록 하고 있습니다.
지적 사항에 대한 대응은 ③의 /handle-review에서 진행합니다.
지적 사항을 하나씩 읽고, 수정할지 말지 이유를 작성하여 각각 답변합니다.
리뷰 지적이 계기가 되어 설계를 재검토한 경우도 있습니다.
- 외부 API 호출 상한 기록 테이블의 권한을,
관리자로부터 제외했습니다. - 외부 API를 호출하는 조건을,
테스트 가능한 함수로 분리했습니다. - 표시 속도 측정에서,
리다이렉트된 시도는 집계에서 제외했습니다.
이 모든 것은, 혼자 작성했다면 깨닫지 못했을 부분들입니다.
여기까지 AI에게 맡기기 위해 규칙으로 고정하는 이야기를 해왔습니다.
문서로 정하고, 스킬로 절차를 정하며, lint나 hooks로 기계적으로 묶습니다.
그러면 AI는 망설이지 않게 됩니다.
명명 규칙도, 파일 배치도, PR 제출 방식도 판단할 여지가 없기 때문입니다.
판단할 여지가 없으면 작업의 품질이 흔들리지 않습니다.
누가 해도 같은 품질에 머무르는 상태가 유지됩니다✨
다만, 여기서 한 번 멈춰서 생각했습니다.
이것은 AI에게만 도움이 되는 것일까?
그런 것은 아닙니다. 인간도 마찬가지입니다.
규칙이 정해져 있고 망설일 여지가 없다면,
인간 신입이라도 첫날부터 규칙에 따라 높은 품질의 작업을 할 수 있습니다.
반대로, 규칙이 암묵적이라면 베테랑조차 사람에 따라 작성 방식이 흔들립니다.
이렇게 생각해보니, 여기에 적은 내용은 AI가 등장하기 전부터 가능했던 것이었습니다.
AGENTS.md는 말하자면 새로 온 사람을 위한 안내서입니다.
ADR은 판단의 기록, 스킬은 작업 절차서, hooks는 사고를 막는 안전장치입니다.
이 모든 것은 팀 개발에서 예전부터 중요하다고 여겨져 온 것들일 뿐이었습니다.
AI가 오기 전에 이렇게까지 규칙을 정해 놓았던 현장이었다면,
인간만으로도 높은 품질의 코드가 작성되었어야 합니다.
AI는, 그것을 하지 않을 수 없게 만들었을지도 모릅니다.
매번 첫날 신입이 오기 때문에, 준비를 미룰 수 없게 된 것입니다🤖
중요한 것은 AI를 위한 준비를 하는 것이 아니라,
AI에게도 사람에게도, 시작하기 쉬운 환경을 조성하는 것입니다.
- AI는 매번 첫날 신입으로 온다. 말로 가르치지 말고, 파일에 놓아둔다📂 - AGENTS.md는 지도, ADR은 버린 안과 이유, 반복 작업은 스킬, 받은 지적은 이유와 함께 메모한다 - 허가는 넓게, 되돌릴 수 없는 조작만 권한과 hooks로 막는다🔒 - 망설일 여지가 없는 환경은, AI에게도 사람에게도 효과적이다. 조성해야 할 것은 누구든 첫날부터 시작할 수 있는 환경입니다.
맡기고 싶은 작업이 있을 때는, 먼저
다음 시간에는 Supabase의 정기 실행 배치(batch)가 아무것도 하지 않고 있는 것을 어떻게 알아차리는지에 대해 작성할 예정입니다🔔
설계 내용 자체를 통해 읽고 싶은 분들을 위해, 해부 문서(dissection document)도 공개하고 있습니다🔬
🔗 ajipita의 내부 (ajipita-inside)
참고가 되셨으면 좋겠습니다🙏