AI가 프로덕션을 부수지 못하게 한 방법
마이그레이션 데이터를 프로덕션으로 옮기던 중이었다. 이미 일부는 들어가 있었지만 아직 서비스에 노출되지 않은, 라이브 직전 상태의 데이터였다. 다음 배치를 더 밀어 넣기 전에 정합성 검사를 한 번 돌렸는데, 그 검사에서 이미 들어가 있던 데이터의 매입가 계산 결과가 어딘가 어긋나 있는 게 걸렸다. 수천 건, 규모로 치면 수십억 원대. 그대로 라이브됐으면 상품 금액이 그만큼 틀어질 오류였다. 사람이 눈으로 훑어서는 그 시점에 절대 못 잡았을 걸, 내가 몇 주에 걸쳐 코드로 쌓아 둔 검증 장치가 잡아냈다.
그 순간에야 이게 진짜 일을 한다는 걸 알았다.
데일 때마다
콜드오픈의 그 장치가 어느 날 갑자기 생긴 건 아니다. 1부에서 4주를 태운 뒤, 나는 AI가 같은 자리에서 반복해 넘어지는 걸 막을 방법부터 찾기 시작했다. 방법이라고 해봐야 거창하지 않았다. 데일 때마다 그 자리에 장치를 하나씩 박는 것이었다. AI에게 작업을 시키면 유독 같은 지점에서 반복해 실패했는데, 한 번 데일 때마다 나는 그 자리에 훅을 하나 박아 다음엔 같은 실수를 못 하게 막았다. 제일 잦은 건 AI가 있지도 않은 필드명이나 상태값을, 심지어 존재하지 않는 API를 실제로 있는 것처럼 자신 있게 갖다 쓰는 부류였다. 하도 반복되길래 확인하지 않은 이름은 아예 쓰지 못한다는 원칙을 규칙 문서에 못 박아 뒀고, 그 뒤로는 적어도 그 실수만은 눈에 띄게 줄었다. 어떤 구간은 매번 긴 문서를 통째로 읽느라 토큰을 많이 먹었는데, 자주 쓰는 절차를 스킬로 굳혀 두니 읽어야 할 양이 줄었다. 여기까지는 그때그때의 응급처치에 가까웠다.
정작 오래 붙든 건 따로 있었다. AI가 코드를 파헤쳐 알아낸 것들을 그때그때 흘려보내지 않고 남기는 일이었다.
덧댄 장치들
먼저 AI에게 무엇을 언제 읽힐지부터 다시 짰다. 처음엔 필요할 법한 문서를 죄다 앞에 쌓아 두고 시작했는데, 그렇게 하니 정작 중요한 게 나머지에 묻혀 버렸다. 그래서 작업의 종류에 따라 그때 꼭 필요한 것만 골라 읽히도록 바꿨다. AI에게 맥락을 주는 일은 그 자체로 작업의 절반이었다.
그다음은 AI가 넘지 못할 선을 코드로 그었다. 프로덕션에 직접 손대거나 되돌릴 수 없게 데이터를 바꾸는 일은 아예 AI 손이 닿지 않도록, 권한으로 한 번 막고 실행 직전에 한 번 더 걸러 내고 규칙 문서로도 못 박아 뒀다. 파괴적인 일은 끝까지 사람이 쥐고, AI에게는 실행 대신 검증용 쿼리를 글로만 내놓게 했다. 믿어서 맡긴 게 아니라, 못 믿어서 울타리를 친 거였다.
정작 제일 애를 먹은 건, AI가 어렵게 알아낸 걸 잊지 않게 만드는 일이었다. 코드를 직접 열어 한참을 헤매야 겨우 만나는 함정이 곳곳에 박혀 있었다.
- 저장할 때는 CSV로 쓰면서 읽을 때는 JSON으로 읽는 필드
- 정상 경로를 슬쩍 비껴가 검증을 건너뛰는 상태값
- 조회 커서가 컬럼을 이름으로 묶다가 엉뚱한 사용자 값이 섞여 드는 지점
이런 걸 한 세션이 어렵게 알아내도, 다음 세션은 그런 게 있었는지도 모른 채 처음부터 같은 코드를 다시 파고들었다. 같은 발견을 매번 새로 사느라 토큰과 시간이 샜다.
그래서 파일을 건드린 세션은 끝나기 전에 자기가 알아낸 것과 아직 확인하지 못한 것을 반드시 기록으로 남기게 만들었다. 안 남기면 세션이 끝나지 않도록 막았다. 처음엔 번거로운 절차였는데, 세션이 몇 번 쌓이고부터 체감이 왔다. 같은 함정을 두 번 설명할 일이 줄었고, 새 세션이 이전 세션이 남긴 메모를 딛고 시작하니 결과가 눈에 띄게 정확해졌다. 그렇게 기록을 강제하자 시스템은 일할수록 똑똑해졌다. 어제 알아낸 게 오늘의 작업을 밀어 주는, 복리였다.
세션이 끝나면 알아낸 게 사라진다. 다음 세션은 매번 바닥에서 같은 것을 다시 알아낸다.
알아낸 걸 남기면 다음 세션이 그 위에서 출발한다. 일할수록 아는 것이 쌓인다.
뒤늦게 단 안전벨트
이 모든 걸 나는 이미 굴러가는 프로젝트 위에서 지었는데, 어디가 부러질지 미리 알고 설계한 것도 아니었다. 사고가 날 때마다 그 자리에 뒤늦게 한 겹씩 덧댔다. 달리는 차에 안전벨트를 나중에 다는 꼴이었다.
장치가 장치를 고치기도 했다. 한동안은 AI가 파일을 저장할 때마다 자동으로 커밋을 남기게 해 뒀는데, 얼마 안 가 커밋 기록이 자잘한 저장 이력으로 뒤덮여 읽을 수 없게 됐다. 그래서 세션이 끝날 때 한 번에 묶어 커밋하도록 바꿨고, 바꾼 이유를 코드 주석에 그대로 적어 뒀다. 다음의 내가 같은 실수를 되풀이하지 않도록.
그래도 통했다. 뒤늦게 덧댄 울타리였든 아니든, 배포 전에 수십억 원대 오류를 잡아낸 건 결국 그 장치였다. 그날 나는 이 장치가 제대로 일을 한다는 걸 비로소 확인했다. 이런 걸 진작 지었어야 했다는 자각은 그다음에 왔다.
다만 덧대기에는 한계가 있었다. 굴러가는 것 위에 겹을 자꾸 얹다 보면 어느 순간 울타리 자체가 누더기가 된다. 그래서 다음 프로젝트에서는 아예 방식을 뒤집기로 했다. 코드보다 울타리를 먼저, 목표를 그 무엇보다 먼저 세워 두고 시작하기로. 그렇게 처음부터 다시 지은 이야기는 3부에 이어 적었다.