챗봇이 글자를 한 자씩 또박또박 뱉는 걸 보면서 왜 저렇게 느린지 궁금하셨다면, 이 글 하나로 답과 해결책을 같이 가져가실 수 있습니다. 요즘 추론 엔진들이 쓰는 투기 디코딩(speculative decoding) 은 답을 한 글자도 바꾸지 않으면서 속도만 2배에서 6배까지 올리는 기술인데, 원리 자체는 초등학생도 이해할 수 있을 만큼 단순합니다. 눈치 빠른 친구에게 먼저 써 보게 하고 선생님은 채점만 합니다.

LLM 추론 가속의 설계학, 추측 해독 표지 슬라이드 이 글에 실린 슬라이드는 원문을 소스로 NotebookLM이 자동 생성한 것입니다. 글을 따라 읽으면서 그림으로 한 번 더 확인하시라고 중간중간 넣었습니다.

글자 하나 쓰는 데 도서관을 한 번 다녀옵니다

큰 언어 모델이 문장을 만드는 방식은 생각보다 답답합니다. 한 글자를 정하면 그 글자를 다시 입력에 붙여서 처음부터 계산하고 그렇게 나온 다음 글자를 또 붙입니다. 백 글자짜리 답변이면 이 과정을 백 번 반복합니다.

여기까지는 많이 알려진 이야기인데, 진짜 문제는 그다음입니다. 한 번의 계산에서 시간을 잡아먹는 건 계산 자체가 아닙니다. 모델의 무게(가중치)를 메모리에서 계산 장치로 끌어오는 일이 훨씬 오래 걸립니다.

도서관에 비유해 보겠습니다. 선생님이 글자 하나를 쓰려면 서고에서 아주 무거운 책 수백 권을 꺼내 책상에 전부 펼쳐야 합니다. 그런데 정작 책을 읽는 시간은 눈 깜짝할 사이죠. 시간의 대부분은 책을 꺼내고 펼치는 데 들어갑니다. 그러고는 글자 하나를 쓰고 책을 도로 집어넣습니다. 다음 글자를 쓰려면 또 처음부터 꺼내야 합니다.

바보 같아 보이지만 달리 방법이 없죠. 다음 글자가 뭔지 알아야 그다음 글자를 계산할 수 있으니까요. 이 답답함을 전문 용어로는 메모리 대역폭 병목이라고 부릅니다. GPU의 계산 능력은 남아도는데 데이터를 나르는 통로가 좁아서 놀고 있는 상태입니다.

자기회귀 생성이 메모리 대역폭에 막혀 연산 능력이 유휴 상태가 되는 구조 도식 계산 능력은 남는데 통로가 막혀 있죠. 투기 디코딩은 바로 이 남는 능력을 씁니다.

눈치 빠른 친구를 옆에 앉힙니다

여기서 한 가지를 눈치채면 길이 열립니다. 모든 글자가 똑같이 어렵지는 않습니다.

“동해물과 백두산이 마르고” 다음에 뭐가 올까요? “닳도록”입니다. 이건 고민할 필요가 없습니다. 괄호를 열었으면 언젠가 닫아야 하고 “그래서 저는”까지 썼으면 다음은 대체로 뻔합니다. 반면 사람 이름이나 낯선 전문 용어, 문장의 방향을 바꾸는 접속사 같은 건 정말로 잘 생각해서 골라야 합니다.

쉬운 글자까지 선생님이 무거운 책을 다 펼쳐 가며 쓸 이유는 없습니다. 그래서 옆자리에 작고 빠른 모델을 앉힙니다. 이 친구를 드래프트 모델이라고 부릅니다. 크기가 작으니 책도 얇습니다. 그래서 훨씬 빨리 씁니다. 대신 가끔 틀립니다.

이 친구가 먼저 다섯 글자쯤을 쭉 써 놓습니다. 그러면 선생님은 그 다섯 글자를 채점합니다. 맞으면 통과시키고 틀린 지점부터는 지우고 자기가 씁니다.

