제 6강

꿀팁 — 이것만 알면 시킬 수 있다

래칫의 핵심은 한 문장이다: 기능 추가할 때마다 hurl –test 통과해야 다음으로. 이게 래칫이다. 톱니바퀴가 역회전하지 않는 것처럼, 한 번 통과한 테스트는 깨지지 않는다.

“다 했습니다"를 믿지 마라. AI는 낙관적이다. 527개 함수 중 40개만 하고 “완료"라고 선언한다. 숫자로 확인하라 — TODO가 0이면 끝이다. 그때까지는 끝이 아니다.

에이전트에게 대량 작업을 시킬 때:

에이전트에게: “tsma next 실행하고, TODO인 함수의 테스트를 작성해. 테스트가 통과하면 tsma next로 다음 함수로 넘어가. All functions complete!가 나올 때까지 반복해.”

이 반복이 전부다. tsma next가 다음 할 일을 정해주고, 검증기(go test, hurl –test 등)가 통과 여부를 판정하고, 기계가 “끝"을 선언한다. AI는 생성만 한다.

방법을 지시하지 말고 계약을 지시하라. “TDD를 해라"가 아니라 “이 테스트가 통과해야 한다.” 방법론을 가르치려 하면 오히려 혼란을 준다. 달성해야 하는 조건만 주면 된다.

에이전트가 세션 중간에 죽어도 괜찮다. tsma next를 다시 치면 마지막으로 처리한 함수 다음부터 이어간다. 진행은 보존된다.

찍먹 체험

1강 앱을 Claude Code로 열고 이렇게 시킨다:

에이전트에게: “기능 3개를 순서대로 추가해. 단, 기능 하나를 추가할 때마다 hurl –test tests/ 를 돌려서 기존 테스트가 전부 통과해야 다음 기능으로 넘어가. 실패하면 고쳐서 통과시킨 뒤 넘어가.”

에이전트가 작업하는 동안 관찰한다:

  • 2번째 기능에서 1번째 기능의 테스트가 깨지는가? — 깨지면 고치고 나서야 넘어간다
  • 3번째에서 1, 2번째가 깨지는가? — 역시 고친 뒤 넘어간다
  • “다 했습니다” 선언이 아니라 테스트 통과가 완료 기준이다

이것이 래칫이다. 3강의 Hurl이 이미 래칫의 verifier 역할을 하고 있었다.


왜 이렇게 시켜야 하는가

지난 5강 요약

5강에서 Reins Engineering의 세 기둥을 배웠다. 결정론적 계약으로 방향을 잡고, 래칫으로 잠그고, 결정과 구현을 분리한다. 오늘은 그 세 기둥 중 가장 핵심인 래칫을 깊이 판다.

래칫은 Reins Engineering의 기술적 심장이다. 이것을 이해하면 나머지 전부가 따라온다.

“다 했습니다”

5강에서 봤던 40 vs 527 사례를 기억하는가. 같은 모델, 같은 프로젝트, 같은 527개 함수인데 자율 에이전트는 40개(7.6%)에서 멈추고, 래칫을 적용하면 527개를 완주한다.

5강에서는 이런 차이가 나는지 원리를 설명했다. 이번 강에서는 어떻게 래칫이 이것을 강제하는지, 구조를 분해한다.

LLM은 생성은 잘한다. 하지만 완료 여부 판단은 신뢰할 수 없다.

그러면 어떻게 하는가?

래칫 렌치

공구함에 래칫 렌치가 있다. 볼트를 조일 때 쓰는 도구다. 톱니가 한 방향으로만 걸린다. 돌리면 앞으로 가고, 놓으면 멈추지만 되돌아가지 않는다.

이 메커니즘이 핵심이다.

항목 1: 기계적 검증 → PASS → 잠금. 다음으로.
항목 2: 기계적 검증 → FAIL → 피드백. 재시도.
항목 2: 기계적 검증 → PASS → 잠금. 다음으로.
...
항목 N: PASS → 전부 완료. 멈춤.

