프롬프트를 입력하면 몇 백 밀리초 뒤에 토큰이 스트리밍으로 나오기 시작합니다. 겉보기엔 단순하지만, 내부에서는 서로 병목이 다른 두 추론 단계가 연속으로 실행됩니다. 이 글은 해당 구조를 1차 원리(First Principles) 관점으로 정리한 글입니다.
원문: https://x.com/akshay_pachaar/article/2050941458614751327
1) LLM의 기본 루프: “다음 토큰 하나” 예측
LLM은 본질적으로 다음 토큰 확률 분포를 계산하고, 샘플링한 토큰을 다시 입력 뒤에 붙여 반복합니다. 이 단순한 반복이 긴 응답을 만듭니다.
2) 텍스트가 숫자가 되는 과정
Tokenization
- 입력 문자열을 토큰으로 분해하고 각 토큰을 정수 ID로 매핑합니다.
- 같은 길이의 문장이라도 언어/표기 방식/토크나이저 학습 커버리지에 따라 토큰 수가 달라집니다.
- 토큰 수 증가는 곧 비용/지연 증가로 이어집니다.
Embedding + Position Encoding
- 토큰 ID는 임베딩 테이블에서 고차원 벡터로 변환됩니다.
- attention은 순서를 자체적으로 모르기 때문에, RoPE 같은 위치 정보가 함께 주입됩니다.
3) Transformer 레이어에서 실제 추론이 일어나는 방식
각 레이어는 크게 두 작업을 합니다.
- Self-Attention: 토큰 간 정보 교환
- Feed-Forward Network: 토큰 내부 비선형 변환
핵심 직관은 “각 토큰이 문맥 전체를 참고해, 지금 필요한 정보만 가중합해 가져온다” 입니다.
4) 왜 첫 토큰은 느리고, 그다음 토큰은 빠른가?
Prefill (Time To First Token: TTFT)
- 프롬프트 전체 토큰을 한 번에 병렬 처리
- 큰 행렬 연산 중심 → compute-bound
- GPU 연산 유닛 활용률이 높음
Decode (Inter-Token Latency: ITL)
- 토큰을 1개씩 생성하는 반복 루프
- 이전 토큰의 K/V는 캐시 재사용, 새 토큰만 계산
- 계산량보다 메모리 접근 비중이 커짐 → memory-bound
즉, 같은 모델/같은 GPU라도 단계별 성능 지배 요인이 완전히 달라집니다.
5) KV Cache: 속도를 만든 대신 메모리를 먹는 장치
KV 캐시는 레이어별로 과거 토큰의 Key/Value를 저장해 재계산을 피합니다.
- 장점: 긴 생성에서 큰 속도 향상
- 단점: 토큰이 늘수록 캐시가 선형 증가해 VRAM 압박 증가
긴 컨텍스트가 비싸고 느려지는 이유는 “모델이 멍청해서"가 아니라, 대부분 “캐시가 무거워져 메모리 병목이 심해져서"입니다.
6) 최신 최적화 방향
- KV 캐시 양자화(INT8/INT4)
- Sliding Window Attention(오래된 토큰 축소)
- Grouped-Query Attention(K/V 공유로 캐시 축소)
- PagedAttention(vLLM)(캐시 메모리 페이지 관리)
- Speculative Decoding(작은 모델 초안 + 큰 모델 검증)
- Continuous Batching(다중 사용자 토큰 단위 인터리빙)
최근 연구 흐름은 “attention 품질"뿐 아니라 “캐시 자체를 작게 설계"하는 방향으로 이동 중입니다.
7) Quantization: 가장 실무적인 성능 레버
가중치 정밀도를 낮추면 메모리 사용량과 메모리 전송 비용이 줄어듭니다.
대략적으로 7B 모델 기준:
- FP32: 28GB
- FP16: 14GB
- INT8: 7GB
- INT4: 3.5GB
실무에서는 품질 저하를 관리 가능한 수준으로 유지하면서 지연과 비용을 크게 낮출 수 있어, 양자화가 가장 우선순위 높은 최적화로 취급됩니다.
8) 운영 관점 체크리스트
모델이 “느리다"는 피드백을 받으면 먼저 둘 중 무엇인지 분리하세요.
- 시작이 느리다 → TTFT 이슈 (Prefill 최적화)
- 스트리밍이 느리다 → ITL 이슈 (Decode/메모리/KV 캐시 최적화)
이 구분 하나만으로도 문제 정의와 해결 우선순위가 훨씬 선명해집니다.