"다음 단어 예측"만으로는 부족하다 — LLM 추론 전 과정

← 전체 목차 · 이전: QKV를 1분 만에 이해하기 · 다음: 메모리를 삼키는 주범 — KV Cache

"대규모 모델이 추론 단계에서 무엇을 하는가"라는 질문에 "다음 단어를 예측한다"만 답하면 핵심 점수를 받지 못한다. 그것은 결론이지 답이 아니다. 요구되는 것은 과정이다 — 입력이 어떻게 행렬이 되고, 어떻게 token 단위로 순환하며, 어떻게 최적화하고, 어떻게 단어를 고르는가.

전처리 1: 분절(Tokenization)

모델은 한글도 한자도 이해하지 못한다. 그 세계에는 차가운 숫자 뭉치만 있다. 첫 단계는 "번역"이다 — 일상 언어를 작은 조각들로 자르는 것.

예: 안녕하세요, 대규모 모델안녕하세요 / , / 대규모 / 모델 4개의 token. 구두점도 별도의 token을 차지한다.

전처리 2: 임베딩(Embedding)

잘라낸 조각들을 긴 숫자 벡터로 변환한다.

Token벡터(앞 3차원만 표시)
안녕하세요[0.2, -0.1, 0.9, ...]
,[-0.5, 0.3, 0.1, ...]
대규모[0.8, 0.4, -0.2, ...]
모델[-0.1, 0.9, 0.5, ...]

분절 + 임베딩 두 단계를 마치면 입력 전체가 거대한 수학 행렬이 되고, 그제서야 모델이 진짜로 "머리를 쓰기" 시작한다.

자기회귀 생성: 본질은 "끝말잇기"

한 문장을 한 번에 다 쓰는 것이 아니라 한 글자씩 밖으로 내보낸다.

프롬프트
  └→ 층층이 순전파 → 다음 글자로 가장 가능성 높은 것을 추측
      └→ "오"를 산출
          └→ 프롬프트 + "오" → 다시 모델에 투입
              └→ 다음 글자가 "늘"인지 추측
                  └→ 프롬프트 + "오늘" → …(계속 순환)
                      └→ 특정 【종료 토큰】을 생성하면 전체 과정 종료
  • 핵심: 매 라운드의 입력 = 원래 프롬프트 + 이미 생성된 전부이므로 시퀀스는 점점 길어진다.
  • 종료 조건은 모델 스스로 "이제 멈춰야 한다"고 판단하는 것, 즉 종료 토큰(EOS) 생성이지 외부에서 멈추라고 외치는 것이 아니다.

추론 최적화: KV Cache

자연히 따라오는 의문 — 한 글자 추측할 때마다 앞의 모든 내용을 다시 봐야 한다면 끔찍하게 느리지 않은가? 실제로 그렇다.

비유: 소설을 읽다가 두 번째 페이지에 왔을 때 첫 페이지를 처음부터 한 글자씩 다시 읽지는 않는다. 앞의 줄거리가 머릿속에 남아 있기 때문이다 — 처음부터 다시 읽을 필요가 없다.

메커니즘: 앞서 이미 계산한 주의력 행렬을 반복 계산하지 않도록, 계산해 둔 중간 데이터를 GPU 메모리에 저장한다.

본질: 전형적인 공간-시간 교환.

새 글자의 주의력  +  캐싱된 과거 데이터  →  다음 글자 출력

디코딩과 샘플링 전략

모델이 매 단계에서 실제로 산출하는 것은 수만 개 단어의 확률 분포다. 거대한 추첨 상자가 눈앞에 놓인 것과 같으며, 어떤 단어를 출력으로 고를지는 디코딩 전략이 결정한다.

디코딩 전략방식특징
그리디 서치(Greedy Search)항상 확률이 가장 큰 단어를 선택경직됨, 앵무새 같음, 다양성 부족
샘플링(Sampling)확률에 따라 무작위 추출더 자연스럽고 다양하며 반복을 피함

온도 파라미터(Temperature)

온도표현
낮음더 엄밀하고 결정성이 높음
높음더 발산적이고 창의적이며, 동시에 정색하고 헛소리할 가능성도 커짐