초안 작성, 병렬 검증, 거부 샘플링 3단계를 나눠 그린 슬라이드 가벼운 초안, 한 번의 병렬 검증, 답을 지켜 주는 거부 샘플링. 이 세 가지가 전부죠.

다섯 글자를 채점하는 값이 한 글자와 거의 같습니다

이 방법이 왜 이득인지가 이 글에서 제일 중요한 대목입니다. 채점도 결국 선생님이 하는데 뭐가 빨라지느냐, 자연스럽게 나오는 질문이죠.

답은 이렇습니다. 책을 한 번 펼친 김에 다섯 글자를 같이 확인하는 건 거의 공짜입니다.

선생님이 한 글자를 쓸 때도 무거운 책을 전부 펼쳐야 하고 다섯 글자를 채점할 때도 똑같이 한 번만 펼치면 됩니다. 시간을 잡아먹던 건 책을 꺼내는 일이었으니까요. 책상에 펼쳐 놓은 상태에서 다섯 자리를 눈으로 훑는 건 원래 남아돌던 능력으로 처리됩니다. 앞에서 GPU의 계산 능력이 놀고 있다고 했는데, 투기 디코딩은 정확히 그 노는 능력을 쓰는 기술입니다.

그래서 이렇게 정리됩니다. 예전에는 다섯 글자를 얻으려면 무거운 책을 다섯 번 펼쳐야 했습니다. 이제는 얇은 책 다섯 번 더하기 무거운 책 한 번입니다. 얇은 책 다섯 번은 무거운 책 한 번보다 훨씬 쌉니다.

답이 바뀌지 않는다는 보장

여기서 걱정이 생깁니다. 친구가 쓴 글자를 그대로 쓰면 답이 나빠지는 것 아닐까요.

안 나빠집니다. 그리고 이게 이 기술의 진짜 매력입니다. 채점 규칙을 잘 만들어 두면 최종 결과물이 선생님이 혼자 처음부터 끝까지 쓴 것과 통계적으로 완전히 똑같아집니다.

규칙은 이렇습니다. 어떤 글자에 대해 친구가 매긴 확신을 q, 선생님이 매긴 확신을 p라고 합시다. 채점은 두 숫자를 비교합니다.

선생님이 그 글자를 쓸 마음이 친구보다 크거나 같으면(p가 q 이상이면) 무조건 통과입니다. 친구가 겸손했던 셈이니 문제가 없습니다. 반대로 친구가 너무 자신만만했다면(q가 p보다 크면), 그 차이만큼만 확률적으로 지웁니다. 정확히는 p를 q로 나눈 값의 확률로 통과시킵니다. 친구는 0.9의 확신으로 썼는데 선생님은 0.45밖에 확신이 없었다면 절반의 확률로만 통과하는 셈이죠.

그리고 지웠을 때가 중요합니다. 그냥 선생님이 평소대로 다시 뽑으면 안 됩니다. 이미 한 번 걸러진 상태라 확률이 기울어져 있기 때문입니다. 그래서 선생님의 확신에서 친구의 확신을 뺀 남은 몫에서 다시 뽑습니다. 음수가 되는 부분은 0으로 자릅니다. 그리고 전체를 다시 1이 되게 맞춘 뒤 뽑습니다.

이 두 가지를 지키면 수학적으로 원본과 같은 분포가 나옵니다. 품질을 속도와 맞바꾼 게 아니라, 그냥 공짜로 빨라진 겁니다.

몇 글자를 미리 쓰게 할까요

친구에게 미리 쓰게 할 개수를 늘리면 무조건 좋을까요. 그렇지가 않습니다.

친구가 한 글자를 맞힐 확률을 70%라고 해 봅시다. 첫 글자가 통과할 확률은 70%입니다. 둘째 글자까지 살아남으려면 첫째도 맞고 둘째도 맞아야 하니 49%입니다. 셋째는 34%, 넷째는 24%로 뚝뚝 떨어집니다. 앞 글자가 지워지는 순간 뒷글자는 문맥이 달라져서 전부 버려지기 때문입니다.

