AI에 코딩을 맡기기 시작한 뒤로 ② — AI와 '일하는' 시스템, 검증 오너십을 갖추기까지
목차
AI 적응기 (4부작)
- 여러 도구를 써보고, 결국 직접 만들기까지
- AI와 '일하는' 시스템 — 엔지니어링과 검증 오너십 ← 지금 읽는 글
- AI 서버가 죽으면 나도 바보가 된다 — 로컬 LLM과 AI 의존
- AI를 쫓아가며, AI와 함께 — 배움의 방식까지 바뀌다
1편이 '무엇을 쓰는가'에 대한 이야기였다면, 이 글은 '어떻게 일하는가'에 대한 이야기다. 솔직히 말하면, 도구를 몇 번씩 갈아타는 동안 정작 더 크게 바뀐 건 도구가 아니라 내 작업 방식 그 자체였다. AI를 쓰는 것과 AI와 일하는 시스템을 갖는 것은 전혀 다른 일이다. 후자가 되려면, 똑똑한 모델 하나가 아니라 그 모델을 둘러싼 기억·검증·격리의 장치가 필요했다.
가장 먼저 바뀐 건 '기억하는 법'이었다
AI와 일하며 제일 먼저 무너진 환상은 "같이 일하다 보면 지식이 알아서 쌓이겠지" 였다.
3월 초, Andrej Karpathy가 정리한 옵시디언 기반 LLM 위키 방식을 접하고 나도 옵시디언을 깔았다. 그날부터 모든 작업 세션을 옵시디언에 적재하기 시작했다. 구조는 두 계층이다.
- 메모리(요약·포인터만, 짧게) — 컴퓨터로 치면 RAM이다. 빠르게 참조할 핵심만 둔다.
- 옵시디언 위키(상세 원본) — SSD다. 결정의 근거, 디버깅의 전말, 실패의 맥락 같은 걸 길게 남긴다.
처음엔 세션 로그가 옵시디언에 쌓이기만 하면 '위키화'까지 알아서 굴러가는 줄 알았다. 착각이었다. 그게 자동이 아니란 걸 6월에야 깨달았는데, 그때 옵시디언엔 raw 세션 로그 2,500개가 그냥 쌓여만 있었다. 그동안 작업이 마무리될 때마다 위키화를 요청하거나 AI가 먼저 제안한 것들만 일부 추려졌을 뿐, 나머지 대부분은 raw 더미에 묻힌 채였다. 그래서 다음에 같은 문제를 만나면, 나는 처음부터 다시 디버깅하고 있었다.
그래서 6월부터 위키화를 백그라운드 크론으로 돌리기 시작했다. 쌓인 세션을 하나씩 훑어, 기록할 가치가 있는 것만 위키로 추린다. 다만 공짜는 아니다 — 밀린 2,500개를 거슬러 처리하는 만큼, 지금도 토큰이 꾸준히 녹아나가고 있다.
이유는 명확하다. LLM의 컨텍스트는 휘발성이 강하다. 한 세션에서 어렵게 도달한 결론도, 창을 닫으면 증발한다. 모델이 기억해줄 거라 믿는 건 착각이고, 그 휘발성을 외부 기억으로 메우는 게 핵심이었다. 위키가 정확히 어떤 효과를 낼지는 솔직히 아직 다 증명하지 못했다. 다만 잘 정리된 나만의 기록이 AI가 맥락을 찾고 더 나은 판단을 내리는 데 분명 도움이 될 거라는 믿음으로 쌓고 있다. (이 위키는 1편의 prefill 스킬이 참조하는 바로 그 지식 베이스이기도 하다.)
검증을 '믿음'이 아니라 '절차'로
1편에서 말한 '의심의 습관'은 시간이 지나며 몇 가지 절차로 굳었다. AI의 결과물을 믿어서가 아니라, 믿지 않아도 되도록 검증을 워크플로우에 박아둔 것이다.
골든 테스트로 동작 동일성을 보장한다
대규모 리팩터링이나 포팅에서 가장 무서운 건 "겉보기엔 똑같이 도는데 미묘하게 달라진" 코드다. 그래서 손대기 전에, 현재 동작을 입력과 출력의 경계에서만 고정하는 테스트를 깔아둔다. 내부 로직은 일부러 들여다보지 않는다. 레거시 리팩토링에서 흔히 쓰는 골든 테스트(golden master test, Michael Feathers의 characterization test 계열) 방식이다.
원리는 단순하다. '지금 코드가 내놓는 출력' 자체를 정답(golden)으로 박제한다. 그 동작이 옳든 그르든, 일단 현재 동작을 기준으로 못박는다. 내부 구현이 아니라 입출력만 검증하기 때문에, 리팩토링으로 안쪽을 통째로 갈아엎어도 이 테스트는 깨지지 않는다.
AI와 함께 쓸 때 이 그물이 빛난다. 리팩토링 전에 한 번 통과(GREEN)시켜두고, AI가 코드를 옮기거나 다시 쓴 뒤에도 여전히 GREEN이면 입출력이 동일하다 — 즉 동작이 보존됐다는 뜻이다. AI가 그럴듯하게 바꿔놓은 코드가 실은 동작을 바꿔버린 경우를, 정확히 이 단계에서 잡아낸다.
배포 전엔 AI를 '공격자'로 돌린다
운영에 나가기 직전, 나는 AI에게 역할을 바꿔 시킨다. "이 코드를 깨뜨려 봐. 이게 왜 틀렸는지 찾아내." 만들 때의 AI와 부술 때의 AI를 분리하는 것이다. 이 적대적 사전리뷰가 효과적인 이유는, 기본값을 '의심'으로 두기 때문이다. 코드를 옹호하려는 관성 대신 반증하려는 관성으로 읽으면, 테스트는 통과하지만 의미가 뒤집힌 버그 같은 게 드러난다. 실제로 이 단계에서, boolean 하나의 의미가 정반대로 뒤집혀 있던 결함을 잡은 적이 있다. 값은 채워지고 테스트도 초록불인데, 그 값이 뜻하는 바가 거꾸로였던 경우다. 만드는 시선으로는 절대 안 보이던 게, 부수는 시선에선 보였다.
모든 작업은 워크트리로 격리한다
기능 단위 작업은 전부 git worktree로 격리한다. 이유는 둘이다. 하나는 AI가 여러 작업을 병렬로 돌릴 때 서로의 변경을 밟지 않게 하기 위해서고, 다른 하나는 실패한 실험을 통째로 버리기 쉽게 하기 위해서다. AI에게 일을 맡기면 실험의 시도 횟수 자체가 늘어난다. 그중 상당수는 버려질 운명인데, 격리해두지 않으면 버리는 비용이 커진다. 워크트리 생성에 약간의 디스크와 셋업 비용이 들지만, "한 실험이 망해도 메인은 깨끗하다"는 안전감이 그 값을 충분히 한다.
TDD는 'Classicist'로 강제한다
이건 AI의 기본 성향과 싸우는 대목이다. LLM에게 그냥 테스트를 짜라고 하면 Mockist(런던파) 편향이 강하게 나온다. 협력 객체를 죄다 mock으로 발라버리고, "이 메서드가 몇 번 호출됐는지"를 검증하는 테스트를 쓴다. 이런 테스트는 구현 세부에 들러붙어, 리팩터링만 해도 우수수 깨진다. 행위가 아니라 호출 횟수를 검증하니, 정작 동작이 틀려도 통과하는 일까지 생긴다.
LLM이 이렇게 기우는 건 우연이 아니다. 학습 데이터에 그런 테스트가 흔하고, "유닛은 고립시켜 테스트하라"는 휴리스틱을 과하게 적용하기 때문이다. 그래서 나는 Kent Beck식 Classicist(시카고파) TDD — 실패하는 테스트부터 쓰고, mock 대신 실제 협력 객체로 행위와 출력을 검증하는 방식 — 를 에이전트에 강제하기로 했다. ai-testing-rules 같은 공개 규칙 모음과 Kent Beck이 공개한 TDD 철학을 종합해, 우리 팀 규칙으로 다듬어 배포했다. mock은 시스템의 경계(네트워크·DB·파일시스템·시계·난수)에서만 쓰고, 내부 구현은 mock으로 가리지 않는다.
큰 조사는 쪼개서 맡긴다
규모가 큰 조사를 한 세션에 다 시키지 않는다. 독립된 컨텍스트를 가진 서브에이전트 여럿에게 각자 한 조각씩 맡기고, 결과만 모은다. 한 에이전트가 모든 맥락을 끌어안으면 오히려 판단이 흐려진다 — 컨텍스트가 길어질수록 핵심이 희석되기 때문이다. 분해가 정확도를 만든다. (덧붙이면, 이 시리즈의 자료 조사도 서브에이전트 하나에게 따로 맡겨 모은 결과다. 그 메타 이야기는 4편에서.)
생산성 폭증의 역설 — 일이 줄긴커녕 폭증했다
5월 중순이었다. 이 무렵부터 'AI가 우리를 대체하겠구나' 하는 두려움이 옅어지기 시작했다. 이유는 단순했다. AI가 그동안 우리가 못 쳐내던 일들을 대신 해주면서, 개발 속도가 폭발적으로 올랐기 때문이다. 윗선이 바라던 기능들이 무서운 속도로 나갔다.
그런데 두려움이 사라진 자리를 채운 건 여유가 아니라 더 많은 일이었다. 속도가 오르자 할 일이 줄기는커녕 오히려 폭증했다. 마침 이 무렵 본 글 하나가 딱 내 얘기였다.

