Budding
동작하는 코드를 일부러 버린다 — spike로 먼저 배우는 법
문서가 빈약한 API를 만났다. 바로 잘 만들려는 대신 30분짜리 버릴 코드부터 짰다. 사실 하나를 확인하고, 그 코드를 버리고, 처음부터 다시 만들었다.
- #swe
- #prototyping
- #learning
홈레이더에서 국토부 RTMS API를 처음 붙이던 날. 문서는 빈약했고 응답 형식은 불명확했다. 보통이라면 zod 스키마, 에러 처리, 재시도까지 갖춘 v1.0을 곧장 짜기 시작했을 거다 — 그리고 실제 응답을 받아본 순간, 응답 형식을 잘못 가정한 채 쌓아올린 절반을 다시 만들고 있었을 거다.
대신 나는 30분짜리 코드 한 토막을 짰다. 버릴 작정으로.
// spike.ts — 버릴 코드. 에러 처리 0, 타입 0.
const res = await fetch(RTMS_URL + params);
const text = await res.text();
console.log(text); // 진짜 응답 형식만 본다
얻은 건 사실 하나였다. "응답이 XML이구나. 거래 배열은 <items> 안에 있고, 빈 결과는 <items/> 빈 태그구나." 이 학습을 손에 쥔 채로 spike를 버리고, 본 구현을 zod 스키마부터 처음 다시 만들었다. 가정이 아니라 사실 위에 쌓으니 다시 만들 일이 없었다.
이게 내가 모르는 영역을 만났을 때 일하는 방식이다. 처음 만지는 라이브러리·API·패턴에서 바로 "잘 만들려고" 하면, 잘못된 기반 위에 정교한 구조를 쌓고, 도중에 깨달은 사실을 반영하느라 반쯤 다시 만든다. 시간은 1.5배, 코드는 누더기. 더 큰 문제는 무엇을 모르는지 모른다는 것이다.
해법 — spike (버릴 코드)
30분~2시간 안에 한 가지 질문만 답하는 최소 코드를 만든다.
- "이 API의 응답 형식이 어떻게 생겼나"
- "이 라이브러리의 성능이 우리 케이스에서 받아들일만한가"
- "이 패턴이 우리 코드베이스의 컨벤션과 충돌하지 않는가"
spike의 핵심은 버릴 각오로 만든다는 것. 코드 정리 0, 테스트 0, 추상화 0. 답만 얻는다.
본 구현은 처음부터 다시
spike에서 얻은 학습으로 본 구현을 처음부터 다시 만든다. spike 코드를 정리해서 본 구현으로 쓰지 않는다.
이게 어려운 부분이다. 동작하는 코드를 버리는 게 비효율로 느껴진다. 하지만 다시 쓰는 데 드는 시간은 본 구현 시간의 일부. spike 코드를 정리하는 시간보다 빠르다.
Always v1.0과의 짝
본 구현은 항상 v1.0(완전체)이다. spike는 v0(throwaway)이다.
- v0: 답만 얻는 코드. 버린다.
- v1.0: 완전체 코드. 컨벤션·테스트·문서·에러 처리 다 있다.
"미완성 v0.5"는 만들지 않는다. v0이거나 v1.0이거나.
진전 기반 timebox
spike는 시간이 아니라 진전으로 끝낸다.
- 답이 명확해지면 즉시 종료 (15분일 수도)
- 1시간 했는데 새 정보 0이면 접근 변경 또는 중단
- "같은 에러 3번 반복"이면 다른 각도
시간 박스만 두면 의미 없이 시간 채우게 됨. 진전 박스가 진짜.
함정
- spike를 정성껏 만드는 것: 30분짜리 spike가 4시간이 되면 spike의 의미가 없다.
- spike를 본 구현으로 쓰는 것: 동작은 하지만 기반이 없다. 6개월 후 본인이 모른다.
- spike 결과를 기록 안 함: spike에서 배운 걸 본 구현 시작 전에 1-2줄로 적는다. 안 적으면 다음 spike 때 또 같은 걸 배운다.
- spike 없이 바로 v1.0: "이 정도면 알아"의 함정. 실제로 만져보면 모른다는 게 드러난다.
핵심
모르는 영역에 부딪히면, 나는 추측으로 쌓지 않고 30분짜리 버릴 코드로 사실을 먼저 확인한다. 무엇을 모르는지 알아낸 다음에야 본 구현을 시작한다.
관련
/notes/plan-mode-one-shot — spike로 학습 후 Plan Mode로 본 구현 1-shot /notes/public-api-integration-patterns — 새 API 붙이기의 일반 패턴