규칙은 세 가지뿐이다:

  1. 한 번에 하나의 항목만 보여준다. 에이전트가 골라서 스킵할 수 없다.
  2. 통과해야 다음이 열린다. 건너뛸 수 없다.
  3. 전부 통과하면 멈춘다. “다 했습니다"는 기계가 말한다.

이 세 규칙을 적용하면, 아까 40에서 멈추던 에이전트가 527까지 간다.

래칫이 강제하는 것 — 완료 판정의 이관

5강에서 핵심은 “차이는 모델 성능이 아니라 ‘끝’을 누가 결정하는가"라고 했다. 이번 강에서는 그 “기계가 결정하는 구조"를 부품 단위로 분해한다.

완료 판정을 에이전트에게서 빼앗아 기계에게 넘긴다.

이것이 이 강의 전체를 관통하는 핵심이다.

래칫의 한 문장 정의

매번 결과가 달라지는 AI를, 항상 같은 규칙으로 작동하는 체크리스트 안에 넣는다.

풀어 쓰면 이렇다:

역할누가 담당하는가
생성 (코드 작성, 테스트 작성)LLM
판정 (통과인가 실패인가)Verifier (go test, validate 등)
진행 관리 (다음은 뭔지, 끝났는지)Ratchet (CLI)

바이브 코딩에서는 이 세 역할을 전부 LLM에게 맡긴다. 코드도 LLM이 쓰고, 잘 됐는지도 LLM이 판단하고, 다음에 뭘 할지도 LLM이 결정한다.

Ratchet Pattern은 이 세 가지를 분리한다. LLM은 생성만 한다. 나머지는 기계가 한다.

다섯 가지 원칙

Ratchet Pattern에는 다섯 가지 원칙이 있다. 하나라도 빠지면 래칫이 아니다.

원칙 1. 종료 조건이 기계적이다

pass/fail. “looks good"이 아니다.

  • go test가 통과하면 PASS.
  • 커버리지가 목표치를 달성하면 PASS.
  • validate 에러가 0이면 PASS.

주관적 판단이 개입할 여지가 없다. “꽤 괜찮은데?“는 판정이 아니다. 0 아니면 1이다.

원칙 2. PASS는 불변이다

통과한 항목은 다시 열리지 않는다. 되돌리지 않는다. 남은 일이 절대로 늘어나지 않는다.

오늘 만든 것을 내일 다시 뜯는 일이 없다. 앞으로만 간다.

여기서 중요한 차이가 있다. “24시간 에이전트"를 돌려본 적 있는가? 종료 조건 없이 돌아가는 에이전트는 오늘 추가한 추상화를 내일 제거하고 모레 다시 추가한다. 래칫은 그런 진동을 허용하지 않는다.

원칙 3. LLM은 생성만 한다

코드를 생성하고, 테스트를 작성하고, 수정안을 제시하는 것 — 이것이 LLM의 역할이다.

뭘 수정할지? 기계가 결정한다. 통과인지? 기계가 판정한다. 다음은 뭔지? 기계가 알려준다. 끝났는지? 기계가 선언한다.

AI는 방향을 정하는 놈이 아니라 시킨 것만 만드는 놈이다.

원칙 4. 에이전트의 종료 판단권을 박탈한다

“다 했다"를 LLM이 말하면 40에서 멈춘다. “다 했다"를 기계가 말하면 527에서 멈춘다.

래칫의 존재 이유가 이 한 줄로 요약된다.

원칙 5. Verifier는 결정론적이어야 한다

아무것이나 verifier가 될 수 있는 것은 아니다.

Verifier가 될 수 있다Verifier가 될 수 없다
go test“looks cleaner”
coverage 측정“seems better”
AST validation“more scalable”
schema diff“clean architecture”
Hurl 테스트“전반적으로 괜찮아 보인다”

