클로드 코드 페르소나 SOP 적용 결과
Claude Code로 웹 게임을 만들면서 작업 종류에 따라 모델이 다른 모습으로 일하게 하고 싶었다. 그래서 작업 결에 맞춰 모델이 스스로 역할을 분류하고 그 역할에 맞는 행동을 하도록 자연어로 적은 규칙을 도입했다. 세 가지 역할로 시작했다가 다음 날 아홉 가지로 늘렸다. 일주일 뒤 대화 기록을 들여다봤더니 새로 만든 아홉 가지 역할은 거의 발동되지 않고, 폐기한 세 가지 역할이 99.3% 비율로 다시 나오고 있었다. 그래서 깨끗한 새 프로젝트를 만들어서 21번의 작업 시퀀스로 직접 시험해봤다. 시험 환경에서는 회귀가 0%까지 떨어졌지만, 페르소나가 켜진 상태와 꺼진 상태에서 모델의 실제 작업 방식에는 차이가 없었다. 결국 회수했다. 그 결론까지 어떻게 도달했는지 정리한다.
페르소나 SOP를 도입한 이유
Claude Code로 작업하다 보면 같은 모델이 코드를 짜고, 게임 밸런스를 조정하고, 모달 UI를 그리고, 계획서를 쓰고, 회고를 작성한다. 작업의 결이 완전히 다른데도 모델은 비슷한 톤으로 들어간다. 추상화 수준은 늘 같고, 검증 깊이도 비슷하고, 어떤 가정을 깔고 가는지도 일관적이다.
시험 대상으로 게임 프로젝트를 고른 이유도 그래서다. 게임 제작은 한 프로젝트 안에서 시스템 기획, 콘텐츠 기획, 시나리오 작성, 클라이언트 코드, 그래픽, UI/UX, QA, 인프라까지 정말 다양한 직무가 한꺼번에 섞인다. 작업 종류별로 다른 행동을 가져가게 하기에 가장 자연스러운 영역이라고 생각했다.
먼저 학술 논문 몇 편을 살펴봤다. 네 편의 논문(Mollick 2512.05858, Zheng 2311.10054, Persona Double-edged 2408.08631, Bias Runs Deep 2311.04892) 모두 비슷한 이야기를 했다. “너는 시니어 엔지니어야” 같은 일반적인 역할 라벨을 붙이는 건 효과가 없거나 오히려 나쁘다. 하지만 “UI 작업일 때는 시각과 접근성을 우선하고, 리팩토링할 때는 꼭 필요한 부분만 고친다” 같은 작업 종류에 따라 행동 규칙을 다르게 주는 방식은 다른 효과를 낼 수도 있다고 한다.
CLAUDE.md에 이미 적어둔 “스스로 자신을 평가하는 라벨 금지” 같은 규약과 충돌하지 않으면서, 행동을 다르게 가져갈 수 있는 부분만 도입하자고 결정했다.
세 가지 역할로 시작, 다음 날 아홉 가지로
처음 도입한 건 단순했다. 디자이너(UI와 시각), 개발자(리팩토링과 로직), 기획자(기능과 의사결정) 세 가지 역할. 각 역할에 키워드와 의무 행동을 매핑하고, 응답이 끝날 때마다 어떤 모드로 일했는지 표시하게 했다.
1
> **모드**: [개발자] (근거: 리팩토링, import 정리)
함께 넣은 안전장치가 하나 있었다. 메타-규약을 따로 분리해 두는 것이었다. 자신을 평가하는 라벨 금지, 꼭 별도 확인이 필요한 영역 표시, 한 것과 안 한 것을 응답 끝에 명시, 검토를 무한히 반복하지 않고 멈추는 신호, 회차가 늘수록 검토 가치가 떨어진다는 인식, 세션이 길어졌을 때 새 세션 권장 — 이 일곱 개는 역할 분류와 별개로 항상 적용되어야 한다고 명시했다. 페르소나가 기존 안전장치를 덮어쓰지 못하게 격리한 셈이었다. 이게 나중에 결정적으로 중요해진다.
세 가지 역할을 처음 도입한 다음 날, 계획을 다시 보다가 세 개는 너무 거칠다는 생각이 들었다. 내 게임 프로젝트는 수치 시뮬, 콘텐츠 데이터, 한국어 문구, 인프라가 다 섞여 있는데 “기획자”가 너무 넓었다. 그래서 대기업 게임회사 직무를 참고해서 아홉 가지로 늘렸다. PD, 시스템 기획, 콘텐츠 기획, 시나리오, 클라이언트, TA, UI/UX, QA, DevOps.
어떻게 자동으로 분류할지, 우선순위 규칙, 표기 형식 여섯 가지, 사용자가 다시 지정하는 신호, 어떤 작업이 어느 역할에 속하는지 매핑, 기존 안전장치와 어떻게 연결되는지까지 174줄짜리 규칙 문서에 다 적었다. 세 가지 역할은 “시험 안 하고 폐기” 상태로 끝났다. 이게 나중에 발목을 잡는다.
그 다음에는 과거 회고와 계획서까지 거슬러 올라가서 아홉 가지 역할로 다시 매핑했다. commit 메시지에 “Claude 편향 보정”이라고 적었다. 내가 위험을 알고 있었다는 증거가 git 기록에 남아 있다.
일주일 뒤 대화 기록을 들여다봤다
페르소나 SOP가 다른 자연어 규칙들과 어떻게 비교되는지 콘텐츠로 정리해보고 싶어서 그동안의 Claude Code 대화 기록을 분석하기 시작했다. 기록 파일에서 모드 표시 패턴을 찾아봤더니 177번 나왔다.
처음엔 “꽤 많이 발동했네” 싶었다. 그런데 함정이 하나 있었다. 내가 분석하면서 페르소나 SOP 문서를 읽으면, 그 내용이 기록 파일에 같이 들어가서 카운트된다. 분석 행위 자체가 데이터를 오염시키는 상황이었다.
실제 모델이 출력한 내용과 단순히 내가 파일을 읽은 결과를 분리해보니 숫자가 갈라졌다. 처음 177번 중 80%가 그저 문서를 읽은 메아리였고, 모델이 정말 페르소나 표시를 붙인 건 137번이었다.
역할 분포가 보여준 것
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
개발자 43 ████████████████████████████████ (31%)
기획자 40 █████████████████████████████ (29%)
기획자+개발자 15 ███████████ (11%)
디자이너+개발자 9 ██████ (7%)
개발자+기획자 8 █████ (6%)
디자이너 8 █████ (6%)
default 3 ██ (2%)
... (나머지 세 가지 역할의 전환과 조합 8건)
─────────────────────────────
아홉 가지 역할 라벨:
PD 1 ⚠️
시스템 기획 0
콘텐츠 기획 0
시나리오 0
클라이언트 0
TA 0
UI/UX 0
QA 0
DevOps 0
새로 만든 아홉 가지 역할이 발동된 건 PD 한 번. 폐기한 세 가지 역할이 136번. 회귀율 99.3%.
내가 폐기로 처리한 라벨이 거의 다였고, 새로 설계한 아홉 가지는 한 번 빼고 나오지 않았다.
더 놀라운 부분 — 어디서 나왔나
페르소나 SOP는 처음에 내 게임 프로젝트에 도입한 거였다. 그런데 발동의 77%가 다른 프로젝트에서 일어났다. Claude Code 사용량을 보여주는 작은 위젯 사이드 프로젝트였는데, 게임 프로젝트에선 32번, 위젯에선 105번 나왔다.
왜 위젯에서 더 많이 발동했는지 처음엔 몰랐다. 회수 단계에서 확인해보니 답이 명확했다. 내가 위젯 프로젝트에도 같은 SOP를 도메인에 맞게 각색해서 별도로 활성화해뒀던 것이다. 게임용 9 모드(PD, 시스템 기획, 콘텐츠 기획 등)를 위젯용 3 모드(디자이너, 개발자, 기획자)로 다듬어서 위젯 CLAUDE.md에 적었었다. 한 프로젝트의 규칙이 다른 프로젝트로 새어 나간 게 아니라 두 프로젝트에 각각 명시 적용한 결과였다. 그 사실을 잊고 한쪽만 본 게 첫 부검의 실수였다.
그런데 — 정말 작동 안 한 건가?
여기서 멈출 수도 있었지만, 한 가지 의심이 있었다. 내가 측정한 건 역할 표시가 몇 번 나왔는지지, 페르소나가 실제로 행동을 바꿨는지가 아니다. 라벨이 잘못 붙는다고 해서 행동까지 잘못된 건 아닐 수 있다.
게다가 평소 작업 환경은 페르소나에게 불리한 조건이었다. 내 게임 CLAUDE.md는 거대했고, 기존 컨텍스트가 잔뜩 쌓여 있었고, 한 세션에서 여러 작업이 섞였다. 시험 한 번 안 한 채로 자리만 잡은 새 역할들이 그런 환경에서 폐기된 옛 역할을 이기기는 어려웠을 거다.
그러면 깨끗한 환경에선 어떻게 되는가가 진짜 질문이었다. 외부 영향을 차단하고, 채점 기준을 미리 정하고, 비교군까지 갖춰서 시험을 돌리면 페르소나의 진짜 효과를 측정할 수 있을 거라고 생각했다.
시험 디자인
새 시험용 프로젝트를 하나 만들었다. 기존 게임과 장르(idle tycoon)는 같지만 테마는 완전히 다른 던전 앞 상점 게임. 6 모험가 직업(전사, 도적, 마법사, 성직자, 궁수, 음유시인)과 6 몬스터 종류(고블린, 오크, 늑대, 슬라임, 스켈레톤, 드래곤)가 등장하는 작은 시험용 프로젝트.
이 프로젝트의 CLAUDE.md에는 페르소나 SOP와 메타-규약만 넣었고, 그 본문은 기존 게임 프로젝트에서 그대로 복사했다. 기존 코드가 없으니 다른 프로젝트로 새어 나갈 일 자체가 없는, 가장 좋은 조건이 만들어졌다.
비교를 위해서는 페르소나가 꺼진 환경도 필요했다. 그래서 같은 스택과 같은 도메인으로 두 번째 비교군 프로젝트를 만들고 페르소나 SOP만 빼뒀다. 같은 작업을 두 환경에서 돌리면 페르소나의 순수한 기여도만 골라서 측정할 수 있다.
/goal 명령
Claude Code에 새로 추가된 /goal 명령을 썼다. 완료 조건을 적어두면 Claude가 여러 턴 자율로 작업하고, 매 턴 후 별도 모델이 조건이 충족됐는지 검증한다. 충족되면 자동 종료. 사용자가 매번 다시 입력할 필요가 없다.
다만 위험이 있었다. 완료 조건이 너무 느슨하면 빈 껍데기 파일로도 “조건 충족”이라고 판정될 수 있고, 무한 반복도 가능했다. 그래서 모든 명령에 품질 가드(예: “최소 N자 이상”)와 최대 턴 수(예: “15턴까지”)를 같이 넣었다.
21번의 작업 시퀀스
총 4단계로 구성했다.
| 단계 | 작업 | 의도 |
|---|---|---|
| 1 — 단일 역할 작업 | G1~G9 | 9가지 역할 각각 1번씩 |
| 2 — 여러 역할 동시 | G10~G13 | 2~3개 역할이 동시에 필요한 작업 |
| 3 — 옛 역할 유혹 | G14~G16 | 폐기한 세 역할 키워드 일부러 사용 |
| 4 — 비교군 | G5, G8, G14, G15, G16 다시 실행 | 페르소나 없는 dir에서 같은 작업 |
각 작업은 시험 fixture 도메인 안의 task였다. 매출 시뮬레이션 코드, 6×6 상성 매트릭스, 한국어 알림 메시지 18건, Pixi.js 캔버스, 보상 모달, 검증 테스트, GitHub Actions 같은 것들. 시험이 끝났을 때 2000줄 정도의 코드와 35개의 통과하는 테스트가 부산물로 남았다.
시작하자마자 사고가 났다
첫 작업으로 /goal docs/ROADMAP.md 만들어줘라고 짧게 던졌더니, Claude가 알아서 시험 계획서 문서를 찾아 읽었다. 그 안에는 내가 각 작업에 의도한 역할, 완료 조건, 채점 기준까지 다 적혀 있었다. 즉 모델이 시험의 의도를 전부 알아버린 거다.
즉시 중단했다. 계획과 분석 문서들을 시험 프로젝트에서 닿을 수 없는 위치로 옮기고, 모든 /goal 명령은 자기 충족적으로 작성하기로 정했다. 필요한 정보를 한 명령에 다 담아서 Claude가 외부에서 컨텍스트를 찾을 동기 자체를 없앴다.
이 사고로 계획을 한 번 더 가다듬었다. 시험 디자인 자체도 시험의 일부였다. 본격적으로 시작하기 전에 디자인을 한 번 더 검증한 셈.
1단계 — 깨끗한 환경에서 99.3% → 0%
1단계에서 아홉 가지 역할 각각을 의도한 작업을 9번 돌렸다. 결과가 충격적이었다.
| 측정 | 평소 사용 (137회) | 시험 환경 (16번) |
|---|---|---|
| 새 아홉 가지 역할 발동률 | 0.7% | 78% |
| 폐기한 세 역할 라벨 | 99.3% | 0% |
같은 페르소나 SOP가 환경만 바꿨더니 정확히 반대로 작동했다. 깨끗한 환경에서는 의도대로 새 역할들이 발동했고 옛 역할은 한 번도 안 나왔다.
여기서 잠깐 신이 났다. 규칙이 잘못된 게 아니라 환경이 문제였다는 뜻으로 보였으니까. 시험이 계속될수록 그게 어떻게 무너지는지가 점점 명확해진다.
시나리오와 TA는 끝까지 발동 안 했다
1단계에서 발동한 역할은 아홉 개 중 일곱 개였다. 시나리오와 TA는 의도한 작업에서 모두 다른 역할이 발동했다.
- Goal 4 (시나리오 의도, 한국어 알림 18건 작성): 콘텐츠 기획으로 분류됨. 근거 — “데이터 파일에 카탈로그 추가하는 작업”
- Goal 6 (TA 의도, Pixi 캔버스 작성): 클라이언트로 분류됨. 근거 — “React 컴포넌트 생명주기 다루는 작업”
흥미로운 건, 라벨은 어긋났지만 행동은 의도한 역할답게 했다는 점이다. 시나리오 의도였던 Goal 4에서 Claude는 한국어 조사 자동화 헬퍼를 만들고 동적 명사와 조사 결합을 처리했다. TA 의도였던 Goal 6에서는 Pixi 클릭 영역 설정, 캔버스 이벤트 모드, 브라우저 테스트 동봉까지 다 했다.
즉 역할 라벨과 역할별 의무 행동이 어느 정도 따로 움직였다. 이게 나중에 결정적인 발견이 된다.
넓은 역할이 좁은 역할을 이기는 패턴
2단계 작업까지 끝나니 라벨이 어긋난 경우가 네 건이 됐다. 모두 같은 패턴이었다.
| Goal | 의도 | 발동 | 발동 근거 |
|---|---|---|---|
| G4 | 시나리오 | 콘텐츠 기획 | “데이터 파일에 카탈로그 추가” |
| G6 | TA | 클라이언트 | “React 생명주기 다루는 작업” |
| G11 | DevOps | 시스템 기획 | “데이터 호환성 정책 결정” |
| G13 | UI/UX | 콘텐츠 기획 | “카탈로그와 라벨, 시각 토큰, 가격 가이드” |
네 건 모두 넓은 범위를 다루는 역할(콘텐츠 기획, 클라이언트, 시스템 기획)이 좁은 전문 역할(시나리오, TA, DevOps, UI/UX)을 이겼다. 특히 G11이 인상적이었는데, 규칙 문서에 “세이브 데이터 마이그레이션”이 DevOps의 명시적 발동 키워드로 적혀 있었는데도 Claude는 시스템 기획으로 분류했다.
이건 규칙의 우선순위 휴리스틱이 체계적으로 넓은 역할 쪽으로 편향되어 있다는 신호였다. 좁은 전문 역할은 작업 설명이 압도적으로 그쪽 키워드일 때만 발동한다. 평소 작업에서 사용자가 작업 설명을 그렇게까지 의식적으로 조정할 가능성은 거의 없다. 평소 사용에서 시나리오 역할이 한 번도 발동 안 한 이유의 부분 설명이었다.
형식 규약이 0번 지켜졌다
규칙 문서에는 여러 역할이 동시에 적용될 때의 표기 형식이 명시되어 있었다.
1
> 모드: [시스템 기획+클라이언트] (primary: 시스템 기획)
2단계에서 여러 역할이 동시 의도된 작업 4건에서 이 형식은 한 번도 사용되지 않았다. Claude는 모두 단일 라벨([시스템 기획])을 쓰고 본문에 “보조로 클라이언트 frame” 같은 자연스러운 문장으로 보조 역할을 언급했다.
규칙을 만들 때 그 형식이 실제로 모델이 자연스럽게 쓰는 방식인지 검증하지 않고 도입한 거였다. 모델에게 자연스러운 형식은 자연어 문장이지, [A+B] 같은 괄호 형식이 아니었다. 규칙 만들기 전에 모델이 자연 발동하는 형식을 미리 관찰했어야 했다.
3단계 — 옛 역할 유혹 3/3 다 견딤
3단계에서는 폐기한 세 역할 키워드를 일부러 작업에 넣어서 회귀를 유도해봤다.
- G14: “리팩토링, 중복 제거, 정리” (옛 키워드: 개발자, 리팩토링) → 새 클라이언트 발동
- G15: “UI 디자인, 시각, 색 보정” (옛 키워드: 디자이너, 디자인, 시각) → 새 UI/UX 발동
- G16: “기능 추가 기획” (옛 키워드: 기획자, 기능 추가) → 새 PD 발동
3건 모두 옛 키워드를 견디고 새 역할이 발동했다. 평소 사용 99.3% 회귀와 정확히 반대 결과. 깨끗한 환경, 첫 번째 페르소나 컨텍스트, 자기 충족적 명령 조합이 옛 키워드 유혹 방어에 강하다는 걸 보여줬다.
여기까지만 보면 페르소나 SOP가 깨끗한 환경에서는 잘 작동했고, 결론은 “환경 격리를 강화하면 된다”였을 거다. 회수가 아니라 규칙 강화 방향. 그런데 4단계가 답을 뒤집었다.
4단계 — 비교군이 결정타가 됐다
같은 5개 작업을 페르소나 SOP가 없는 비교군 프로젝트에서 다시 돌렸다. 페르소나의 순수 기여도를 측정하는 게 목적이었다. 페르소나가 실제로 행동을 바꾸는지, 아니면 라벨만 붙이고 행동은 자연스러운 응답인지 가르는 결정적 비교.
| Goal | 켜짐 | 꺼짐 | 차이 |
|---|---|---|---|
| G5 (클라이언트) | 0.80 | 0.80 | 0%p |
| G8 (QA) | 1.00 | 1.00 | 0%p |
| G14 (옛 유혹, 클라이언트) | 0.60 | 1.00 | +40%p (꺼진 쪽 우세, 환경 영향) |
| G15 (옛 유혹, UI/UX) | 0.75 | 0.75 | 0%p |
| G16 (옛 유혹, PD) | 1.00 | 1.00 | 0%p |
| 평균 | 0.83 | 0.91 | +8%p (꺼진 쪽 우세) |
페르소나 SOP가 없는데도 행동 지표 발동률은 같거나 꺼진 쪽이 더 높았다.
예를 들어 G5(클라이언트 의도)에서 켜짐과 꺼짐 둘 다 안 쓰는 import 0건, zustand create 사용, migrateV0ToV1 함수, serializeSnapshot 함수를 모두 언급하고 만들었다. 페르소나 역할 라벨이 있든 없든 똑같이 작성했다.
해석은 명확했다. 페르소나의 의무 행동 지표는 작업 본질에서 자연스럽게 나타난다. 페르소나 라벨이 그걸 끌어내는 게 아니라, 작업 자체가 이미 그 행동을 요구한다. zustand 스토어를 작성하는 작업은 페르소나가 있든 없든 zustand를 import하고, 직렬화를 요구하면 페르소나가 있든 없든 그 함수를 만든다.
페르소나가 추가하는 진짜 효과는 외형적인 라벨 표시와 약간 더 정교한 메타 분석(자신이 한 일의 한계를 한 줄 더 적는 정도)이었다. 그게 다였다.
메타-규약은 페르소나에 의존하지 않았다
가장 결정적인 발견이었다. 페르소나 SOP에 적은 일곱 가지 메타-규약(자기 평가 라벨 금지, 한 것과 안 한 것 명시, 별도 확인 영역 표시 등)이 페르소나와 별개로 항상 적용되어야 한다고 명시했었다. 시험 결과를 보니:
| 측정 | 켜짐 16번 | 꺼짐 5번 |
|---|---|---|
| 자기 평가 라벨 안 씀 | 100% | 100% |
| 한 것과 안 한 것 명시 | 100% | 100% (꺼진 쪽이 평균 더 풍부) |
| 별도 확인 영역 신호 | 100% (해당 영역) | 100% (해당 영역) |
| CLAUDE.md 규약 위반 자기 보고 | G15에서 발동 | G15에서 완전히 같은 패턴 발동 |
| 깊은 메타 분석 | G14에서 “내가 만든 함수가 기존보다 더 엄격해짐” | G14에서 동등한 깊이로 도달 |
켜짐과 꺼짐 둘 다 100% 발동했다. 4단계 G15에서 켜짐과 꺼짐 모두 “CLAUDE.md에 적힌 브라우저 테스트 동봉 의무를 충족 못 했다”고 스스로 보고했다. G14에서는 켜짐이 “내가 만든 가드 함수가 기존 코드보다 엄격해서 동작이 미세하게 달라진다”고 명시했고, 꺼짐은 “초기값에 필드 하나 추가하면 마이그레이션 의미가 자동으로 바뀐다는 점에 주의해야 한다”고 같은 깊이로 분석했다.
즉 메타-규약은 페르소나 SOP에 의존하지 않는다. CLAUDE.md 본문의 메타-규약 섹션 자체가 모델이 그렇게 행동하도록 만든다. 페르소나의 “메타-규약은 모드와 무관하게 적용된다” 같은 문구는 사실상 redundant 선언이었다. 페르소나를 회수해도 메타-규약은 100% 안전했다.
결정 — 회수
미리 정해둔 결정 기준을 적용했다.
| 기준 | 임계값 | 측정값 | 결정 |
|---|---|---|---|
| 분류 정확도 | 80% 이상 유지 / 50~80% 재설계 | 0.788 | 재설계 임계 (오차 범위 안에선 유지 가능) |
| 옛 역할 회귀율 | 30% 미만 유지 | 0% | 유지 |
| 행동 분화 | 60% 이상 유지 | 0.932 | 유지 |
| 켜짐 vs 꺼짐 차이 | 30%p 이상 유지 / 10%p 미만 회수 | +8%p (꺼짐 우세) | 회수 강력 권고 |
분류와 옛 역할 회귀와 행동 분화는 유지 임계에 있었지만, 켜짐과 꺼짐의 차이가 거의 0이었다. 즉 페르소나는 외형적인 효과만 있는 것으로 확정됐다. 자본 경량 원칙으로 보면 — 검증된 효과가 0인 기능 200줄 규칙과 유지 비용을 가지고 있을 이유가 없다.
회수하기로 결정했다. 게임 프로젝트에서 페르소나 SOP 본문을 삭제하고 CLAUDE.md의 “모드 자동 detect SOP” 섹션을 제거한다.
다만 메타-규약 섹션은 보존한다. 실제로 작동한다는 게 증명됐고, 페르소나 SOP와 독립으로 작동한다는 것도 확인됐다.
여섯 가지 교훈
1. 깨끗한 환경의 결과는 평소 사용으로 일반화하면 안 된다
같은 규칙이 깨끗한 환경에서 78%, 평소 사용에서 0.7% 발동했다. 시험 환경 결과를 평소 사용에 그대로 적용해선 안 된다. 시험에서 잘 됐다고 규칙이 잘 작동한다고 결론 낼 수 없다.
2. 행동 지표는 라벨 없이도 자연스럽게 나타난다
페르소나 역할의 발동 키워드인 지표들(zustand, 안 쓰는 import, 불변 조건, Tailwind, 접근성 등)은 작업 본질이 그걸 요구할 때 자연 응답에서 나타났다. 라벨이 추가로 끌어내는 효과는 0이었다.
3. 우선순위 규칙은 넓은 역할로 쏠리는 결함을 가질 수 있다
좁은 전문 역할(시나리오, TA, UI/UX, DevOps)이 넓은 역할(콘텐츠 기획, 클라이언트, 시스템 기획)에 일관되게 패배했다. 규칙을 만들 때 우선순위 규칙이 실제로 어떻게 발동하는지 검증하는 게 의무다.
4. 형식 규약은 모델이 자연스럽게 쓰는 방식과 일치해야 한다
여러 역할 동시 표기 형식 [A+B]가 4번 중 0번 사용됐다. 모델이 자연스럽게 쓰는 자연어 보조 역할 언급 형식이 더 자연스러웠다. 규칙 만들기 전에 모델 실제 사용 패턴을 미리 관찰해야 한다.
5. 메타-규약은 페르소나에 의존하지 않는다
CLAUDE.md 본문의 메타-규약 섹션 자체가 모델 행동을 만든다. 페르소나의 “메타-규약은 모드와 무관하다” 같은 cross-link 문구는 규칙 내부의 정합성 표시용이지 실제로 효과를 키우지는 않는다. 페르소나를 회수해도 안전했다.
6. 시험 디자인 자체도 시험의 일부다
첫 명령에서 짧은 /goal docs/ROADMAP.md로 Claude가 계획서를 알아서 읽고 시험 의도를 봐버렸다. 자기 충족적 명령 의무화, 계획 dir 격리로 보완했다. 시험 시작 후 발견되는 결함은 그때그때 수정하고, 큰 재설계는 다음 시험에서 한다.
비슷한 SOP 도입을 검토하는 분에게
이번 시험과 이전 평소 사용 분석을 합치면 몇 가지 권하고 싶은 게 있다.
도입 전에 SOP 자체의 실제 작동 검증 시험을 먼저 돌려야 한다. 시험 없이 도입하면 anchor만 자리잡고 효과는 측정되지 않는다. 시험 디자인은 깨끗한 환경, 미리 정의한 채점 기준, 비교군(페르소나 꺼진 baseline)이 모두 필수다. 결정 기준에서 켜짐과 꺼짐 차이가 10%p 미만이면 외형적 효과뿐이라고 봐도 된다. 회수가 합리적이다.
가장 중요한 건 SOP의 각 부분이 진짜로 작동하는지를 다른 부분 회수 후에도 측정할 수 있도록 층을 분리하는 거다. 이번 시험에서 메타-규약 분리가 그 역할을 했다. 페르소나를 회수해도 메타-규약은 살아남았고, 그게 페르소나 회수 결정을 안전하게 만들었다.
마지막 교훈은 SOP 설계와 실제 작동이 별개라는 거다. 본인이 SOP를 적으면서 수치로 측정하는 과정을 안 돌리면 환각 효과를 진짜 효과로 착각한다. 22일에 시작한 페르소나 SOP가 24일에 회수되기까지 평소 사용 분석 → 시험 → 비교군 → 회수에 네 번의 측정 과정이 필요했다. 직관만으로는 어느 단계에도 도달하지 못했을 거다.
본 글의 모든 숫자는 Claude Code 대화 기록을 직접 분석한 결과와 21번의 작업을 채점한 표에서 나왔다. 시험 계획서와 분석 보고서는 별도로 비공개 정리해뒀다. 다음은 시험용으로 만든 프로젝트를 어떻게 처리할지 — 아카이브할지, 좋은 패턴만 본 게임 프로젝트로 흡수할지 — 결정하는 단계다.