핵심 통찰

  1. "다음 단어 예측"은 결론이지 답이 아니다 — 요구되는 것은 과정이다. 입력이 어떻게 행렬이 되고, 어떻게 token 단위로 순환하고, 어떻게 최적화하고, 어떻게 단어를 고르는가. 한 줄 결론을 네 단락의 파이프라인으로 펼쳐내는 것이 점수를 받는 자세다.
  2. 추론 단계는 한 번의 순전파가 아니라 상태를 가진 순환이다 — 매 라운드의 입력이 "원래 프롬프트 + 이미 생성된 내용"이므로 시퀀스는 단조 증가한다. 이 점을 이해하면 이후의 모든 성능 문제(길이에 따른 지연 증가, 길이에 따른 메모리 증가)를 스스로 도출할 수 있다.
  3. KV Cache의 본질은 "공간으로 시간을 사는" 고전적 엔지니어링 트레이드오프다 — 수학적 결과를 바꾸지 않고, 이미 계산한 K/V 중간량을 캐싱해 매 단계의 중복 계산을 "전체 시퀀스"에서 "새 token 하나"로 낮춘다. 최적화를 물으면 먼저 재사용 가능한 중간 결과가 있는지 생각할 것.
  4. "공간을 바꾼" 이상 공간이 새로운 병목이 된다 — 입력이 100만 token이면 KV Cache는 「시퀀스 길이 × 층수 × 주의력 헤드 수」에 비례해 팽창하고 메모리가 먼저 버티지 못한다. 장점에서 대응되는 대가를 스스로 도출할 수 있는지가 초급과 중급 답변의 분수령이다.
  5. 생성 품질 문제는 모델이 아니라 디코딩 전략에 있는 경우가 많다 — 모델이 출력하는 것은 확률 분포이며, "앵무새"나 "경직됨"은 말을 못 해서가 아니라 그리디 서치가 언제나 argmax를 취하기 때문이다. 문제를 진단할 때 **"분포 자체가 나쁜지" vs "분포에서 잘못 고르는지"**를 먼저 구분할 것.
  6. 온도는 "결정성 ↔ 창의성"의 다이얼이지 "똑똑함 ↔ 멍청함"의 다이얼이 아니다 — 온도가 높으면 창의성과 함께 환각 위험도 필연적으로 따라온다. 둘은 같은 뿌리다. 엄밀한 작업(추출, 분류, 코드)은 온도를 낮추고, 창작 작업에서만 높인다.
  7. 좋은 기술 표현은 비유에 기댄다 — "끝말잇기"로 자기회귀를, "소설 둘째 페이지에서 첫 페이지를 다시 읽지 않는다"로 KV Cache를, "거대한 추첨 상자"로 확률 분포를 설명한다. 현장에서 정확한 비유를 낼 수 있다는 것은 외운 것이 아니라 이해했다는 증거다.

엔지니어링 실전 Tips

  • 추가 질문의 인터페이스를 스스로 건네줄 것: KV Cache를 설명하고 나서 "대가는 메모리다"를 먼저 보태면, 대화를 자신이 준비해 둔 메모리 병목·처리량 최적화 영역으로 끌어올 수 있다.
  • 두 종류의 성능 지표를 구분할 것: 첫 token 지연(입력 전체의 계산량이 지배하는 prefill 단계)과 이후 token당 지연(메모리 대역폭이 지배하는 decode 단계). KV Cache가 주로 최적화하는 것은 후자다.
  • 롱컨텍스트 시나리오에서는 메모리 계산부터: KV Cache 크기 ≈ 시퀀스 길이 × 층수 × KV 헤드 수 × head_dim × 2(K와 V) × 정밀도 바이트 수. 시퀀스가 길어지면 모델 가중치 자체보다 커진다.
  • 프로덕션 서비스의 기본 파라미터: 결정성 작업(정보 추출, SQL·코드 생성, 분류·태깅)은 낮은 온도 또는 그리디로, 카피·브레인스토밍은 높은 온도 + 샘플링으로. 같은 모델도 온도를 바꾸면 두 가지 인격이 된다.
  • 모델이 "반복"하면 먼저 모델을 탓하지 말 것: 디코딩 설정이 순수 그리디이거나 온도가 지나치게 낮게 잡혀 있는지 먼저 확인하고, 그다음에 반복 페널티 같은 파라미터를 고려할 것.
  • 분절 단계도 비용이다: 구두점 하나도 token 하나를 차지한다. 프롬프트의 체감 길이와 실제 token 수는 자주 어긋난다.