그래서 열 글자를 미리 쓰게 해도 평균적으로 살아남는 건 서너 개뿐입니다. 나머지는 친구의 헛수고인데 그 헛수고에도 시간은 듭니다. 한 회차에 평균 몇 글자가 통과하는지를 나타내는 값을 τ(타우)라고 부르는데, 미리 쓰는 개수를 아무리 늘려도 τ는 어느 지점부터 거의 늘지 않습니다.

드래프트 적중률에 따른 평균 통과 길이 곡선. 적중률이 낮으면 미리 쓰는 개수를 늘려도 곡선이 겹칩니다. 적중률이 40% 근처면 3개를 미리 쓰든 7개를 미리 쓰든 결과가 거의 같습니다. 개수를 늘려서 이득을 보려면 친구가 먼저 똑똑해져야 합니다.

지연 시간 공식 L = (T_draft + T_verify) / tau 를 시소로 표현한 슬라이드 한 글자당 걸리는 시간은 초안 시간과 채점 시간을 합쳐 평균 통과 길이로 나눈 값. 결국 분모를 키우는 싸움입니다.

이 그림이 지난 몇 년간의 연구 방향을 그대로 설명합니다. 미리 쓰는 개수를 늘리는 건 금방 한계에 부딪히니까, 사람들은 친구를 더 잘 맞히게 만드는 쪽으로 갔습니다.

친구를 만드는 방법이 계속 좋아졌습니다

처음에는 단순했습니다. 같은 계열의 작은 모델을 하나 더 데려와 앉히는 방식입니다. 추가 학습이 필요 없어서 편하고 2배에서 3배 정도 빨라지지만, 모델을 두 개 띄워야 하니 GPU 메모리를 그만큼 더 씁니다.

독립 초안 모델 구조와 2배에서 3배 가속을 보여주는 슬라이드 작은 모델을 하나 더 띄우는 가장 단순한 형태. 편한 대신 메모리를 두 배로 씁니다.

그다음에 나온 Medusa는 친구를 따로 두는 대신 선생님 머리에 손을 여러 개 달았습니다. 각 손이 두 번째, 세 번째, 네 번째 글자를 동시에 예측합니다. 2.2배에서 3.6배가 나왔는데 약점이 있었습니다. 손끼리 서로 상의를 하지 않아서 뒤쪽 손일수록 엉뚱한 글자를 내놓습니다.

Medusa와 MTP의 다중 헤드 예측 구조 슬라이드 본체에 손을 여러 개 답니다. 손끼리 상의를 안 하는 게 한계죠.

MTP(다중 토큰 예측) 는 그 손들을 완성된 모델에 나중에 붙이지 말고 처음 배울 때부터 같이 키우자는 접근입니다. 덤으로 본체 모델의 실력까지 좋아지는 효과가 있어서, 추론이 3배 빨라지는 건 오히려 부산물에 가깝습니다.

지금 가장 널리 쓰이는 건 EAGLE 계열입니다. 발상의 전환이 하나 있었습니다. 친구에게 “다음 글자가 뭘까”를 묻는 대신, “선생님 머릿속이 다음에 어떤 상태가 될까”를 묻습니다. 글자보다 머릿속 상태를 물려받는 편이 훨씬 잘 맞았습니다. 여기서 2.7배에서 3.5배가 나왔습니다. 뒤이어 나온 EAGLE-2는 친구가 자신 없어 할 때 여러 갈래를 동시에 준비해 두는 방식으로 3.05배에서 4.26배까지 올렸습니다. EAGLE-3는 다시 글자 예측으로 돌아오되 학습할 때부터 실전과 똑같은 조건으로 연습시켜서 최대 6.5배를 보고했습니다.

EAGLE 계열이 숨겨진 상태를 기반으로 초안을 만드는 구조 슬라이드 글자가 아니라 선생님 머릿속 상태를 물려받는 방식. 지금 가장 널리 쓰입니다.

