계획이 코드보다 먼저다 — 는 걸 나중에 알았다
설계문서 없이 시작해서 전부 뒤엎은 이야기
어느 저녁, AI 채팅창에서 이런 분석이 나왔다.
"분석기가 텍스트를 돌려보내는데, 오케스트레이터는 구조화된 객체를 기대하고 있습니다. 인터페이스가 맞지 않습니다."
이 문장을 읽고 내가 이해한 건 절반 정도였다. "분석기"와 "오케스트레이터"가 내 프로젝트의 모듈 이름이라는 건 알았다. "인터페이스가 안 맞는다"는 것도 대충 감이 왔다. 한쪽이 보내는 형식과 다른 쪽이 받는 형식이 다르다는 뜻일 것이다. 콘센트 구멍이 안 맞는 것처럼.
하지만 그 순간 내가 느낀 건 기술적 이해가 아니라, 조금 더 근본적인 감정이었다. 아, 이건 처음부터 다시 해야 하는구나.
V2라고 부르는 첫 번째 버전이 있었다. Python 파일 18개. 유튜브 채널을 모니터링하고, 새 영상이 올라오면 자막을 가져와서 AI에게 분석을 시키는 시스템이었다. 내 컴퓨터에서 돌렸고, 돌아가긴 했다. "돌아간다"는 사실에 꽤 감격했었다. 코드를 한 줄도 직접 쓰지 않았는데 프로그램이 작동하다니.
문제는 이걸 웹 서비스로 확장하려고 했을 때 터졌다.
내 컴퓨터에서 나 혼자 쓰는 프로그램과, 인터넷에 올려서 여러 사람이 쓰는 서비스는 구조적으로 다르다. 식당으로 비유하면, 집에서 가족 밥 해먹는 것과 식당을 여는 것의 차이다. 레시피(핵심 기능)는 같을 수 있지만, 주방 설비, 위생 관리, 주문 시스템, 계산대 — 이런 것들이 전부 필요하다.
관제탑(내가 AI 채팅창을 부르는 이름이다)에게 V2의 구조를 분석해달라고 했다. 돌아온 진단서에 이슈가 여섯 개 적혀 있었다.
첫 번째, 분석 결과를 저장할 테이블이 데이터베이스에 없었다. 데이터베이스를 엑셀 파일이라고 생각하면, 분석 결과를 적어둘 시트 자체가 빠져있었다는 뜻이다. V2에서는 분석 결과를 그때그때 파일로 저장했기 때문에 이 시트가 필요 없었다. 하지만 웹 서비스에서는 여러 사용자의 결과를 체계적으로 보관해야 하니까, 시트가 있어야 했다.
두 번째, 사용자를 구분할 수 있는 장치가 없었다. V2는 나 혼자 쓰는 프로그램이었으니 "사용자"라는 개념 자체가 필요 없었다. 하지만 웹 서비스가 되면 "이 분석 결과는 A 사용자의 것이고, 저건 B 사용자의 것"이라는 구분이 필수다.
세 번째가 관제탑이 지적한 그 문제였다. 분석기 모듈은 분석을 끝내고 텍스트 한 덩어리를 돌려보냈다. 그런데 그 결과를 받아서 다음 단계로 넘기는 오케스트레이터 모듈은 구조화된 객체 — 제목, 요약, 핵심 포인트, 관련 개념이 각각 분리된 형태 — 를 기대하고 있었다. 편지를 보냈는데 상대방이 택배 상자를 기다리고 있는 셈이었다.
나머지 세 개도 비슷한 맥락이었다. 전부 "나 혼자 쓸 때는 문제없지만 여러 사람이 쓰는 서비스가 되면 터지는" 종류의 이슈들.
솔직히 당황했다. 몇 주 동안 만든 것을 다시 만들어야 한다는 뜻이었으니까. 하지만 동시에 이상한 안도감도 있었다. 문제를 모른 채로 웹 서비스를 올렸다가 나중에 터지는 것보다, 지금 알아서 다행이라는.
결국 V3로 전면 리팩터링을 결정했다. 리팩터링이란, 기능은 그대로 두고 내부 구조를 다시 짜는 것이다. 메뉴는 바꾸지 않지만 주방 동선을 재설계하는 것. 다만 내 경우에는 규모가 커서, 사실상 주방을 뜯어고치는 수준이었다.
이번에는 다르게 했다. 코드를 한 줄도 쓰기 전에 문서를 먼저 만들었다.
아키텍처 문서 — 전체 시스템이 어떻게 생겼는지, 데이터가 어떤 순서로 흘러가는지를 그림으로 그렸다. 빌드 프롬프트 — AI에게 "이번에는 이것만 만들어줘, 이건 절대 건드리지 마"라고 지시하는 문서. 체크리스트 — 각 단계에서 확인해야 할 항목을 나열한 것. 비용 모델 — AI를 돌리는 데 돈이 얼마나 드는지 계산한 것. 다국어 스펙 — 한국어, 일본어, 영어 각각에서 뭐가 달라져야 하는지.
다섯 종류의 문서. 코드보다 문서가 먼저.
체크리스트를 만들면서 "95% 완성"이라는 말이 얼마나 위험한지를 알게 됐다. V2가 정확히 그랬다. 핵심 기능은 작동했다. 95%쯤 완성된 것처럼 보였다. 하지만 나머지 5% — 사용자 구분, 데이터 저장 구조, 모듈 간 인터페이스 — 가 해결되지 않으면 다음 단계(웹 서비스화)로 넘어갈 수가 없었다. 5%가 100%를 가로막고 있었다.
문서를 먼저 만드는 것이 이상하게 들릴 수 있다. 빨리 만들어야 하는데 왜 글을 쓰고 앉아 있느냐고. 하지만 코드를 모르는 사람에게 문서는 특히 중요하다. 내가 직접 코드를 검토할 수 없으니까, AI에게 "이 문서에 적힌 대로 만들어"라고 시키는 것이 유일한 품질 관리 수단이다. 문서가 정확하면 코드도 정확해진다. 문서가 모호하면 AI는 제 나름대로 해석해서 만들고, 그 해석이 내 의도와 다를 확률이 높다.
V3를 다시 시작한 밤. 터미널에 앉아서 코드를 실행하는 대신, 채팅창에서 문서를 다듬고 있었다. 생산적이지 않은 기분이 들었다. 하지만 이후로 V3를 만드는 과정에서, V2에서 겪었던 종류의 문제는 한 번도 일어나지 않았다.
🔧 이 에피소드의 기술 용어 해설
리팩터링 (Refactoring) 기능은 그대로 두고 코드의 내부 구조를 다시 짜는 것. 식당 비유로, 메뉴는 안 바꾸고 주방 동선을 재설계하는 것. V2→V3가 이 작업이었는데, 규모가 커서 사실상 주방을 새로 지은 수준이었다.
데이터베이스 테이블 데이터를 저장하는 엑셀 시트 같은 것. 시트가 없으면 데이터를 저장할 곳이 없다. V2에서는 분석 결과를 저장할 시트 자체가 빠져있었다.
인터페이스 (Interface) 모듈 간에 데이터를 주고받는 규격. 콘센트 구멍 모양이라고 생각하면 된다. 한쪽은 2구인데 다른 쪽이 3구 플러그를 꽂으려고 하면 안 맞는다.
DI — 의존성 주입 (Dependency Injection) 레고 조립 설명서 같은 것. 각 부품(모듈)이 어떤 다른 부품과 결합하는지를 미리 정해두는 설계 패턴. 이게 없으면 부품을 바꿀 때마다 전체를 뜯어야 한다.
오케스트레이터 (Orchestrator) 여러 모듈의 작업 순서를 조율하는 지휘자. "먼저 자막을 가져오고, 그다음 AI에게 분석을 시키고, 결과를 저장해라"를 관리하는 중앙 모듈.