도구 하나를 다섯 번 고친 이유
손맛 안에는 /devil이라는 슬래시 커맨드가 있다. 사용자가 어떤 결론에 자신만만하게 도착하면, 그 결론을 그 자리에서 두들겨보는 도구다. devil’s advocate. 잘 알려진 사고 기법이고, 이걸 커맨드 하나로 만들었으니 끝일 줄 알았다.
다섯 번 고쳤다.
처음 도입한 v0.6.0이 4월 2일이었다. 본질이 마지막으로 한 번 더 흔들린 v0.11.0이 4월 26일. 그 24일 동안 도구가 다섯 단계를 거쳤고, 단계마다 그 도구가 나한테 한 가지씩 가르쳐줬다. 이 글은 그 다섯 단계 이야기다.
v0.6 — imp가 처음 등장한 날
01편에서 짚었던 그 격차 — AI가 자신만만한 헛소리를 내놓으면, 사람도 그 자신감에 설득돼서 그냥 수락해버린다는 것 — 그 격차를 깨려면 도구가 하나 필요했다. 자기-반박을 강제하는 도구.
처음 이름은 imp였다. 작은 마귀. 장난스러운 어감이 마음에 들었다. 본문 설명은 그냥 “Devil’s advocate for reasoning.”
첫 디자인은 단순했다. 사용자의 주장을 한 줄로 요약해서 다시 말하고, 세 축에서 공격한다 — 증거(빠지거나 cherry-pick 됐나), 논리(추론에 비약이 있나), 대안(같은 사실에서 다른 결론도 나오나). 그러고 작동 중인 인지 편향 이름을 댄다. 마지막에 balance table 한 장. Strength랑 Verdict 컬럼.
쓸만했다. 처음 두 번은.
v0.7 — 이름이 거짓말이었다
세 번째 사용에서 멈칫했다. 명령어는 /imp인데, 본문 설명에서는 줄곧 “devil’s advocate”라고 부르고 있었다. 한 글 안에서 같은 도구가 두 이름으로 돌아다니고 있었던 거다. 도구를 부를 때마다 머릿속에서 “아 그게 imp였지” 하고 한 번씩 변환이 걸렸다.
작은 일 같지만, 작은 일이 아니다. 이름은 곧 도구의 정체성이니까. 정체성이 헷갈리면 자동화돼야 할 동작에 자꾸 마찰이 낀다. 한 번씩이 쌓이면 결국 도구 자체를 안 부르게 된다.
v0.7.0(4월 6일)에서 /imp → /devil로 갈았다. Breaking change였다. 사용자(=역시 나)가 명령어를 다시 외워야 했다. 그래도 했다. 이고 갈 거짓말은 빨리 회수해야 한다.
같은 사이클에서 core 디시플린에 Rhythm Rules(Pace / Weight / Learn)도 들어왔다. devil은 이제 단독 도구가 아니라 더 큰 검증 시스템의 한 축이 됐다. Pace는 “언제 쓸지”, Weight는 “얼마나 무겁게 쓸지”, Learn은 “결과를 어떻게 메모리에 남길지”. devil은 그중에서 Pace와 Weight를 결정하는 부품 하나가 된 셈이다.
v0.7.1 → v0.10 — 표가 안 읽혔다
이제 진짜 사용 단계로 들어가니, balance table이 잘 안 읽혔다.
| Original claim | Counter-argument | Strength | Verdict |
“Strength”가 도대체 무엇의 strength인가? 원래 주장의 강도? 아니면 counter-argument의 강도? 매번 본문을 다시 읽어 확인했다. 짧은 명사구 컬럼명이 의미를 못 실어 나르고 있었다.
v0.7.1(4월 10일) — 컬럼명에 주체를 박았다.
| Original claim | Counter-argument | Counter strength | Claim verdict |
훨씬 나았다. 그런데 일주일 더 쓰다 보니 또 거슬렸다. “Counter strength”가 너무 짧은 명사구라 첫눈에 의미가 안 들어왔다. 사람이 표를 읽을 때 머릿속에 처음 던지는 질문은 “이 컬럼이 나한테 묻는 게 뭐지?”인데, 그 답이 컬럼명에 직접 들어 있어야 더 빨리 읽힌다.
v0.10.0(4월 17일) — 명사구를 질문문으로 갈았다.
| Original claim | Counter-argument | Counter (strong/moderate/weak) | Claim after challenge |
정식 헤더 텍스트는 “How strong is the counter-argument?”고, 답 옵션을 괄호로 같이 노출했다. “Verdict”라는 추상명사도 버리고 “Claim after challenge” — 도전 이후의 주장 — 로 갈았다. 시간축이 들어 있는 표현이라 훨씬 직관적이다.
작은 변경 같지만, 두 번에 걸쳐서 갈았다. 컬럼명은 사용자가 표를 읽기 시작하는 첫 신호다. 첫 신호가 모호하면 그 아래 데이터 전체가 그냥 noise로 떨어진다. 결국 컬럼명 자체가 의미를 실어 나르는 거니까, 두 번 갈 만한 자리였다.
v0.11 — devil이 나를 지치게 했다
가장 큰 진화는 4월 26일에 왔다. 그리고 이게 좀 어이없는 얘긴데, 도구가 잘 작동해서 생긴 문제였다.
devil이 너무 잘 의심했다.
내가 어떤 결정을 내릴 때마다 /devil을 부르면, devil은 성실하게 약점을 찾아냈다. 그것도 진짜 약점이었다. cherry-pick 가능성, 인과 방향이 안 검증된 부분, 같은 데이터로 설명되는 다른 가설. 다 진짜였다.
문제는 그게 내 다음 행동을 바꾸지 않는다는 거였다.
예를 들어보자. “이 글을 어떤 시리즈로 묶을까” 같은 결정에 devil을 부르면, devil은 “시리즈 분류 자체가 임의적이다, 독자는 시리즈를 안 본다, 카테고리 통계가 비어 있다” 같은 진짜 약점들을 정직하게 surfacing한다. 다 맞는 말이다. 그런데 나는 그 글을 어쨌든 어딘가에 묶어야 했고, 어디로 묶어도 일주일 후에 옮길 수 있었다. devil이 꺼내준 약점들은 사용자의 다음 행동에 아무 영향이 없었다.
이걸 이름 붙였다 — reactive contradiction. 진짜 약점인데 tangential한 것. 도구는 똑똑해 보이고, 결과는 churn.
이게 도구의 시그니처 실패 모드라는 걸 깨달은 게 v0.11 직전이었다.
답은 게이트였다. v0.11에서 §2.5라는 새 섹션이 들어갔다. Project-relevance gate.
CCT(Claim-crux / Counter-fit / Cause-chain — devil이 load-bearing assumption을 찾는 기존 단계) 뒤에 게이트 한 단계를 추가했다. 세 가지 질문을 통과해야만 §3 depth drive로 넘어간다.
| 질문 | 목적 |
|---|---|
| Stakes | 이 추론이 틀리면 사용자가 여기서 잃는 것은? |
| Amendment cost | 이 결정이 lifecycle 어디에 있나 — 초안인가, 커밋된 운영 상태인가? |
| Next-action delta | 이 counter를 surfacing하면 사용자의 다음 행동이 실제로 바뀌나, 아니면 글자만 추가되나? |
세 답으로 verdict를 매긴다.
[devil] Project relevance: "{material | load-bearing-but-low-stakes | off-project}"
material— 진짜 stakes가 있다. §3 depth로 진행.load-bearing-but-low-stakes— 진짜 약점인데 깊은 추궁을 정당화할 만한 stakes가 아니다. 짧게 노트하고 멈춤.off-project— 약점이 기술적으로는 맞지만 결정 자체랑 무관하다. 그렇게 말하고 멈춤.
off-project라는 출구가 핵심이었다. 그 전까지 devil의 종결은 “claim survives” 또는 “claim weakened/flipped” 두 가지뿐이었다. 둘 다 도전이 일단 들어간 후의 상태. 하지만 도전 자체가 빗나간 경우는 표현이 없었다. 그래서 devil은 빗나간 도전이라도 어쨌든 던지고 봤다. 그게 reactive contradiction의 구조적 원인이었던 거다.
off-project가 추가되고 나서야 devil은 정직한 퇴장이라는 옵션을 가진다. 도구는 자기 일이 없을 때 일어서지 말아야 한다. 그게 게이트의 본질이다.
다섯 번 고치고 배운 것
1. 검증 도구도 검증되어야 한다. devil은 자기 자신을 검증할 수 없으니, 신호는 사용자의 피로다. 도구를 부르고 나서 “쓸만했네”가 아니라 “이걸 또 봐야 하나” 소리가 나오면, 그건 도구가 자기 일을 못 하고 있다는 증거다.
2. 이름은 도구의 정체성이다. imp/devil 거짓말을 끌고 가지 않은 게 v0.7의 의미였다. 매 호출마다 사용자가 머릿속 변환을 한 번씩 더 해야 한다면, 그건 누적되는 비용이 된다.
3. 표 컬럼명은 noise/signal의 분기점이다. 두 번 갈았다. 명사구에서 질문문으로 가고 나서야 비로소 표가 읽혔다. 표는 데이터를 담지만, 컬럼명은 그 데이터를 어떻게 읽을지를 담는다. 후자가 모호하면 전자도 의미가 없다.
4. 부지런해 보이는 도구가 진짜 부지런한 건 아니다. 도구가 매번 약점을 찾아주고, 매번 정직하게 surfacing할 때 — 그게 정작 진짜 작업이 아니라 작업처럼 보이기만 하는 것일 수 있다. devil은 똑똑하게 작동했지만, 사용자한테는 churn을 안기고 있었다. 퇴장도 결과다. 도구가 항상 무언가를 surfacing해야 한다는 가정 자체가 함정이었다.
다음 진화는 이미 보인다
게이트가 추가된 게 글 쓰는 시점 기준 일주일도 안 됐는데, 벌써 다음 의문이 생기고 있다.
- Stakes를 사용자가 항상 명시하지는 않는다. devil이 그걸 어떻게 추정해야 하나? 추정이 빗나가면 다시 reactive contradiction으로 회귀하지 않나?
load-bearing-but-low-stakes랑off-project의 경계가 사용자 입장에서 명확한가? 둘 다 “stop here”인데 의미가 다른 건데.- devil이 자기 verdict를 self-critique 해야 하는 상황은? “이 게이트 verdict 자체가 너무 보수적이다” 같은 메타 도전이 필요한 순간 말이다.
도구를 다섯 번 고쳤지만, 도구 짓는 일은 끝나지 않는다. 다음 릴리스에 어떤 진화가 들어갈지는, 결국 사용자가 어디서 또 지치는지가 알려줄 거다.
써보기
/plugin marketplace add jun0-ds/sonmat
/plugin install sonmat@sonmat
설치하고 어떤 결정에 대해서든 /devil을 한번 불러보세요. 결과가 churn처럼 느껴지면, 그 자리에서 도구가 자기 일이 없다는 신호를 무시하고 있는 거다. 그 신호를 잡아내는 게 사용자가 도구를 길들이는 첫 단계이고요.
시리즈 손맛 (sonmat) 만들기 세 번째 글. 이전 글: 이 문제를 고치려고 sonmat을 만들었다. sonmat에도 같은 버그가 있었다.