출력은 그대로, 코딩 에이전트 응답 생성 처리량만 최대 4.76배 — KAIST AgSpec

KAIST의 AgSpec은 코딩 에이전트가 답을 써 내려가는 구간만 가속한다. greedy 조건에선 출력을 바꾸지 않고, 생성 처리량이 기존 최고 방식보다 평균 18.0% 높았다.
English  ·  日本語  ·  한국어
← 목록으로
온
온틀 리서치
2026년 10월 04일 수정 2026.10.16 읽기 15분 조회 2

KAIST 연구진이 코딩 에이전트의 속도를 끌어올리는 프레임워크 AgSpec을 내놓았다. 방법은 명확하다. '추측 디코딩'이라는 기존 가속 기법을 코딩 에이전트의 작동 구조에 맞게 다시 깎았다. 손본 건 딱 두 군데다. 베껴 쓸 텍스트를 어디에 담아둘지, 그리고 한 번에 몇 글자를 미리 써볼지. 검색 엔진을 새로 만드는 게 아니라 이미 돌아가는 엔진 위에 얹는 방식이라, 기존 파이프라인에 그대로 붙는다.

범위부터 분명히 하자. 여기서 빨라지는 건 '모델이 응답을 써 내려가는 구간'뿐이다. 테스트를 돌리고 도구를 호출하는 시간까지 포함한 전체 작업 시간이 아니라, 그 안에서 모델이 글자를 만들어내는 시간이다. 그리고 이 가속은 출력을 한 글자도 바꾸지 않은 채 이뤄진다. 더 빠르게, 같은 답을 줄 뿐이다.

폭은 이렇다. 기존에 가장 빠르던 방식보다 '생성 처리량'이 평균 18.0% 높았고, 토큰(단어 조각)을 한 글자씩 순서대로 만드는 기본 방식과 견주면 최대 4.76배였다. 여기서 처리량은 1초에 확정하는 토큰 수, 곧 얼마나 빨리 써 내려가느냐다. 다만 이 최대 배율은 요청을 한 번에 16개씩 묶어 처리하고 프롬프트를 읽어 들이는 시간을 뺀, 순수 생성 구간만 놓고 잰 '처리량' 지표라는 점을 분명히 해야 한다. 요청 하나하나의 응답 지연시간이 그대로 4.76배 줄어든다는 뜻이 아니다 — 같은 가속률이 단일 요청에도 똑같이 적용된다는 가정이 서야 비로소 시간으로 환산해 볼 수 있다.

그런데 이 논문에서 정말 눈길을 끄는 대목은 배율의 크기가 아니다. 같은 AgSpec을 어떤 엔진 위에 얹느냐에 따라 효과가 극적으로 갈렸다는 것, 그것도 원래 덜 똑똑한 엔진일수록 더 크게 뛰었다는 점이다. 이 얘기는 결과를 보며 이어가자.

추측 디코딩, 왜 필요한가

큰 언어 모델은 토큰을 한 번에 하나씩 순서대로 만든다. 토큰 하나를 뽑을 때마다 모델 전체를 한 번씩 돌려야 한다. 그래서 답이 길수록 이 순차 단계가 쌓여 느려진다.

추측 디코딩은 여기에 분업을 끼워 넣는다. 값싼 '초안 작성자'가 다음에 올 토큰 여러 개를 미리 찍어 보고, 본 모델이 그걸 한꺼번에 검증해 맞은 것만 확정한다. 맞힌 토큰 하나당 본 모델이 따로 돌려야 할 순차 단계 하나를 아끼는 셈이다. 검증은 본 모델이 직접 뽑았을 때의 확률분포를 그대로 지키도록 설계돼, 통과한 토큰만 남는다. 그래서 이 논문처럼 매번 확률이 가장 높은 토큰을 고르는 방식(greedy)으로 돌리면 최종 출력은 본 모델이 한 토큰씩 만든 것과 완전히 같다. 품질 손실이 0이라는 말은 이 조건에서 성립한다.

AgSpec이 쓰는 건 그중에서도 '검색 기반' 추측 디코딩이다. 초안을 별도 모델이 아니라 이미 갖고 있는 텍스트에서 가져온다. 지금 프롬프트, 앞서 생성한 응답, 미리 쌓아둔 저장소에서 지금 문맥과 이어질 법한 대목을 찾아 그대로 복사한다. 코드에서 이 복사가 특히 잘 먹힌다. 식별자와 코드 조각, 저장소의 관례가 계속 반복되고, 에이전트 세션에서는 같은 하위 작업과 수정 루프가 길고 뻔한 시퀀스를 끝없이 찍어내기 때문이다.

코딩 에이전트라서 생기는 구멍