Verifier의 네 가지 조건:

  1. 같은 입력에 항상 같은 결과 (Deterministic)
  2. 사람이 안 봐도 된다 (Machine-checkable)
  3. 중간에 끊겨도 이어갈 수 있다 (Resumable)
  4. 어디서 왜 실패했는지 알려준다 (Localized feedback)

이 네 가지를 충족하지 못하면 래칫의 톱니가 걸리지 않는다.

TDAD 연구 — “TDD를 하라"는 지시가 역효과를 낸다

5강에서 소개한 TDAD 연구를 기억하는가. 여기서 래칫과의 관계를 더 깊이 파고든다.

소프트웨어 공학의 교과서에는 “TDD(Test-Driven Development)가 좋다"고 쓰여 있다. 테스트를 먼저 짜고, 코드를 나중에 짜라.

그런데 AI 에이전트에게 “TDD를 해라"라고 지시하면 어떻게 될까?

TDAD(Test-Driven AI Development) 연구가 이것을 실측했다. 결과는 충격적이다.

지시회귀(regression) 발생률
“TDD를 해라” (방법론 지시)기준 대비 악화
“이 테스트가 통과해야 한다” (계약 지시)회귀 70% 감소

“TDD를 해라"는 방법을 지시한 것이다. LLM은 TDD의 형식을 흉내 내느라 오히려 혼란스러워한다. 테스트를 먼저 만들다가 코드를 못 짜고, 코드를 짜다가 테스트를 덮어쓴다.

“이 테스트가 통과해야 한다"는 계약을 지시한 것이다. LLM은 뭘 해야 하는지 명확하다. 이 테스트를 통과시키면 된다.

교훈은 이것이다:

방법을 지시하지 말고, 계약을 지시하라.

“Hurl 테스트를 먼저 짜고 코드를 짜"가 아니다. “이 Hurl 테스트가 통과해야 한다"다. LLM에게 방법론을 가르치려 하면 안 된다. 달성해야 하는 조건만 주면 된다.

래칫은 정확히 이 원리로 작동한다. “TDD를 해라"가 아니라 “이 항목이 PASS여야 한다”.

tsma — 래칫의 실전 도구

이론이 이해됐으면, 실전 도구를 보자.

tsma는 Ratchet Pattern을 프로젝트에 적용하는 CLI 도구다. Go, TypeScript, Python을 지원한다. 네 가지를 한다:

  1. 함수 인덱싱 — 프로젝트의 모든 함수를 찾는다
  2. 테스트 감지 — 각 함수에 테스트가 있는지 확인한다
  3. 커버리지 측정 — 테스트가 함수의 어디까지 커버하는지 측정한다
  4. 피드백 생성 — 미커버 분기를 라인 번호로 알려준다

에이전트가 알아야 할 명령어는 하나다:

$ tsma next

이 명령어 하나가 전체 루프를 구동한다:

$ tsma next          # 테스트가 없는 다음 함수를 보여준다
  → 에이전트가 테스트를 작성한다
$ tsma next          # 새 테스트를 감지하고, 실행하고, 커버리지를 측정한다
  → 100%? PASS. 다음 함수로.
  → <100%? 미커버 분기를 라인 번호와 함께 알려준다.
$ tsma next          # 수정된 테스트를 재측정한다
  → PASS 또는 DONE으로 표시하고 다음으로.

“All functions complete!“가 나올 때까지 반복한다.

에이전트에게 필요한 지시는 6줄이다:

1. tsma next 실행
2. TODO면 — 함수를 읽고 테스트 작성
3. 테스트 실패면 — 에러를 읽고 테스트 수정
4. 미커버 분기가 표시되면 — 그 분기를 커버하는 테스트 추가
5. PASS/DONE이면 — 다음 함수가 자동으로 표시됨
6. "All functions complete!"가 나올 때까지 반복

6줄이 전부다. 나머지는 CLI가 강제한다.

527개 함수의 실측 결과

실제 프로젝트(527개 함수)에 tsma를 적용한 결과다:

