루프를 돌리기 전에 설계합니다: 토큰을 태우지 않는 에이전트 루프 엔지니어링
개요
최근 개발자 커뮤니티에서 “루프를 돌리기 전에 루프를 설계하라”는 조언이 빠르게 퍼지고 있습니다. 핵심은 단순합니다. 잘못 설계된 루프는 토큰을 태우고 쓸 만하지 않은 결과물을 안긴다는 것입니다. 프롬프트를 한 번 잘 쓰는 일과, 그 프롬프트를 반복해서 에이전트에게 먹이는 시스템을 설계하는 일은 완전히 다른 작업입니다.
이 변화를 한 문장으로 요약하면 이렇습니다. 예전에는 사람이 모델에게 프롬프트를 줬다면, 이제는 사람이 루프를 설계하고 그 루프가 모델에게 프롬프트를 줍니다. 일을 찾아내고, 에이전트에게 나눠주고, 결과를 검증하고, 무엇이 끝났는지 기록하고, 다음에 할 일을 정하는 작은 시스템을 먼저 만든 다음, 그 시스템이 사람 대신 에이전트를 깨우게 하는 것입니다.
ThakiCloud는 쿠버네티스 기반 AI/ML SaaS 플랫폼을 운영하면서 내부적으로 수십 개의 무인 루프와 반복 에이전트 작업을 돌립니다. 그 과정에서 하루에 700달러가 청구되는 비용 사고를 한 번 겪었고, 그 사고에서 배운 내용을 그대로 루프 가드레일로 만들어 운영하고 있습니다. 그래서 이 주제는 우리에게 추상적인 트렌드가 아니라 매일의 운영 설계 과제입니다. 이 글은 루프를 돌리기 전에 무엇을 설계해야 하는지, 그리고 그것을 실제 플랫폼 운영에 어떻게 적용했는지를 정리합니다.
루프 엔지니어링이란 무엇인가
루프 엔지니어링은 에이전트에게 매번 직접 지시하는 대신, 에이전트를 지시하는 시스템을 짜는 일입니다. 사람이 루프 안에 계속 들어가 있으면 에이전트가 한 단계를 끝낼 때마다 다음 지시를 입력해야 합니다. 루프 엔지니어링은 그 자리에 작은 자동화를 끼워 넣습니다. 시스템이 할 일을 찾고, 적절한 에이전트에게 넘기고, 결과를 점검하고, 진행 상황을 적어두고, 다음 행동을 결정합니다.
이때 중요한 것은 자율성의 수준을 사람이 의도적으로 정한다는 점입니다. 완전 자율로 두면 토큰과 통제력을 모두 잃기 쉽고, 매 단계마다 사람이 확인하면 자동화의 이점이 사라집니다. 좋은 루프는 이 사이에서 자율성과 검증 지점을 명시적으로 배치합니다. 어디까지는 에이전트가 알아서 하고, 어디서부터는 사람이나 별도의 검증자가 개입하는지를 설계 단계에서 정해두는 것입니다.
또 하나의 전제는 루프가 수렴하거나 멈출 줄 알아야 한다는 것입니다. 끝나는 조건이 없는 루프는 자동화가 아니라 누수입니다. 그래서 루프 설계의 절반은 “언제 멈추는가”를 정의하는 일입니다.
실행 전에 설계해야 하는 네 가지
설계 없이 루프를 시작하는 것이 가장 흔한 실패 패턴입니다. 돌리기 전에 다음 네 가지를 명시적으로 정해두면 대부분의 토큰 누수와 품질 붕괴를 막을 수 있습니다.
첫째, 목표를 명확한 결과물로 정의합니다. “코드를 개선해줘” 같은 모호한 목표는 루프가 수렴할 기준이 없습니다. “이 테스트 명령이 통과할 때까지”처럼 검증 가능한 종료 조건을 정해야 합니다. 종료 조건이 곧 루프의 끝점입니다.
둘째, 루프를 돌리기 전에 메모리 파일을 먼저 씁니다. 무엇이 끝났고, 무엇이 다음이며, 무엇을 시도했다가 실패했는지를 적는 하나의 마크다운 파일이나 보드를 둡니다. 이 파일이 루프의 척추 역할을 합니다. 에이전트가 매 반복마다 이 파일을 읽고 갱신하면, 컨텍스트가 길어져도 상태가 유실되지 않습니다.
셋째, 만드는 에이전트와 검증하는 에이전트를 분리합니다. 일을 한 에이전트가 스스로 “다 됐다”고 판정하게 두면 안 됩니다. 검증 가능한 조건을 가진 별도의 게이트를 두거나, 자기만의 지시를 가진 두 번째 에이전트가 결과를 감사하게 합니다. 검증 단계가 없는 루프는 환각을 누적합니다.
넷째, 최대 반복 횟수와 토큰 예산, 그리고 정리(teardown) 단계로 루프를 캡합니다. 그런 다음 처음 한 번은 끝까지 돌려보고 출력된 모든 줄을 읽습니다. 루프가 정말 의도대로 동작하는지는 한 번 전부 읽어봐야만 알 수 있습니다. 이 검수를 건너뛰면 잘못 설계된 루프가 며칠 동안 조용히 토큰을 태웁니다.
[ 1. 목표 정의 ] 검증 가능한 종료 조건 (예: 테스트 통과)
|
v
[ 2. 메모리 파일 ] done / next / tried-failed 를 적는 척추
|
v
[ 3. 루프 실행 ] --- 일 찾기 → 에이전트 디스패치 → 결과 ---+
^ |
| v
[ 4. 검증자 분리 ] 만든 에이전트 ≠ 판정 에이전트 ---> [ 게이트 통과? ]
| |
| 실패 → 다음 반복 | 통과
+---------------------------------------------------+
|
v
[ 5. 캡 ] max-iter · token budget · teardown → 멈춤
이 흐름에서 가장 자주 빠뜨리는 칸이 4번 검증자 분리와 5번 캡입니다. 이 두 칸이 빠지면 루프는 무한히 돌거나, 그럴듯하지만 틀린 결과를 합쳐서 내놓습니다.
두 가지 비용: 토큰과 주의력
루프의 청구서는 두 가지 통화로 옵니다. 하나는 토큰이고 다른 하나는 사람의 주의력입니다. 한 번의 무인 실행이 수백만 토큰을 태울 수 있고, 그것이 정당한 경우는 그 토큰이 토큰값보다 더 가치 있는 무언가를 사는 경우뿐입니다.
여기서 핵심 통찰은 비싼 모델로 폴링이나 모니터링을 돌리는 것이 거의 항상 낭비라는 점입니다. 가격 스냅샷을 찍거나, 상태를 비교하거나, 헬스 체크를 하는 작업은 본질적으로 판단이 거의 필요 없습니다. 이런 작업을 매 틱마다 최상위 모델로 돌리면 비용은 폭증하는데 얻는 것은 단순 비교 결과 한 줄뿐입니다.
그래서 루프를 설계할 때 가장 먼저 던져야 할 질문은 “이걸 정말 모델이 매 틱마다 판단해야 하는가”입니다. 답이 아니라면 그 루프는 모델 없이 스크립트와 스케줄러로 돌리고, 사람이나 이벤트가 있을 때만 모델을 호출해야 합니다. 모델이 꼭 필요한 반복이라면 모델 등급을 낮추고, 상태를 파일에 두고, 매 깨어남이 최소한의 컨텍스트로 시작하게 만들어야 합니다.
ThakiCloud가 700달러 사고에서 배운 것
이 원칙들은 우리에게 교과서가 아니라 청구서로 도착했습니다. 어느 날 하루 동안 아홉 개의 세션이 전부 최상위 모델로 돌았고, 그중 한 모니터링 세션 하나가 9시간이 넘는 시간 동안 1,100회가 넘는 반복을 돌며 비용의 절반을 차지했습니다. 비용 분석을 해보니 거대한 컨텍스트가 매 반복마다 다시 읽히면서 캐시 읽기 비용이 전체의 상당 부분을 먹고 있었습니다. 원인은 캐시 미스가 아니라 거대한 컨텍스트와 반복 횟수와 비싼 단가의 곱이었습니다.
그래서 우리는 사고에서 배운 내용을 그대로 가드레일로 만들었습니다. 첫째, 반복 모니터링은 모델의 핫 루프에서 빼서 스케줄러(cron, launchd)로 옮겼습니다. 가격 모니터나 상태 비교는 이제 모델 없이 스크립트로 돌고, 특이사항이 감지될 때만 보고 채널로 알림을 보냅니다. 모델 비용이 0이 됩니다.
둘째, 꼭 모델로 돌려야 하는 루프는 짧고 상태가 없게(stateless) 유지합니다. 상태는 파일에 두고, 매 깨어남이 최소 컨텍스트로 시작하며, 한 세션이 일정 반복을 넘기기 전에 컨텍스트를 리셋합니다. 세션 컨텍스트가 비대해질수록 매 반복의 캐시 읽기가 선형으로 증가하기 때문입니다.
셋째, 오케스트레이션을 담당하는 메인 세션은 중간 등급 모델로 두고, 진짜 복잡한 추론이 필요한 단계만 최상위 모델 서브에이전트로 격리합니다. 사고 당일의 문제는 서브에이전트가 아니라 메인 세션 자체가 비싼 모델이었다는 데 있었습니다. 워커는 싸게, 게이트만 비싸게라는 원칙이 여기서 나왔습니다.
도구 선택: 목표, 루프, 스케줄을 구분합니다
루프를 설계할 때 우리가 가장 강조하는 것은 “반복/자동/계속”이라는 요청이 오면 어떤 도구로 풀 것인지부터 고르는 일입니다. 세 가지는 서로 다른 기계입니다.
목표를 달성 조건까지 자율적으로 추구하고 끝이 “완료” 상태인 작업은 목표 모드로 둡니다. 검증 명령 게이트와 예산과 상태 파일이 붙어 수렴형으로 동작합니다. 코드를 테스트 통과까지 반복 구현하는 작업은 종료 게이트를 테스트 명령으로 박은 개발 루프로 돌립니다. 세션 도중 외부 상태를 주기적으로 폴링해야 하는 작업은 인터벌 루프로 돌리되, 캐시 수명을 고려해 폴링 간격을 정합니다. 그리고 정해진 시각에 무인으로 반복되는 작업은 스케줄러로 돌립니다. 이것이 우리 환경의 주력이고, 모델을 매 틱 부르지 않으므로 비용이 0에 수렴합니다.
이 구분을 흐리면 사고가 납니다. 24시간 모니터링을 인터벌 루프에 누적하면 비용이 폭증하고, 정해진 시각 반복을 목표 모드에 넣으면 수렴 기준이 없어 헤맵니다. 그래서 우리는 루프 시작 전에 “이건 목표인가, 루프인가, 스케줄인가”를 먼저 답하게 합니다.
ThakiCloud K8s AI/ML SaaS 플랫폼 적용 및 시사점
루프 엔지니어링은 단일 개발자의 생산성 팁을 넘어 멀티테넌트 플랫폼 운영의 핵심 역량입니다. ThakiCloud는 고객마다 격리된 환경에서 에이전트와 파이프라인을 운용하는데, 각 테넌트의 무인 루프가 통제 없이 토큰을 태우면 그대로 운영 비용과 안정성 문제가 됩니다.
우리는 무인 루프를 중앙 레지스트리와 표준 신호 버스로 관리합니다. 어떤 루프가 무엇을 읽고 무엇을 쓰는지를 한곳에서 선언하고, 루프끼리 결합할 때는 임의의 공유 파일이 아니라 선언된 신호 토픽으로만 연결합니다. 레지스트리에 없는 루프는 보이지 않고, 보이지 않는 루프는 방치되어 비용 사고의 씨앗이 됩니다. 그래서 새 루프를 추가할 때마다 레지스트리 등재를 강제합니다.
플랫폼 관점에서 이것은 곧 제품 경쟁력입니다. 쿠버네티스 위에서 Kueue로 GPU 작업을 큐잉하고, 테넌트별로 모델 서빙을 격리하는 구조에서, 루프의 비용과 종료 조건을 코드로 강제하는 능력은 온프레미스 고객이 자체 인프라에서 에이전트를 안전하게 돌릴 수 있게 하는 토대가 됩니다. 비용이 통제되지 않는 자율 에이전트는 데모로는 인상적이지만 프로덕션에서는 부채입니다. 우리가 파는 것은 그 부채를 가드레일로 바꾸는 운영 설계입니다.
실무자 관점에서도 시사점이 분명합니다. 데이터 과학자나 ML 엔지니어가 야간 배치로 실험을 돌리거나 데이터 파이프라인을 자동화할 때, 검증자 분리와 토큰 캡과 메모리 파일이라는 세 가지만 챙겨도 비용 사고의 대부분을 막을 수 있습니다. 이 패턴은 특정 벤더에 묶이지 않고 어떤 에이전트 하니스에서도 통용됩니다.
한계 및 반론
루프 엔지니어링이 만능은 아닙니다. 가장 강한 반론은 모든 작업이 루프로 풀리지는 않는다는 것입니다. 단발성 질문이나 한 번의 파일 편집을 억지로 루프에 넣으면 설계 오버헤드만 늘고 얻는 것이 없습니다. 루프는 반복적이고 검증 가능한 작업에만 가치가 있습니다.
또 하나의 반론은 검증자 분리가 공짜가 아니라는 점입니다. 별도의 검증 에이전트를 두면 토큰이 추가로 들고, 검증자 자체가 틀릴 수도 있습니다. 검증자가 한 번도 무언가를 걸러내지 못한다면 그것은 검증이 제대로 동작하지 않는다는 신호일 수 있습니다. 그래서 검증 단계는 만든 에이전트와 다른 시각, 가능하면 적대적인 관점으로 설계해야 합니다.
마지막으로 자동화의 유혹 자체를 경계해야 합니다. 루프가 매끄럽게 도는 것처럼 보이면 사람은 점검을 게을리하게 됩니다. 그러나 청구서의 두 번째 통화인 주의력은 자동화한다고 사라지지 않습니다. 처음 한 번은 끝까지 읽고, 주기적으로 결과를 표본 검수하는 규율이 빠지면, 잘 설계된 루프도 결국 쓸 만하지 않은 결과물을 조용히 쌓아 올립니다.
결국 루프 엔지니어링의 핵심은 자율성을 늘리는 것이 아니라 자율성의 경계를 명확히 그리는 것입니다. 어디까지 맡기고 어디서 멈추며 무엇으로 검증하는지를 돌리기 전에 정하는 규율, 그것이 토큰을 태우지 않는 루프와 부채가 되는 루프를 가릅니다.
관련 슬라이드
본문 내용을 NotebookLM(doodle_collage 스타일)으로 요약한 슬라이드입니다.



