추론 (2) — ChatGPT 작동 원리, 컨텍스트·시스템·streaming의 정체
LLM 이론 집중코스 · 3-B편 (입출력·시스템·streaming)
3-A편 (추론 메커니즘 본체)을 안 읽으셨다면 먼저 보고 오세요. 이 글은 그 위에 쌓는 글이에요.
3-A에서 모델 안에서 일어나는 일을 끝까지 봤어요. 한 글자씩 답이 나오는 메커니즘부터 KV 캐시·GPU·VRAM·HBM·양자화·Softmax·Sampling·BPE까지. 이번 글(3-B)에서는 그 모델을 둘러싼 입출력 구조예요. 책상의 크기, 시스템 프롬프트의 권위, 스킬 메타데이터의 표지 없는 도서관 비유, md vs PDF, JSON streaming까지.
이 글에서 답할 질문들 — 직접 학습하면서 부딪힌 지점 그대로
2. 시스템 프롬프트가 사용자 메시지보다 강한 이유
3. 스킬 메타데이터 = 표지 없는 도서관에 표지 붙이기 (이 비유는 이 글에서 만든 것)
4. “프롬프트를 토큰화하는 것은 누가 어떤 단계에서 하는지? 토크나이저·어휘집은 회사마다 비밀인지?”
5. “하나도 띄어쓰기를 안 해도 답변 품질은 떨어지지 않는지 이론적으로?”
6. “md 파일이 AI가 인식하기 편하다는데, md는 AI를 위해 만들어진 건가? PDF와 뭐가 다른가?”
7. “LLM 출력이 JSON 형식으로 오는 이유? JSON이 뭐고 AI를 위해 만들어졌나? JSON 안 쓰면 어떻게 되지?”
8. “토큰 단위로 보내는 게 사용자 만족도라면 한꺼번에 보내는 게 경제적으로 합리적이지 않나?”
이 중 한 질문이라도 답이 궁금하면 — 시작합시다.
컨텍스트 윈도우 — 책상의 정확한 정체
여기까지 보면 자연스럽게 다음 의문이 떠올라요. “그래서 LLM이 한 번에 처리할 수 있는 입력 길이는 얼마예요?”
답: 컨텍스트 윈도우(Context Window)가 그 한계예요.
비유로 잡으면 책상의 크기예요. 책상 위에 시스템 프롬프트, 이전 대화, 새 질문, 도구 정보, 그리고 모델이 답으로 만드는 토큰까지 다 올라가 있어야 해요. 책상이 크면 한 번에 많이 올릴 수 있고, 작으면 적게 올림.
모델별 책상 크기 (2026년 5월 기준)
| 모델 | 컨텍스트 윈도우 |
|---|---|
| Claude Opus 4.7 | 1,000,000 토큰 (1M) |
| Claude Sonnet 4.6 | 1,000,000 토큰 |
| Claude Haiku 4.5 | 200,000 토큰 |
| GPT-5.5 | 1,000,000 토큰 |
| Gemini 3.1 Pro | 1,000,000 토큰 |
| Llama 3.1 (로컬) | 128,000 토큰 |
회사·모델마다 달라요. 같은 회사 안에서도 작은 모델은 작은 윈도우인 경우가 많아요.
진짜 책상 안을 들여다본 모습
추상적인 비유 같죠? 근데 진짜로 책상 안을 볼 수 있어요. 제가 Claude Code(개발자 도구)에서 /context를 입력했을 때 본 화면이에요.
![Claude Code 컨텍스트 윈도우 사용량 — claude-opus-4-7[1m] 1M 토큰 책상의 실제 모습](https://shuntailor.net/wp-content/uploads/2026/04/4-context-usage-cropped-1.png)
이걸 보면 비유가 진짜로 일어나는 일이라는 게 보여요.
- Skills 4.6k (0.5%) — 스킬 메타데이터(이름·설명)만 올라가 있음. 본문은 아래에서 다룰 표지 비유가 정확히 여기 보임
- System tools 12.9k (1.3%) — 사용 가능한 도구의 사용법만
- Messages 297.6k (29.8%) — 가장 많은 자리. 사용자랑 주고받은 모든 대화
- Autocompact buffer 33k — 압축 예정 자리. 책상이 꽉 차기 전에 압축할 영역 미리 잡아둠 (3편 뒤에 나올 압축 개념)
- Free space 637k (63.7%) — 아직 빈 자리
책상 위에 올라가는 것
[책상 = 컨텍스트 윈도우 1M 토큰]
├─ 시스템 프롬프트 (모델 정체성·기본 행동)
├─ 도구 정의 (사용 가능한 함수들)
├─ 스킬 메타데이터 (이름·설명만)
├─ 이전 대화 (User ↔ Assistant 주고받은 메시지)
├─ 새 사용자 메시지
└─ 모델이 만들 답 (출력 토큰까지 윈도우에 포함)
모델이 만드는 답도 윈도우에 들어가요. 즉 입력 99만 토큰 + 출력 1만 토큰 = 100만으로 꽉 참.
책상이 꽉 차면? — 누가 자르는가
“가장 오래된 토큰부터 잘린다”고 막연히 알고 있는 분이 많은데, 정확히는 다음과 같아요.
LLM 자체는 자르지 않아요. 한도 넘기면 에러로 거부해요.
프롬프트 + 시스템 + 이전 대화 + 도구 = 1,000,001 토큰 던짐
↓
API 응답: 400 Bad Request
"context_length_exceeded: max 1000000"
자동으로 안 잘려요. 자르는 일은 그 위의 앱이 해요.
| 환경 | 책상 꽉 찰 때 동작 |
|---|---|
| API 직접 호출 | 에러 반환. 개발자가 미리 줄여 보내야 함 |
| ChatGPT 일반 화면 | 옛 대화부터 잘라서 보냄 (자동 truncation, 압축 없음) |
| Claude Code·Cursor | 압축 후 보냄 (요약으로 옛 대화 압축) |
정리하면 이래요:
– “GPT 일반 화면에서는 압축이 없어서 잘리고 느려진다” — 맞아요. 단순 자르기.
– “개발 모드에서는 압축이 자동, 그런데 압축 후엔 정확도가 떨어진다” — 정확합니다. 압축은 요약이라 정보 손실이 발생해요.
컨텍스트가 길어지면 답변 품질은?
여기서 한 가지 더 짚을 게 있어요.
“컨텍스트가 5만일 때와 90만일 때의 LLM의 답변은 그래도 떨어지지만 그 감소 기울기는 완만하다.”
여기서 기울기는 — 컨텍스트 길이가 늘어날수록 답변 품질이 얼마나 빨리 떨어지는지예요. 그래프로 그리면 가로축이 컨텍스트 길이 (5만 → 90만), 세로축이 답변 품질. 그 선이 얼마나 가파르게 내려가는지가 기울기.
답변 품질
│
1 ┤●━●━━● ← 기울기 완만 (LLM 현실)
│ ●━●━●
│
1 ┤●
│ ╲
│ ● ← 기울기 가파름 (만약 이랬다면)
│ ╲
│ ●
└─────────────── 컨텍스트 길이
5만 90만
LLM은 완만 쪽이에요. 1차 자료가 가르키는 현상이 Lost in the Middle인데:
– 책상이 클수록 모델이 중간에 있는 정보를 까먹기 쉬움
– 시작과 끝은 잘 기억하는데 중간은 약함
– 90만 토큰 던지면 어딘가 빠짐 가능성 늘어남
근데 기울기가 완만하다는 게 핵심이에요. 5만 토큰에서는 거의 완벽, 90만에서는 살짝 떨어지지만 완전히 무용지물이 되는 건 아님. 90만이 5만의 18배 길이라는 걸 생각하면 — 답변 품질이 18배 떨어지는 게 아니라 살짝 떨어지는 정도. 그게 완만의 의미예요.
KV 캐시 vs 책상
:
“KV 캐시는 추론시에 중복된 내용을 출력하지 않고 비용을 효율화하는 비용에 관점을 맞춘 것이고 책상의 크기는 맥락 유지를 위해서 즉 답변 품질 유지를 위한 기능으로 생각한다.”
거의 정확하지만 살짝 보정 필요. 둘이 같은 시스템의 다른 측면이에요.
| 컨텍스트 윈도우 (책상) | KV 캐시 | |
|---|---|---|
| 무엇 | 모델이 처리 가능한 최대 토큰 수 (한도) | 그 토큰들의 K, V를 저장한 GPU 메모리 |
| 목적 | 입력 한계를 정함 | 재계산 피해 속도 향상 |
| 단위 | 토큰 수 (1M, 200K) | 바이트 (GB) |
즉 책상은 한도, KV 캐시는 그 한도 안의 토큰들을 GPU에 보관하는 실제 메모리 공간. 책상이 1M이면 KV 캐시도 그 1M 토큰의 K, V를 다 들고 있어야 함. 그래서 컨텍스트가 길어지면 KV 캐시 메모리가 비례해서 커지고, 그게 추론 비용의 큰 부분.
비용 — 직관 검증
“10만과 100만의 입력 비용은 정확히 10배” 라는 직관 — 사실일까?
답: 거의 맞지만 살짝 다름.
- API 가격 정책: 입력 토큰당 가격은 고정 (예: $3/1M tokens). 그래서 가격은 선형. 정확.
- 실제 GPU 비용: Attention의 연산량이 토큰 수에 제곱에 가까움. 100만은 10만의 100배 연산량. 그래서 OpenAI/Anthropic은 내부적으로 100만 토큰을 더 비싸게 처리하고 있어요. 사용자에게는 선형으로 청구.
회사들이 제곱 비용을 선형 가격으로 부담하는 셈이에요. 그래서 1M 컨텍스트를 공식 지원하기 시작한 모델이 늘어나는 데 시간이 걸린 거. 인프라가 따라잡아야 해서.
책상 위에 누가 먼저 앉나 — 시스템 프롬프트와 스킬 표지
책상의 크기를 잡았으니, 이제 그 책상에 누가 앉는지를 봅시다. 책상에 올라가는 것들 중 권위가 강한 자리가 있어요. 그게 시스템 프롬프트와 스킬 메타데이터예요.
시스템 프롬프트 — 책상의 가장 앞자리
시스템 프롬프트 — 모델이 어떤 정체성·행동·제약을 가져야 하는지, 사용자 메시지보다 먼저 박아놓는 텍스트. 책상에 올라가는 것 중 가장 먼저 자리잡는 자산이에요.
[시스템 프롬프트 예시]
"당신은 Claude입니다. Anthropic이 만든 AI 어시스턴트.
사용자에게 도움이 되도록 답하세요.
한국어 질문에는 한국어로 답하세요.
모르는 건 모른다고 말하세요.
..."
모델 정체성부터 기초 행동 규칙까지 시스템 프롬프트에 들어가요. 환경별로 누가 작성하느냐가 갈려요.
| 환경 | 시스템 프롬프트 |
|---|---|
| API 직접 호출 | 개발자가 자유롭게 작성 |
| ChatGPT/Claude.ai 구독 | 회사가 박아둔 것. 사용자는 볼 수도 없음 |
| 로컬 모델 (Ollama, LM Studio) | 사용자/개발자가 자유롭게 작성 |
근데 여기서 자연스러운 의문 — 같은 토큰열인데 왜 시스템 프롬프트가 사용자 메시지보다 강한가?
답은 한 줄이에요. 학습 단계에서 그렇게 배웠기 때문이에요. 학습 데이터에 system: ~~ user: ~~ assistant: ~~ 같은 구조가 어마어마하게 많이 들어가 있었고, 모델이 거기서 system 영역의 지시를 따르는 패턴을 배웠어요. 시스템 프롬프트의 권위는 학습으로 박힌 행동 양식이지 기술적으로 다른 영역이 아니에요.
그래서 사용자가 시스템 프롬프트를 덮어쓰려고 시도하는 게 prompt injection이에요. 모델이 학습에서 system을 우선시하도록 배웠지만, 영리한 사용자 메시지로 그걸 흔들 수 있어요.
스킬 메타데이터 — 표지 없는 도서관에 표지 붙이기
시스템 프롬프트 자리 옆에 또 하나의 자산이 박혀 있어요. 스킬 메타데이터. 이건 이 글에서 만든 비유로 풀어볼게요.
책에 표지가 없으면 LLM이 모든 책 내용을 다 읽어야 해요. 그게 컨텍스트 증폭. Anthropic이 스킬 개념을 도입해서 책에 표지(이름 + description)를 붙였어요. 시스템 프롬프트에는 표지(메타데이터)만 들어가니까 컨텍스트 절약. 단, LLM이 표지 보고 “이 책 필요” 라고 판단해야 책을 펼쳐요. 잘못 판단하면 정확도 떨어짐.
이게 컨텍스트 절약 vs 정확도 손실의 트레이드오프예요.
책1 전문 (1만 토큰) +
책2 전문 (1만 토큰) +
… × 50권 = 50만 토큰
→ 책상이 그 자체로 가득 참
→ 사용자 메시지 들어갈 자리 없음
→ 컨텍스트 폭증. API 비용 폭증.
책1 표지 (50 토큰) +
책2 표지 (50 토큰) +
… × 50권 = 2,500 토큰
→ 책상의 0.25%만 차지
→ LLM이 “이 책 필요” 판단 시에만 펼침
→ 컨텍스트 200배 절약. 비용 절약.
구조 정리
[스킬 없는 시절]
시스템 프롬프트:
- 책1 전문 (1만 토큰)
- 책2 전문 (1만 토큰)
- 책3 전문 (1만 토큰)
- ...
→ 책상 위에 책 50권 다 올려놓음 = 컨텍스트 폭증
[스킬 도입 후]
시스템 프롬프트:
- 책1 표지 (50 토큰): "스킬명: blog-writer / 설명: 블로그 글 쓰기"
- 책2 표지 (50 토큰): "스킬명: pixel-office / 설명: 폴더 구조 시각화"
- ... × 50권
→ 책상에 표지만 = 50 × 50 = 2500 토큰
LLM이 표지 보고 "어, 지금 blog-writer 필요" 판단:
→ 그 책만 펼쳐서 본문 읽음
→ 나머지 49권은 안 읽음
트레이드오프
[비용 관점]
스킬 사용: 컨텍스트 작음 → API 비용 절약 → 구독료 효율
스킬 안 씀: 컨텍스트 큼 → API 비용 증가
[답변 품질 관점]
스킬 사용: LLM이 "이 책 필요" 판단을 잘못할 위험
스킬 안 씀: 모든 책이 시스템 프롬프트에 박혀 있어서 항상 참고 가능 → 답변 품질 유리
연구 결과로도 컨텍스트에 모든 정보를 박아두면 정확도가 더 높다는 게 많아요. 다만 그게 비용을 무시한 비교. 비용을 같이 보면 스킬이 합리적.
컨텍스트가 길어지면 답변 품질은?
잡은 마지막 포인트:
“컨텍스트가 5만일 때와 90만일 때의 LLM의 답변은 그래도 떨어지지만 그 감소 기울기는 완만하다. 안 떨어지는 것은 아니다.”
정확. 떨어지긴 함. 안 떨어지는 게 아님. 다만 곡선이 완만해서, 90만 컨텍스트에서도 충분히 쓸만함. 90만 컨텍스트가 5만의 18배인 걸 생각하면 답변 품질 감소가 그 만큼은 아님.
이게 1M 컨텍스트 모델이 상품으로 의미 있는 이유. 진짜로 18배 더 많은 정보를 한 번에 처리할 수 있어요. 답변 품질이 2배 떨어지는 건 아닌 완만한 감소.
도구(Tool)도 같은 구조
스킬과 비슷한 게 도구(Tool, Function calling). 사용 가능한 함수의 이름·인수·설명만 시스템 프롬프트에 박혀 있고, 모델이 “이 도구 필요” 라고 판단하면 그 함수를 호출하는 JSON을 출력.
[도구 정의 (시스템 프롬프트에 박힘)]
{
"name": "search_web",
"description": "웹 검색을 수행합니다",
"parameters": {
"query": "검색어"
}
}
스킬과 같은 표지 없는 도서관의 다른 형태. 도구 본체가 시스템 프롬프트에 박히는 게 아니라 사용법만 박힘.
입력의 정체 — 토큰화·띄어쓰기·md vs PDF
책상 위에 누가 앉는지를 봤으니, 이제 우리가 던지는 텍스트가 그 책상에 어떻게 도착하는지를 봅시다. 토큰화는 누가 어디서 하는지, 띄어쓰기는 어떻게 인식되는지, 그리고 왜 PDF보다 md가 LLM에게 친숙한지까지 — 한 흐름으로.
토큰화는 서버에서, 입력받자마자
지금까지 토큰 을 자연스럽게 써왔는데, 언제·어디서·누가 그걸 만드는지를 짚고 가야 해요.
답은 한 줄이에요. OpenAI/Anthropic 서버에서, 입력받자마자, BPE 토크나이저로.
흐름:
[1] 사용자: "오늘 날씨 어때?" 텍스트 입력
[2] ChatGPT 화면(클라이언트)이 그대로 API에 던짐 — 토큰화 X, 텍스트 그대로
[3] OpenAI 서버 도착
[4] 서버에서 BPE 토크나이저로 토큰화
"오늘 날씨 어때?" → [101, 234, 567, 89]
[5] 그 토큰들을 GPU에 올려서 추론 시작
토큰화는 모델 자체가 하는 게 아니에요. 모델 옆에 붙어 있는 토크나이저(BPE 어휘집)가 해요. 모델이랑 별도 파일이지만 같이 배포돼요.
OpenAI Playground 같은 데서 토큰 수 미리 보는 도구를 본 적 있으실 거예요. 그건 클라이언트 측에서 같은 BPE 토크나이저를 돌려서 미리 보여주는 거. 실제 추론 토큰화는 서버에서 다시 해요.
토크나이저 공개 정책 — 회사마다 다름
| 회사 | 토크나이저 어휘집 |
|---|---|
| OpenAI | 공개 (tiktoken 라이브러리, GitHub 오픈소스) |
| Anthropic (Claude) | 비공개 (엔드포인트로만 토큰 수 알 수 있음) |
| Google (Gemini) | 부분 공개 |
| Meta (Llama) | 공개 (오픈소스 모델이라 토크나이저도 공개) |
OpenAI는 어휘집 자체를 공개해요. pip install tiktoken으로 누구나 다운받아서 실제 토큰이 어떻게 잘리는지 확인 가능. 왜 공개? — 개발자가 토큰 수 미리 계산해서 비용 견적 내야 하니까.
Anthropic은 비공개. 토큰 수 알고 싶으면 Anthropic API에 이 텍스트 토큰 몇 개? 라고 물어보는 엔드포인트로만 가능해요. 토큰 수만 알려주고 어떻게 잘렸는지는 알려주지 않아요.
띄어쓰기는 토큰의 일부다
여기서 자주 헷갈리는 지점이 따라와요. “한국어는 단어와 조사가 띄어쓰기 없이 오는데, LLM은 띄어쓰기를 어떻게 인식하지?”
답은 의외로 단순해요. 띄어쓰기는 LLM에게 토큰의 일부예요.
영어 BPE를 보면 명확. ” hello” 와 “hello” 가 서로 다른 1토큰이에요. 띄어쓰기가 글자처럼 토큰에 박혀 들어가요. 즉 모델은 띄어쓰기를 별도로 인식하는 게 아니라, 글자 데이터의 일부로 봐요.
띄어쓰기 안 한 텍스트의 답변 품질은 언어마다 차이가 있어요. 영어는 띄어쓰기가 단어 경계의 핵심이라 심하게 떨어져요. 한국어는 살짝 떨어지지만 영어보다 덜해요 — 한국어는 원래 띄어쓰기가 모호한 언어라 학습 데이터에 띄어쓰기 안 된 한국어가 일정 비율 들어가 있어서요. 중국어·일본어는 거의 영향 없음. 원래 띄어쓰기를 안 쓰는 언어니까요.
이론적으로도 실제로도 띄어쓰기 안 하면 품질이 떨어져요. 다만 정도가 언어마다 다르고, 완전히 망가지진 않아요.
md가 PDF보다 LLM에게 친화적인 이유
토큰화·띄어쓰기를 잡았으면 자연스럽게 또 하나의 의문이 떠올라요. “같은 내용이라도 md 파일로 주면 LLM이 더 잘 읽는다는데, md는 AI를 위해 만들어진 거야? 우연히 AI가 잘 읽는 형식이 된 거야? PDF와 뭐가 다르지?”
답부터 — md(Markdown)는 AI를 위해 만들어진 게 아니에요. 우연히 AI가 가장 편하게 읽는 형식이 됐어요.
Markdown은 2004년 John Gruber와 Aaron Swartz가 만들었어요. 목표는 단순했어요. 사람이 일반 텍스트로 글을 빠르게 쓰면, 그게 자동으로 HTML로 변환되어 웹에 올라가게 하는 것. 블로거·개발자가 글 쓰는 속도를 안 잃으면서 구조 있는 글을 쓰게 하려고 만든 거예요. 이때 LLM 같은 건 존재하지도 않았어요.
근데 2020년대에 LLM 시대가 오자 md가 우연히 AI에게 가장 친숙한 형식이 돼버렸어요. 세 가지 이유로.
첫째, 순수 텍스트라 토큰화가 깔끔해요. md는 바이너리 인코딩·압축·이미지 임베드·서체 메타데이터 같은 게 없어요. 파일을 그대로 열면 텍스트 그 자체. BPE 토크나이저가 추가 처리 없이 곧장 토큰으로 자를 수 있어요. PDF는 정반대 — 시각적 레이아웃 우선 형식이라 텍스트가 위치 좌표에 박혀 있고, 한 줄도 여러 텍스트 블록으로 쪼개져요. 텍스트 추출만 해도 순서가 뒤섞이거나 표가 깨지는 일이 흔해요.
둘째, 구조가 평문 안에 박혀 있어요.
## 제목 (큰 헤더)
### 부제 (작은 헤더)
- 리스트 항목
- **강조**된 글자
| 표 | 도 |
##은 큰 헤더, **는 강조, -는 리스트. 모델이 이런 마커를 어마어마하게 많이 학습 데이터에서 봤어요. 그래서 마커가 들어오면 여긴 헤더야, 여긴 강조야 를 자동으로 인식해요. PDF에서 같은 구조를 추출하면 그냥 평문으로 떨어져서 모델이 이 줄이 헤더인지 본문인지 구분 불가. 1차 자료 표현 그대로 — “평문은 정보를 평평하게 만들어 모델이 관계를 파악하기 어렵게 한다”.
셋째, 학습 데이터에서 압도적이에요. GitHub README, 기술 블로그, Stack Overflow, 위키 일부, 문서 사이트 — 인터넷 텍스트의 큰 비중이 이미 md예요. LLM이 학습할 때 md를 수십억 번 봤어요. 모델이 md를 모국어처럼 이해하는 이유. PDF는 학습 데이터에 상대적으로 적게 들어가요 (저작권·추출 어려움). 게다가 PDF에서 텍스트 추출한 결과가 지저분하니 모델이 PDF 표기를 거의 못 익혀요.
성능 차이는 1차 자료에서 확인돼요. 같은 내용을 md로 깨끗하게 정리 vs PDF에서 거칠게 추출 비교 시 — RAG 검색 정확도가 최대 35% 향상, 토큰 사용량이 20~30% 적게 들어요. ChatGPT/Claude에 정보 줄 때 PDF를 그대로 던지지 말고 md로 변환해서 던지는 게 답변 품질·비용 양쪽 다 유리한 이유예요.
| md | ||
|---|---|---|
| 만들어진 이유 | 사람이 글 쓰기 편하라고 (2004년, AI 무관) | 시각적 인쇄·문서 보존 (1993년) |
| 순수 텍스트? | 예 | 아니요 (바이너리 + 좌표) |
| 구조가 평문에 박힘? | 예 (##, **, -) |
아니요 (시각 레이아웃) |
| 학습 데이터 비중 | 매우 큼 | 작음 |
| LLM 친화도 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
md는 AI 친화적인 게 목표가 아니라 결과였어요. 사람이 글 쓰기 편하게 만든 형식이 우연히 AI도 가장 잘 읽는 형식이 된 — 이게 현재 LLM 시대의 흥미로운 우연 중 하나예요. 같은 이유로 Cursor·Claude Code 같은 개발자 도구에서 코드 + 문서를 같이 던질 때 md가 표준이에요. AI가 가장 정확히 읽기 때문.
출력의 정체 — JSON·SSE·Streaming
입력의 정체를 잡았으니 이제 출력이에요. 모델이 만든 토큰이 어떻게 사용자 화면까지 도착하는지. 한 흐름으로 따라가요.
출력은 JSON에 포장된 토큰이에요
자연스러운 의문 — “출력이 LLM에서 JSON으로 오는 걸로 아는데 왜 JSON인지.”
먼저 정확히 짚을 게 있어요. 출력 자체가 JSON은 아니에요. 토큰을 JSON 안에 담아서 보내는 거예요.
JSON부터 — JavaScript Object Notation. 데이터를 텍스트로 표현하는 표준 형식. 이름은 JavaScript에서 따왔지만 모든 프로그래밍 언어가 다 읽을 수 있어요.
{
"이름": "테이라",
"나이": 30,
"취미": ["블로그", "AI", "Pixel Office"]
}
{ } 안에 키: 값 쌍, [ ] 안에 목록, 문자열은 "따옴표", 숫자는 그대로. 단순.
JSON이 만들어진 건 2001년이에요. AI랑 무관. 원래는 웹 브라우저와 서버 사이 데이터 주고받기 위해 만들어졌고, 그게 표준이 되면서 모든 인터넷 서비스가 JSON을 쓰게 됐어요. LLM API가 나왔을 때 기존 JSON을 그대로 채택했어요. AI 때문에 새로 만든 게 아니에요.
근데 왜 JSON으로 포장하는지가 자연스럽게 떠올라요. 답은 메타정보 때문이에요.
GPU 안에서 모델이 토큰 1개를 만들면 — 토큰 ID 하나(예: 234)가 나오고, 어휘집 보고 “좋” 같은 텍스트로 변환되고, 그게 사용자에게 가야 해요. 근데 그냥 “좋” 만 평문으로 보내면 정보가 부족해요. 첫 토큰인지 마지막인지, 누적 토큰 수는, 에러는 없는지, 모델 이름은. 메타정보랑 같이 묶어서 보내려면 JSON 같은 포장지가 필요해요.
실제 OpenAI 응답 예시:
data: {"id":"chatcmpl-123","object":"chat.completion.chunk",
"created":1234,"model":"gpt-4",
"choices":[{"delta":{"content":"좋"},"index":0}]}
data: {"id":"chatcmpl-123","choices":[{"delta":{"content":"다"}}]}
data: [DONE]
토큰 한 개(좋, 다)가 JSON 안에 들어가서 와요. JSON은 포장지, 안에 든 게 진짜 토큰이에요.
JSON이 의무는 아니에요. 다른 형식도 가능 — XML(태그 형식, 옛날 표준), Protocol Buffers(Google이 만든 더 빠르고 작은 형식), MessagePack(JSON 압축형)도 있어요. 근데 LLM API는 다 JSON을 써요. 모든 언어가 읽을 수 있고, 사람도 눈으로 읽을 수 있고(디버깅 편함), 표준이라 모든 도구가 지원해요. 살짝 비효율이지만 충분히 빠른 거예요. 즉 가장 효율적이라서가 아니라 가장 보편적이라서 쓰는 거. 효율을 따지면 Protocol Buffers가 더 빠르지만 그 대신 호환성을 잃어요.
Streaming — 다다닥 효과의 정체
Streaming — 답 전체가 만들어질 때까지 기다리지 않고, 토큰이 만들어지는 즉시 한 글자씩 사용자에게 흘려보내는 전송 방식. ChatGPT 화면에 답이 다다닥 뜨는 효과의 정체예요.
이제 마지막 의문 — 왜 토큰을 한 번에 보내지 않고 한 글자씩 보낼까?
답 전체가 만들어진 뒤 한 번에 보내면 사용자가 1초~10초씩 기다리며 “안 멈췄나?” 의심하게 돼요. 답 전체가 만들어진 뒤 한 번에 보내면 사용자가 1초~10초씩 기다리며 “안 멈췄나?” 의심하게 돼요. 답이 길수록 더 답답해지고요. 토큰 단위로 보내면 첫 토큰 도착이 곧 화면 첫 글자, 다음 토큰이 다음 글자. 사용자가 답이 만들어지는 과정을 실시간으로 봐요.
기술적으로는 SSE (Server-Sent Events) 라는 표준 프로토콜로 보내요. HTTP 연결을 한 번 열어두고 서버가 일방적으로 토큰을 계속 흘려보내는 방식이에요.
사용자 → 서버: "오늘 날씨 어때?" (요청 1번)
서버 → 사용자: "좋" (실시간)
서버 → 사용자: "다" (실시간)
서버 → 사용자: "." (실시간)
서버 → 사용자: [DONE]
ChatGPT 답이 글자별로 다다닥 뜨는 그 시각 효과 = autoregressive로 만들어진 토큰을 SSE로 JSON 포장해서 흘려보내는 결과. 두 단계가 합쳐진 결과물이에요.
근데 여기서 또 자연스러운 의문 — “토큰 단위로 보내는 게 만족도를 위한 거라면, 한꺼번에 보내는 게 경제적으로 더 합리적이지 않나?”
답: 합리적이라기보다 경제적으로는 거의 같아요. 토큰 단위로 보내든 한꺼번에 보내든 생성 비용은 같아요 (어차피 한 토큰씩 만들어지니까). 네트워크 비용도 거의 같음 (총 데이터양 비슷). 차이는 사용자가 첫 글자 보는 속도뿐.
그래서 모든 LLM 회사가 streaming을 기본으로 채택해요. 비용 거의 같은데 사용자 만족도 차이가 큰 거예요.
다만 작은 차이 가 있어요. Streaming은 HTTP 연결을 답변 끝까지 열어둬요 — 서버 동시 연결 수에 한계가 와요. 한꺼번에 보내면 답 다 만든 뒤 1번만 보내니까 서버 부담이 적고요. 대규모 서비스에서는 streaming의 동시 연결 수가 진짜 비용이 돼요. 근데 워낙 사용자 만족도 차이가 커서 동시 연결 비용을 감수하고 streaming을 써요. ChatGPT처럼 수억 명이 동시에 쓰는 서비스는 이 동시 연결 관리가 큰 일이에요. OpenAI가 GPU만큼이나 네트워크 인프라에 투자하는 이유.
여기까지가 3-B 끝 — 그리고 다음 글의 분기점
여기서 3-A·3-B 두 글이 닫혀요. 두 글이 합쳐서 풀어준 막힘 25개를 한 번에 짚으면:
3-A편: 1. 추론 vs 학습 / 2. 한 글자씩 = 32층 매번 통과 (autoregressive) / 3. KV 캐시 + Q·K·V / 4. Prefill vs Decode / 5. 가중치 안 변해도 GPU 필요 / 6. VRAM·메모리 대역폭·HBM / 7. 1바이트=8비트 / 8. 모델 크기 + 양자화 + 405B / 9. A100/H100/H200 / 10. 역전파 거꾸로 / 11. Softmax / 12. Sampling / 13. Temperature / 14. Top-K·Top-P / 15. 학습 정답 vs 추론 정답 / 16. BPE 어휘집 / 17. 한글 토큰
3-B편 (이 글): 18. 컨텍스트 윈도우 = 책상 / 19. 자르기는 LLM 아닌 앱이 한다 / 20. 시스템 프롬프트의 권위 / 21. 스킬 메타데이터 = 표지 비유 / 22. 토큰화는 서버에서 / 23. 띄어쓰기는 토큰의 일부 / 24. md vs PDF — md가 AI에게 친화적인 우연 / 25. JSON·SSE streaming
이게 LLM 추론의 기본 메커니즘 전부예요. 여기까지만 알아도 ChatGPT가 한 글자씩 답하는 그 모든 동작을 완벽하게 머리에 그릴 수 있어요.
근데 이게 2024년까지의 그림이에요. 2024년 9월에 OpenAI가 o1을 발표하면서, 그리고 2026년 4월에 GPT-5.4 Pro가 60년 미해결 Erdős 수학 문제를 80분에 풀어버리면서, 추론의 그림 자체가 한 단계 진화했어요.
다음 글(3.5편)에서 다룰 내용은 이거예요.
여기서부터는 3.5편 영역
- Reasoning 모델 (o1, o3, GPT-5.4 Pro, Claude Extended Thinking) — 답하기 전에 혼잣말로 한참 생각하고 답하는 새 방식
- 23×47을 한 번에 왜 못 풀까 — LLM의 곱셈 한계와 토큰화의 관계
- 계산기를 도구로 부르면 되지 않나? — 에이전트의 정확한 정의
- 모델 vs 에이전트 — 그 경계가 정확히 어디인가
- 사고 토큰의 기준 — Web 검색·Fetch는 어떻게 청구되나
- Erdős #1196 사건 — 진짜 수학적 추론인가, 아니면 조합 시도가 우연히 맞은 건가
- 창의성이란 무엇인가 — 변형적 창의성 9개 사례 (코페르니쿠스·다윈·칸트·쿤·피카소 등)
- AI가 인간의 창의력을 넘을 수 있나 — 이 글이 던지는 큰 질문
직접 학습하면서 부딪힌 진짜 어려운 질문들이 거기 다 박혀 있어요. 3편이 기본기라면 3.5편은 2026년 LLM의 가장 뜨거운 자리.
→ 3.5편 읽으러 가기: 추론의 진화 — Reasoning, 에이전트, 그리고 AI가 진짜 추론을 하는가
핵심 정리 — ChatGPT 작동 원리 한 줄로
추론 = 학습으로 박힌 80억 가중치 위로 입력이 한 번 통과하면서, 32층 끝의 점수를 Softmax → Temperature → Sampling을 거쳐 한 토큰씩 뽑는 과정. KV 캐시로 이전 토큰 K·V를 재활용하고, VRAM에 가중치를 통째로 올려서 곱셈을 빠르게 하고, 양자화로 큰 모델을 GPU에 욱여넣고, 컨텍스트 윈도우(책상) 위에 시스템 프롬프트·스킬 표지·도구 정의·이전 대화·새 질문이 다 올라가고, 결과는 SSE/JSON으로 한 토큰씩 사용자에게 흘러나간다.
핵심 3가지:
-
추론은 한 번 통과 + 토큰 뽑기. 가중치를 바꾸는 단계가 없음. 정답이라는 개념도 없음. KV 캐시로 이전 토큰 재활용 → 첫 글자만 느리고 그 다음은 빠름.
-
GPU·VRAM·HBM·양자화·컨텍스트 윈도우는 다 같은 문제의 답이다. “어떻게 80억 곱셈을 1초에 30~150번 하면서, 큰 모델을 메모리에 욱여넣고, 긴 입력을 책상에 올리는가.” 회사 전쟁의 본질이 이거예요.
-
출력은 SSE/JSON으로 한 토큰씩 흐름. ChatGPT 화면 다다닥 효과의 정체. JSON은 AI 무관 2001년 개념, 지금은 표준이라 채택.
다음 편 예고
3.5편: 추론의 진화 — Reasoning, 에이전트, 그리고 AI가 진짜 추론을 하는가
3편이 2024년까지의 LLM 추론 메커니즘이라면, 3.5편은 2024~2026년의 진화예요. Reasoning 모델·에이전트·도구 호출이 어떻게 LLM의 한계를 늘리고 있는지, 그리고 그 끝에 AI가 진짜 수학을 한 사건이 있어요.
그 이후로는 4편(생성·Generation 깊이) → 5편(Attention) → 6편(Transformer) → 7편(양자화·RAG·Fine-tuning)으로 시리즈가 닫혀요.
자주 묻는 질문
Q. ChatGPT에서 답이 한 글자씩 뜨는 건 연출인가요, 진짜인가요?
진짜예요. autoregressive decoding이라고 부르며, 모델이 한 토큰을 만들면 그걸 SSE 프로토콜로 즉시 사용자에게 흘려보내요. 답을 다 만들어두고 보여주는 게 아니라 *만들어지는 동안* 보내는 거예요.
Q. 가중치가 안 변하는 추론에 왜 GPU가 필요해요?
가중치는 안 변하지만 *입력 × 가중치* 곱셈은 매번 새로 해야 해요. 한 토큰에 약 10억 곱셈, 그걸 1초에 30~150번. CPU로는 너무 느리고 GPU의 병렬 곱셈 능력이 필요해요.
Q. 컨텍스트 윈도우가 꽉 차면 LLM이 옛 대화부터 자르나요?
아니요. LLM 자체는 한도 넘기면 *에러로 거부*해요. 자르기는 ChatGPT 같은 앱이 해요. 개발자 도구(Cursor, Claude Code)는 자르기 대신 *압축*으로 처리하는데, 압축 후엔 정확도가 떨어져요.
Q. 한국어가 영어보다 토큰을 많이 먹는다는데, 그래서 비용이 더 들어요?
네. UTF-8에서 한글 1글자가 3바이트라서 BPE 시작 시 한 글자가 3토큰으로 잡혀요. 학습 데이터의 영어 비중이 압도적이라 BPE가 한글을 통째로 어휘집에 등록 안 함. 결과적으로 같은 의미를 한국어로 쓰면 영어 대비 2~3배 토큰. OpenAI API 비용도 그만큼 더 듦.
Q. Anthropic은 토크나이저를 왜 비공개해요?
OpenAI는 tiktoken 라이브러리를 공개해서 누구나 토큰 수 미리 계산 가능하지만, Anthropic은 비공개. 토큰 수 알고 싶으면 별도 엔드포인트로만 가능해요. 회사마다 정책이 다른 부분이에요.
Q. 405B 모델은 왜 H100 8대가 표준이에요?
405B를 8bit 양자화하면 405GB. 가중치만 보면 H100 80GB 6대로도 가능하지만, 실제 서빙은 KV 캐시(사용자별)·중간 계산·여유까지 포함해서 약 525~585GB 필요. 그래서 NVIDIA가 H100 8대(640GB)를 권장.
소스 / 더 읽을거리
- HuggingFace, “KV Caching Explained” — 블로그
- NVIDIA, “Mastering LLM Techniques: Inference Optimization” — 블로그
- Wikipedia, “High Bandwidth Memory” — Wikipedia
- Wikipedia, “Byte” (1바이트=8비트의 역사) — Wikipedia
- Wikipedia, “JSON” — Wikipedia
- arXiv, “Tokenization counts” (BPE와 한글 토큰 이슈) — 논문
- Simon Willison, “How streaming LLM APIs work” — 블로그
- GitHub, “openai/tiktoken” (OpenAI 공개 토크나이저) — GitHub
저자: VibeCoding Tailor (테이라)
shuntailor.net 운영. 고려대 공대생 · Lovable 공식 앰버서더. 고려대 캠퍼스타운 창업 경진대회 우수상으로 교내 창업사무실에 입주, 지금은 개발에 집중 중. 내가 IT·AI를 공부하며 막힌 지점은 모두가 막힐 지점이라는 가정으로, 그 막힘을 하나씩 깊이 파헤쳐 「쉽깊잼(쉽고·깊고·재미있게)」을 실현한다. 이 블로그는 AI 시대의 표준을 만들기 위해 시작한 미디어다.