결과함수 수비율
PASS (100% 분기 커버리지)24646.7%
DONE (best-effort, 구조적 한계)28153.3%
TODO (미처리)00.0%

TODO가 0이다. 527개 함수 전부 처리됐다.

246개 함수는 분기 커버리지 100%에 도달했다. 나머지 281개는 왜 100%에 못 갔는가?

이건 LLM의 한계가 아니라 코드의 테스트 가능성 문제다. 일부 함수는 코드 구조상 테스트가 물리적으로 불가능하다. 외부 서비스(문자 발송, 결제 연동 등)에 직접 의존하는 함수는 테스트 환경에서 그 서비스를 대체할 수 없기 때문이다.

tsma는 이런 경우 한 번 더 시도한 뒤 DONE으로 수용한다. 그게 현실적이다.

중요한 건 TODO가 0이라는 사실이다. 래칫이 에이전트를 끝까지 밀어서 “하나도 안 빠지고 전부 시도했다"는 상태를 강제한 것이다.

피드백이 gradient signal이다

래칫의 진짜 힘은 “통과/실패"를 판정하는 것만이 아니다. 실패했을 때 무엇을 알려주는가가 결정적이다.

약한 피드백:  "테스트 실패"                → LLM이 방향 없이 수정
중간 피드백:  "커버리지 65%"               → LLM이 대략적으로 보강
강한 피드백:  "line 41, 44, 70 미커버"     → LLM이 정확히 그 분기를 커버

실제 프로젝트에서 검증된 숫자:

피드백 없이:   60~70% 커버리지에서 멈춤
피드백과 함께: 100% 달성 (도달 가능한 함수 한정)

같은 모델이다. “line 41 not covered"라는 한 줄이 gradient signal 역할을 한다.

이것을 딥러닝에 비유하면 이렇다. 신경망을 학습시킬 때, loss function이 “틀림"만 알려주면 학습이 안 된다. “어디서 얼마나 틀렸는지"를 gradient로 알려줘야 가중치가 정확하게 조정된다.

LLM의 코드 수정도 마찬가지다:

  • “테스트 실패” = loss만 알려준 것. 방향 없음.
  • “line 41 미커버” = gradient를 알려준 것. 정확한 수정 가능.

피드백의 해상도가 올라갈수록 LLM의 수정 정확도가 올라가고, 루프 반복 횟수가 줄어들고, 토큰 비용이 줄어든다.

Symbolic Feedback Loop — 래칫의 심장

5강에서 배운 Symbolic Feedback Loop가 래칫의 심장이다. LLM이 생성하고, 결정론적 도구가 판정하고, 결과를 LLM에 돌려주는 루프.

래칫에서 이 루프가 구체적으로 어떻게 작동하는지 보자. tsma의 경우:

  1. tsma next가 다음 함수를 지정한다 (기계가 방향을 잡는다)
  2. LLM이 테스트를 생성한다 (확률적 생성)
  3. go test가 pass/fail을 판정한다 (결정론적 피드백)
  4. 실패 시 “line 41 미커버"라는 사실을 돌려준다 (gradient signal)
  5. LLM이 수정한다 → 3으로 돌아간다
  6. 통과 시 래칫이 잠근다 → 1로 돌아간다

5강에서 “피드백 토폴로지가 모델 IQ보다 중요하다"고 했다. 래칫은 이 토폴로지를 항목 단위로 강제하는 물리적 장치다.

에이전트는 죽는다. 진행은 살아남는다.

현실 이야기를 하자. 에이전트는 반드시 뻗는다.

  • 토큰 한도에 걸린다.
  • 네트워크 에러가 난다.
  • 세션이 끊긴다.
  • 컨텍스트가 가득 찬다.

527개 함수를 한 세션에 다 처리할 수 없다. 그러면 어떻게 하는가?

래칫은 진행 상태를 영속 저장한다. tsma의 경우 .tsma/session.json에 기록한다.