문제는 코딩 에이전트의 생김새가 챗봇과 다르다는 데 있다. 챗봇은 질문 하나에 답 하나로 끝난다. 코딩 에이전트는 요청 하나를 여러 턴에 걸쳐 처리한다. 한 턴은 모델을 한 번 부르고 도구를 한 번 돌리는 사이클이다. 파일을 고치는 코더, 테스트를 돌려 결과를 확인하는 실행자처럼 역할을 나눠, 모델 호출과 도구 실행을 번갈아 한다. 한 번에 성공하는 일은 드물다. 실패하면 다음 턴에서 이전 시도를 상당 부분 다시 쓰며 고쳐 나간다. 바로 이 '여러 턴에 걸친 재사용'이 기존 가속 방식이 놓친 지점이다. 창고를 무엇으로 채울지, 초안을 몇 글자 낼지를 정하는 규칙이 전부 '요청 하나' 단위에 머물러 있어서, 턴과 턴을 가로지르는 재사용을 담아내지 못했다.

초안이 실제로 도움이 되려면 두 가지가 맞아야 한다. 첫째, 베껴 올 텍스트가 창고에 있어야 한다. 둘째, 그 형태가 지금 쓰려는 결과물과 맞아떨어져야 한다. 기존 방식은 이 둘에서 모두 미끄러졌다.

재료에 빗대 보자. 쓸 수 있는 텍스트는 세 군데에 있다. 지금 식탁에 올려둔 재료(이번 세션에서 오간 프롬프트와 응답), 냉장고에서 꺼내 도마에 올린 재료(이번에 열어본 저장소 파일), 그리고 늘 선반에 있는 조미료(미리 쌓아둔 대용량 참조 텍스트). 기존 방식은 식탁 위 재료만 쳐다보거나, 아예 남의 집 창고에 해당하는 조미료만 뒤졌다. 정작 냉장고 속 재료 — 이전 턴에서 내가 만든 출력과 방금 열어본 파일 — 는 꺼내 쓰지 못했다. 파일이 프롬프트 길이 제한에 잘려 나가는 순간 손이 닿지 않았고, 재시도는 이전 시도의 호출이 끝나 버리면 그 내용을 끌어올 수 없었다.

형태도 문제였다. 창고는 에이전트가 '읽은 그대로'의 텍스트를 담는데, 코더가 내놓는 건 '어디를 어떻게 고칠지 적은 수정 지시서(패치)'다. 같은 코드라도 읽을 때와 고칠 때의 형식이 다르다. 그래서 읽은 모양 그대로 저장해 둔 텍스트는 정작 코더가 쓰는 줄과 어긋나 매칭이 깨졌다.

AgSpec의 두 손질

AgSpec의 판단은 이렇다. 문제는 '텍스트를 어떻게 매칭하느냐'는 알고리즘이 아니라, 그 매칭을 둘러싼 정책 — 창고에 무엇을 담고 몇 글자를 초안으로 낼지 — 에 있다. 그래서 엔진은 건드리지 않고 그 위에 정책 두 벌을 얹는다.

세 개의 창고

첫 손질은 창고를 셋으로 나눈 것이다. 앞의 재료 비유를 그대로 가져오면 이렇게 대응한다.

  • 세션 창고 = 식탁 위 재료. 이번 세션의 프롬프트, 도구 출력, 생성한 토큰을 담는다. 세션 안의 모든 호출과 에이전트가 공유하니, 이전 호출과 이전 턴의 텍스트가 계속 검색 대상으로 남는다.
  • 워크스페이스 창고 = 냉장고 속 재료. 이번 세션에서 열어본 저장소 파일을 담는다. 파일을 더 열수록 커진다.
  • 글로벌 창고 = 선반의 조미료. 이번 세션과 무관한 대용량 참조 텍스트. 서비스 시작 전에 만들어 고정한다.

앞의 둘은 세션과 함께 생겼다 사라지는 '라이브' 창고고, 글로벌만 세션을 가로질러 고정이다. 비로소 냉장고를 연 것 — 이전 턴의 내 출력과 방금 열어본 파일 — 이 검색 대상에 들어온 셈이다.

여기에 형태 문제를 푸는 장치가 하나 더 붙는다. 파일을 처음 열 때, 읽은 원본만 담지 않고 '에이전트가 고칠 때의 모양'으로 미리 변형한 복사본을 함께 넣어 둔다. 흔한 수정 포맷에서는 그대로 두는 줄 앞에 공백을, 지우는 줄 앞에 마이너스를 붙인다. 그래서 AgSpec은 모든 줄 앞에 공백을 붙인 복사본과 마이너스를 붙인 복사본을 미리 만들어 둔다. 코더가 패치에 어떤 줄을 복사해 넣든 둘 중 하나와 맞는다. 읽은 모양과 고치는 모양이 어긋나 매칭이 깨지던 문제를, 변형본을 미리 깔아 두는 것으로 막은 셈이다.

