LLM은 어떻게 글을 읽고 쓰는가 — 입력부터 출력까지
대화형 AI에게 질문을 던지면, 마치 사람처럼 문장을 이해하고 답을 써 내려가는 것처럼 보인다.
하지만 그 안에서 벌어지는 일은 생각보다 단순하고, 또 생각보다 기계적이다.
이 글에서는 두 가지 질문에 답해 본다.
LLM은 어떻게 글을 만들어내는가,
그리고 우리가 입력한 프롬프트는 모델에 어떤 모습으로 들어가는가.
1부. LLM은 어떻게 글을 만들어내는가
핵심은 "다음 토큰 맞히기"
먼저 결론부터. LLM이 하는 일의 본질은 "지금까지의 맥락 다음에 올 단어 조각을 확률적으로 예측하는 것" 하나다. 거대한 통계 모델이 "이 문맥 다음에는 이 조각이 올 가능성이 높다"는 패턴을 방대한 텍스트로부터 익혔고, 그 패턴을 매 순간 적용할 뿐이다. 우리가 보기엔 사고하고 작문하는 것 같지만, 내부적으로는 "다음 조각 예측 → 선택 → 반복"을 빠르게 수행하고 있다.
이 과정을 단계별로 풀어 보자.
토큰화: 문장을 조각내기
모델은 글자를 직접 다루지 않는다. 입력 문장은 먼저 **토큰(token)**이라는 작은 조각으로 쪼개진다. 토큰은 하나의 단어일 수도 있고, 단어의 일부일 수도 있다. 예를 들어 영어의 " the"는 공백을 포함해 한 토큰이 되기도 하고, 한국어 한 글자가 두세 토큰으로 나뉘기도 한다. 토큰과 글자는 1:1이 아니라는 점만 기억하면 된다.
임베딩: 숫자로 바꾸기
쪼갠 토큰은 곧바로 숫자 벡터로 변환된다. 컴퓨터는 글자를 직접 계산하지 못하므로, 각 토큰을 수백~수천 차원의 숫자 배열로 바꾼다. 이 벡터에는 토큰의 의미와 문맥적 성격이 담긴다. 비슷한 의미의 토큰은 비슷한 벡터로 표현되는 식이다.
어텐션: 문맥을 읽기
여기가 핵심이다. 어텐션(attention) 메커니즘은 각 토큰이 문장 안의 다른 모든 토큰과 얼마나 관련 있는지를 계산한다. "그 사과는 빨갛다"라는 문장에서 "빨갛다"가 "사과"와 강하게 연결되는 것을 모델이 스스로 알아내는 식이다. 이 계산을 수십 개의 층(layer)에 걸쳐 반복하면서, 모델은 점점 더 풍부한 문맥 표현을 쌓아 올린다.
확률 분포, 그리고 선택
마지막 층을 지나면 모델은 어휘집에 있는 모든 토큰에 대해 "이게 다음에 올 확률"을 계산한다. 예를 들어 "하늘은 ___" 다음에는 "파랗다 80%, 맑다 10%, 높다 5%…" 같은 확률 분포가 나온다.
그다음 이 분포에서 실제 토큰 하나를 **샘플링(sampling)**으로 고른다. 항상 1등만 고르는 게 아니라 약간의 무작위성(temperature 같은 설정으로 조절된다)을 주어, 자연스럽고 다양한 문장이 나오게 한다.
자기회귀: 한 글자씩 쌓기
고른 토큰을 입력의 끝에 다시 붙이고, 위 과정을 처음부터 되풀이한다. "파랗다"를 골랐다면 입력은 "하늘은 파랗다"가 되고, 다시 모델에 넣어 그다음 토큰을 예측한다. 이렇게 한 토큰씩 차례로 문장을 완성해 가는 방식을 자기회귀(autoregressive)라고 부른다. LLM이 답을 또박또박 흘려 쓰듯 출력하는 모습은, 바로 이 한 토큰씩 생성하는 과정이 화면에 비치는 것이다.
2부. 프롬프트는 어떻게 모델에 들어가는가
출력의 원리를 봤으니, 이번엔 반대편이다. 우리가 입력하는 다양한 종류의 프롬프트는 모델에 어떤 모습으로 들어갈까. 핵심을 먼저 말하면, "여러 종류"라는 건 사람이 보기에 그런 것이고, 모델 입장에서는 결국 하나의 토큰 시퀀스로 합쳐져서 들어간다.
역할(role)이라는 개념
대화형 AI의 입력은 보통 "역할"이 붙은 메시지들로 구성된다.
시스템(system): 모델의 역할, 성격, 지켜야 할 규칙을 지정한다. 보통 맨 앞에 한 번 들어가고, 사용자에게는 보이지 않는 경우가 많다.
사용자(user): 실제로 사람이 입력하는 질문이나 요청.
어시스턴트(assistant): 모델이 이전에 했던 답변. 대화가 이어질 때 맥락을 유지하기 위해 다시 포함된다.
채팅 템플릿과 특수 토큰
이 역할별 메시지들은 모델에 들어가기 직전에 **채팅 템플릿(chat template)**을 거쳐 하나로 합쳐진다. 각 메시지의 경계에는 <|system|>, <|user|>, <|assistant|> 같은 **특수 토큰(special token)**이 붙어서, 모델이 "여기부터 시스템 지시, 여기부터 사용자 질문"이라고 구분할 수 있게 한다.
그 결과물은 색으로 구분되던 메시지들이 특수 토큰을 경계로 한 줄로 이어진, 평평한 토큰 시퀀스다. 모델이 실제로 "보는" 것은 바로 이 한 줄이다. 그리고 이 시퀀스가 1부에서 설명한 생성 과정의 입력이 된다.
모델은 기억이 없다
여기서 자주 오해하는 부분이 있다. 모델 자체에는 대화를 기억하는 기능이 없다. 무상태(stateless) 구조다. 그래서 멀티턴 대화에서는 매 턴마다 지금까지의 시스템·사용자·어시스턴트 메시지 전체를 다시 합쳐서 입력한다. 대화가 길어질수록 입력 토큰이 계속 늘어나는 이유가 바로 이것이다. "AI가 앞 대화를 기억한다"기보다는, 매번 전체 대화록을 다시 읽혀 주는 셈이다.
다양한 입력도 결국 한 줄
형태가 다양해 보이는 다른 입력들도 결국 같은 시퀀스에 섞여 들어간다.
퓨샷 예시(few-shot): "이렇게 입력하면 이렇게 답해라"는 예시 몇 개를 시스템이나 사용자 메시지 안에 넣는다.
검색·문서 맥락(RAG): 외부에서 찾아온 문서를 사용자 메시지 앞에 붙여 함께 넣는다.
도구·함수 정의: 모델이 쓸 수 있는 도구 명세도 보통 시스템 영역에 토큰으로 들어간다.
첨부 파일·이미지: 텍스트는 토큰으로, 이미지는 별도 인코딩을 거친 뒤 같은 시퀀스에 합류한다.
즉 입력의 본질은 단 하나다. "특수 토큰으로 구획된, 하나의 긴 토큰 열을 만들어 모델에 넣는 것."
맺으며
두 편의 이야기는 사실 하나로 이어진다. 우리가 입력한 프롬프트는 역할 토큰으로 구분된 하나의 토큰 시퀀스로 합쳐지고, 모델은 그 시퀀스를 받아 다음 토큰을 한 개씩 예측하며 답을 써 내려간다. 입력도 출력도, 결국은 토큰이라는 같은 언어로 흐른다.
LLM이 신비롭게 느껴지는 건, 이 단순한 "다음 토큰 예측"이 충분히 큰 규모에서 반복될 때 놀라울 만큼 그럴듯한 결과를 내놓기 때문이다. 다음 글에서는 한 발 더 안쪽으로 들어가, 이 토큰들의 정체와 생성 속도를 결정하는 요인을 살펴본다.
작성 참고
이 글은 Claude의 도움을 받아 내용을 정리하였습니다.