LLM 추론 인프라와 토큰 경제학 — 모델은 하드웨어의 그림자
노정석 · 최승준
Dwarkesh×Reiner Pope의 칠판 강연을 3일 공부해 풀어낸 추론 인프라 정주행 — prefill·decode·KV cache·MoE 기초부터 NVL72 랙·HBM 20TB의 하드웨어까지. t_compute와 t_mem 두 수식으로 latency·토큰당 비용·최적 배치(300×sparsity)를 도출하고, 200K 가격 티어·캐시 계층·input/output 가격차를 역산한다. 프론티어 랩의 진짜 moat는 서빙 엔지니어링이라는 결론.
EP 96: LLM 추론 인프라와 토큰 경제학 — 모델은 하드웨어의 그림자
생각 덩어리
추론의 시대 — Dwarkesh 칠판 강연과 DeepSeek 복선
Dwarkesh가 포맷을 바꿨어요. 갑자기 칠판을 가지고 와서 판서를 하면서 가르쳐 주는 그런 형태의 포맷을 새로 했는데요. 그 내용이 굉장히 좋았습니다.
이제는 training보다 추론이 훨씬 중요해진 시기가 왔기 때문에 그 추론이 어떻게 일어나는지에 대해서 한번 깊게 배워볼 필요가 있는데, 이번 Dwarkesh 에피소드가 정확하게 그 내용을 이야기하고 있습니다.
요새 100만 토큰의 context length를 프론티어 랩들이 다 제공을 하고 있는데 사실 100만은 굉장히 비싼 서빙이거든요.
이 DeepSeek이 computation과 메모리 사용에 있어서도 context가 커지더라도 매우 효율화했다. computation은 3분의 1, 메모리는 10분의 1로 줄였는데
NVL72와 랙당 20TB — 5T·10T 모델이 갑자기 가능해진 이유
이 Blackwell NVL72 GPU 간 통신이 예전에는 8개까지만 됐는데 지금은 72개가 됐고
지금 나오고 있는, 작년부터 올해 막 출하되고 있는 GB200이나 GB300은 메모리가 192GB에 막 288GB짜리도 있고 이러거든요.
요즘 만나는 모델이 왜 확 4.5, 4.6쯤부터 달라졌는가가 설명이 되는 거죠.
그런데 지금 갑자기 나오고 있는 모델들은 막 5T 모델에 10T 모델, 이런 모델 사이즈가 갑자기 확 커졌단 말이에요.
가격표의 수수께끼 — 모델은 하드웨어의 그림자
input token과 output token은 가격 차이가 있고, 심지어 이 가격 차이도 어떤 데는 얼마 안 나고 어떤 데는 많이 나요.
심지어 Gemini 같은 걸 보다 보면 context length가 200K, 그러니까 20만까지는 좀 괜찮다가 20만 넘으면 다른 가격 티어로 받는 이런 가격표들도 있거든요.
계산에 걸리는 시간과 이 메모리를 recall하는 데 걸리는 시간, 이 두 개의 조합으로 현대의 LLM inference의 모든 가격이 결정이 된다.
AI 모델은 이 하드웨어의 그림자다. 이렇게 발전하고 모델이 그렇게 발전하기 때문에 하드웨어가 그런 방향으로 틀기도 하고, 하드웨어가 그렇게 되어 있기 때문에 모델이 그걸 fully utilize하기 위해서 바뀌기도 하죠.
prefill과 decode — 이해하면 졸업
사실 prefill과 decode의 개념이 이해가 되시면 졸업해도 되는데
그게 트랜스포머에 들어가서 이 모델이 그다음 토큰을 뱉어내기 위해서 선준비를 해야 되잖아요. ... 그 선준비를 하는 과정이 저희가 prefill이라고 보시면 돼요. 그리고 그 prefill이 대부분 긴 input token에 관한 내용이라고 생각하시면 얼추 맞습니다.
QKV에서 Q는 한 번 사용하고 버려지는 거고, KV는 뒤로 갈수록 뒤에 있는 query 토큰들이 앞에 있는 KV들을 전부 다 봐야 되잖아요. 그래서 하나씩 다 저장하는 거라고 생각하시면 맞을 것 같아요.
KV cache — 층마다 토큰마다 쌓이는 재활용 자산
입력이 만약에 100글자였다. 100글자마다 한 레이어에서 다 KV가 붙고, 그다음 레이어에서 또 KV가 붙고, 61번 그 KV가 100글자마다 다 붙는다고 대강 생각하시면 되거든요.
그 모든 층에 QKV가 만들어지고, KV는 남겨 놔요. 나중에 다시 계산하기 위해서.
좋은 아이디어는 이미 앞에 KV들은 앞에 것들 다 계산해 두었다는 거거든요. 재활용할 수 있다. query는 그 새로 생긴 한 토큰에 대해서 다시 생기지만 나머지는 이미 있던 걸 쓰고, 새로 생긴 토큰의 KV를 거기에다 합쳐주는 그런 방식으로 진행이 됩니다.
QKV는 저자의 설계 — 의미를 묻지 말 것
QKV의 어떠한 의미에 대해서 이해하시려고 하면 어려워져요. 이거는 트랜스포머의 저자가 “이거 토큰들이 들어오는 것들을 그 안에서 서로의 연관성을 계산하게 하려면 어떻게 해야지?”라고 하면서 그냥 자신들이 구조적으로 만든 일종의 bias입니다.
그렇게 만들어 놓은 일종의 inductive bias, 저희가 그냥 어떤 저자의 설계라고 생각하시면 맞아요.
얘가 왜 이렇게 되면 query가 되고 key가 되고 value가 돼요라는 질문은 하시지 말고 넘어갑시다.
MoE의 오해 — expert는 과목 전문가가 아니다
저 MLP 부분이 예전에는 큰 하나의 블록이었고, 그 모든 것들을 다 계산을, dense하다는 표현을 했죠. 촘촘하다고, 다 계산했어야 됐는데 MoE가 이제 걔를 쪼개 놓은 거죠.
expert라는 개념이 전문가니까 내가 수학을 물어보면 수학은 어떤 expert가 처리하고, 물리를 물어보면 어떤 건 다른 expert가 처리해서 expert가 지식들을 담고 있는 다른 단위인가 보다라고 생각하시는 분들이 있는데 그렇지 않습니다. “I am a boy.” 라고 치더라도 그게 다 각자 다른 expert를 지나갈 가능성이 있습니다.
그런 거가 왜 그러냐라고 물어보시면 저희도 몰라요.
랙 안은 빠르고 랙 밖은 느리다 — NVLink와 통신 병목
이 안에서의 계산은 굉장히 NVLink 같은 걸로 빠르게 되고, 요새 NVSwitch라는 게 또 있더라고요. 빠르게 되는데 랙 사이에는 이게 좀 오래 걸리고 멀어지는 것 같습니다.
사실 랙 안에서는 서로 GPU들끼리 통신하는 게 빠르고 랙 밖으로 넘어가면 느려지니까 가장 빠른 네트워크 안에서 처리하는 게 무조건 답이겠네요.
roofline — t_compute와 t_mem, 큰 쪽에 bound
저희가 결국은 그냥 Codex나 Claude Code나 아니면 ChatGPT에다 뭘 글을 쓰고 엔터를 딱 누르면 그게 돌아오는 결과가 나오는 시간이 있잖아요.
첫 토큰 나오는 시간이 또 미묘하게 다르지 않나요?
LLM이 무언가를 이렇게 결과를 내는 데 걸리는 시간은 t_mem과 t_compute, 이 두 개로 얘기를 하거든요. 그래서 메모리 시간과 compute 시간, 그 둘 중에서 많이 걸리는 거에 제한이 된다, bound 된다
추론의 batch — 한 열차에 승객을 꽉꽉 채운다
batch를 한 유저라고 가정했을 때 어떤 유저는 “Hi”라고 한 문장을 쓸 수도 있고, 어떤 유저는 그냥 Codex에서 막 50K짜리 context를 던질 수도 있고, 어떤 유저는 그냥 한 단락일 수도 있고, 사실은 length가, 그러니까 길이가 너무 다 달라지잖아요.
스케줄러가 있고 메타 레이어가 있어서 그거를 “이 batch에 100번째 있는 거는 유저 최승준이고, 103번째 있는 토큰은 노정석이고, 누구 것인 토큰은 누구인 거고”라고 그 토큰들에 대한 인덱스를 다 갖고 있고
비싼 자원이기 때문에 놀면 안 되거든요. 놀면 안 되기 때문에 이 한 스텝, 스텝 돌 때마다 꽉꽉 채워서 돌려야 돼요. 그래서 GPU 사용률을 거의 한 70에서 80%를 돌려야 이게 남는 장사가 되는 거니까.
추론에서는 batch와 sequence를 그냥 하나로 다 펴버려서 그냥 그거를 하나의 열차로 두고 그 열차 안에 여러 유저들의 workload를 동시에 태우는 거죠.
두 개의 수식 — compute는 active만, memory는 전부
t_compute는 batch 곱하기 이 number of parameters, active parameters의 number에 bound 된다고 표현하기 위해서 이 표현을 쓴 거죠. 걔를 FLOPs, 초당 몇 번 계산할 수 있느냐로 나누면 거기에 걸리는 단위 시간이 나오겠죠.
그러면 memory time은 어떻게 결정이 되냐. 첫 번째로는 N_total인데 ... 얘는 다 들고 있어야 되잖아요. 계산할 때 메모리에 전체 이 모델 weight를 다 올려서 가지고 있어야죠.
계산할 때는 active한 것만 weight 끌어다 써서 하면 되는데, 메모리 계산할 때는 다 들고 있어야 된다는 거군요.
캐시 히트의 경제학 — 밥 먹고 오면 다시 prefill
KV cache는 시간 지나면 날아가는 거기 때문에 다시 prefill로 처음부터 앞에 입력까지 다 긁어가지고 다시 만들기도 할 거잖아요.
만약에 cache가 hit가 안 되면, 내가 뭐라고 말하고 엔터 탁 치고 갑자기 옆에서 누가 불러서 밥 먹고 와서 1시간 있다 오면 사실상 cache에서 다 날아가죠. 그런 경우에는 사실 다시 prefill인 거죠. ... 사실 input 토큰의 가격이 그때 다시 계산되니까 비싸죠.
근데 만약 cache에서 불러오는 거면, cache가 hit되면 싸게 가져올 수 있으니까 싸지는 거고, 이런 것들이 inference의 경제학이 있는 거죠.
PagedAttention — KV cache의 메모리 가상화
그 다른 부분들을 굉장히 효율화해서 하나의 memory block에 그냥 잔뜩 담아두게 만드는 게 사실은 vLLM이 만들었던 PagedAttention이라는 혁신이거든요.
그냥 하나의 block 단위로 나눠서 마치 저희가 pointer로 전부 그 KV cache들이 어디에 있는지 전부 찍어 놓는 거예요.
이런 것들을 그냥 어떻게 하나의 vectorized 연산으로 다 만들 거냐가 이 추론 과정의 정말 모든 거라고 봐도 무방하더라고요.
하나의 GPU를 정해진 시간에 그렇게 utilization을 maximize해서 2천 명씩 동시에 serving을 하지 않으면 저희가 이걸 20불씩 내고 쓸 수가 없는 거죠.
20TB의 배분 — 모델 5TB, KV cache 13~14TB
5T 모델을 승준님 말씀하신 것처럼 FP8으로 계산하면 걔가 모델을 그냥 fully 적재하는 데만 5TB 용량을 빼앗아 가죠. ... 그럼 나머지 15TB가 남잖아요.
많은 분들이 또 혼돈을 일으키시는 부분이, 그럼 거기에 모델 4개를 적재하면 되는 거 아니냐라고 말씀하시지만 아니죠.
무엇보다도 제일 크게 차지하는 거는 KV cache죠.
20TB 중에서 한 13, 14TB 정도는 KV cache에 할당하더라고요. 그리고 한 2TB 정도를 중간에 계산하는 activation variable들.
amortize와 latency lower bound — 한 번 올린 weight는 분할 상각
이 메모리를 한 번 올리고 나면 얘는 오래 쓰면 쓸수록 사실 거기에 들어간 비용을 상쇄할 수 있는 거니까 이 표현으로는 amortize한다고 분할 상각한다는 얘기를 회계 용어를 끌어와서 쓰는데
배치가 작을 때는 메모리에 bound되고 ... 배치가 커지면 이제 compute에 bound된다라는 intuition이 나오네요.
어떤 작은 task를 시작하더라도 이 weight를 다 로딩하는 시간은 기본으로 걸리기 때문에 이게 latency lower bound라고 얘기를 하는 거죠.
토큰당 비용 곡선 — 가격 역산이라는 새 관점
저는 이 부분은 이 다음 얘기는 태어나서 처음 들었어요. 저렇게 계산하면 되겠구나라는 거는 우리가 계산과 생각을 해 본 적이 없다라는 사실을 저도 알게 됐고
얘를 이해하고 나면 사실은 IDC 가격이, 하드웨어 가격을 저만큼 투입하고 제가 토큰당 얼마를 생성하는데 그 가격을 input token당 100만 토큰당 5불을 받고 그다음에 output token은 10불, 15불을 받고 이런 것들을 계산하면 그 프론티어 랩들의 inference farm의 어떤 경제성, 수율 이런 것들이 개선될 수 있겠다.
이분들이 reverse engineering 한 거잖아요, 일종의. 가격 가지고.
이분들도 roofline analysis라고 그러거든요. 그냥 천장에 어렴풋한 선을 가지고 큰 생각 실험을 해보는 거지 정확한 계산은 아니라는 얘기를 중간중간 몇 번을 합니다.
매직 넘버 300 — 최적 배치 2400의 산수
확실한 거는 H100, H200, GB200, GB300, Rubin 이렇게 가면서 모든 숫자는 다 좋아져요. FLOPs도 좋아지고 HBM 용량도 커지고 그리고 HBM의 대역폭도 커져요.
이 사람들도 그냥 guesstimation을 하는데 FLOPs / 메모리 대역폭의 크기는 하드웨어가 계속 발전함에도 불구하고 FP4를 가정했을 때 약 300의 배율을 유지하고 있다. 여기서 300이라는 숫자가 나온 거죠.
B는 저 300이라는 숫자와 sparsity를 곱한 거. 엄밀하게 얘기하면 sparsity로 나눈 숫자여야 되는 거죠. sparsity는 분수니까, 예를 들어 최신 sparsity가 막 8분의 1에서 12분의 1 되니까 예를 들어 8분의 1이다. 계산해 보면, 배치가 8 곱하기 300, 2400.
sparsity가 돈이다 — 배치는 동시 서빙 유저 수
저는 DeepSeek V4를 지금 메인 모델로 쓰고 있거든요. ... 이게 Claude Opus급이다. 그 급이다라고 말은 못 하지만 확실한 건 Claude Sonnet보다는 좋아요.
sparsity를 높이면 배치를 높게 쓸 수 있다. 배치를 높게 쓸 수 있다는 얘기는 뭐냐. 한 사이클당 서빙할 수 있는 유저의 숫자를 훨씬 늘릴 수 있다는.
어차피 GPU를 사서 NVIDIA한테 준 돈과 단위 시간당 들어가는 전기세는 고정이니 결국은 그냥 프론티어 랩 입장에서는 얘가 단위 시간당 더 많은 유저를 서빙하는 게 무조건 이익이라는 얘기거든요.
거꾸로 말하면 그만큼의 유저를 못 모으는 회사는 불리한 거네요.
20ms 연산 열차 — drain time이 정한 클럭
이 앞에 승강장에서 토큰들이 탔으면 걔가 한 번 쫙 다 연산을 하고 저 위에 승강장에서 내리는데 그때까지 걸리는 시간이 한 20ms가 되도록 조정한다고 얘기를 하고 있거든요.
이 drain time이라는 용어를 가져옵니다. 이 drain time이 HBM 메모리가 288GB인데 GB300 기준으로 걔 대역폭이 이제 20TB/s이니까 ... 그러면 분자로 second만 나올 거잖아요. 그 second가 20밀리세컨드다.
퉁 쳐서 20에서 30밀리세컨드 정도가 이 HBM이 전체 메모리를 한 번 다 읽어내는 시간이다. 그러니까 그게 20ms이니 20ms를 기준으로 한 사이클을 짜면 되겠다라는 걸 만든 거죠.
chunked prefill — 진짜 moat는 서빙 엔지니어링
심하게 요약을 하면 결국은 20ms에 한 번씩 출발하는 연산 열차에 배치의 최적치는 얼마다라고 얘기를 해 주는데 저 배치를 어떻게 놓치지 않고 꽉꽉 채워서 보낼 것이냐.
prefill이 굉장히 길어지면 사실은 하나짜리 decode하는 애들이 거기에 밀려날 가능성이 있기 때문에 prefill도 5만짜리 토큰이 들어오더라도 걔를 굉장히 잘게 쪼개서 여기저기 넣더라고요. 그렇게 넣어서 그걸 이제 chunked prefill이라고 부르던데
프론티어 랩들의 진짜 어떤 그들의 자산, moat라고 볼 수 있는 것들은 이런 엔지니어링 인프라 능력인 것 같아요. 이 엔지니어링 인프라 능력이 가장 핵심이 되어 가는 것 같아요.
어떻게 하드웨어를 잘 이해하고 사용자의 워크로드를 잘해서 이 serving throughput을 늘릴 수 있느냐라는 거는 이거는 굉장히 중요한 기술이다. 그리고 이것들을 이제 밖에 다 공유하지 않고 있죠.
200K 임계점 — 가격 티어는 memory-bound의 자백
computation은 아무리 빨라지더라도 메모리가 거기에 따라가지 못하기 때문에 전반적인 속도가 다 memory-bound로 떨어지는 그런 시점이 생기는데, KV cache의 길이 때문에 그게 이분들이 추정하건대 그 optimal point가 200k 정도 되는 것 같다.
200k가 넘어가면 그걸 처리하기 위해서 유저 숫자를 현저하게 적게 받아야 하는 그런 GPU 클러스터가 있는 거죠. 그리고 많은 코딩 워크로드나 이런 것들이 그쪽으로 배치되고 있을 가능성이 있고, 거기는 사실 제공자 입장에서는 좀 비싸게 받아야 되는 그런 영역인 거죠.
이런 것들을 가지고 역산을 주룩주룩 해보면 ... 랙 1대가 전체 토큰 처리하는 거에 약 1,000분의 1이 랙 1대, 그러니까 결국 랙이 1,000대쯤 있을 거다라는 추정도 해볼 수 있는 거다.
결국에는 가격을 비용 근처에서 선정하고, 왜냐하면 경쟁 상황이다 보니까, 그것 때문에 역산이 가능하다, 그런 뉘앙스를 얘기했던 것 같아요. 그런 프론티어 랩들이 의도치 않게 지금 정보를 주고 있었다.
캐시 계층 사다리 — HBM에서 HDD까지
제가 Claude Code로 작업을 하고 있어요. 그럼 그 작업을 계속하고 있을 때는 사실상 KV cache가 어떤 기계의 HBM에 올라가 있을 거잖아요. 그러면 내가 하는 작업들은 계속 그 기계로 보내는 게 무조건 유리하잖아요.
어떠한 기간 동안 예를 들어 1분은 HBM에서 그걸 잡고 있는 거죠. 메모리에서 그냥 기다리는 게 얘를 없애고 다른 유저의 워크로드를 받아버리는 것보다는 더 이익인 상황이 있으니까, 그게 cache 전략인데
내려버리는 단계가 CPU 옆에 있는 DRAM으로 내리는 거, 한 1단계. 다음 flash drive에 올리는 게 2단계. 아니면 진짜 전통적인 HDD에 내려버리는 게 4단계. 이런 식으로 하고, 그마저도 다 시간이 expire돼 버리고 나면 싹 없애버리고.
context 관리가 병목 — Claude Code 이전은 애들 장난
저희가 2년밖에 안 됐잖아요. 이게 AI 신기하다 뭐 하다라고 하더라도 Claude Code를 본격적으로 쓰기 전까지는 저는 다 애들 장난이었다고 생각하거든요.
중간에 tool call 한 번 갔다 오면 tool call이 읽어오는 정보도 전부 다 prefill해야 되는 데이터고, 그래서 context를 어떻게 manage하느냐가 가장 핵심적인 bottleneck이 돼버리고, 그것들이 가장 큰 기술 발전에 있어서 가장 중요한 요소가 돼버렸다는 생각이 들고요.
모델 training하는 거랑 별 상관이 없는 완전히 inference와 serving의 infrastructure 기술이거든요.
Dwarkesh의 공부법 — flashcard 자가 시험
Dwarkesh가 자기가 이거를 어떻게 공부했는지를 flashcard를 만들어서 한 거를 제가 번역을 Codex 시켜서 해봤습니다.
이게 자기가 맞춰보려고 이런 것들을 문제를 스스로 내고서는 알고 있나 모르나 그런 걸 확인하나 봐요.
이게 없으면 사실 금방 날아가는 거긴 해요. 이거 만들었다고 내 거가 되는 건 아니잖아요. 오늘 저희가 간만에 좀 머리에 열 나는, 생각 토큰이 많이 쓰이는 세션이었어요.
마무리 — 상상캠퍼스 전시와 포지션을 잡은 사람
(원본 말미 — 최승준의 수원 상상캠퍼스 어린이 체험 전시 소개. 손을 뻗어 행성·항성을 다루고 주먹을 쥐면 새 항성계가 생성되는 인터랙티브 작업.)
물론 이것도 AI들의 힘을 빌어서 만든 건데, 이렇게 손을 뻗쳐가지고 행성이라든가 항성 같은 것들을 조금 다뤄볼 수 있게 하는.
이 친구가 항상 어떻게 더 지식의 frontier를 더 전진시켜야 하는지, 그리고 그거를 좀 쉽게 이야기해서 대중에게 전달해야 하는지 무언가 명확하게 포지션을 잡은 것 같아요.
근데 보면 굉장히 열심히 공부를 해요. 인터뷰이 한 명 만나면 2주 정도를 공부한대요.