— Threads의 한 게시물. "생산성이 100배 늘어나니까 해야 될 일도 100배 늘어난다." 이 한 줄이 그즈음 내 상태를 정확히 요약했다.
여러 작업을 동시에 돌리다 보면 정신이 하나도 없었다. 컨텍스트 스위치가 너무 잦아서, 조금 전까지 내가 무슨 작업을 하고 있었는지조차 까먹을 지경이었다. AI가 일을 빨리 끝내줄수록, 동시에 굴릴 수 있는 일의 가짓수가 늘었고, 그만큼 내 머릿속에 동시에 올려둬야 하는 맥락의 수도 늘었다. 생산성의 병목이 'AI의 속도'에서 '내 컨텍스트 스위칭 능력'으로 옮겨간 것이다. 위의 검증 절차와 2계층 기억 장치는, 사실 이 폭증을 견디기 위한 방어이기도 했다. 머리로 다 붙들 수 없으니, 시스템에 맡긴 것이다.
경계가 사라지고, 살아남는 사람의 윤곽이 보였다
정신없는 와중에도 'AI 시대에 어떤 방향을 잡아야 하나'에 대한 감은 어렴풋이 잡혔다. 가장 또렷한 건 경계가 흐려진다는 감각이었다. AI를 쓰다 보니 내가 개발자인지 기획자인지 헷갈릴 지경이 됐다. 물론 기획의 영역, 개발의 영역은 여전히 남아 있다. 다만 그 사이에서 한 사람 한 사람이 하나의 팀처럼 움직이게 된다.
결국 인프라든 코드베이스든, 그 바닥을 깊이 아는 사람이 AI를 더 잘 다뤘다. AI는 너무 뛰어나지만, 한편으론 과하게 엔지니어링하거나(1편의 gstack 이야기) 반대로 구멍이 뚫린 채 동작하는(위 boolean 버그) 문제가 여전히 남아 있다. 이 간극이 미래에 어디까지 메워질지는 모르겠다. 다만 지금으로선 두 부류가 살아남지 않을까 싶다. 하나는 이 간극을 조율할 수 있는 사람, 다른 하나는 토큰을 전략적으로 쓸 수 있는 사람.
모델은 계속 강해질 거고, 아직은 개발자가 인프라 영역을 쥐고 있다. 하지만 최근 작업 기록을 돌아보면, 그 인프라마저 CLI 위에서 AI로 빠르게 대체되고 있었다. 내가 놓치던 부분을 캐치해 고치고, 로그를 훑어 문제를 짚어내는 일이 — 생각보다 훨씬 빠르게 다가오고 있었다.
이렇게 '대체의 공포'는 일단 가라앉았다. 그런데 그 자리에, 전혀 다른 결의 두려움이 새로 자라고 있었다. AI가 나를 대체하는 게 아니라, AI 없이는 내가 아무것도 못 하게 되는 것 아닌가. 다음 편은 바로 그 두려움 — AI 의존과, 그것을 줄여보려 로컬 LLM까지 굴려본 이야기다.