AI 코딩, 저는 이렇게 개발하고 있습니다
목차
요즘은 코드를 직접 치는 시간보다 AI에게 구현을 맡기는 시간이 더 깁니다. 그렇다고 “이 기능 만들어 줘” 한마디 던지고 나온 결과를 그대로 쓰지는 않습니다. 설계는 메인 세션이 하고, 구현은 옆 창의 코딩 에이전트에게 넘기고, 검토는 다른 모델에 맡기고, 마지막 확인은 다시 설계한 쪽이 합니다.
이 구조를 직접 자동화하면서 가장 오래 붙잡은 문제는 하나였습니다. AI가 정말 일을 끝냈는지 어떻게 믿을 것인가. 이 글은 그 질문의 답을 찾아간 기록입니다.
구조부터 잡았습니다
자리마다 도구는 이렇게 골랐습니다.
| 자리 | 도구 | 고른 이유 |
|---|---|---|
| 작업 공간 | Ghostty, Herdr | 에이전트가 하는 일을 터미널에서 그대로 보고, 필요한 자동화만 얹을 수 있다 |
| 메인 세션 | Claude Code | 설계와 검토처럼 긴 판단을 한 대화 안에서 이어 가기 편하다 |
| 코더 | Command Code + DeepSeek V4.1 Flash | 싸다 |
Orca나 Paseo 같은 멀티 에이전트 도구도 살펴봤습니다. 완성된 화면은 편하지만 저는 완료 판정과 라우팅 규칙을 계속 고쳐 가며 써야 했습니다. Herdr는 터미널을 창(pane) 단위로 나누고 창 안에서 도는 에이전트의 상태를 읽어 주는 정도의 도구라 그 위에 규칙을 직접 얹기 좋았습니다.
코더를 싼 모델로 둔 이유는 거창하지 않습니다. 돈이 없었습니다. 코딩 에이전트는 같은 코드를 생각보다 여러 번 읽어서 구현과 수정을 비싼 모델에 맡기면 비용이 금방 불어납니다. 처음에는 Codex에 DeepSeek를 붙이려 했습니다. 그런데 지금 Codex는 예전 설정(wire_api = "chat")을 거부하고 Responses API 방식만 받습니다. DeepSeek가 그 경로를 지원하는 것까지는 확인했지만 계정 잔액이 없어 402에서 멈췄습니다. 지금은 크레딧으로 결제한 Command Code에 DeepSeek를 고정해 씁니다.
끝났다는 걸 어떻게 알 것인가
설계한 작업을 코더에게 보내고 끝나면 결과를 받아 오면 됩니다. Herdr가 지원하는 에이전트라면 상태가 바뀔 때까지 기다리는 명령이 있습니다.
herdr agent prompt coder "<지시>" --wait --until doneCommand Code는 지원 목록에 없었습니다. Herdr가 상태를 읽지 못하니 끝났다는 신호를 직접 만들어야 했습니다. 처음 떠올린 방법은 단순했습니다. 끝나면 특정 문자열을 찍게 하고 그 문자열이 화면에 나오길 기다립니다.
herdr pane run "$PANE" cmd -p "... 마지막에 DELEGATE-RESULT 아래에 보고해" ...herdr pane wait-output "$PANE" --match 'DELEGATE-RESULT'돌리자마자 성공했습니다. 너무 빨랐습니다. 코더는 아직 아무것도 하지 않았습니다.
두 번의 거짓 성공
첫 번째: 자기 명령어를 결과로 읽었습니다
감지기가 매칭한 줄은 제가 코더에게 보낸 명령어였습니다. 지시문 안에 DELEGATE-RESULT가 들어 있는데 그 명령이 터미널에 그대로 찍히니 감지기는 그걸 결과로 읽었습니다.
두 번째: 지난 실행의 흔적을 읽었습니다
지시를 파일로 빼서 명령줄에서 표식을 없애고 다시 돌렸습니다. 또 곧바로 성공했습니다. 이번에는 조금 전 실행이 남긴 DELEGATE-RESULT가 스크롤백에 그대로 있었습니다. 터미널 버퍼는 지워지지 않으니 고정된 문자열을 기다리면 과거의 성공을 지금의 성공으로 읽습니다.
두 번 다 시스템 입장에서는 정상이었습니다. 에러도 예외도 없이 다음 단계로 넘어갔습니다. 여기서 위임 자동화를 보는 기준이 바뀌었습니다. 실패는 멈추지만 거짓 성공은 계속 갑니다.
화면 대신 파일을 봅니다
처음에는 표식을 고쳤습니다. 실행할 때마다 번호가 다른 표식을 쓰고 줄바꿈으로 잘리지 않은 원래 줄을 읽게 했습니다. 그걸로 실제 완료 시점에 멈추긴 했습니다.
그런데 코더를 대화형으로 띄워 두고 지시를 타이핑해 넣는 방식으로 바꾸자 한계가 보였습니다. 대화형 화면은 계속 다시 그려집니다. 표식이 나타났다 사라지고 줄이 잘리고 테두리 문자와 섞입니다. 표식을 아무리 다듬어도 근거가 화면이라는 사실은 그대로였습니다.
그래서 완료 신호를 화면 밖으로 옮겼습니다. 코더에게 모든 작업이 끝난 뒤 마지막 순서로 결과 파일을 쓰게 하고 그 파일이 생기는지만 봅니다.
herdr pane send-text "$PANE" "... 모든 작업이 끝나면 마지막으로 .delegate/result-$TOKEN.md 에 결과를 기록해라."for i in $(seq 1 360); do [ -f ".delegate/result-$TOKEN.md" ] && break sleep 5done화면은 계속 바뀌지만 파일은 있거나 없거나 둘 중 하나입니다.
대화형으로 띄우면 코더가 파일을 쓰거나 명령을 돌릴 때마다 승인 창에서 멈춥니다. 그래서 승인을 건너뛰는 모드로 띄웁니다. 대신 작업 브랜치 위에서만 돌리고 바꾼 것은 diff로 전부 확인합니다.
끝난 것과 맞은 것은 따로 봅니다
결과 파일이 생겼다는 건 구현 단계가 끝났다는 신호일 뿐입니다. 코더는 틀린 코드를 쓰고도 결과 파일을 만들 수 있습니다. 심하면 테스트를 고쳐 놓고 통과라고 적을 수도 있습니다. 그래서 완료 판정과 성공 판정을 나눴습니다.
성공 판정에서는 두 가지를 지킵니다.
- 검토는 구현한 모델과 다른 모델이 합니다. 구현하면서 이미 판단을 내린 모델은 자기 결과를 다시 볼 때 같은 실수를 넘기기 쉽습니다. 검토 모델이 사용 한도에 걸려 검토를 못 하면 그 사실을 기록으로 남기고 조용히 통과시키지 않습니다.
- 테스트는 설계한 세션이 다시 돌립니다. 결과 파일에
Tests passed라고 적혀 있어도 믿지 않습니다.
코더를 고르는 기준도 같은 흐름에서 정했습니다. 같은 기능을 고치는 도중에 코더를 바꾸면 새 코더는 관련 코드를 처음부터 다시 읽느라 토큰을 더 씁니다. 그래서 작업 묶음 하나가 끝날 때까지 코더와 세션을 바꾸지 않습니다.
실제 작업에 태워 보니
이 흐름으로 저장소 두 곳의 실제 기능을 돌렸습니다. b-studio에서는 파일 삭제 도구, 계획 승인 게이트, 샌드박스 자원 정리 같은 기능 여덟 개와 화면 정리 다섯 개를 묶음 열세 개로 나눠 전부 커밋했습니다. DBTower에서는 콘솔 화면 재설계를 묶음 여섯 개로 나눠 커밋했습니다. 화면 묶음에는 E2E 테스트 14건과 브라우저 확인을 완료 조건으로 걸었습니다.
설계할 때 걱정한 일들이 실제로 일어났습니다.
한 번에 통과하는 묶음은 드물었습니다. b-studio 기능 묶음 여덟 개 중 다섯 개가 두세 번 만에 통과했습니다. 수정 지시는 같은 창에 새 번호를 붙여 다시 보냈습니다. 끝났는지는 매번 결과 파일로 판정했습니다. DBTower에서는 가끔만 실패하던 E2E 테스트를 코더가 파고들어, 취소 버튼이 값을 되돌리는 일을 서버 응답에 묶어 둔 화면 결함을 찾아냈습니다.
검토기도 틀렸습니다. b-studio에서 검토기가 낸 지적 중 두 건은 실제 환경과 코드로 확인해 보니 사실이 아니어서 반영하지 않았습니다. 검토 결과도 그대로 따르지 않고 한 번 더 확인을 거칩니다.
검토기가 놓친 버그를 마지막 확인이 잡았습니다. 바뀐 파일만 검증하는 기능을 만들 때, 새로 만든 폴더가 파일 하나처럼 검증 단계로 넘어가 EISDIR로 죽었고 폴더 안의 실제 파일은 하나도 검증되지 않았습니다. git status --porcelain이 추적하지 않는 폴더를 한 줄로 접어 보여 주기 때문이었습니다. 이 버그는 설계한 세션이 Docker에서 직접 돌려 보고서야 드러났습니다.
코더 한도가 바닥나 메인 세션이 대신 구현한 묶음도 있었습니다. 그때는 먼저 승인을 받고 그 사실을 기록에 남겼습니다. 같은 세션을 유지하는 게 비용을 실제로 얼마나 아껴 주는지는 아직 재지 못했습니다. 외부 사이트를 브라우저로 여는 일도 제가 확인한 시점까지는 네트워크 환경 때문에 막혀 있었습니다.
마치며
처음에는 좋은 모델을 쓰면 AI 코딩이 잘될 줄 알았습니다. 직접 자동화해 보니 모델보다 먼저 정해야 할 규칙이 있었습니다. 누가 설계하고 누가 구현할지, 무엇을 완료로 보고 누가 그걸 검증할지, 실패하면 어디까지 되돌릴지 같은 것들입니다.
완료 문자열 하나를 믿었다가 코더가 아무것도 하지 않았는데도 두 번이나 성공으로 판정됐습니다. 그 뒤로는 화면 대신 파일을 보고, 파일도 그대로 믿지 않고 다른 모델에게 보이고, 마지막에는 테스트를 다시 돌립니다. 자동화를 더 늘려도 이 기준 하나는 지키려고 합니다.
코딩은 맡겨도, 잘 끝났다는 판단까지 맡기지는 않습니다.
댓글
댓글 수정/삭제는 GitHub Discussions에서 가능합니다.