지금까지 표준은 전부 무엇을 만드는가에 대한 것이었다. 패키지를 어떻게 나누고, DTO를 어떻게 만들고, 계약을 어떻게 적는지. 그런데 그 표준들을 어떤 태도로 실행하는가는 어디에도 없었다.
빈자리가 실제로 사고를 냈다. 테스트 냄새 어휘를 검토하면서 아리맘 저장소의 무테스트 도메인을 셌는데, 이런 값이 나왔다.
무테스트 도메인 6개 (42%) ← 보고했다
프로덕션 대 테스트 줄 비율 1 : 0.12
전부 틀린 값이었다. 로컬 dev가 28커밋 뒤처진 상태로 쟀기 때문이다. git fetch 후 origin/dev로 다시 재니 무테스트 도메인은 하나(3%), 줄 비율은 1 : 0.28이었다. 같은 세션에서 계약 칸 수도 33개로 보고했다가 실제 130개로 정정했다.
두 번 다 원인이 같다. git fetch 한 번을 아끼려다 결론 전체가 틀렸다. 빠르게 하려던 것이 정확도를 통째로 버렸고, 그래서 아낀 시간보다 훨씬 많은 시간을 정정에 썼다.
여기서 정해야 할 것이 드러났다 — 빠름과 정확도를 어떤 비율로 섞을 것인가.
먼저: 이 표준이 다루지 않는 것
이건 자바 코드에 대한 규칙이 아니다. 다른 표준들과 층이 다르다.
| 다른 표준 | 이 표준 | |
|---|---|---|
| 대상 | 만들어지는 코드 | 만드는 과정의 판단 |
| 검사 | 컴파일러·테스트·게이트가 본다 | 기계가 볼 수 없다 |
| 어길 때 | 빌드가 막힌다 | 아무 일도 안 일어난다 |
검사할 수단이 없다는 것이 이 표준의 근본 제약이다. 게이트로 막을 수 없으니 규칙을 적어두는 것 말고는 강제할 방법이 없다. 그래서 이 표준은 「지키는지 검사하는 규칙」이 아니라 「말하지 않으면 기본값으로 어기게 되는 것」을 적는 자리다.
그리고 이 제약이 규칙의 위치를 정했다. 스킬이 아니라 「항상 적용」 문서에 들어간다. 스킬은 description의 호출 조건을 모델이 보고 부르는 구조인데, 이 규칙에는 호출 조건이 없다. 언제나 켜져 있어야 하는 것을 조건부 호출 장치에 넣으면 영영 안 불린다.
원칙 1. 정확도를 저울에 올리지 않는다
정해야 했던 건 이거였다 — 빠름과 정확도가 부딪힐 때 무엇을 기준으로 자르는가.
안 A — 「빠르고 정확하게 한다」만 적는다
어떤 것을 함에 있어서 빠르고 정확하게 할 수 있는 방향으로 선택하고 제안한다.
얻는 것은 한 줄로 끝난다는 것이다. 둘 다 하라는 말이라 반대할 여지가 없고, 대부분의 상황에서는 실제로 둘이 부딪히지 않는다.
버린 이유는 부딪히는 순간에 아무것도 안 알려준다는 것이다. 위의 git fetch 건이 정확히 그 순간이었다. 확인을 건너뛰는 쪽이 「빠른 것」으로 정당화되고, 규칙은 그걸 막지 않는다. 둘 다 좋다는 규칙은 하나를 버려야 할 때 침묵한다.
안 B — 「부딪히면 정확도가 이긴다」
둘이 부딪히면 정확도가 이긴다. 빠름은 정확도를 지킨 안에서만 추구한다.
- 빠른 방법이 정확도를 떨어뜨린다면 고르지 않는다. 느려도 맞는 쪽을 고른다.
얻는 것은 안 A가 침묵하던 자리에서 답이 나온다는 것이다. 우선순위가 명시되어 있으니 git fetch를 건너뛰는 선택이 규칙 위반으로 잡힌다.
버린 이유는 느림의 면죄부가 된다는 것이다. 「느려도 맞는 쪽을 고른다」는 문장은, 조금이라도 의심스러우면 느린 길을 골라도 규칙을 지킨 것이 되게 만든다. 전수 조사를 하고, 확인을 세 번 하고, 안전한 쪽으로만 가도 이 규칙 안에서는 전부 정답이다. 막으려던 것과 반대 방향으로 똑같이 시간을 버린다.
이 안은 실제로 한 번 적었다가 버렸다. 적어놓고 보니 그 문장이 곧 「고민되면 느리게 가라」로 읽혔다.
골랐다 — 안 C. 정확도를 전제로 고정하고 그 안에서 최속을 찾는다.
정확도는 저울에 올리는 것이 아니라 전제다.
그 전제를 고정한 채 가장 빠른 길을 찾는다.
하나를 버리고 하나를 고르는 일이 아니라,
정확한 방법들 중에서 제일 빠른 것을 고르는 일이다.
안 A는 부딪힐 때 침묵하고, 안 B는 부딪힐 때 느린 쪽에 백지수표를 준다. 안 C는 애초에 부딪히는 구도로 보지 않는다. 정확도는 후보를 거르는 조건이고, 빠름은 남은 후보 중에서 고르는 기준이다. 층이 다르므로 저울에 같이 올릴 수 없다.
여기서 두 줄이 따라 나온다.
- 「느리지만 정확하다」에 안주하지 않는다. 정확도를 지키는 방법이 여럿이면 그중 가장 빠른 것을 끝까지 찾는다
- 빠른 방법이 정확도를 떨어뜨리면 그 방법만 버린다. 거기서 멈추지 말고, 정확도를 지키면서 빠른 다른 길이 없는지 한 번 더 찾는다
대신 이 선택은 판단을 매번 해야 하는 대가를 치른다. 안 B는 「의심되면 느린 쪽」이라는 기계적 규칙이라 생각할 필요가 없는데, 안 C는 「정확한 방법이 무엇무엇이고 그중 뭐가 제일 빠른가」를 매번 세워야 한다. 이 대가는 감수한다 — 기계적 규칙으로 줄일 수 있는 판단이었으면 애초에 게이트로 만들었을 것이다.
70 : 30은 우선순위가 아니라 가중치다
숫자를 붙인 이유는 「정확도가 이긴다」가 100 : 0으로 읽히기 때문이다. 100 : 0이면 빠름은 고려 대상이 아니게 되고, 그게 안 B가 무너진 지점이다.
30은 정확도가 같을 때 시간이 실제로 판단을 가른다는 뜻이다. 0이 아니다.
원칙 2. 더 빠른 길이 보이면 진행 도중에 말한다
원칙 1이 「무엇을 고르는가」였다면 이건 「언제 말하는가」다. 더 빠른 길을 알아채고도 말하는 시점이 늦으면 알아챈 값이 사라진다.
정해야 했던 건 이거였다 — 시킨 방식이 느리다고 판단했을 때 언제 말하는가.
안 A — 끝내고 나서 회고로 말한다
얻는 것은 말이 정확해진다는 것이다. 끝까지 해봤으니 실제로 얼마나 걸렸는지 알고, 대안이 정말 빨랐을지도 근거를 갖고 말할 수 있다.
버린 이유는 이미 시간을 다 쓴 뒤라 회수가 안 된다는 것이다. 「이렇게 했으면 30분 아꼈다」는 말은 그 30분을 돌려주지 않는다. 시간이 비용이라는 전제에서는 사후 보고가 가장 비싼 형태다.
안 B — 시작 전에 계획을 승인받는다
얻는 것은 가장 이른 시점에 개입한다는 것이다. 아무것도 안 했을 때 방향을 트니 버리는 것이 없다.
버린 이유는 느리다는 걸 알게 되는 시점이 대개 도중이라는 것이다. 시작 전에는 정보가 없다. 위의 아리맘 측정도 파일을 몇 개 열어보고 나서야 「도메인 폴더로 세면 계약표가 안 보인다」는 걸 알았다. 시작 전 승인은 모르는 상태에서 한 판단을 승인받는 절차가 되고, 그러면 승인이 형식이 된다.
골랐다 — 안 C. 알아챈 시점에 말한다. 그게 도중이어도 끊는다.
안 A는 회수 불가능한 시점이고, 안 B는 정보가 없는 시점이다. 알아챈 시점은 정보가 생긴 가장 이른 순간이고, 아직 남은 시간이 있는 순간이다. 두 조건을 동시에 만족하는 유일한 지점이다.
대신 말이 늘어 대화가 끊기는 대가를 치른다. 그래서 말하는 형식을 함께 못 박았다.
준비 비용이 드는 방법이면 비용과 회수 지점을 숫자로 같이 말한다. 「10분 들여 스크립트를 짜면 이후 매번 30초」
숫자가 없으면 그냥 「이 방법이 더 좋아 보인다」가 되고, 그건 판단을 상대에게 넘기는 것이다.
「지금 가진 것만으로」에 갇히지 않는다
빠른 길을 못 찾는 흔한 이유는 후보 목록이 좁아서다. 도구를 새로 깔기·스크립트 작성·자동화·병렬 실행·유료 수단·접근 자체를 바꾸기가 전부 후보다.
실제로 이 세션에서 걸렸다. 뮤테이션 테스트 측정이 「이 기계에 Docker가 없다」로 막혀 있었는데, 그건 지금 가진 것만 후보로 본 결과였다. Docker를 설치하는 것이 후보에 들어가면 막힌 것이 아니다.
원칙 3. 앞 단계의 결과를 그대로 믿고 넘어가지 않는다
원칙 1과 2는 고르는 규칙이다. 이건 실행 중의 규칙이고, 앞의 사고가 실제로 난 지점이다.
git fetch를 안 한 것은 사실 두 번째 잘못이다. 첫 번째 잘못은 「무테스트 도메인 42%」라는 값을 보고도 이상하다고 느끼지 않은 것이다. 계약 커버리지 게이트를 이미 도입한 저장소에서 42%가 나올 수 없다는 건 그 자리에서 알 수 있었다.
정해야 했던 건 이거였다 — 틀린 값이 결론까지 흘러가는 것을 어디서 막는가.
안 A — 마지막에 검사 단계를 하나 둔다
얻는 것은 비용이 한 번뿐이라는 것이다. 매 단계 확인하는 것보다 싸고, 실제로 대부분의 파이프라인이 이 모양이다.
버린 이유는 사후라서 되돌릴 것이 이미 쌓여 있다는 것이다. 틀린 값 위에 세운 판단·표·결론을 전부 다시 만들어야 한다. 아리맘 건이 그랬다 — 값 하나가 틀렸는데 발견 세 개와 결론 하나를 통째로 다시 썼다.
안 B — 매 단계 사람에게 확인받는다
얻는 것은 틀린 값이 한 단계 이상 못 간다는 것이다.
버린 이유는 자동화의 값을 없앤다는 것이다. 매 단계 사람이 봐야 하면 사람이 직접 하는 것과 드는 시간이 같아진다. 원칙 2에서 시간을 아끼자고 해놓고 여기서 다 토해내는 셈이다.
골랐다 — 안 C. 매 단계 스스로 판단하되, 검문은 한 줄로 한다.
결과가 예상과 다르면 그냥 넘어가지 않는다. 왜 다른지를 먼저 본다.
안 A는 늦고 안 B는 비싸다. 어긋난 값은 그 자리에서 스스로 티가 난다 — 42%는 예상과 달랐고, 33칸도 예상과 달랐다. 둘 다 그 자리에서 걸 수 있었다.
이 검문이 좋은 이유는 비용이 예상을 갖고 있을 때만 발생한다는 것이다. 예상이 없으면 어긋남도 없으니 그냥 지나간다. 즉 아는 만큼만 비용을 낸다.
대신 예상 자체가 틀렸을 때는 못 잡는 대가가 있다. 예상과 결과가 나란히 틀리면 어긋남이 안 생긴다. 이건 이 검문으로 막을 수 없고, 그래서 원칙 1의 「최신 기준으로 다시 잰다」가 따로 필요하다.
속도 때문에 범위를 좁혔으면 좁혔다고 밝힌다
이건 원칙 1의 정확도를 실행 중에 지키는 줄이다. 범위를 좁히는 것 자체는 옳다 — 전수 조사보다 대상을 좁히는 쪽이 빠르고, 원칙 1이 권하는 방향이다.
틀리는 건 좁힌 결과를 전체인 것처럼 말할 때다. 일부를 보고 「없다」고 하면, 받는 쪽은 전수 조사 결과로 알아듣는다. 좁혔다고 밝히면 그건 여전히 정확한 답이다.
판단 기준 정리
| 질문 | 답 | 결론 |
|---|---|---|
| 빠른 방법이 정확도를 떨어뜨리는가 | 그렇다 | 그 방법만 버린다. 거기서 멈추지 말고 다시 찾는다 |
| 정확한 방법이 여럿인가 | 그렇다 | 그중 가장 빠른 것을 고른다. 안전한 쪽이 아니다 |
| 확인이 귀찮아서 건너뛰려 하는가 | 그렇다 | 30을 아끼려고 70을 버리는 것이다. 확인한다 |
| 지금 방식이 느리다고 알아챘는가 | 그렇다 | 그 자리에서 말한다. 비용과 회수 지점을 숫자로 |
| 준비 비용이 드는 방법인가 | 그렇다 | 후보에서 빼지 않는다. 회수 지점을 계산해서 댄다 |
| 앞 단계 결과가 예상과 다른가 | 그렇다 | 넘어가지 않는다. 왜 다른지를 먼저 본다 |
| 속도 때문에 범위를 좁혔는가 | 그렇다 | 좁혔다고 밝힌다. 전체인 것처럼 말하지 않는다 |
| 되돌리기 어려운 일인가 | 그렇다 | 대상을 확인하고 승인받은 뒤에 한다 |
이 표준을 정하기까지
시작은 표준이 아니라 설정이었다. 「모든 클로드 코드 세션에 적용하고 싶다」는 요청이었고, 확인해보니 유저 레벨 CLAUDE.md가 아예 없었다. 무엇을 적을지는 그다음 문제였다.
「일머리」라는 말이 먼저 나왔고 정의가 붙었다. 「어떤 것을 함에 있어서 빠르고 정확하게 할 수 있는 방향으로 선택하고 제안해야 한다」. 이게 안 A다. 그대로 적었다.
근거가 붙으면서 규칙이 한쪽으로 기울었다. 「시간은 곧 돈이고 노동력이다. 빠르고 정확하게 할 수 있으면 수단과 방법을 가리지 말고 제안하라」. 이 말이 원칙 2를 만들었다 — 후보를 좁히지 않는 것, 도중에라도 말하는 것. 그런데 이 상태의 규칙은 빠름 쪽으로만 밀고 있었고 제동 장치가 없었다.
제동을 스스로 걸었다. 「빨라도 정확해야 한다. 100으로 보면 정확도 70, 빠름 30이다.」 비율이 여기서 나왔다.
여기서 방향이 한 번 꺾였다. 70:30을 받아 「둘이 부딪히면 정확도가 이긴다. 느려도 맞는 쪽을 고른다」로 적었는데, 곧바로 정정이 왔다 — 「최대한 정확한 것을 찾으면서 빠른 방법을 생각하면서 일해야 한다」. 적어놓은 문장이 느림의 면죄부였다는 걸 그 자리에서 잡아낸 것이다. 안 B를 버리고 안 C로 간 지점이고, 이 표준에서 제일 중요한 전환이다. 「정확도가 이긴다」와 「정확도를 전제로 고정한다」는 한 글자 차이처럼 보이지만 후자만이 「느려도 된다」를 막는다.
마지막에 뿌리가 들어왔다. 「항상 생각하면서 일해라, 아무 생각 없이 일하지 말자」. 이게 원칙 3이 됐다. 앞의 두 원칙이 고르는 규칙이었다면 이건 실행 중의 규칙이고, 실제로 사고가 났던 지점을 정확히 겨눈다.
적용 범위를 물으면서 구조 문제가 드러났다. 「다른 PC의 세션에도 적용되는가」. 답은 아니었다 — ~/.claude/CLAUDE.md는 로컬 파일이고 동기화 수단이 없었다. 그래서 원본을 my-agent-os에 두고 심링크로 물렸고, 이 저장소에는 공개 표준으로 따로 실었다.
규칙을 넣을 자리를 고르면서 층이 갈렸다. 처음엔 스킬로 만들려 했는데, 스킬 35개가 전부 description에 「~할 때 적용한다」는 호출 조건을 갖고 있었다. 일머리에는 그 조건이 없다. 조건 없는 규칙을 조건부 호출 장치에 넣으면 안 불린다는 게 명백해져서, 「항상 적용」 쪽으로 옮겼다.
정리
- 정확도는 저울에 올리는 것이 아니라 전제다. 그 전제를 고정한 채 가장 빠른 길을 찾는다
- 「느리지만 정확하다」는 정답이 아니다. 정확한 방법이 여럿이면 그중 가장 빠른 것을 끝까지 찾는다
- 빠른 방법이 정확도를 깎으면 그 방법만 버린다. 거기서 멈추지 않고 다시 찾는다
- 더 빠른 길은 알아챈 그 자리에서 말한다. 끝나고 나서도, 시작 전에도 아니다
- 준비 비용이 드는 방법을 후보에서 빼지 않는다. 대신 회수 지점을 숫자로 댄다
- 결과가 예상과 다르면 넘어가지 않는다. 어긋난 값이 대개 진짜 문제를 가리킨다
- 범위를 좁혔으면 좁혔다고 밝힌다. 일부를 전체처럼 말하지 않는다
- 이 표준은 기계가 검사할 수 없다. 그래서 게이트가 아니라 「항상 적용」 문서에 산다
AI 코드 어시스턴트에 바로 적용하기
이 표준은 스킬이 아니라 「항상 적용」 문서에 들어간다. 호출 조건이 없는 규칙이라 조건부로 불리는 스킬에 넣으면 안 불린다.
coding-standards/CLAUDE.md에 아래 절이 들어가고, ruby tools/always-on.rb가 AGENTS.md와 .github/copilot-instructions.md를 같은 내용으로 다시 뽑는다.
## 일머리 — 무엇을 하든 지킨다
- 정확도를 저울에 올리지 않는다. 정확한 방법들 중에서 가장 빠른 것을 고른다. 빠른 방법이 정확도를 떨어뜨리면 그 방법만 버리고, 거기서 멈추지 말고 정확하면서 빠른 다른 길을 다시 찾는다. 「느리지만 정확하다」에 안주하지 않는다.
- 확인할 수 있는 것은 확인하고 말한다. 추측으로 답하지 않고, 검증한 뒤에 됐다고 한다. 안 된 것과 건너뛴 것은 그대로 말한다. 수치와 상태는 최신 기준으로 다시 잰다.
- 속도 때문에 범위를 좁혔으면 좁혔다고 밝힌다. 일부만 본 것을 전체를 본 것처럼 말하지 않는다.
- 더 빠른 길이 보이면 진행 도중에 말한다. 끝나고 나서 말하지 않는다. 도구 설치·스크립트 작성·자동화·병렬 실행·접근 전환이 전부 후보다. 준비 비용이 드는 방법은 비용과 회수 지점을 숫자로 같이 댄다.
- 앞 단계의 결과를 그대로 믿고 넘어가지 않는다. 값이 말이 되는지 보고 다음으로 간다. 결과가 예상과 다르면 왜 다른지를 먼저 본다.
- 방법이 여럿이면 나열하지 말고 하나를 골라 추천한다. 되묻는 것은 답에 따라 결과물이 달라지는 것에 한한다.
자신만의 철학을 만들어가는 중입니다.
댓글남기기