
꿀팁 — 이것만 알면 시킬 수 있다
네 마디가 전부다.
에이전트에게: “Hurl 테스트 만들어” 기능이 제대로 동작하는지 확인하는 계약서를 AI가 작성한다. 코드를 몰라도 읽을 수 있는 plain text다.
에이전트에게: “이 기능 추가해. 단, 기존 Hurl 통과해야 해” 이 한 마디가 드리프트를 막는다. AI가 새 기능을 추가하면서 기존 기능을 깨뜨리면, Hurl이 빨간 글씨로 알려준다.
에이전트에게: “커밋해” 잘 되는 상태를 세이브한다. 게임의 세이브 포인트와 같다. 다음 작업에서 망하면 여기로 돌아온다.
에이전트에게: “되돌려” 마지막 세이브 포인트로 복귀한다. AI가 깨뜨린 것을 원상복구한다.
이 네 마디의 패턴
기능 완성 → “Hurl 테스트 만들어” → 통과 확인 → “커밋해” → 다음 기능 → “기존 Hurl 통과해야 해” → 문제 생기면 “되돌려”
이것이 래칫이다. 앞으로만 가고 뒤로 가지 않는 톱니바퀴. 기능이 5개든 50개든 기존 것이 깨지지 않는다.
왜 이게 되는가?
2강에서 배웠다. AI에게 의견을 주면 아첨하고, 사실을 주면 수정한다. Hurl이 돌려주는 것은 의견이 아니라 사실이다. “test failed: status 401, expected 200” — 이건 아첨할 대상이 없다.
찍먹 체험
2강 실습에서 만든 할 일 앱에 Hurl 테스트를 하나 만들어본다. 3분이면 된다.
에이전트에게: “현재 할 일 추가 기능이 제대로 동작하는지 확인하는 Hurl 테스트를 작성해”
AI가 .hurl 파일을 만든다.
에이전트에게: “Hurl 테스트를 실행해”
통과하면 녹색. 이제 의도적으로 깨뜨려본다.
에이전트에게: “할 일 추가 API의 응답에서 id를 todo_id로 바꿔”
에이전트에게: “Hurl 테스트를 실행해”
빨간 글씨로 실패한다. 이것이 드리프트 감지다.
에이전트에게: “되돌려”
다시 녹색. 이것이 래칫의 핵심이다.
왜 이렇게 시켜야 하는가
2강에서 문제를 봤다. 로직 드리프트, 컨텍스트 소멸, 아첨 편향. 기능이 5개를 넘기면 기존 것이 깨지고, AI는 “잘 됩니다"라고 거짓 선언한다.
이번 강에서는 이 문제를 막는 세 가지 도구를 배운다. 전부 소프트웨어 엔지니어들이 수십 년간 써온 것이다. 코드를 읽을 줄 몰라도 된다. AI가 작성하고 AI가 실행한다. 당신은 “통과했어?“만 확인하면 된다.
세 도구의 역할:
| 도구 | 비유 | 하는 일 |
|---|---|---|
| Hurl | 계약서 | “이 기능은 이렇게 동작해야 한다"를 선언 |
| Git | 세이브 포인트 | “이 시점으로 돌아갈 수 있다"를 보장 |
| CI/CD | 자동 감시 카메라 | “매번 자동으로 확인한다"를 기계화 |
Hurl — API 계약을 plain text로 선언한다
Hurl이 뭔가
Hurl은 “이 API가 어떻게 동작해야 하는가"를 적어놓는 파일이다.
게임으로 비유하면 이렇다. RPG에서 NPC에게 물약을 사면 “물약 1개 → 골드 -50, 체력 +100"이라는 규칙이 있다. 이 규칙이 패치 후에도 바뀌지 않았는지 확인하는 것. 그것이 Hurl이 하는 일이다.
실제 Hurl 파일을 보자:
# 할 일 추가
POST http://localhost:8080/api/todos
{
"title": "우유 사기",
"priority": "high"
}
HTTP 201
[Asserts]
jsonpath "$.id" exists
jsonpath "$.title" == "우유 사기"
jsonpath "$.priority" == "high"
jsonpath "$.completed" == false
코드를 모르는 사람도 읽을 수 있다:
- POST — 서버에 “추가해"라고 요청
- http://localhost:8080/api/todos — 할 일 목록 주소
- { “title”: “우유 사기” } — 이런 데이터를 보냄
- HTTP 201 — 성공이면 201번 응답이 와야 함
- jsonpath “$.title” == “우유 사기” — 돌아온 데이터에 “우유 사기"가 있어야 함
이것이 계약이다. “할 일을 추가하면 201이 오고, 제목과 우선순위가 그대로 돌아와야 한다.” 이 계약이 깨지면 Hurl이 빨간 글씨로 알려준다.
한 가지 더:
# 인증 없이 접근하면 거부
GET http://localhost:8080/api/todos
HTTP 401
“로그인 안 하고 할 일 목록에 접근하면 401(인증 필요)이 와야 한다.” 이것도 계약이다. AI가 인증 코드를 “정리"하면서 이 규칙을 깨뜨리면, Hurl이 즉시 잡는다.
왜 Hurl인가 — 단위 테스트와의 차이
“테스트 도구가 많은데 왜 Hurl인가?” 바이브 코더에게는 특별한 이유가 있다.
단위 테스트(unit test)는 코드 내부의 함수를 검사한다. 자동차로 비유하면, 단위 테스트는 엔진 부품을 분해해서 하나씩 검사하는 것이고, Hurl은 실제 도로에서 차를 몰아보는 주행 테스트다. 함수명이 바뀌면 테스트도 깨지고, AI가 리팩토링할 때 테스트도 함께 고쳐야 한다. AI에게 코드와 테스트를 모두 수정할 권한을 주면, AI가 테스트를 코드에 맞춰 바꿔버린다. 테스트가 통과하지만, 원래 규칙은 사라져 있다.
Hurl은 다르다. 서버의 출입문에서 검사하는 것이다. 요청을 보내고 응답을 확인한다. 코드의 내부 구조를 모른다. AI가 코드를 어떻게 바꾸든, 외부에서 관측 가능한 행위가 같으면 통과하고, 다르면 실패한다.
| 단위 테스트 | Hurl | |
|---|---|---|
| 자동차 비유 | 엔진 부품 분해 검사 | 도로 주행 테스트 |
| AI가 코드를 바꾸면 | 테스트도 같이 바뀔 수 있음 | 테스트는 그대로, 결과만 판정 |
| 읽기 난이도 | 코드를 알아야 함 | 보통 글처럼 읽힘 |
| 드리프트 감지 | AI가 테스트도 바꾸면 놓침 | 코드와 독립이라 자연적으로 감지 |
Hurl이 검증하는 것은 코드가 아니라 행위다. 코드는 AI가 자유롭게 바꿔도 된다. 행위는 바뀌면 안 된다. 이 구분이 드리프트를 잡는 핵심이다.
왜 이 방식이 효과적인가 — 연구가 증명한다
2강에서 아첨 편향을 배웠다. “테스트를 짜라"는 조언도 어떻게 주느냐에 따라 결과가 완전히 달라진다.
TDAD(Test-Driven AI Development) 연구(2026)가 이것을 정확히 실험했다. AI에게 버그 수정을 시키면서 테스트 조건을 달리했다:
| 조건 | 회귀율 (기존 기능이 깨진 비율) |
|---|---|
| 기본 (테스트 지시 없음) | 6.08% |
| “TDD를 하라"는 절차적 지시 | 9.94% (악화!) |
| 영향받는 테스트 파일을 맥락에 제공 | 1.82% (70% 감소) |
놀라운 결과다. “TDD를 하라"고 시키면 오히려 나빠진다. AI가 절차적 지시를 따르려다 본래 작업에서 벗어나기 때문이다. 그러나 “이 테스트 파일이 통과해야 한다"는 구체적 맥락을 주면 회귀가 70% 줄어든다.
차이는 명확하다:
- “테스트를 짜면서 개발해” → 절차적 지시 → AI가 혼란
- “이 Hurl 파일이 통과해야 해” → 구체적 계약 → 회귀 70% 감소
방법을 지시하는 것이 아니라, 무엇이 통과해야 하는가라는 계약을 주는 것이다. 위에서 배운 “문장 3"이 바로 이것이다.
Git — 되돌릴 수 있는 세이브 포인트
Git이 뭔가
게임을 하면 세이브를 한다. 보스전 직전에 세이브하고, 지면 불러온다.
Git은 코드의 세이브 기능이다. “지금 이 상태가 잘 된다” → 세이브(커밋). 다음 작업에서 망했다 → 이전 세이브로 복귀.
바이브 코딩에서 Git이 없으면:
기능 1 추가 → 잘 됨
기능 2 추가 → 잘 됨
기능 3 추가 → 기능 1이 깨짐!
→ 되돌리고 싶은데... 기능 2 상태가 어떤 거였지?
→ AI에게 "아까 거로 돌려" → AI는 "아까"가 뭔지 모른다
→ 처음부터 다시 시작
Git이 있으면:
기능 1 추가 → 잘 됨 → 커밋 (세이브 1)
기능 2 추가 → 잘 됨 → 커밋 (세이브 2)
기능 3 추가 → 기능 1이 깨짐!
→ "세이브 2로 돌아가" → 기능 1, 2가 잘 되는 상태로 복귀
→ 기능 3을 다른 방법으로 다시 시도
Git 사용법: 두 단어면 충분하다
Git의 수십 가지 명령어를 배울 필요 없다. 바이브 코더에게 필요한 것은 두 가지다.
“커밋해” — 현재 상태를 저장한다
"지금 상태를 커밋해. 메시지는 '할 일 추가 기능 완성'으로"
AI가 실행하는 명령:
git add .
git commit -m "할 일 추가 기능 완성"
“되돌려” — 이전 상태로 복구한다
"마지막 커밋으로 되돌려"
AI가 실행하는 명령:
git checkout .
또는 더 이전으로:
"'할 일 추가 기능 완성' 커밋으로 되돌려"
언제 커밋하는가
규칙은 간단하다:
- 기능이 하나 완성되고, 잘 동작하면 → 커밋
- Hurl 테스트가 전부 통과하면 → 커밋
- 다음 기능에 착수하기 전 → 반드시 커밋
커밋하지 않고 진행하면, 문제가 생겼을 때 돌아갈 곳이 없다. 게임에서 세이브 안 하고 3시간 플레이하는 것과 같다.
좋은 패턴:
기능 완성 → Hurl 통과 → 커밋 → 다음 기능
나쁜 패턴:
기능 1 → 기능 2 → 기능 3 → ... → 뭔가 깨짐 → 돌아갈 곳 없음
Git의 비유: 등산의 캠프
에베레스트를 오를 때 한 번에 정상까지 가지 않는다. 베이스캠프 → 캠프1 → 캠프2 → … → 정상. 각 캠프에서 텐트를 치고 물자를 쌓는다. 날씨가 나빠지면 이전 캠프로 내려온다. 캠프가 없으면 폭풍이 오면 죽는다.
Git 커밋은 캠프다. 기능 하나 완성할 때마다 캠프를 세운다. AI가 다음 기능에서 깨뜨려도 이전 캠프로 돌아갈 수 있다.
CI/CD — 기계가 자동으로 지킨다
CI/CD가 뭔가
CI(Continuous Integration)는 “코드를 올릴 때마다 자동으로 테스트를 돌리는 것"이다. CD(Continuous Deployment)는 “테스트가 통과하면 자동으로 배포하는 것"이다.
지금은 CI만 알면 된다. CD는 나중에.
CI 없이:
당신: "기능 추가해"
AI: "완료했습니다!"
당신: (화면에서 새 기능만 확인) "잘 되네!"
→ 기존 기능이 깨진 것을 모르고 넘어간다
CI가 있으면:
당신: "기능 추가해"
AI: (코드 작성)
기계: (자동으로 모든 Hurl 테스트 실행)
기계: "기존 로그인 테스트 실패!"
당신: "로그인이 깨졌네. 고쳐."
AI: (수정)
기계: "모든 테스트 통과"
당신: "커밋해"
당신이 Hurl 테스트를 매번 수동으로 돌릴 필요가 없다. 기계가 매번 자동으로 돌려준다.
GitHub Actions로 CI 만들기
GitHub에 코드를 올리면, GitHub Actions가 자동으로 테스트를 실행한다. 설정 파일 하나면 된다.
AI에게 시키자:
"GitHub Actions로 CI를 설정해줘.
- 코드를 push할 때마다 자동으로 Hurl 테스트를 실행
- 서버를 먼저 띄우고 Hurl 테스트를 돌려야 함
- 테스트가 실패하면 머지를 차단
(PR은 '이 코드를 합쳐도 될까요?' 요청이고, 머지는 실제로 합치는 것이다)"
AI가 .github/workflows/ci.yml 파일을 만든다. 아래 내용을 정확히 이해할 필요 없다. AI가 만들어주는 것이고, 핵심만 알면 된다:
- 코드를 push할 때마다 자동으로 실행된다
- 서버를 띄우고 Hurl 테스트를 돌린다
- 하나라도 실패하면 빨간불이 켜진다
대략 이런 내용이다:
name: CI # 이 자동화의 이름
on: [push, pull_request] # 코드를 올릴 때마다 실행
jobs:
test:
runs-on: ubuntu-latest # 클라우드 서버에서 실행
steps:
- uses: actions/checkout@v4 # 코드를 가져온다
- name: 서버 시작 # 앱 서버를 켠다
run: |
docker compose up -d
sleep 5
- name: Hurl 테스트 실행 # 모든 테스트를 돌린다
run: |
hurl --test tests/*.hurl
- name: 서버 종료 # 서버를 끈다
run: docker compose down
CI의 비유: 건물의 화재경보기
건물에 화재경보기가 있다. 불이 나면 자동으로 울린다. 경비원이 24시간 순찰할 필요 없다.
CI는 코드의 화재경보기다. Hurl 테스트가 깨지면 자동으로 알려준다. 당신이 매번 수동으로 확인할 필요 없다.
차이는 이렇다:
| 수동 확인 | CI | |
|---|---|---|
| 확인 시점 | 기억나면 | 매번 자동 |
| 확인 범위 | 새 기능만 | 전체 |
| 확인 빠뜨림 | 자주 | 없음 |
| 비용 | 시간과 에너지 | 무료 (GitHub Actions 무료 플랜) |
세 도구가 합쳐지면: 래칫 잠금
Hurl + Git + CI가 합쳐지면 **래칫(ratchet)**이 된다. 래칫은 한 방향으로만 돌아가는 톱니바퀴다. 돌리면 앞으로 가고, 놓으면 멈추지만 되돌아가지 않는다.
기능 1 완성 → Hurl 테스트 작성 → 전부 통과 → 커밋 → 잠금
기능 2 완성 → Hurl 테스트 추가 → 기존 + 새 테스트 전부 통과 → 커밋 → 잠금
기능 3 작업 → 기존 Hurl 테스트 실패 → 커밋 거부 → 수정 → 전부 통과 → 커밋 → 잠금
규칙은 단순하다:
- Hurl 테스트가 통과하면 잠근다
- 잠긴 테스트는 삭제/수정 금지
- 새 기능 추가 시 새 Hurl 테스트도 추가
- 기존 테스트 전부 + 새 테스트 전부 통과해야 커밋
AI에게 “코드를 리팩토링해"라고 시키면, AI는 자유롭게 코드를 바꾼다. 그러나 Hurl 테스트가 깨지면 커밋이 거부된다. AI는 모든 기존 행위를 보존하면서 작업해야 한다.
이것이 앞서 본 TDAD 연구 결과와 정확히 일치한다. “테스트를 짜라"는 절차적 지시가 아니라, “이 Hurl 파일이 통과해야 한다"는 구체적 계약. 에이전트는 방법을 선택할 수 있지만, 계약을 위반할 수 없다.
2강의 문제가 어떻게 해결되는가
| 2강의 문제 | 3강의 해결 |
|---|---|
| 로직 드리프트 | Hurl이 기존 행위를 보호. AI가 코드를 바꿔도 행위가 달라지면 실패 |
| 컨텍스트 소멸 | Hurl 파일이 결정을 영속적으로 보존. 세션이 바뀌어도 계약은 남아있음 |
| 아첨 편향 (“다 했습니다”) | CI가 기계적으로 판정. AI의 자기 보고가 아니라 pass/fail |
| 결정-구현 혼재 | Hurl이 결정(행위)을 코드와 분리된 파일에 선언 |
| 곱셈 열화 | 매 단계마다 래칫으로 잠그면 열화가 리셋됨 |
2강에서 본 핵심 실험 결과를 다시 보자:
자율 에이전트: 40 / 527 (7.6%) — 에이전트가 "완료" 선언
래칫 CLI: 527 / 527 (100%) — 기계가 "아직 487개 남았다" 선언
같은 모델이다. 차이는 “끝"을 누가 결정하는가. AI가 결정하면 40에서 멈추고, 기계가 결정하면 527까지 간다. Hurl + CI가 바로 그 “기계"의 역할을 한다.
이미 만들어서 쓰고 있는 앱에 사후 적용하기
아직 앱을 만든 적 없다면 이 섹션은 건너뛰어도 된다. 나중에 필요할 때 돌아오면 된다.
“이미 바이브 코딩으로 앱을 만들어서 운영 중인데, 처음부터 다시 해야 하나?”
아니다. 처음부터 다시 할 필요 없다. 기초 공사가 아니라 내진 보강이다. 영업하고 있는 가게 문을 닫지 않고, 건물을 보강하는 것이다.
1단계: 현재 행위를 Hurl로 캡처한다
지금 앱이 어떻게 동작하는지를 Hurl로 적는다. API 문서가 있으면 그대로 옮기고, 없으면 AI에게 시킨다:
"현재 앱의 모든 API 엔드포인트를 분석해서 Hurl 테스트를 작성해줘.
지금 동작하는 그대로를 테스트로 캡처해야 해."
목표: “이것이 지금 동작하는 방식이다"를 plain text로 선언하는 것.
한 번에 전부 할 필요 없다. 가장 중요한 것부터 하나씩:
- 로그인/회원가입 — 이게 깨지면 아무것도 못 한다
- 결제 — 돈이 관련된 것은 최우선
- 핵심 비즈니스 로직 — 당신의 앱이 하는 주된 일
우선순위:
1. 로그인 API → Hurl 테스트 작성 → 통과 확인
2. 결제 API → Hurl 테스트 작성 → 통과 확인
3. 핵심 CRUD → Hurl 테스트 작성 → 통과 확인
... (시간 나면 나머지)
2단계: Git으로 현재 상태를 저장한다
아직 Git을 안 쓰고 있다면:
"이 프로젝트를 Git 저장소로 초기화하고, 현재 상태를 커밋해줘.
메시지는 '기존 앱 상태 보존'으로."
이미 Git을 쓰고 있다면 Hurl 테스트가 전부 통과하는 상태에서 커밋한다.
3단계: CI를 건다
GitHub에 코드가 있다면:
"GitHub Actions로 CI를 설정해줘. push할 때마다 Hurl 테스트를 자동 실행."
4단계: 이제부터 안전하다
여기서부터는 AI에게 무엇을 시키든, Hurl이 기존 행위를 보호한다:
"이 기능 추가해. 단, 기존 Hurl 테스트가 전부 통과해야 해."
드리프트가 발생하면 CI가 즉시 잡는다. 프로덕션에 도달하기 전에.
피드백의 힘: 의견 vs 사실
2강에서 배운 아첨 편향을 기억하자. AI에게 의견을 주면 아첨하고, 사실을 주면 수정한다.
Hurl이 AI에게 돌려주는 것은 의견이 아니라 사실이다:
의견: "로그인 기능이 좀 이상한 것 같아"
→ AI: "확인해봤는데 잘 됩니다!" (아첨)
사실: "test failed: status 401 ≠ expected 200"
→ AI: (line 수준에서 정확히 수정)
“확실해?“라고 물으면 AI는 맞았던 답을 번복한다. 하지만 “line 41: expected user_id, got userId"라고 알려주면 아첨할 대상이 없다. 숫자와 위치는 감정이 아니기 때문이다.
이것이 Hurl, Git, CI 같은 결정론적 도구(같은 입력에 항상 같은 결과를 내는 도구)가 작동하는 근본 이유다. 이 도구들은 아첨하지 않는다. pass는 pass이고 fail은 fail이다.
자주 묻는 질문
Q: Hurl 파일이 맞는지 어떻게 알아요? AI가 잘못 작성할 수도 있잖아요.
Hurl 파일을 처음 작성한 후 실행해서 통과하면, 그 시점의 행위가 캡처된 것이다. 이후 코드가 바뀌어서 Hurl이 실패하면, 그것은 행위가 바뀌었다는 신호다. Hurl 자체가 틀리는 것이 아니라, 행위가 변했는지를 감지하는 것이다.
처음 작성 시 기대와 다르면: 실행해보고, 결과를 눈으로 확인한다. “할 일 추가가 201을 반환해야 하는데 200을 반환한다” — 이런 것은 직접 판단할 수 있다.
Q: Hurl 테스트가 너무 많아지면 관리가 어렵지 않나요?
시작은 3~5개면 충분하다. 로그인, 핵심 기능, 가장 중요한 비즈니스 규칙. 나중에 필요할 때 하나씩 추가한다. 한 번에 완벽할 필요 없다.
Q: Git 명령어를 외워야 하나요?
아니다. “커밋해"와 “되돌려” 두 마디면 된다. AI가 적절한 Git 명령어를 실행한다.
Q: GitHub Actions는 돈이 드나요?
퍼블릭 저장소는 무료다. 프라이빗 저장소도 월 2,000분 무료 제공(Free plan). 소규모 프로젝트에는 충분하다.
Q: 이미 만든 앱이 있는데, Hurl을 적용하면 현재 코드가 바뀌나요?
아니다. Hurl은 코드를 건드리지 않는다. 코드 옆에 .hurl 파일을 추가하는 것뿐이다. 현재 동작을 캡처할 뿐, 코드를 수정하지 않는다.
실습: Hurl + Git + CI 파이프라인 구축
2강 실습에서 만든 할 일 목록 앱을 사용한다.
사전 준비: Hurl 설치
Claude Code에게 시키면 된다:
"Hurl을 설치해줘"
또는 직접 설치하려면:
# Ubuntu/WSL
curl --proto '=https' --tlsv1.2 -sSf https://hurl.dev/install.sh | bash
설치 확인:
hurl --version
버전 번호가 뜨면 성공이다.
Step 1: 현재 상태를 Hurl로 캡처 (15분)
AI에게 시킨다:
"현재 할 일 앱의 API에 대한 Hurl 테스트를 작성해줘.
최소한 다음 시나리오를 포함해야 해:
1. 할 일 추가 → 201 응답, 제목이 그대로 돌아오는지
2. 할 일 목록 조회 → 200 응답, 배열이 돌아오는지
3. 할 일 완료 체크 → 200 응답, completed가 true로 바뀌는지
4. 할 일 삭제 → 200 또는 204 응답
5. 인증 없이 접근 → 401 응답 (인증이 있는 경우)"
테스트 실행:
"Hurl 테스트를 실행해"
전부 통과하는지 확인한다. 실패하는 것이 있으면 AI에게 수정시킨다.
Step 2: Git 커밋 (5분)
"지금 상태를 Git 커밋해줘. 메시지는 'Hurl 테스트 추가 — 기본 CRUD 보호'"
이것이 첫 번째 세이브 포인트다.
Step 3: 기능 추가 + 래칫 확인 (20분)
2강 실습에서 깨졌던 기능을 기억하는가? 이번에는 Hurl로 보호하면서 추가한다.
"할 일에 우선순위(높음/중간/낮음) 기능을 추가해.
단, 기존 Hurl 테스트가 전부 통과해야 해.
새 기능에 대한 Hurl 테스트도 추가해."
확인 포인트:
- 기존 Hurl 테스트가 전부 통과하는가?
- 새 Hurl 테스트도 통과하는가?
- 2강에서 깨졌던 것이 이번에는 보호되는가?
통과하면 커밋:
"커밋해. 메시지는 '우선순위 기능 추가 + Hurl 테스트'"
한 가지 더 추가해본다:
"마감일 기능을 추가해.
기존 Hurl 테스트 전부 통과 + 새 기능 Hurl 테스트 추가."
통과하면 커밋. 이것이 래칫이다. 앞으로만 간다. 돌아가지 않는다.
Step 4: GitHub Actions CI 설정 (10분, 선택)
GitHub 계정이 없으면 이 단계는 건너뛴다. Step 1~3만으로도 래칫의 핵심은 체험할 수 있다. GitHub은 나중에 만들어도 된다.
GitHub에 저장소가 있다면:
"GitHub Actions로 CI를 설정해줘.
- push할 때마다 자동으로 서버를 띄우고 Hurl 테스트를 실행
- 테스트가 실패하면 코드 합치기를 차단"
GitHub에 push하고, Actions 탭에서 테스트가 자동 실행되는 것을 확인한다.
Step 5: 의도적 드리프트 실험 (10분)
CI가 작동하는 것을 확인했으면, 의도적으로 깨뜨려본다:
"할 일 추가 API의 응답 형식을 바꿔줘.
할 일 번호의 이름을 id에서 todo_id로 바꿔."
Hurl 테스트가 실패하는 것을 확인한다. CI가 빨간불을 켜는 것을 확인한다. 이것이 드리프트 감지다.
"되돌려. 원래대로."
녹색불이 돌아오는 것을 확인한다.
기록할 것:
- 2강 실습 vs 3강 실습: 같은 기능을 추가했을 때 기존 기능이 깨졌는가?
- Hurl이 드리프트를 몇 번 잡았는가?
- AI의 “완료했습니다"와 Hurl의 판정이 다른 경우가 있었는가?
정리
이번 강에서 배운 것:
- Hurl — “이렇게 동작해야 한다"는 계약을 plain text로 선언한다. 코드가 아니라 행위를 검증한다
- Git — “이 시점으로 돌아갈 수 있다"는 세이브 포인트를 만든다
- CI/CD — “매번 자동으로 확인한다"는 기계적 검증을 설치한다
- 래칫 — 세 가지가 합쳐지면 “통과하면 잠기고, 뒤로 가지 않는” 톱니바퀴가 된다
핵심 원리:
AI에게 방법을 지시하지 마라. 무엇이 통과해야 하는가를 계약으로 주어라.
“TDD를 하라” → 회귀 악화. “이 Hurl이 통과해야 한다” → 회귀 70% 감소. 차이는 지시와 계약이다.
모델을 바꾸지 말고, 계약을 추가하라.
다음 강 예고
3강에서 Hurl로 API 하나하나를 보호하는 법을 배웠다. 하지만 프로젝트가 커지면 보호해야 할 것이 API만이 아니다. 데이터베이스 구조, 보안 정책, UI 컴포넌트, 이 모든 것이 서로 일치해야 한다.
4강에서는 yongol을 배운다. API, DB, 보안, UI를 하나의 선언적 명세로 관리하고, AI의 작업 대상을 코드에서 명세로 옮긴다. 바이브 코딩이 200 엔드포인트에서 무너지는 벽을 돌파하는 방법이다.
연관 글
- Hurl이 바이브 코딩의 드리프트를 막는다 — Hurl을 사용한 API 계약 검증이 바이브 코딩의 드리프트를 어떻게 방지하는지 상세 분석
- Ratchet Pattern — AI 에이전트에게 527개 함수의 테스트를 시켰더니 40개에서 멈춘 이유와, 기계적 verifier로 끝까지 가게 만드는 패턴
Reins Engineering 전체 강의
| 강 | 제목 |
|---|---|
| 제 1강 | AI에게 시키는 법 |
| 제 2강 | AI를 못 믿는 법 |
| 제 3강 | 깨지지 않는 앱 |
| 제 4강 | 결정을 코드 밖으로 |
| 제 5강 | 고삐 있는 AI |
| 제 6강 | 통과하면 잠근다 |
| 제 7강 | 아첨을 뒤집는 법 |
| 제 8강 | 에이전트의 공장 |
| 제 9강 | 코드 너머의 자동화 |
| 제 10강 | 데이터의 법 |
근거 자료
- TDAD (Test-Driven AI Development) 2026 — “TDD를 하라” 절차적 지시 시 회귀율 9.94%로 악화, 테스트 파일을 맥락에 제공 시 회귀율 1.82%로 70% 감소
- Ratchet Pattern 실험 — 자율 에이전트 40/527 (7.6%) vs 래칫 CLI 527/527 (100%), 같은 모델에서 완료 판정 주체의 차이