문장은 한 번에 태어나지 않는다
ChatGPT에게 질문을 던지면 답변이 줄줄 흘러나오는 것처럼 보입니다. 마치 머릿속에서 완성된 문단을 한꺼번에 떠올린 뒤, 그것을 화면에 옮겨 적는 것 같습니다. 하지만 LLM의 내부 동작은 우리가 느끼는 인상과 조금 다릅니다.
LLM은 긴 답변을 한 번에 완성하지 않습니다. 아주 짧은 단위로, 다음에 올 가능성이 높은 조각을 하나 고릅니다. 그 조각을 기존 문장 뒤에 붙입니다. 그리고 다시 그다음 조각을 예측합니다. 이 과정을 반복하면 어느 순간 우리 눈에는 자연스러운 문장, 문단, 글 한 편이 나타납니다.
여기서 말하는 조각이 바로 토큰입니다. 토큰은 단어일 수도 있고, 단어의 일부일 수도 있고, 문장 부호나 공백일 수도 있습니다. 정확히 텍스트가 어떻게 토큰으로 나뉘는지는 뒤에서 자세히 다루겠습니다. 지금은 토큰을 "모델이 읽고 쓰는 텍스트의 작은 단위"라고 생각하면 충분합니다.
예를 들어 사용자가 다음과 같이 입력했다고 해봅시다.
오늘 점심은
이 문장 뒤에는 여러 말이 올 수 있습니다.
| 후보 토큰 | 그럴듯한 이어쓰기 |
|---|---|
| 김치찌개 | 오늘 점심은 김치찌개 |
| 라면 | 오늘 점심은 라면 |
| 샐러드 | 오늘 점심은 샐러드 |
| 회사 | 오늘 점심은 회사 |
| 매우 | 오늘 점심은 매우 |
사람은 이 후보들을 보며 "김치찌개나 라면은 자연스럽고, 회사나 매우는 조금 어색하네"라고 느낍니다. LLM도 비슷한 일을 합니다. 다만 느낌으로 판단하는 것이 아니라, 각 후보 토큰에 점수를 매기고 그 점수를 확률로 바꿉니다.
이것이 다음 토큰 예측의 핵심입니다.

