LLM 동작 원리
토큰화, 임베딩, Self-Attention, 자기회귀 생성, 샘플링, KV Cache
LLM 동작 원리
토큰화, 임베딩, Self-Attention, 자기회귀 생성, 샘플링, KV Cache
AI가 생성하는 시대
파운데이션 모델이 바꾸는 소프트웨어 개발의 패러다임
LLM 동작 원리
토큰화 · 임베딩 · Self-Attention · 샘플링 · KV Cache
LLM 동작 원리 — 한눈에
토큰에서 답변까지 — 실무 설계의 근거가 되는 원리
LLM은 다음 토큰 하나를 고르는 기계
LLM(Large Language Model · 대규모 언어 모델)은 입력 텍스트를 토큰 → 벡터 → 문맥 → 확률 → 선택을 거쳐 한 토큰씩 출력합니다 — 각 단계가 비용·캐싱·컨텍스트 설계와 직결됩니다.
- 추론 파이프라인 7단계
- Temperature · Top-P 샘플링
- KV Cache — 프롬프트 캐싱의 원리
토큰은 비용으로, Attention은 컨텍스트 설계로, KV Cache는 프롬프트 캐싱으로 이어집니다 — 원리를 알아야 설계가 나옵니다.
발표자 노트
LLM을 한 문장으로 줄이면 다음 토큰 하나를 고르는 기계입니다. 이 단순한 정의에서 오늘 다룰 모든 것이 나옵니다. 원리를 배우는 이유는 시험이 아니라 설계 때문인데요, 토큰을 알면 비용이 보이고, Attention을 알면 컨텍스트 설계가 보이고, KV Cache를 알면 프롬프트 캐싱이 왜 싸고 빠른지가 보입니다.
추론 파이프라인 — 전체 그림
한 사이클에 토큰 하나 — 일곱 단계를 돌 때마다 답이 한 조각씩 자랍니다
"대한민국의 수도는 ___"
입력 — 다음 토큰은?
→
LLM — 일곱 단계
① 토큰화
→
② 임베딩·위치 인코딩
→
③ Self-Attention
→
④ FFN
Transformer 블록 ×N
⑤ Softmax·확률 분포
→
⑥ 샘플링
→
⑦ 자기회귀
→
서울
출력 — 빈칸을 채울 토큰 1개
↻
출력 토큰을 입력 끝에 붙여 다시 ①부터 — EOS(종료 토큰)가 나올 때까지 반복 · 100토큰 답변 = 이 순환 100번 (자기회귀)
7단계 전체가 다음 토큰 하나를 고르는 과정입니다.
발표자 노트
"대한민국의 수도는"까지 넣으면 모델이 "서울"이라는 토큰 하나를 내놓습니다. 그 한 번을 위해 안에서 일곱 단계가 돌아가고요. 가운데 점선 묶음, Self-Attention과 FFN이 논문에서 말하는 Transformer 블록이고, 실제 모델에서는 이 묶음이 수십 층 반복됩니다. 아래 순환 표시가 중요한데, 만들어진 토큰을 입력 끝에 붙여서 다시 처음부터 돕니다. 100토큰짜리 답변이면 이 순환이 100번 돈 결과인 거죠. 이 그림 하나만 기억하시면, 이어지는 상세 슬라이드들은 전부 이 순환의 확대판입니다.
추론 파이프라인 7단계
토큰화부터 자기회귀까지 일곱 단계의 원리와 그림
이어지는 예시
"대한민국의 수도는 ___" — 다음 토큰은?
일곱 단계가 이 빈칸 하나를 채웁니다
1. 토큰화
- → 토큰 수 = 비용 + 컨텍스트 한계
2. 임베딩 + 위치 인코딩
- → 이 벡터가 RAG 검색의 원리
3. Self-Attention
- → 컨텍스트 엔지니어링의 근거 (어디에 주목하는지)
4. FFN
5. Softmax + 확률 분포
- → Bedrock 추론 파라미터에서 조절하는 것
6. 샘플링
- → Bedrock 추론 파라미터에서 조절하는 것
7. 자기회귀 + KV Cache
- → 프롬프트 캐싱이 빨라지는 이유
발표자 노트
일곱 단계를 하나씩 열어보겠습니다. 토큰화가 문장을 조각내고, 임베딩이 조각을 벡터로 바꾸고, Attention이 문맥을 섞습니다. FFN을 지나면 Softmax가 후보들의 확률을 만들고, 샘플링이 하나를 고르고, 자기회귀가 그 결과를 다시 입력으로 돌려보내죠. 각 탭의 오른쪽 그림이 같은 예시 문장을 따라가니까, 빈칸 하나가 채워지는 과정으로 이어서 보시면 됩니다.
토큰화 — 모든 것의 단위
API 비용, 컨텍스트 한계, 응답 길이 — 전부 토큰 수로 결정
규칙
"unhappiness"
→
un
happiness
3토큰 — 사전에 없어도 조합
"안녕하세요"
→
안녕
하
세요
3토큰 — 한국어 비효율
= 돈
📥 입력·출력 토큰 수
×
토큰 단가
=
💵 API 비용
컨텍스트 윈도우 = 토큰 한도
같은 의미라면
한국어 7토큰
영어 6토큰
— 희귀 단어가 많으면 한국어는 글자당 2~3토큰까지
토큰 수 = 비용 + 컨텍스트 한계. 이 원리가 프롬프트 캐싱(비용 절감)과 컨텍스트 엔지니어링(한도 내 최적 배치)의 출발점입니다.
발표자 노트
토큰화에서 실무적으로 중요한 건 두 가지입니다. 위쪽의 BPE는 사전에 없는 단어도 조각으로 조합한다는 것, 그래서 신조어나 고유명사도 처리가 되는 겁니다. 아래쪽이 돈 이야기인데, API 요금과 컨텍스트 한도가 전부 토큰 수 기준입니다. 같은 의미라도 한국어가 영어보다 토큰을 더 쓰는 경향이 있어서, 한국어 서비스는 비용 견적을 잡을 때 이 점을 감안하셔야 합니다.
토큰화 장면 — 문장이 조각나는 순간
실제 문장 하나가 어떻게 토큰 ID 배열이 되는지 — 모델이 보는 그대로
"대한민국의 수도는 서울입니다"입력 문장
→
BPE 토큰화서브워드 병합
→
대한45021
민국38294
의1074
수도52014
는1123
서울31577
입니다12084
토큰 7개 · ID 시퀀스
→
LLM언어 모델
"The capital of Korea is Seoul"같은 의미의 입력
→
BPE 토큰화서브워드 병합
→
The464
capital6810
of295
Korea12801
is374
Seoul48213
토큰 6개 · ID 시퀀스
→
LLM언어 모델
발표자 노트
실제 문장이 조각나는 모습을 그대로 보시죠. "대한민국의 수도는 서울입니다"가 일곱 조각이 되고, 조각마다 사전 번호가 붙어서 모델에게는 이 ID 시퀀스만 전달됩니다. 모델은 글자를 본 적이 없다는 것, 이게 포인트입니다. 아래 영어 문장은 같은 의미가 여섯 조각이고요. 자주 쓰는 단어는 큰 조각으로 잡히고 희귀한 단어는 잘게 쪼개지는 게 BPE의 성질입니다.
임베딩과 위치 인코딩 — 의미를 벡터로
의미는 벡터 거리로, 순서는 회전각으로 — 토큰이 숫자가 되는 방식
공간
정보
개가 ↻1
사람을 ↻2
물었다 ↻3
— 개가 주체
사람이 ↻1
개를 ↻2
물었다 ↻3
— 사람이 주체
이 임베딩 벡터가 RAG 검색의 원리입니다 — 문서와 질문을 같은 벡터 공간에 놓고 코사인 유사도로 가장 가까운 것을 찾아 프롬프트에 주입합니다 (Bedrock Knowledge Bases, PART 4에서 다룹니다).
발표자 노트
토큰 ID는 그냥 번호라서 의미가 없습니다. 임베딩이 이 번호를 수천 차원 좌표로 바꾸면서 의미가 생기는데, 왼쪽 그림처럼 왕에서 남자를 빼고 여자를 더하면 여왕 근처에 떨어집니다. 의미 관계가 방향으로 보존되는 거죠. 오른쪽은 순서 문제인데, 개가 사람을 문 것과 사람이 개를 문 건 같은 조각들이라도 완전히 다른 사건이잖아요. Attention 자체는 순서를 모르기 때문에 RoPE가 위치마다 회전각을 새겨 넣습니다. 이 벡터 공간이 나중에 RAG 검색의 원리가 되니까 잘 기억해 두세요.
Self-Attention: 어디에 주목?
Q·K·V 행렬 연산으로 토큰 간 관련도를 계산
"는" 토큰 벡터
임베딩 — 아직 문맥 없음
→
SELF-ATTENTION 레이어
① Q·K·V 생성
→
② 관련도 점수 (Q·Kᵀ)
→
③ Softmax 정규화
→
④ × V 가중합
Q "무엇을 찾나" · K "무엇을 주나" · V "실제 정보" — 관련도를 합=1 가중치로 만들어 V를 섞습니다 (Multi-Head 병렬 주목)
→
문맥 반영 벡터
"는"에 수도·대한민국 문맥이 스며듦
예시 — 마지막 토큰 "는"의 주목 가중치
"대한민국의 수도는 ___"
Attention이 "어디에 주목하는지"를 결정합니다. 프롬프트 앞쪽/뒤쪽 배치, 컨텍스트 순서 설계가 중요한 이유 — 컨텍스트 엔지니어링의 근거입니다.
발표자 노트
임베딩까지는 토큰이 각자 따로 노는 상태입니다. Self-Attention이 여기에 문맥을 섞어주는데, 각 토큰이 질문 Q를 던지고 다른 토큰들의 K와 맞춰본 뒤 관련도만큼 V를 가져오는 구조입니다. 아래 예시를 보시면 "는" 토큰이 수도와 대한민국에 크게 주목하고 있죠. 그 결과 빈칸에는 도시 이름이 어울린다는 판단이 서는 겁니다. 모델이 어디에 주목하는지가 프롬프트에서 정보 배치 순서가 중요한 이유이고, 컨텍스트 엔지니어링의 근거가 됩니다.
Softmax와 Temperature — 분포 조절
로짓을 확률로 바꾸는 Softmax — Temperature가 분포의 뾰족함을 결정
"대한민국의 수도는 ___" 다음 토큰 후보의 로짓
서울 2.1
부산 1.2
대전 0.6
인천 −0.4
→
로짓 ÷ T → Softmax
→
확률 분포 (합 = 1)
Temperature는 정답을 바꾸는 게 아니라 분포의 뾰족함을 바꿉니다 — 낮으면 1등 독식(재현 가능), 높으면 후보가 고르게(다양성).
발표자 노트
모델의 마지막 출력은 후보마다 매겨진 점수, 로짓입니다. Softmax가 이걸 합이 1인 확률로 바꾸는데, 그 앞에서 Temperature로 나누는 게 핵심 장치입니다. 세 패널이 전부 같은 로짓이고 T만 다릅니다. 0.2면 서울이 86%로 거의 독식하고, 1.3이면 후보가 고르게 퍼지죠. Temperature는 정답을 바꾸는 게 아니라 분포의 뾰족함을 바꾼다, 이렇게 기억하시면 됩니다.
샘플링 전략 — 분포에서 토큰 고르기
Temperature로 만든 확률 분포에서 다음 토큰을 실제로 선택하는 세 가지 방법
같은 분포 (T=0.7)
서울 0.52 · 부산 0.26 · 대전 0.14 · 인천 0.08
— 전략의 차이는 "후보를 어떻게 남기느냐"
서울 0.52
부산
대전
인천
→
1등 고정 — 항상 "서울"
서울 0.52
부산 0.26
대전
인천
→
🎲 상위 2개 중 추첨
서울 0.52
부산 0.26
대전 0.14
인천
→
🎲 누적 90% 안에서 추첨
전략의 차이는 후보를 어떻게 남기느냐 — 1등만(Greedy) · 개수로(Top-K) · 누적 확률로(Top-P).
발표자 노트
분포가 만들어졌으면 이제 하나를 골라야죠. Greedy는 항상 1등만 뽑으니까 코드 생성이나 분류처럼 재현성이 필요한 곳에 씁니다. Top-K는 후보를 개수로 자르는데, 분포 모양과 무관하게 개수가 고정이라 경직된 면이 있고요. 그래서 실전 기본값은 Top-P입니다. 누적 확률로 자르니까 분포가 뾰족하면 후보가 줄고 평평하면 늘어나는, 상황에 적응하는 방식입니다.
Top-P 실전 — 누적 확률로 후보 자르기
T=0.7 분포에 Top-P 0.9를 적용하는 순간 — 확률 순으로 쌓다가 90%에서 자릅니다
🎲
남은 후보 3개 중 확률 비율로 추첨
→
"서울"
(대체로 — 가끔 부산·대전도 나옵니다, 그게 다양성)
Temperature와 Top-P는 Bedrock Converse API의 inferenceConfig(temperature·topP)에서 조절합니다 — 모델 Playground 슬라이더로 직접 체험할 수 있습니다.
발표자 노트
Top-P 0.9가 실제로 작동하는 순간입니다. 확률 순으로 쌓다가 누적 90%를 넘는 지점에서 자르니까 인천은 후보에서 빠지고, 남은 셋 중에서 확률 비율로 추첨합니다. 대체로 서울이 나오지만 가끔 부산도 나오는데, 그게 버그가 아니라 의도된 다양성입니다. 이 값들은 Bedrock Converse API의 inferenceConfig에서 직접 조절하실 수 있고, Playground 슬라이더로 한번 체감해 보시길 권합니다.
자기회귀와 KV Cache
토큰을 1개씩 생성하며 반복 — KV Cache로 재계산을 방지
대한
민국
의
수도
는
→
LLM ①~⑥
→
+ 서울
🗄️ 대한 ~ 는
캐시 재사용 — 재계산 없음
서울
← 새 토큰 몫만 계산
→
LLM ①~⑥
→
+ 입니다
↻
EOS(종료 토큰)가 나올 때까지 반복 — 100토큰 답변 = 이 사이클 100번 · 긴 컨텍스트에선 이 캐시가 GPU 메모리의 큰 몫을 차지 — GQA·MLA처럼 K·V를 줄이는 모델 설계가 초장문 컨텍스트의 배경
프롬프트 캐싱(Prompt Caching)은 이 KV Cache를 API 호출 간에 재사용합니다. 시스템 프롬프트의 KV를 저장해두면 다음 호출에서 즉시 이어서 생성 — 비용 90% 절감.
발표자 노트
사이클 1에서 "서울"을 만들었으면, 그걸 입력 끝에 붙여 사이클 2를 돕니다. 그런데 매번 앞 토큰들을 전부 다시 계산하면 답이 길어질수록 느려지겠죠. 그래서 사이클 1에서 계산한 K·V를 캐시에 저장해 두고, 사이클 2에서는 새 토큰 몫만 계산합니다. 연산량이 N 제곱에서 N으로 내려가는 겁니다. 프롬프트 캐싱이 90% 할인되는 이유가 바로 이건데요, 시스템 프롬프트의 KV를 호출 간에 재사용하니까 계산 자체를 안 하는 겁니다. 참고로 긴 컨텍스트에서는 이 캐시 자체가 메모리 병목이라, 요즘 모델들은 GQA나 MLA처럼 K·V를 줄이는 구조로 설계됩니다. 1M 토큰 컨텍스트가 가능해진 배경입니다.
파운데이션 모델의 동작 원리와 한계를 알아야 올바른 아키텍처를 설계합니다.