가장 최근에 나온 DFlash는 아예 다르게 접근합니다. 글자를 하나씩 순서대로 쓰는 대신 한 덩어리를 통째로 한 번에 만들어 냅니다. 확산 모델이 이미지를 흐릿한 상태에서 점점 또렷하게 만드는 것과 비슷한 방식을 글자 블록에 씁니다. 평균 4배에서 6배가 나옵니다. 친구를 더 크게 키울수록 잘 붙습니다.

DFlash의 블록 병렬 확산 드래프팅을 표현한 슬라이드 한 글자씩 계단을 오르는 대신 블록을 통째로 내려놓는 쪽으로.

여기에 DSpark를 하나 더 얹으면 최근 흐름이 보입니다. 이 방식은 초안을 더 잘 만드는 데 매달리지 않습니다. 대신 지금 서버에 요청이 얼마나 몰려 있는지와 친구가 얼마나 자신 있어 하는지를 같이 보고 채점을 언제 할지 조절합니다. 한 사람이 체감하는 속도를 60%에서 85%까지 올렸는데, 대신 챙길 게 늘어서 구현이 복잡해집니다.

DSpark의 신뢰도 기반 검증 스케줄링을 표현한 슬라이드 초안을 더 잘 만드는 대신 채점 일정을 짭니다. 최근 연구가 옮겨 간 방향이죠.

방식 초안을 만드는 법 한 회차 평균 통과 속도
별도 작은 모델 한 글자씩 순서대로 약 3.6 2배에서 3배
Medusa 여러 손이 동시에 3.0에서 3.5 2.2배에서 3.6배
EAGLE-3 한 글자씩 순서대로 5에서 7.5 최대 6.5배
DFlash 블록을 통째로 4에서 8 6배 이상
DSpark 반자기회귀 + 채점 일정 조절 3.1에서 6.2 사용자 체감 1.6배에서 1.85배

손님이 많아지면 효과가 줄어듭니다

여기서 많이들 걸려 넘어지는 지점이 있습니다. 논문에 적힌 6배를 기대하고 켰는데 실제 서비스에서는 별로 빨라지지 않는 경우입니다. 대개 이유는 하나입니다.

도서관에 나 혼자 있을 때는 책을 꺼내는 시간이 정말 아깝습니다. 그런데 손님이 백 명 줄을 서 있으면 이야기가 달라집니다. 책을 한 번 꺼내서 백 명 몫을 한꺼번에 처리하니까, 책 꺼내는 비용은 이미 백 명이 나눠 부담하고 있습니다. 아까울 게 없어진 겁니다.

배치 크기가 커지면 가속 효과가 떨어지는 곡선 슬라이드 동시 요청이 늘수록 곡선이 내려앉습니다. 오른쪽 빗금 구간이라면 켜도 얻는 게 거의 없죠.

투기 디코딩은 동시 사용자가 적을 때 가장 크게 이깁니다. 사용자가 많아져서 GPU 계산 능력이 이미 꽉 찬 상태라면, 남는 능력을 쓰겠다는 이 기술의 전제 자체가 사라집니다. 심하면 초안 만드는 비용만 더해져서 손해가 나기도 합니다.

그래서 판단 기준은 이렇게 잡으면 됩니다. 한 사람의 응답이 얼마나 빨리 오는지가 중요한 서비스라면 켤 만합니다. 대화형 챗봇, 코딩 도우미, 여러 단계를 거치며 스스로 판단하는 에이전트가 여기 해당합니다. 반대로 밤새 대량으로 문서를 처리하는 배치 작업이라면 굳이 켜지 않아도 됩니다.

직접 켜 보기

요즘 주요 추론 엔진은 전부 지원합니다. vLLM, SGLang, llama.cpp, MLX 모두 설정 한두 줄이면 됩니다. SGLang에서 DFlash 방식으로 띄우는 예시입니다.

python -m sglang.launch_server \
  --model-path <본체 모델 경로> \
  --speculative-algorithm DFLASH \
  --speculative-draft-model-path <드래프트 모델 경로> \
  --speculative-num-draft-tokens 5