초안을 몇 글자 낼지

둘째 손질은 초안 길이다. 초안 토큰은 수용되면 단계를 아끼지만, 거부되면 검증만 낭비한다. 이 낭비는 요청이 한꺼번에 몰려 검증이 붐빌수록 커진다. 그래서 '몇 글자까지 내밀 것인가'를 두 축으로 정한다.

하나는 미리 정해 둔 상한이다. 초안은 뒤로 갈수록 맞을 확률이 떨어진다. 한 글자를 더 검증하는 비용을 그 글자가 메워 주는 지점까지만 내미는 게 이득이다. 그 한계선을 과거 작업 기록을 재생해 미리 구해 둔다. 역할마다 쓸모 있는 길이가 다르니, 이 상한은 에이전트 역할별로 따로 잡는다.

다른 하나는 돌아가며 조정하는 배율이다. 같은 역할이라도 쓸모 있는 길이는 턴마다, 턴 안에서도 흔들린다. 그래서 최근 몇 번의 시도에서 실제로 수용된 길이를 보고, 다음 초안을 더 길게 낼지 짧게 낼지 실시간으로 당겼다 줄인다. 미리 잰 상한이 천장을 잡고, 이 배율이 그 안에서 현장에 맞춰 움직이는 구조다.

어떤 엔진에 얹느냐가 효과를 갈랐다

이제 앞에서 미뤄 둔 대목이다. AgSpec은 엔진 위에 얹는 프레임워크라, 같은 엔진을 'AgSpec 있음/없음'으로 깔끔하게 비교할 수 있다. 여기서 드러난 그림이 이 논문의 백미다.

이미 과거 응답을 재활용하고 매칭 길이에 맞춰 초안을 늘릴 줄 아는 엔진(SuffixDecoding) 위에서는, AgSpec을 얹어도 처리량이 16.5% 느는 데 그쳤다. 처리량은 1초에 확정하는 토큰 수, 곧 얼마나 빨리 써 내려가느냐다. 반면 그 두 장치가 아예 없는 엔진(SAM-Decoding) 위에서는 처리량이 64.6% 뛰었고, 한 번의 추측으로 버는 토큰 수는 거의 두 배가 됐다.

메시지는 분명하다. 엔진이 원래 덜 똑똑할수록 AgSpec이 끌어내는 잠재력이 컸다. 똑똑한 엔진은 이미 비슷한 일을 스스로 하고 있어 더 얹을 여지가 적었던 것이다.

극적인 건 순위가 뒤집혔다는 사실이다. SAM-Decoding은 혼자서는 12개 설정 전부에서 SuffixDecoding에 뒤졌다. 그런데 AgSpec을 얹자 그중 9개 설정에서 SuffixDecoding을 앞질렀다. 원래 더 느리던 엔진이, 정책 두 벌을 갈아끼운 것만으로 더 빠르던 엔진을 역전한 것이다. 한 사례에서는 속도 향상이 2.72배에서 3.61배로 올라갔다.

저장소가 아예 없어 냉장고(워크스페이스 창고)가 텅 비는 환경에서도 효과는 남았다. 그 조건에서도 더 빠른 AgSpec 변형은 가장 빠른 기존 방식을 35~145% 앞섰다. 식탁(세션)에 쌓이는 텍스트에서 계속 검색하고, 길이 제어가 검증 피드백으로 쉼 없이 적응한 덕이다.

세부: 무엇으로 어떻게 쟀나

평가 모델 셋, 저장소 수준 벤치마크 둘(여러 에이전트가 역할을 나눠 여러 턴을 도는 상황)과 일반화용 벤치마크 둘(저장소 없는 환경, 한 에이전트가 모든 역할을 겸하는 환경)을 썼다. 측정은 프롬프트를 읽어 들이는 시간을 뺀, 순수 응답 생성 구간의 처리량과 수용 길이다. 출력 품질은 이 평가가 쓴 greedy 조건에서 기본 방식과 같은 출력을 내므로 측정 대상이 아니다. 비교군은 기본 방식, 검색 기반 다섯 종, 학습된 초안 방식 하나. 누수를 막기 위해 글로벌 창고는 평가와 겹치지 않는 별도 과제 로그로 만들었고, 평가 과제는 창고 구성에서 제외했다.

한계와 전제

빠르게 해 주지만 공짜는 아니다. 전제가 몇 가지 깔려 있다.

발신 형태로 미리 변형해 두는 장치는, 에이전트가 코드를 읽고 고치도록 감싸는 작업 틀(스캐폴드)이 어떤 수정 포맷을 쓰는지에 기댄다. 포맷이 세션 전에 알려져 있어야 변형본을 미리 만들 수 있고, 쓰는 틀이 바뀌면 변형도 손봐야 한다. 역할별 상한도 과거 작업 기록을 재생해 잡으므로, 그 기록을 모을 수 있는 환경을 전제한다.