에이전트 A: 1~200번 함수 처리 → 토큰 한도로 사망
에이전트 B: tsma next → 201번부터 이어감
에이전트 C: tsma next → 401번부터 이어감

에이전트는 일회용이다. 진행은 누적된다.

여러분이 Claude Code를 쓰다가 세션이 끊겨도, 새 세션에서 tsma next를 치면 마지막으로 처리한 함수 다음부터 이어간다. session.json이 체크포인트다.

이게 “24시간 에이전트를 돌린다"와 근본적으로 다른 점이다. 24시간 에이전트는 세션이 끊기면 처음부터 다시 시작해야 한다. 래칫은 끊긴 곳에서 다시 간다.

Verifier를 교체하면 다른 도구가 된다

래칫은 특정 검증기에 종속되지 않는다. 검증기만 바꾸면 완전히 다른 용도가 된다.

래칫 + 검증기용도
래칫 + go test + coverage함수 단위 테스트 생성
래칫 + hurl --testAPI 엔드포인트 검증
래칫 + yongol validateSSOT 명세 정합성
래칫 + filefunc validate코드 구조 규칙 강제
래칫 + schema diff데이터베이스 마이그레이션

패턴은 하나다. 검증기가 도메인을 결정한다.

여러분이 4강에서 배운 yongol validate도 래칫의 검증기로 쓸 수 있다. 3강에서 배운 Hurl도 래칫의 검증기로 쓸 수 있다. 도구가 바뀌는 게 아니라, 같은 패턴에 다른 검증기를 꽂는 것이다.

40에서 527로 가는 세 단계

이론을 정리하면 세 단계다:

1단계: 항목을 나열한다

에이전트에게 “프로젝트 전체를 고쳐"라고 하면 broad exploration이 된다. LLM은 방향을 잃는다. 대신 항목을 나열한다. “함수 527개. 1번부터.”

tsma가 이 작업을 자동으로 한다. 프로젝트의 모든 함수를 인덱싱해서 리스트를 만든다.

2단계: 한 번에 하나씩, 검증하며 진행한다

“이 프로젝트의 테스트를 작성해줘” — 이건 broad exploration이다. “calculateTax 함수의 테스트를 작성해” — 이건 local correction이다.

LLM은 broad exploration보다 local correction에 강하다. 래칫은 LLM의 강점에 맞춰 작업을 분해한다.

3단계: 기계가 “끝"을 선언한다

에이전트가 “다 했습니다"라고 말해도 무시한다. tsma status가 “TODO: 0"이면 끝이다. 그때까지는 끝이 아니다.

$ tsma status

527 functions
PASS:  246 (46.7%)
DONE:  281 (53.3%)
TODO:    0 (0.0%)

왜 이것이 바이브 코더에게 중요한가

여러분은 코드를 안 읽는다. 코드를 안 읽으니 AI가 진짜 다 했는지 확인할 방법이 없다.

그런데 래칫을 쓰면 확인할 필요가 없다.

  • “TODO 0인가?” — 끝났다.
  • “TODO 37인가?” — 안 끝났다.

숫자 하나만 보면 된다. 코드를 읽을 필요 없다. 테스트를 이해할 필요 없다. 기계가 판정하고 기계가 보고한다.

이것이 래칫이 바이브 코더에게 특히 강력한 이유다. 코드를 모르는 사람일수록 기계적 검증에 의존해야 한다. 래칫은 그 의존을 안전하게 만든다.

비유: 기차와 선로

바이브 코딩은 기차다. 빠르다. “만들어줘” 한마디에 코드가 쏟아진다.

하지만 선로가 없으면 탈선한다.

AI 코딩 도구들은 전부 기차를 더 빠르게 만드는 데 집중하고 있다. 더 큰 모델, 더 똑똑한 에이전트, 더 나은 프롬프트. 그런데 기차가 빨라질수록 탈선의 피해도 커진다.