켠 다음에는 로그에서 두 숫자를 확인하시면 됩니다. 하나는 적중률(acceptance rate)이고 다른 하나는 회차당 평균 통과 길이입니다. 통과 길이가 2를 못 넘고 있다면 친구와 선생님의 궁합이 안 맞는 상태라, 미리 쓰는 개수를 늘리기보다 드래프트 모델을 바꾸는 쪽이 맞습니다.

켜기 전에 확인할 순서

저희가 GPU 서빙을 운영하면서 비싸게 배운 게 하나 있습니다. 투기 디코딩은 마지막에 켜는 것이지 처음에 켜는 게 아닙니다.

2026년 8월에 저희 B200 장비에서 서빙 설정만 바꿔 가며 처리량을 측정한 적이 있습니다. 같은 모델, 같은 GPU, 같은 엔진인데 설정 두 개 때문에 단일 스트림 처리량이 18.8배 차이가 났습니다. 컴파일이 꺼져 있었고, 동시에 처리할 수 있는 요청 수가 기본값 32에 묶여 있었습니다. 초당 7.4 토큰이던 게 138.8 토큰이 됐습니다.

이 상태에서 투기 디코딩을 켜면 어떻게 될까요. 6배 빨라진다는 기술로 18.8배 손해를 메우려고 애쓰는 셈입니다. 순서가 뒤바뀐 겁니다. 기본 설정을 먼저 바로잡고, 그 위에서 투기 디코딩을 얹어야 이 기술이 원래 낼 수 있는 몫을 냅니다.

저희 추론 제품인 Metis는 이런 서빙 설정을 테넌트가 일일이 만지지 않아도 되게 다루는 게 일입니다. 그리고 이 기술이 특히 잘 맞는 곳이 Paxis 쪽입니다. 에이전트는 한 번의 요청을 처리하면서 도구를 부르고 결과를 읽고 다시 판단하기를 여러 번 반복하는데, 이때 동시 사용자 수는 대체로 적고 한 스텝의 지연이 그대로 체감 속도가 됩니다. 앞에서 말한 “손님이 적을 때 가장 크게 이긴다”는 조건에 정확히 들어맞습니다.

투기 디코딩을 이미 한 번 시험해 보고 접으셨다면, 저희가 같은 경험을 하고 다시 열어 본 기록도 함께 보시면 도움이 되실 겁니다. 투기 디코딩이 느려진 게 아니라 lookup이 안 맞았던 겁니다에서 방식 선택 하나로 11.9배가 갈린 과정을 정리해 두었습니다. DFlash 블록 확산 드래프팅vLLM에서 EAGLE 운영하기도 실제 설정 값을 담고 있습니다.

정리

투기 디코딩을 한 문장으로 줄이면 이렇습니다. 빠른 친구가 먼저 써 보고, 느리지만 정확한 선생님이 한꺼번에 채점합니다. 채점 규칙을 제대로 만들어 두면 답은 한 글자도 달라지지 않습니다.

방식별 초안 패턴, 평균 통과 길이, 보고된 가속 배수를 정리한 비교표 슬라이드 지금까지 나온 방식을 한 장으로 모으면 이렇습니다. 숫자는 각 연구가 보고한 값입니다.

기술의 흐름도 짚어 볼 만합니다. 처음에는 “친구를 어떻게 똑똑하게 만들까”가 전부였습니다. 별도 모델에서 시작해 선생님 머리에 손을 달았고, 글자 대신 머릿속 상태를 물려주는 데까지 왔습니다. 그런데 최근 연구들을 보면 질문이 바뀌고 있습니다. 여러 사용자가 몰릴 때 채점을 언제 어떻게 몰아서 할 것인가, 그러니까 초안 만들기보다 검증 일정 짜기가 더 어려운 문제로 올라오고 있습니다. 이 부분이 다음 몇 년의 싸움터가 될 것 같습니다.

이 글의 원본 설명은 Leonie Monigatti의 Speculative Decoding입니다. 수식과 논문 링크가 필요하시면 원문을 함께 보시길 권합니다.

태그: DFlash, EAGLE, LLMOps, 추측 디코딩, vLLM, 드래프트 모델, 입문, 추론 최적화, 투기 디코딩

카테고리:

업데이트: