프로덕션급 작업을 위한 루프 설계
TMT원문: Designing Loops for Production-Grade Work — Liquid AI, 2026-08-18
2025년 말, 우리는 한 가지 질문에 답하기 위해 실험을 진행했습니다. "코딩 에이전트가 프로덕션급 문제를 맨바닥에서부터 스스로 해결할 수 있을까?"
이를 위해 당시 공개된 것 중 가장 뛰어난 코딩 모델을 탑재한 에이전트 두 개에게 실제 문제와 실제 마감 기한을 주고 일을 맡겼습니다. 이 실험의 결과물이 toktoktok이라는 토크나이저 학습기이며, 현재 GitHub에 오픈소스로 공개되어 있습니다.
이 글에서는 에이전트가 프로덕션급 문제를 스스로 해결하게 만드는 효과적인 루프 설계에 대해 배운 것, 즉 여러 분야에 정통한 전문가에게 목표를 제시하는 방법과 검증 인프라를 구축하는 방법을 공유합니다.
자율성을 검증하려면 진짜 과제가 필요한 이유
어휘 크기가 엣지 LLM에 미치는 영향에 관한 연구의 일환으로, 단일 머신에서 수조 개의 토큰을 처리할 수 있는 바이트 페어 인코딩(BPE) 토크나이저 학습기가 필요했습니다. 그런데 토크나이저 학습 도구의 선택지는 빈약했습니다. sentencepiece는 BPE가 아닌 토크나이저에 최적화되어 있는 데다 느리고, Hugging Face tokenizers는 우리 말뭉치에서 메모리 부족으로 멈췄으며, tiktoken은 학습 기능 자체가 없습니다.
그래서 프로덕션급 BPE 토크나이저 학습기를 직접 만들어야 했습니다. 기존 라이브러리를 써 본 경험으로 진짜 병목은 메모리 크기라는 것도 알고 있었고, 기존 도구에는 우리에게 필요한 두 가지 기능, 즉 기존 토크나이저에서 이어서 시작하는 웜 스타트(어휘 확장)와 언어별 어휘 예산 배분이 빠져 있었습니다. 덕분에 실제 마감 기한이 있는 구체적인 과제가 생겼고, 코딩 에이전트가 과제를 스스로 해결할 만큼 믿을 만한지 확인할 효과적인 수단도 확보한 셈입니다. 이 과제가 다음 조건을 충족했기 때문입니다.
프로덕션급 과제. 에이전트로 문제를 자율 해결하게 하는 흔한 방식으로는 이 질문에 답할 수 없습니다. 첫째, 에이전트는 주로 프로토타이핑에 쓰이고 프로덕션 수준의 기준을 요구받는 일이 드뭅니다. 둘째, "SQLite를 Rust로 포팅하라"거나 "Zig로 C 컴파일러를 작성하라"처럼 이미 존재하는 것을 다른 언어로 다시 구현하는 과제가 많은데, 이는 모델이 사전 학습 중에 봤을 법한 것을 옮겨 쓰는 일에 가깝습니다. 우리 과제는 둘 다와 달리 프로덕션에 실제로 배포한다는 분명한 목표가 있었고, BPE 토크나이저 학습은 비교적 최근 기술이라 공개된 참조 구현이 드물어 '시험 분포(test distribution)' 문제 표본으로 안성맞춤이었습니다.
여러 분야에 걸친 전문성. Liquid AI의 전문가들은 각자 깊이가 있지만, 저마다 한 분야에서만 그렇습니다. ML 연구자들은 OpenAI의 cl100k가 왜 모든 세 자리 숫자에 순위를 예약해 두는지 기억만으로 설명할 수 있지만, Rust 코드는 한 줄도 써 본 적이 없습니다. Rust 엔지니어들은 이 문제에 필요한, 메모리를 세심하게 다루는 멀티스레드 시스템 코드를 늘 작성하지만, 토크나이저를 학습시켜 본 적은 없습니다.
이 두 집단은 전혀 겹치지 않으며, 어느 쪽도 혼자서는 이 문제를 풀 수 없습니다. 사람으로 해결하는 우회로는 둘 다 손실이 큽니다. 한쪽이 상대 분야의 절반을 먼저 배우거나, 두 사람을 붙여 협업으로 진행하면서 조율 비용을 대신 치러야 합니다. 우리가 에이전트를 겨눈 지점이 바로 이 간극입니다. "우리 엔지니어 누구도 혼자서는 갖추지 못한 폭의 전문성을 에이전트가 감당할 수 있을까?"
외부 검증 가능성. 산출물은 tiktoken과 Hugging Face tokenizers에서 로드되어야 합니다. 서드파티 소프트웨어와의 이런 상호운용성 덕분에, 에이전트가 손댈 수 없는 코드로 작업 결과를 검사할 수 있습니다. 성공 여부를 에이전트가 스스로 보고하는 것이 아니라, 두 서드파티 라이브러리가 올바른 토큰을 내놓는지 아닌지로 판가름합니다.
무엇을 만들어야 했는지에 대한 세부 내용도 그 자체로 흥미롭지만, 이 글에서 중요한 것은 따로 있습니다. 진짜 프로덕션급이고, 단일 분야 전문가에게는 어려우며, 외부에서 검증할 수 있는 과제만이, 에이전트가 사람의 감독 없이 일을 해낼 수 있는지에 정직하게 답하는 유일한 방법이라는 점입니다.
실험 준비
이 실험에는 2025년 말 기준 공개된 코딩 모델 중 가장 강력한 두 가지인 Claude Opus 4.5와 GPT-5.2 기반 Codex를 코딩 에이전트로 골랐고, 둘 다 플래닝 모드로 작업하게 했습니다. 에이전트가 코드를 한 줄이라도 쓰기 전에, 주변에 두 가지를 먼저 마련했습니다. 겨냥할 목표, 그리고 목표에 도달했는지 확인할 방법입니다.
목표는 명세 파일에 기술했습니다. 운영자가 작성한 AGENTS.md/CLAUDE.md 문서 하나로, 구현 방법이 아니라 결과물과 제약 조건을 담았습니다. 아키텍처의 최우선 제약은 메모리입니다. 설계의 복잡도 예산을 메모리에 쏟아, RAM보다 훨씬 큰 말뭉치도 공정하게 표현되도록 합니다. 연산과 I/O는 부차적인 문제로 보고 단순하게 처리합니다. 시스템 수준 프로그래밍 언어(Rust)와 멀티스레딩이면 충분하다는 판단이었습니다.
에이전트가 명시된 목표에 도달했는지 검증하기 위해, 에이전트가 영향을 미칠 수 없는 두 가지를 제공했습니다.
- 프로덕션 데이터: 에이전트에게 우리의 프로덕션 학습 데이터셋에 대한 샌드박스 접근 권한과 이를 감당할 수 있는 머신을 주었습니다. 구체적으로는 128코어 256스레드에 2TB 메모리를 갖춘 AMD EPYC 9755 장비입니다.
- 외부 검증 하니스: 학습된 어휘는
tiktoken과 Hugging Facetokenizers로 로드할 수 있어야 하고, 여러 언어, 숫자, 통화 표기, 탭, CRLF 줄바꿈, 소스 코드에 걸쳐 인코딩·디코딩 왕복과 두 라이브러리 간 토큰 ID 수준의 일치를 검사받아야 합니다.
이 구성 요소들이 갖춰지자 에이전트는 명시된 목표를 향해 작업을 시작할 수 있었습니다.
실험을 돌려 보니
두 코딩 에이전트 모두에게 실험을 진행했습니다. 운영자는 바깥에서 지켜보기만 했고, 하니스 출력만 읽을 뿐 코드는 단 한 줄도 읽지 않았습니다.
둘 다 장난감 수준의 학습기는 한 번에 만들었다
두 에이전트 모두 30분 안에 동작하는 학습기를 만들어 냈습니다. 설정을 파싱하고, 말뭉치를 순회하고, 하드코딩된 병합 규칙을 적용하고, BPE 학습을 돌려서, 자체 단위 테스트를 통과하는 유효한 .tiktoken 파일을 출력했습니다.
둘 다 몇 메가바이트 규모의 데이터로 장난감 토크나이저를 성공적으로 학습시켰습니다. 산출물은 tiktoken에서 로드되었고 모든 테스트가 통과했습니다. 평가를 여기서 멈췄다면, 두 실행 모두 성공이라고 결론지었을 겁니다.
루프 없이는 어느 쪽도 프로덕션 규모에 도달하지 못했다
하지만 어느 학습기도 전체 프로덕션 데이터셋을 버텨 내지 못했습니다. 첫 실행에서는 단계마다 모든 단위 테스트가 통과했는데, 몇 메가바이트짜리 깨끗한 텍스트로는 아래 문제들이 하나도 드러나지 않기 때문입니다.
| 발견해야 했던 것 | 드러난 방식 | 잡아낸 수단 | 수정에 든 노력 |
|---|---|---|---|
| 파일 인코딩. Parquet은 논리적으로 같은 컬럼에 여러 인코딩을 허용한다 | 테스트에서는 잘 읽히던 파일이 실제 말뭉치에서는 소리 없이 잘못 처리됨 | 실제 말뭉치 파일 | 수 시간 |
| 메모리 인식. 문서별 Vec 오버헤드가 실제 데이터보다 커짐 | 목표 말뭉치의 약 1% 지점에서 메모리 부족 발생 | 전체 규모 실행 | 이틀에서 사흘: 청크 배칭, 센티널, 다중 세그먼트 순회 |
| 잘못된 병렬화. 핵심 경로의 일부만 병렬화하면 나머지는 순차 실행으로 남는다 | 모든 코어가 바쁘게 도는데도 처리량은 여전히 못 쓸 수준 | 전체 규모 실행 | 하루에서 이틀 |
사전 토큰화 속도. \s+(?!\S) 패턴은 백트래킹 정규식 엔진을 강제한다 | 프로파일러에서 사전 토큰화가 병목으로 확인되고, 악의적인 공백 입력에서 처리 시간이 제곱으로 늘어남 | 전체 규모 실행 | 수 시간, 여기에 정확성에 대한 판단까지 필요 |
순위 정렬. tiktoken은 순위 순서에서 병합 순서를 도출하므로 순위가 연속이어야 한다 | 어휘가 아무 오류 없이 로드되지만 의도와 다르게 인코딩됨 | 외부 하니스 | 수 시간 |
| 중복 병합. 학습된 병합이 기존 토큰과 겹쳐 어휘가 줄어들 수 있다 | 어휘가 N개 모자라고 이후의 모든 순위가 밀림 | 외부 하니스 | 수 시간 |
숫자 인코딩. Rust의 regex 크레이트는 {1,3}+를 ({1,3})+로 재해석한다 | tokenizers와 tiktoken이 숫자만 빼고 전부 일치 | 외부 하니스 | 한 줄 |
그다음 에이전트가 실제 데이터를 상대로 루프를 돌게 했습니다. 실행하고, 벽에 부딪히고, 증상을 보고하고, 에이전트가 진단해서 고치고, 다시 실행하는 식입니다.
다섯 번 넘게 반복해도 진전이 거의 없자, 여전히 학습 처리량 문제로 헤매고 있던 Codex/GPT-5.2 트랙은 중단했습니다. 이는 자원 배분에 따른 결정이었습니다. 운영자는 한 명이고 마감은 실제였으며, 그 시점에 같은 횟수를 반복한 Claude Opus 4.5 트랙이 더 앞서 있었습니다. 우리가 보기에 Claude의 첫 버전은 명세의 뉘앙스와 제약 뒤에 담긴 의도를 GPT-5.2보다 더 확실하게 알아차린 덕분에 더 좋은 출발점에서 시작했습니다.
Claude Opus 4.5는 몇 차례 반복을 더 거치며 남은 문제들을 정리했고, 전체 프로덕션 구성을 소화하는 학습기를 완성했습니다. 다국어와 코드 데이터 수조 개 토큰을, 여러 단계에 걸쳐, 단일 머신에서 며칠 만에 학습을 끝냈습니다. 산출물은 외부 하니스를 깔끔하게 통과했습니다.
루프가 필요했던 이유
이 실험은 *"코딩 에이전트가 프로덕션급 문제를 맨바닥에서부터 스스로 해결할 수 있을까?"*라는 질문에 답하기 위한 것이었습니다. "어느 에이전트도 한 번에 성공하지 못했다"를 모델 능력에 대한 이야기로 읽고 싶어지지만, 그것은 잘못된 결론입니다. 처음에 세운 기준으로 보면 실험은 성공했습니다. 다만 성공을 이끈 것은 어느 한 번의 기발한 턴이 아니라 루프였습니다.
이 저장소의 2천 줄은 단 한 번의 응답으로 나온 산물이 아니라, 반복 과정이 쌓아 남긴 결과물입니다. 자명하지 않은 코드는 거의 전부, 써야 한다는 사실만 알면 쓰는 것 자체는 어렵지 않습니다. 비싼 부분은 그 코드를 써야 한다는 사실을 알아내는 일입니다.
결국 에이전트가 사람의 감독 없이 목표를 달성할 수 있느냐는, 실제 환경의 제약을 향해 수렴하는 반복 루프가 있느냐에 달려 있습니다. 이런 루프가 있어야 에이전트가 현실 세계의 지저분함을 하나씩 발견하고 겪어 낼 수 있습니다.
자율 루프를 돌리며 배운 것
이 실험으로 코딩 에이전트가 루프만 있으면 과제를 스스로 해결할 수 있다는 것을 확인했지만, 더 중요한 수확은 효과적인 루프를 설계하는 방법에 대한 두 가지 교훈이었습니다. 이 교훈은 오늘날 우리 엔지니어링 팀의 일상적인 관행이 되었습니다.
여러 분야 전문가에게 맞는 방식으로 목표를 명세하라
실험을 통해 코딩 에이전트가 여러 분야에 걸친 전문가이며, 우리 엔지니어 누구도 갖지 못한 폭의 전문성을 아우른다는 것을 알게 되었습니다. 알고 보니 에이전트는 OpenAI cl100k의 정규식도 알고 있었고, Rust의 rayon도 알고 있었습니다. 우리가 이 일에 투입할 수 있는 사람 중에 둘 다 아는 사람은 없었습니다. 이 사실은 목표를 명세하는 방식 자체를 바꿉니다. 마치 우리 팀 업무까지 훤히 아는 다른 팀 동료와 대화하는 느낌에 가깝기 때문입니다.
토크나이저 경험이 없는 뛰어난 소프트웨어 엔지니어에게 이 문제를 넘기려면 실제로 무엇이 필요할지 생각해 봅시다. 당연한 답은 상세한 명세서를 써 주는 것입니다. 여기서 전문성 전수의 고전적인 딜레마가 나타납니다. 명세를 너무 짧게 쓰면 엔지니어가 그 내용을 전부 느린 방법으로 직접 알아내야 합니다. 반대로 실제 실행에 옮길 수 있을 만큼 길게 쓰면 그것은 이미 의사코드이고, 그 지경이면 도메인 지식이 본인에게 필요했던 것이라 사실상 일을 직접 다 한 것이나 다름없습니다.
LLM은 이 딜레마에 갇히지 않습니다. 배경지식을 이미 갖춘 채로 오기 때문입니다. 그러면 명세라는 것의 성격이 달라집니다. 우리 명세는 짧았습니다. 동작 방식이 아니라 결과물과 제약 조건을 적었습니다.
우리 명세에 실제로 있던 예를 하나 들어 보겠습니다. "학습 시작 전에 모든 두 자리, 세 자리 숫자를 위한 어휘를 예약하라." 배경지식이 없는 엔지니어에게 이 문장은 자의적인 요구사항으로 보입니다. 문장 자체에 이유가 담겨 있지 않기 때문에, 문자 그대로 구현하고도 틀릴 수 있습니다. 이 요구사항의 목적은 모델에게 일관된 숫자 표현을 주는 데 있습니다. 말뭉치에서 어떤 숫자 쌍이 우연히 자주 나왔느냐에 산술 능력이 좌우되지 않게 하려는 것입니다. 예를 들어 GPT-2의 토크나이저는 학습 데이터의 빈도 때문에 2019는 고유 토큰으로 갖고 있지만 2029는 그렇지 않습니다. 이 배경을 모르면 지시사항의 어느 부분이 핵심인지, 파이프라인의 어느 단계에 들어가야 하는지, 설계의 다른 부분에 어떤 영향을 주는지 판단할 수 없습니다.
현실 세계의 제약으로 검증하라
운영자는 생성된 코드를 단 한 줄도 읽지 않았습니다. 이것이 용인될 수 있었던 유일한 이유는, 성공 기준이 에이전트가 조작할 수 없는 것이었기 때문입니다. 루프 설계에서 흔히 보이는 실수가 바로 허술한 검증입니다. 장난감 규모의 데이터로 검증하거나, 에이전트가 자기 단위 테스트를 고쳐 쓰는 식으로 검증에 영향을 미칠 수 있게 두는 경우입니다.
핵심 교훈은 다음 요소를 갖춰, 현실의 제약을 향해 수렴하는 루프를 설계하라는 것입니다.
- 실제 프로덕션 데이터로, 실제 규모에서 반복하십시오. 정작 중요했던 실패들은 테스트 스위트에서는 보이지 않았고, 전체 규모의 프로덕션 데이터에서만 발견할 수 있었습니다.
- 외부 하니스로 검증하십시오. 자율 작업을 받아들일 수 있게 만드는 것이 바로 이 부분입니다. 운영자가 코드를 전혀 읽지 않고도 괜찮았던 것은, 정확성을 tiktoken과 Hugging Face tokenizers, 즉 에이전트가 작성하지도 않았고 영향을 미칠 수도 없는 소프트웨어가 정의했기 때문입니다. 에이전트 자체의 테스트 스위트를 증거로 받아들였다면, 각자 테스트는 통과하지만 서로 조용히 다른 어휘를 만들어 내는 구현 두 개를 얻었을 겁니다. 제삼자가 산출물을 판정할 수 있도록 문제를 구성하십시오.
이제는 일상이 된 것들, 그리고 앞으로
여기까지가 2025년 말에 진행한 실험의 결과와 교훈입니다. 그렇습니다. 코딩 에이전트는 사람의 감독 없이도 프로덕션급 문제를 맨바닥에서부터 스스로 해결할 수 있습니다. 단, 루프 안에서 돌 때만 그렇습니다.
이때 배운 교훈은 오늘날 우리 엔지니어링 팀의 일상적인 관행이 되었습니다. 반년이 지난 지금 우리가 가장 공을 들이는 부분은 목표를 명세하는 일이고, 실제 데이터와 외부 검증으로 루프를 구축하는 것은 표준 관행으로 자리 잡았습니다.
지금은 토크나이저 학습기처럼 루프가 수렴할 명확하고 검증 가능한 최종 목표가 있는 일회성 개발을 훨씬 넘어서는 루프들을 돌리고 있습니다. 요즘 돌리는 루프 상당수는 오히려 열린 형태로, 하나의 정답이 없는 목표를 향해 조금씩 개선해 나갑니다. 커널을 튜닝하고, 지속적 통합(CI)을 감시하고, 들어오는 풀 리퀘스트를 분류하고, 프로덕션 로그에서 이상 징후를 찾는 일들입니다. 어느 경우든 우리는 코드가 아니라 지표를 확인합니다.
요즘 모델은 그때보다 눈에 띄게 좋아졌지만, 이런 방식이 일상이 된 진짜 이유는 루프 전체를 통째로 맡길 수 있을 만큼 모델이 믿을 만해졌다는 데 있습니다. 이것이 일반화된다면, 순수한 코딩 능력의 변화보다 ML과 소프트웨어 엔지니어링이 이루어지는 방식에 더 큰 전환이 될 것입니다.
공개 정보
toktoktok은 Apache 2.0 라이선스의 오픈소스로 https://github.com/Liquid4All/toktoktok에 공개되어 있습니다. tiktoken 호환 BPE 어휘를 처음부터 학습하거나 기존 어휘를 확장할 수 있고, .txt와 .parquet 파일을 읽으며, 다단계 학습으로 언어와 도메인별로 어휘 예산을 배분하고, 사용자가 선언한 메모리 예산 안에서 동작합니다. Hugging Face 변환 스크립트는 양방향으로 동작하며, 무엇이든 기록하기 전에 동등성을 먼저 검증합니다.
이 코드의 모든 줄은 에이전트가 작성했고, 우리는 그중 한 줄도 읽지 않았습니다.
감사의 말
Mathias Lechner가 작성했고, Leonie Monigatti가 기여했습니다.
이 실험에 필요한 하드웨어를 쓸 수 있게 해 준 AMD와의 파트너십에 감사드립니다.
인용
이 글을 인용할 때는 다음과 같이 표기해 주십시오.
Liquid AI, "Designing Loops for Production-Grade Work", Liquid AI Blog, Aug 2026.
@article{liquidAI2026loops,
author = {Liquid AI},
title = {Designing Loops for Production-Grade Work},
journal = {Liquid AI Blog},
year = {2026},
note = {www.liquid.ai/blog/agent-loops},
}