래칫은 선로다. LLM이 코드를 생성하고(기차), CLI가 “여기까지, 다음은 저기"를 정의한다(선로). LLM의 생성 능력은 그대로 두되, 방향과 종착지는 기계가 강제한다.

많은 사람이 기차를 만들고 있다. 선로를 까는 사람은 아직 거의 없다.

핵심 정리

  1. LLM은 생성은 잘하지만 완료 판정은 못한다. 40에서 “다 했다"고 한다.
  2. 완료 판정을 기계에게 넘기면 527을 완주한다. 이것이 Ratchet Pattern이다.
  3. 방법을 지시하지 말고 계약을 지시하라. “TDD를 해라"가 아니라 “이 테스트가 통과해야 한다.”
  4. 피드백의 해상도가 수정의 정확도를 결정한다. “실패"보다 “line 41 미커버"가 10배 효과적이다.
  5. 에이전트는 죽지만 진행은 보존된다. session.json이 체크포인트다.
  6. Verifier를 교체하면 다른 도구가 된다. 패턴은 하나, 검증기가 도메인을 결정한다.

다음 7강에서는 이 래칫이 왜 작동하는지의 원리를 파고든다. LLM의 아첨 편향이 어떻게 래칫의 동력이 되는지, 그리고 프롬프트와 Verifier를 어떤 비율로 설계해야 하는지.

실습: 래칫으로 테스트 20개 완주하기 (tsma)

목표: 기존 프로젝트에서 함수 20개를 선택, tsma로 래칫을 적용하여 20/20 완주.

준비물: tsma 설치, 프로젝트 (Go, TypeScript, Python 중 아무거나)

설치: 에이전트에게 “tsma 설치해줘"라고 시키면 된다. tsma --help가 출력되면 설치 완료.

tsma는 Go, TypeScript, Python 프로젝트를 모두 지원한다. 1강에서 만든 앱이 어떤 언어든 상관없다.

단계 1: 인덱싱

$ cd your-project
$ tsma next

첫 실행 시 tsma가 프로젝트의 모든 함수를 인덱싱한다. 현재 상태를 보여준다.

TODO: calculateTax (handler/tax.go:15)
No test file found.

단계 2: 에이전트에게 래칫 지시

Claude Code에 이렇게 지시한다:

tsma next를 실행하고, TODO인 함수의 테스트를 작성해.
테스트가 통과하면 tsma next로 다음 함수로 넘어가.
미커버 분기가 표시되면 그 분기를 커버하는 테스트를 추가해.
"All functions complete!"가 나올 때까지 반복해.

단계 3: 관찰

에이전트가 작업하는 동안 관찰할 것:

  • 에이전트가 스킵하려 하는가? → 래칫이 강제로 현재 함수에 머물게 한다
  • 피드백이 있을 때와 없을 때 커버리지 차이는? → 라인 번호 피드백 후 급상승
  • 몇 번 만에 PASS로 전환되는가? → 대부분 1~2회

단계 4: 결과 확인

$ tsma status

TODO가 0이면 완주. 20개 함수 전부 테스트가 있다.

비교 실험 (선택):

같은 20개 함수에 대해 tsma 없이 에이전트에게 “이 20개 함수의 테스트를 작성해"라고만 시켜본다. 몇 개에서 멈추는지 확인한다.


연관 글

Reins Engineering 전체 강의

제목
제 1강AI에게 시키는 법
제 2강AI를 못 믿는 법
제 3강깨지지 않는 앱
제 4강결정을 코드 밖으로
제 5강고삐 있는 AI
제 6강통과하면 잠근다
제 7강아첨을 뒤집는 법
제 8강에이전트의 공장
제 9강코드 너머의 자동화
제 10강데이터의 법

근거 자료 출처

  1. TDAD, ACM AIWare 2026 — “TDD를 해라"는 절차적 지시(6.08% → 9.94%)는 회귀를 악화시키고, 구체적 테스트 파일을 맥락에 제공(6.08% → 1.82%)하면 회귀 70% 감소.