효과의 폭이 설정에 따라 크게 출렁인다는 점도 염두에 둬야 한다. 요청이 한꺼번에 크게 몰리는 상황에서는 검증 자체가 붐벼, 이득이 1.08배까지 얇아지는 설정도 있었다. 대형 배치에서는 기대만큼 안 나올 수 있다는 뜻이다. 라이브 창고는 세션이 길어질수록 커지는데, 아주 긴 세션에서 그 메모리와 검색 부담이 어떻게 변하는지는 더 따져볼 지점이다.

마지막은 한계라기보다 성격의 재확인이다. 추측 디코딩이 지키는 것은 본 모델의 출력 확률분포다. 이 논문처럼 greedy로 돌리면 출력이 그대로이고, 무작위 샘플링에서는 같은 분포를 따를 뿐 개별 생성문까지 동일하다는 보장은 아니다. 어느 쪽이든 AgSpec은 더 빠르게 답을 줄 뿐, 더 나은 답을 주지는 않는다. 에이전트의 성공률 자체를 올리고 싶다면 다른 레버가 필요하다.

그래서 무엇을 해야 하나

이 논문의 실용적 교훈은 간단하다. 속도를 끌어올리는 출발점은 '더 똑똑한 엔진으로 갈아타는 일'이 아니라 '내 파이프라인이 무엇을 반복하는지 측정하는 일'이라는 것. 무엇을 창고에 먹이고 몇 글자를 받아낼지만 작업 구조에 맞춰 바꿔도, 엔진을 그대로 둔 채 상당한 속도가 남아 있었다.

이 지점이 온틀처럼 여러 고객 프로젝트를 동시에 운영하는 입장에서 특히 무겁다. 한 장면을 따라가 보자. 고객이 "이 저장소의 버그를 고쳐 달라"고 요청을 넣는다. 코더가 파일을 읽고 패치를 만들고, 실행자가 테스트를 돌린다. 실패하면 다음 턴에서 이전 패치를 거의 다시 쓴다. 고객 화면에는 이 구간이 '진행중'으로 뜨고, 턴이 쌓일수록 고객은 기다린다. 바로 이 반복이 검색 기반 가속이 가장 잘 먹히는 자리다 — 이전 턴의 내 출력과 방금 열어본 파일을 창고가 덮고, 코더의 수정 포맷에 맞춘 변형본이 깔려 있다면.

문제는 그 결이 프로젝트마다 다르다는 점이다. 어떤 역할이 어떤 포맷으로 무엇을 반복하는지가 제각각이다. 그러니 한 번은 측정해야 한다. 우리 파이프라인에서 어떤 턴이 무엇을 다시 쓰는지 재 보고, 그 패턴을 역할별 상한에 반영해 둘 때 비로소 이 가속이 제값을 한다. 고객의 '진행중' 시간을 줄이는 일은, 역설적이게도 엔진을 바꾸는 데서 시작하지 않는다.

자주 묻는 질문

프롬프트를 처음 읽어 들이는 시간도 빨라지나요?

아닙니다. AgSpec이 재고 줄이는 건 모델이 응답을 써 내려가는 구간뿐입니다. 초기 프롬프트를 읽어 들이는 구간은 측정에서 아예 빼고 봤습니다. 긴 입력을 한 번에 소화하는 단계가 병목이라면, 그건 이 프레임워크가 겨냥하는 지점이 아닙니다.

학습해서 초안을 뽑는 방식과는 뭐가 다른가요?

본 모델에 작은 예측부를 덧붙여 학습시키는 방식은 초안을 '만들어' 냅니다. AgSpec은 반대로 이미 가진 텍스트에서 '베껴' 옵니다. 그래서 추가 학습도, 초안 전용 GPU도 필요 없습니다. 대신 베껴 올 재료가 창고에 실제로 쌓이고 형태가 맞아야 이득이 납니다. 반복이 많은 코딩 에이전트가 이 조건에 잘 맞습니다.

에이전트별 상한을 한 번 재 두면 계속 써도 되나요?

미리 잰 상한은 천장 역할이라 비교적 안정적이지만, 실시간 배율이 그 안에서 현장에 맞춰 움직입니다. 다만 역할 구성이나 수정 포맷, 반복 패턴이 바뀌면 천장 자체가 어긋납니다. 파이프라인을 손본 뒤에는 상한을 다시 재는 편이 안전합니다.

특정 모델에서만 효과가 나나요?

특정 모델 전용 기법이 아닙니다. 서로 다른 여러 모델과 서로 다른 검색 엔진 위에서 모두 구현해 효과를 확인했습니다. 다만 폭은 모델·배치·워크로드에 따라 출렁이므로, 내 설정에서 소규모로 먼저 재 보고 판단하는 게 맞습니다.

참고자료