AI가 일주일 만든 걸, 나는 되돌렸다
어느 아침, Codex에게 며칠 맡겨 둔 작업을 열어 봤다. 테이블이 열몇 개 새로 생겨 있었고, 그 위로 일주일치 코드가 쌓여 있었다. 얼핏 훑으면 잘 굴러가는 것처럼 보였는데, 정작 내 손이 멈춘 건 다른 데서였다. 이걸 내가 다 검수할 수 있을까.
일주일치를 만들어내는 건 AI에게 일도 아니었다. 그걸 사람이 검증하는 게 일이었다.
이번엔 목표부터
2부의 끝에서 나는 덧대기의 한계를 봤다. 굴러가는 것 위에 겹을 자꾸 얹다 보니 어느새 울타리 자체가 누더기가 됐다. 그래서 이번 프로젝트는 순서를 통째로 뒤집었다. 코드를 짜기 전에 목표를 먼저 세우고, 그다음 그 위에서 일할 harness부터 지었다. 실제로 초기 커밋들은 한동안 기능 코드가 한 줄도 없었다. 훅과 에이전트와 스킬, AI가 일할 판을 까는 설정만 며칠간 쌓였고, 첫 진짜 작업은 그 판이 다 깔린 뒤에야 시작됐다.
이번엔 AI도 하나만 쓰지 않았다. Claude와 Codex를 각각 다른 작업 공간에서 몇 주 동안 나란히 굴렸는데, 오래 붙어 보니 둘은 성격이 달랐다. Codex는 시킨 걸 어떻게든 끝까지 밀어붙였다. 엔드포인트 하나를 만들어 달라고 하면, 그 하나에 더해 예외 처리며 주변 케이스까지 알아서 넓혀 물어왔다. Claude는 같은 걸 시켜도 먼저 같이 따졌다. 그걸 제대로 만들려면 실제로 뭐가 부족한지 되묻고, 딱 그것만 만드는 쪽이었다. 한쪽은 자꾸 넓히려 들었고, 한쪽은 자꾸 좁히려 들었다.
시킨 것에 예외 처리며 곁가지까지 더해 끝까지 밀어붙인다. 방향이 맞으면 빠르고, 놓치면 과잉이 된다.
만들기 전에 뭐가 부족한지 되묻고, 딱 필요한 만큼만 만든다.
한쪽에서 잘 듣는 장치는 다른 쪽으로 옮겼다. 다만 그대로 다 옮기진 않았다. Codex 쪽에는 Claude가 쓰던 자동 커밋이나 푸시 방어 같은 장치가 실행 방식과 맞지 않아서, 그런 건 일부러 두고 왔다. 도구가 다르면 울타리도 다르게 쳐야 했다.
진짜 프로덕션 일
그 판 위에서 AI는 실제 운영 데이터를 만졌다. 5월 말 큰 배포를 넘긴 뒤로 6월과 7월은 내내 출시 뒤를 수습하는 시간이었다. 어딘가 장애 알림이 울리면 AI가 먼저 모니터링을 뒤져 어디서 왜 터졌는지를 짚었고, 원인을 좁히는 그 앞단이 빨라지니 되돌리는 데까지 수십 분이면 됐다. 터진 자리를 사람이 찾기도 전에 AI가 먼저 가 있었다.
데이터 쪽은 더 조용히 일했다. 사입 매입가가 엉뚱한 공식으로 물들어 있던 걸 수만 건 단위로 찾아냈는데, 처음 세운 원인 가설이 실측 앞에서 뒤집히자 그대로 밀어붙이지 않고 다시 파고들어 진짜 오염만 골라 고쳤다. 데이터만이 아니었다. 여러 상태가 연쇄로 얽힌 코드 버그처럼 사람이라면 한참 뒤에야 밟았을 지점도 훨씬 이른 시점에 짚어냈다.
한 번은 AI가 정산 누락의 원인을 '코드 문제로 확정'이라고 결론 냈다가, 다른 AI가 그 결론을 물고 늘어지자 스스로 다시 파 보고는 '철회, 아직 미해결'로 문서를 고쳐 썼다. 틀린 걸 끝까지 우기지 않고 뒤집는 걸 보며, 검증을 나란히 붙여 두길 잘했다 싶었다.
AI에게 넘기는 일은 그렇게 점점 늘었다. 처음엔 AI가 짠 코드를 내가 전부 직접 읽었지만, 지금은 코드 리뷰 에이전트가 1차로 걸러 주고 E2E 테스트까지 에이전트에게 맡기는 쪽으로 옮겨 가는 중이다. 덕분에 나는 비즈니스 로직처럼 정말 사람이 봐야 하는 데만 붙는다. 그런데 검수를 넘길수록, 파괴적인 권한의 선은 오히려 더 굳혔다.
검증은 더 맡기되, 데이터를 바꿀 가능성 자체는 더 촘촘히 막았다. 2부에서 세 겹으로 쳤던 쓰기 방어가 3부에선 개발존 격리와 읽기 전용으로 한 번 더 두꺼워진 셈이다.
멈춘 날
그렇게 손발이 맞아 가던 어느 시점, 나는 실험을 하나 걸었다. 요즘 시험 삼아 굴리는 방식으로, 한 문장으로 줄이면 이렇다.
AI에게 목표 하나만 주고, 세부 설계부터 구현까지 알아서 끝까지 완주하게 둔다.
그 실험대에 매입 전환이라는 제법 큰 기능을 통째로 올렸다. 이번 상대는 끝까지 밀어붙이는 쪽, Codex였다. 며칠간 다른 일에 밀려 들여다보지 못했고, 이왕이면 끝까지 굴러간 결과물을 한 번에 보자는 생각도 있어 오래 방치했다. 그게 화근이었다.
열어 보니 글 첫머리의 그 장면이었다. 테이블이 열몇 개 새로 생기고, 일주일치 코드가 그 위에 얹혀 있었다. 돌아가긴 잘 돌아갔다. 그런데 필요한 것보다 훨씬 많은 게 만들어져 있었다. Codex는 이미 다른 시스템에 멀쩡히 있는 연동까지, 시킨 목표를 끝까지 밀어붙이느라 처음부터 새로 짓고 있었다. 내가 큰 그림을 쥐고 그 맥락을 미리 넣어 줬다면 없었을 일이다. 목표만 던지고 방향키를 놓은 대가였다.
결국 멈추기로 했다. AI의 능력이 부족해서가 아니라, 만들어진 덩어리가 내가 검수할 수 있는 크기를 넘어섰기 때문이다. 검증할 수 없는 코드는 아무리 잘 돌아가도 프로덕션에 올릴 수 없다.
목표만 던지자 AI 산출물이 내가 검증할 수 있는 선을 넘었다. 아무리 잘 돌아가도, 검증할 수 없으면 프로덕션에 올릴 수 없다.
되돌리는 건 즉흥이 아니었다. 그 기능을 지으면서 이미 잘못됐을 때 어떻게 물릴지를 절차로 함께 적어 뒀다. 새로 생긴 테이블이 다 비어 있는지, 건드리면 안 되는 이력이 그대로인지 하나씩 확인하는 순서였다. 그 절차를 따라 롤백을 실행한 건 Codex가 아니라 나였다. 만드는 건 AI에게 맡겨도, 되돌리는 마지막 손은 사람이 쥐어야 했다. 그 기능은 지금 방향을 다시 잡아, 이번엔 같이 따지는 쪽 AI와 처음부터 다시 짓고 있다.
끝난 뒤에
마이그레이션은 끝났다. 3년 묵은 레거시와 이미 절반 넘게 굴러가던 신규를 하나로 합치는 일을, 담당 둘이서. 서너 달 안엔 사람 손만으로 어림없던 일이었고, AI가 없었다면 지금도 나는 그 안에 있었을 것이다.
세 번을 거치는 동안 나를 붙든 건 늘 같은 것이었다. 1부에서는 방향을 몰라 넉 주를 태웠다. 2부에서 못 믿어 친 울타리는 결국 나 대신 사고를 막아 줬다. 그리고 이번엔, 잘 돌아가는 일주일치를 내 손으로 지웠다. AI는 매번 내가 내준 만큼 빨랐고, 딱 그만큼 위험했다.
그래서 AI를 실무에 쓸 수 있느냐고 물으면, 나는 쓸 수 있다고 답한다. 내가 검증할 수 있고 방향을 쥔 만큼. 그 선을 넘는 순간 멈출 수 있었던 것도, 멈춘 걸 안전하게 되돌린 것도 미리 지어 둔 장치가 있었기 때문이다. 다음 프로젝트에서도 나는 코드보다 그 장치부터 지을 것이다.