후보 토큰에는 확률이 붙는다
LLM이 다음 토큰을 예측한다는 말은, 단순히 정답 하나를 찍는다는 뜻이 아닙니다. 모델은 "다음에 올 수 있는 모든 토큰"에 대해 가능성을 계산합니다. 이 가능성의 목록을 확률 분포라고 부릅니다.
조금 단순화해서 생각해봅시다. 모델의 어휘 사전에 다음 다섯 개 토큰만 있다고 가정합니다.
| 입력 | 후보 토큰 | 확률 |
|---|---|---|
| 오늘 점심은 | 김치찌개 | 0.35 |
| 오늘 점심은 | 라면 | 0.25 |
| 오늘 점심은 | 샐러드 | 0.18 |
| 오늘 점심은 | 피자 | 0.15 |
| 오늘 점심은 | 회의 | 0.07 |
확률을 모두 더하면 1이 됩니다. 모델은 "김치찌개가 무조건 정답이다"라고 말하는 것이 아닙니다. "내가 학습한 언어 패턴과 지금까지의 문맥을 보면, 김치찌개가 올 가능성이 35%, 라면이 올 가능성이 25%, 샐러드가 올 가능성이 18% 정도다"라고 말하는 셈입니다.
실제 모델의 후보는 다섯 개가 아니라 수만 개에서 수십만 개에 이릅니다. 모든 후보 토큰에 점수가 매겨지고, 그 점수들이 확률로 바뀝니다. 모델 내부에서는 먼저 각 토큰에 대한 원시 점수인 로짓(logit)이 만들어집니다. 로짓은 아직 확률이 아닙니다. 이 점수들을 소프트맥스(softmax)라는 계산을 통해 0과 1 사이의 확률로 바꾸면, 모든 후보 토큰의 확률 합이 1이 됩니다.
수식으로 쓰면 다음과 같은 느낌입니다.
P(다음 토큰 | 지금까지의 토큰들)읽는 방법은 간단합니다. "지금까지의 토큰들이 주어졌을 때, 다음 토큰이 무엇일 확률인가?"입니다. LLM은 매 순간 이 질문을 풀고 있습니다.
가장 높은 확률을 고르면 항상 좋은가
가장 쉬운 방법은 확률이 가장 높은 토큰을 고르는 것입니다. 앞의 예에서는 "김치찌개"가 0.35로 가장 높으니, 다음 토큰으로 김치찌개를 선택합니다. 이런 방식을 흔히 탐욕적 선택(greedy decoding)이라고 부릅니다. 지금 이 순간 가장 좋아 보이는 후보를 고르는 방식입니다.
탐욕적 선택은 안정적입니다. 같은 입력이 들어오면 대부분 같은 방향으로 답변이 흘러갑니다. 업무용 요약, 코드 생성, 데이터 추출처럼 예측 가능성이 중요한 작업에서는 이런 안정성이 큰 장점입니다.
하지만 항상 가장 높은 확률만 고르면 답변이 지나치게 평범해질 수 있습니다. "오늘 점심은" 뒤에 매번 가장 흔한 음식만 나오면 재미가 없습니다. 창작 글을 쓰거나 다양한 아이디어를 얻고 싶을 때는 조금 덜 뻔한 후보도 선택될 필요가 있습니다.
그래서 LLM은 종종 샘플링(sampling)을 사용합니다. 샘플링은 확률 분포를 보고 그 비율에 따라 하나를 뽑는 방식입니다. 김치찌개의 확률이 35%라면 자주 뽑히겠지만, 라면이나 샐러드도 가끔 선택될 수 있습니다. 확률이 낮은 후보는 덜 뽑히지만 완전히 배제되지는 않습니다.
차이는 카드 뽑기에 비유할 수 있습니다. 탐욕적 선택은 가장 높은 점수의 카드만 계속 집는 방식입니다. 샘플링은 점수가 높을수록 더 많이 들어 있는 카드 더미에서 하나를 뽑는 방식입니다. 그래서 같은 프롬프트라도 샘플링을 사용하면 결과가 달라질 수 있습니다.
Temperature: 확률 분포의 온도 조절
LLM을 API로 사용하다 보면 temperature라는 설정을 자주 만납니다. 이름 그대로 "온도"입니다. 온도가 낮으면 모델의 선택이 차분하고 안정적이 됩니다. 온도가 높으면 선택이 느슨해지고 다양해집니다.
다시 "오늘 점심은" 예로 돌아가 보겠습니다.
| 후보 토큰 | 원래 확률 |
|---|---|
| 김치찌개 | 0.35 |
| 라면 | 0.25 |
| 샐러드 | 0.18 |
| 피자 | 0.15 |
| 회의 | 0.07 |
temperature를 낮추면 높은 확률의 후보가 더 강해지고, 낮은 확률의 후보는 더 약해집니다. 김치찌개나 라면처럼 이미 그럴듯한 후보가 더 자주 선택됩니다. 반대로 temperature를 높이면 확률 차이가 완만해집니다. 샐러드, 피자, 심지어 조금 어색한 후보도 선택될 가능성이 커집니다.
일반적으로 다음처럼 이해하면 됩니다.
| 설정 | 경향 | 어울리는 작업 |
|---|---|---|
| 낮은 temperature | 안정적이고 반복 가능성이 높음 | 요약, 분류, 코드, 정보 추출 |
| 중간 temperature | 자연스러움과 다양성의 균형 | 일반 대화, 설명, 초안 작성 |
| 높은 temperature | 창의적이지만 엉뚱할 수 있음 | 브레인스토밍, 시 창작, 아이디어 발산 |
중요한 점은 temperature가 모델을 더 똑똑하게 만드는 설정은 아니라는 것입니다. temperature는 모델이 이미 계산한 확률 분포를 어떻게 사용할지 조절합니다. 낮춘다고 지식이 늘어나지 않고, 높인다고 깊은 추론 능력이 생기지 않습니다. 다만 선택의 성격이 달라집니다.
top-k: 후보를 상위 k개로 제한하기
샘플링을 하되 너무 이상한 후보까지 뽑히는 것은 막고 싶을 때가 있습니다. 이때 사용할 수 있는 방법이 top-k입니다. top-k는 말 그대로 확률이 높은 상위 k개의 후보만 남기고, 나머지는 버리는 방식입니다.
예를 들어 top-k를 3으로 설정하면 다음과 같이 됩니다.
| 후보 토큰 | 원래 확률 | top-k=3 적용 후 |
|---|---|---|
| 김치찌개 | 0.35 | 남김 |
| 라면 | 0.25 | 남김 |
| 샐러드 | 0.18 | 남김 |
| 피자 | 0.15 | 제외 |
| 회의 | 0.07 | 제외 |
이제 모델은 김치찌개, 라면, 샐러드 중에서만 다음 토큰을 뽑습니다. 피자도 아주 이상한 후보는 아니지만, 상위 3개 밖이므로 제외됩니다. 회의처럼 문맥상 어색한 후보도 함께 제외됩니다.
top-k는 후보의 개수를 직접 제한한다는 점에서 직관적입니다. k가 작을수록 안정적이고, k가 클수록 다양해집니다. 다만 언제나 "상위 몇 개"가 적절한지는 문맥에 따라 다릅니다. 어떤 상황에서는 그럴듯한 후보가 3개뿐일 수 있고, 어떤 상황에서는 50개 이상이 모두 자연스러울 수도 있습니다.
top-p: 확률의 덩어리로 후보를 고르기
top-k가 후보 개수를 기준으로 제한한다면, top-p는 확률의 누적합을 기준으로 후보를 제한합니다. top-p는 nucleus sampling이라고도 부릅니다. 핵심 후보군만 남긴다는 뜻으로 이해하면 됩니다.
예를 들어 top-p를 0.8로 설정했다고 합시다. 모델은 확률이 높은 후보부터 차례로 더해 누적 확률이 0.8에 도달할 때까지 후보를 남깁니다.
| 후보 토큰 | 확률 | 누적 확률 | 포함 여부 |
|---|---|---|---|
| 김치찌개 | 0.35 | 0.35 | 포함 |
| 라면 | 0.25 | 0.60 | 포함 |
| 샐러드 | 0.18 | 0.78 | 포함 |
| 피자 | 0.15 | 0.93 | 포함될 수 있음 |
| 회의 | 0.07 | 1.00 | 제외 |
누적 확률이 0.8을 넘기는 지점까지 후보를 선택하므로, 구현에 따라 피자까지 포함될 수 있습니다. 이렇게 하면 매 순간 문맥에 맞춰 후보군의 크기가 유연하게 달라집니다. 확률이 몇 개 후보에 몰려 있으면 후보군은 작아지고, 여러 후보가 비슷하게 가능하면 후보군은 커집니다.
실무에서는 temperature, top-k, top-p를 함께 조절하는 경우가 많습니다. 다만 처음부터 모든 값을 복잡하게 만질 필요는 없습니다. 먼저 기본값으로 결과를 확인하고, 답변이 너무 딱딱하면 다양성을 조금 높이고, 너무 산만하면 안정성을 높이는 식으로 접근하면 됩니다.
한 토큰이 다음 토큰의 문맥이 된다
이제 가장 중요한 반복 구조를 보겠습니다. LLM의 답변 생성은 다음과 같은 루프로 이루어집니다.
1. 사용자의 입력을 토큰으로 바꾼다.
2. 지금까지의 토큰들을 보고 다음 토큰의 확률 분포를 계산한다.
3. 설정에 따라 다음 토큰 하나를 선택한다.
4. 선택한 토큰을 기존 토큰 뒤에 붙인다.
5. 다시 2번으로 돌아간다.
6. 종료 조건을 만나면 생성을 멈춘다.예를 들어 사용자가 다음과 같이 입력했다고 해봅시다.
고양이는 왜
모델이 첫 번째로 "상자"라는 토큰을 골랐다고 합시다.
고양이는 왜 + 상자이제 모델의 입력은 더 이상 "고양이는 왜"가 아닙니다. 방금 자신이 만든 "상자"까지 포함한 "고양이는 왜 상자"가 새 문맥이 됩니다. 그다음에는 "를", "좋아", "할까" 같은 후보가 높은 확률을 얻을 수 있습니다.
고양이는 왜 상자
고양이는 왜 상자를
고양이는 왜 상자를 좋아
고양이는 왜 상자를 좋아할까
고양이는 왜 상자를 좋아할까요?이 과정을 빠르게 반복하면 화면에는 문장이 자연스럽게 흘러나오는 것처럼 보입니다. 하지만 내부에서는 매번 "다음 하나"를 고르고 있습니다. 긴 답변도 결국 다음 토큰 예측이 수백 번, 수천 번 이어진 결과입니다.
이 구조를 이해하면 LLM의 장점과 약점이 동시에 보입니다. 장점은 유연성입니다. 모델은 매 순간 지금까지의 문맥을 다시 보고 다음 말을 이어갈 수 있습니다. 그래서 사용자의 질문, 앞서 나온 답변, 대화의 분위기를 반영할 수 있습니다. 약점은 초반 선택이 이후 문맥을 바꾼다는 점입니다. 한 번 엉뚱한 방향으로 토큰이 선택되면, 그다음 예측은 그 엉뚱한 문맥 위에서 계속 진행될 수 있습니다.
같은 질문인데 왜 답이 달라질까
많은 사람이 처음 LLM을 사용할 때 신기하게 느끼는 지점이 있습니다. 같은 질문을 했는데 답이 조금씩 달라집니다. 어제는 짧고 단정하게 설명하더니, 오늘은 예시를 많이 들어 설명합니다. 같은 프롬프트를 복사해서 넣어도 문장 표현이 바뀌기도 합니다.
그 이유는 앞에서 본 샘플링에 있습니다. 모델이 매 순간 확률 분포를 만들고, 그중 하나를 뽑는다면 결과에는 자연스럽게 변동성이 생깁니다. 첫 번째 토큰이 조금 달라지면 두 번째 토큰의 문맥도 달라집니다. 두 번째가 달라지면 세 번째도 달라집니다. 작은 차이가 뒤로 갈수록 커질 수 있습니다.
예를 들어 같은 프롬프트가 있다고 합시다.
초보자에게 LLM을 한 문장으로 설명해줘.
한 번은 이렇게 시작할 수 있습니다.
LLM은 많은 텍스트를 학습해 다음에 올 말을 예측하는 인공지능 모델입니다.
다른 한 번은 이렇게 시작할 수 있습니다.
LLM은 문맥을 읽고 그다음에 올 가능성이 높은 단어를 이어 붙이는 언어 모델입니다.
둘 다 맞는 설명입니다. 다만 첫 선택과 이후 선택이 달랐을 뿐입니다. 사람에게 같은 질문을 해도 매번 완전히 같은 문장으로 답하지 않는 것과 비슷합니다. 차이는 사람의 변덕이 아니라, 모델의 확률적 생성 과정에서 나온다는 점입니다.
재현 가능한 생성을 만들려면
서비스를 만들 때는 "매번 조금씩 다른 답변"이 장점이 될 수도 있고 문제가 될 수도 있습니다. 글쓰기 도우미나 아이디어 생성기에서는 다양성이 유용합니다. 하지만 영수증에서 금액을 추출하거나 고객 문의를 정해진 카테고리로 분류하는 작업에서는 흔들림이 적어야 합니다.
재현 가능한 결과가 필요하다면 다음 설정을 확인해야 합니다.
temperature를 낮게 설정해 높은 확률의 토큰이 선택되도록 한다.
top-k나 top-p를 제한해 지나치게 낮은 확률의 후보가 선택되지 않게 한다.
같은 모델 버전, 같은 프롬프트, 같은 시스템 메시지, 같은 파라미터를 사용한다.
API가 seed 값을 지원한다면 같은 seed를 지정해 샘플링의 무작위성을 통제한다.
출력 형식이 중요하다면 자유 서술보다 JSON 같은 구조화된 형식을 요구한다.
여기서도 주의할 점이 있습니다. 어떤 시스템에서는 temperature를 0에 가깝게 두면 거의 같은 결과가 나오지만, 항상 모든 환경에서 완벽히 동일한 출력을 보장한다고 단정할 수는 없습니다. 모델 버전이 바뀌거나, 서버 내부 구현이 달라지거나, 프롬프트의 공백 하나가 바뀌어도 결과가 달라질 수 있습니다. 실무에서는 "확률을 낮추어 안정성을 높인다"와 "완전한 재현성을 보장한다"를 구분해야 합니다.
확률 분포 뒤에 있는 '생각하는 느낌'
LLM의 답변을 읽다 보면 모델이 정말 생각하는 것처럼 느껴집니다. 질문의 의도를 파악하고, 예시를 들고, 가끔 농담도 합니다. 이런 경험은 분명 인상적입니다. 하지만 이 장에서 기억해야 할 핵심은 하나입니다.
LLM의 말하기 뒤에는 매 순간의 확률 분포가 있습니다.
모델은 지금까지의 토큰을 보고 다음 토큰 후보들에 점수를 매깁니다. 그 점수는 확률로 바뀝니다. 생성 설정에 따라 가장 높은 후보를 고르거나, 확률적으로 하나를 샘플링합니다. 선택된 토큰은 다시 문맥에 붙고, 모델은 그다음 토큰을 예측합니다. 이 반복이 우리가 보는 답변을 만듭니다.
물론 이것만으로 LLM의 모든 능력을 설명할 수는 없습니다. 왜 어떤 문맥에서는 특정 토큰의 확률이 높아지는지, 모델은 문장 안의 멀리 떨어진 단어들을 어떻게 연결하는지, 단어의 의미는 숫자 안에 어떻게 담기는지 아직 많은 질문이 남아 있습니다. 앞으로의 장에서 우리는 이 질문들을 하나씩 풀어갈 것입니다.
다음 장에서는 텍스트가 모델 안으로 들어가기 위해 어떤 변신을 거치는지 살펴봅니다. 사람에게 문자는 의미의 단위이지만, 컴퓨터에게 문자는 그대로 이해되는 대상이 아닙니다. LLM이 다음 토큰을 예측하려면 먼저 텍스트가 숫자가 되어야 합니다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.