1. 임베딩과의 관계
임베딩은 숫자로 끝나고, LLM은 다음 단어를 계속 만들어낸다.
- 임베딩은 "텍스트→벡터" 변환만 하고 끝남
- LLM은 같은 트랜스포머 계열 구조를 쓰지만 벡터에서 다시 텍스트를 생성한다.
- 둘 다 "문맥을 이해한다"는 점은 같은데, 출력 형태가 다른 것.
[ML] 벡터 임베딩(Vector Embedding) - 의미를 벡터로
cf) TF-IDF [ML] TF-IDF(Term Frequency-Inverse Document Frequency)1. TF-IDF?정의단어의 빈도(TF)와 역문서빈도(IDF)를 곱해서, 문서 내 각 단어의 "중요도"를 가중치로 매기는 방법단순히 "몇 번 나왔는가"만 세는 빈
blog.chaenii.me
2. 트랜스포머
트랜스포머의 핵심은 어텐션(attention) 메커니즘이다.
깊은 구조까지 알 필요는 없고, 풀고자 한 문제만 이해하면 충분하다.
이전 모델의 한계
- 문장을 한 단어씩 순서대로 읽으면서 "기억"을 누적하는 방식
- 문장이 길어지면 앞부분의 정보가 점점 희석되는 문제가 있었다
트랜스포머의 해법 - 전체를 한 번에
문장 전체를 동시에 보면서, 각 단어가 다른 모든 단어와 얼마나 "관련 있는지"를 직접 계산한다 (어텐션 스코어)
e.g) "그것은 책상 위에 있었다. 강아지가 그것을 물어뜯었다"에서 "그것"이 무엇을 가리키는지, 문장 전체를 동시에 보면서 가중치를 매겨 판단한다
어텐션 수식 (구조만 보면 충분)
각 단어는 세 가지 벡터로 변환된다:
| 벡터 | 역할 | 비유 |
| Query ($Q$) | "나는 무엇과 관련 있는가?" 를 묻는다 | 검색 키워드 |
| Key ($K$) | "나는 어떤 내용을 담고 있는가?" 를 알린다 | 책의 목차·태그 |
| Value ($V$) | 실제로 전달할 정보 | 책의 본문 |
계산 순서:
- 한 단어의 $Q$와 다른 모든 단어의 $K$를 내적 → 관련도 점수
- 소프트맥스로 정규화 → 가중치 (전체 합 = 1)
- 그 가중치로 $V$들을 가중평균 → 최종 출력
$$
\text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
- $\sqrt{d_k}$로 나누는 건 벡터 차원이 커질수록 내적 값이 커져서 소프트맥스가 한쪽으로 쏠리는 걸 막기 위한 스케일 조정이다.
- 흥미로운 점: $QK^T$가 벡터 유사도에서 본 내적과 본질적으로 같은 연산이다.
- "이 단어와 저 단어가 얼마나 관련 있는가"를 코사인 유사도와 같은 방식(내적)으로 계산
- $\sqrt{d_k}$로 나누는 건 벡터 차원이 커질수록 내적 값이 커져서 softmax 출력이 한쪽으로 쏠리는 걸 막기 위한 스케일 조정이다.

- 문맥이 길어도 정보가 희석되지 않음
- 병렬 계산 가능: 순서대로 읽지 않아도 됨
- 학습 속도 증가
3. LLM 텍스트 생성 원리: 다음 토큰 예측
- LLM이 텍스트를 생성하는 원리 - 지금까지 나온 단어들을 보고, 다음에 올 단어(정확히는 토큰)가 무엇일지 확률로 예측하는 것:
$$
P(w_t \mid w_1, w_2, \ldots, w_{t-1})
$$
- 전체 어휘(e.g. 5만 개 토큰)에 대해 "다음 토큰이 이것일 확률" 전부 계산 → 확률분포 생성
- 그중 하나를 골라 출력
- 그 단어를 다시 입력에 추가 → 그다음 단어를 또 예측
- 반복 → 문장 완성
확률분포는 어떻게 만들어지는가: 소프트맥스(softmax):
- 신경망의 마지막 층은 어휘의 각 토큰마다 "점수"(logit)라는 임의의 실수를 출력한다.
- 소프트맥스가 이 점수들을 합이 1인 확률처럼 바꿔준다.
$$
P(w_i) = \frac{e^{z_i}}{\sum_j e^{z_j}}
$$
$z_i$는 토큰 $i$의 점수(logit).
지수함수를 쓰는 이유
- 항상 양수를 보장해서 확률처럼 다룰 수 있게 함
- 점수 차이를 "증폭"시켜서 점수가 높은 토큰일수록 확률이 비례 이상으로 더 커지게 함
- 점수가 약간만 높아도 확률은 훨씬 더 높아지는 식

4. Temperature: 확률분포에서 어떻게 뽑을 것인가
확률분포가 만들어진 다음, 실제로 어떤 토큰을 뽑을지를 결정하는 파라미터가 temperature다.
- temperature = 0: 항상 확률이 가장 높은 토큰을 그대로 선택(그리디 디코딩). 같은 입력엔 거의 항상 같은 출력
- temperature 높음(예: 1.0 이상): 확률이 낮은 토큰도 가끔 선택될 수 있게 함 — 같은 질문에도 매번 표현이나 결론이 조금씩 달라질 수 있음
temperature는 소프트맥스에 들어가기 전에 점수(logit) $z_i$를 $T$로 나누는 방식으로 구현된다:
$$
P(w_i) = \frac{e^{z_i/T}}{\sum_j e^{z_j/T}}
$$
- $T$가 작을수록(0에 가까울수록): 점수 차이가 나누기를 통해 더 크게 벌어져서 소프트맥스가 1등 토큰에 거의 모든 확률을 몰아줌(분포가 뾰족해짐)
- $T$가 클수록: 점수 차이가 줄어들어 여러 토큰에 확률이 고르게 퍼짐(분포가 평평해짐)
- $T=0$: 수학적으로는 나눗셈이 정의 안 되지만, 실제 구현에서는 "그냥 1등을 그대로 선택"하는 것으로 처리함

temperature=0이라고 해서 "신경망을 안 쓰고 룰베이스로 작동하는 것"이 아니다.
temperature=0이어도 모델은 여전히 입력 전체를 신경망으로 통과시켜 문맥을 이해하고 확률분포를 계산하는 무거운 연산을 그대로 한다.
temperature가 바꾸는 건 그 확률분포에서 마지막에 토큰 하나를 뽑는 방식뿐.
룰베이스는 신경망 연산이 전혀 없는 if-then 코드라서, temperature와 상관없이 LLM과는 완전히 다른 메커니즘이다.
법률·의료처럼 일관성이 중요한 도메인에서는 같은 질문에 항상 같은 답이 나오게 하기 위해 temperature를 0 또는 0에 가깝게(e.g. 0.1) 낮게 설정하는 게 일반적이다.
5. 토크나이저: 텍스트를 토큰으로 쪼개는 방법
- 토크나이저(tokenizer): LLM이 텍스트를 처리하기 전에 텍스트를 토큰으로 쪼갠다
- 각 토큰을 정수 ID로 변환한 뒤 모델에 입력한다.
토큰은 단어와 다르다. 현대 LLM은 거의 다 서브워드(subword) 토크나이저를 쓴다.
"unhappiness" → ["un", "happiness"] 처럼 자주 나오는 조합은 하나의 토큰, 드문 단어는 더 작게 쪼개진다.
한국어는 영어보다 토큰 효율이 낮다:
- 영어: 단어 하나 ≈ 토큰 1~2개
- 한국어: 어절 하나 ≈ 토큰 2~5개 (조사·어미가 별도 토큰으로 분리되는 경우가 많음)
이는 실전에서 두 가지 영향을 미친다:
- 비용: API는 보통 토큰 수 기준으로 과금한다. 한국어 문서는 같은 분량이어도 영어보다 토큰 수가 더 많이 나와 비용이 높아진다
- 컨텍스트 윈도우 소진: 아래 항목 참고
6. 컨텍스트 윈도우
- 컨텍스트 윈도우(context window): LLM이 입력으로 받을 수 있는 최대 토큰 수
- 입력(프롬프트 + 이전 대화)과 출력(생성할 텍스트)을 합친 토큰 수가 이 한계를 넘으면 잘리거나 오류가 난다.
컨텍스트 윈도우가 크면 좋지만, 토큰이 많아질수록 비용·지연도 선형 이상으로 증가한다.
또한 컨텍스트가 너무 길면 "lost in the middle" 현상이 생긴다.
모델이 입력의 앞부분과 뒷부분은 잘 참조하는 반면 중간 부분을 잘 못 참조하는 경향.
RAG 설계에서 너무 많은 청크를 프롬프트에 넣지 않는 이유 중 하나다.
7. 프롬프트 유형
LLM에게 같은 작업을 시키더라도 프롬프트 방식에 따라 품질이 크게 달라진다.
시스템 프롬프트(system prompt): 사용자 메시지 앞에 붙는 특별 지시문. 모델의 역할, 행동 방침, 응답 형식을 미리 설정한다.
e.g) "당신은 쇼핑몰 CS 챗봇입니다. 답변은 한국어로, 200자 이내로 합니다."
프롬프팅 방식:
- Zero-shot: 예시 없이 지시만 한다. "이 리뷰의 감성을 긍정/부정으로 분류해줘."
- Few-shot: 예시 몇 개를 먼저 보여주고 패턴을 따르게 한다. 복잡한 작업일수록 Few-shot이 Zero-shot보다 안정적인 결과를 낸다
예시:
리뷰: "배송이 너무 빠르고 포장이 깔끔해요!" → 긍정
리뷰: "제품 불량이 있어서 실망했어요" → 부정
---
리뷰: "가격 대비 품질이 괜찮네요" → ?
- Chain-of-thought(CoT): "단계별로 생각하면서 답해줘"라고 지시해서 모델이 중간 추론 과정을 출력하게 한다. 수학 문제·복잡한 논리 추론에서 정확도가 높아진다
8. 환각(Hallucination)
환각(hallucination): LLMdl 없는 사실을 그럴듯하게 만들어내는 경향.
- 모르는 내용에 대해 "확인이 필요합니다"가 아니라 그냥 만들어서 답한다
- 존재하지 않는 논문·법령·인물 정보를 자신감 있게 제시한다
- 특히 정확한 숫자, 날짜, 고유명사에서 자주 발생한다
왜 생기는가:
LLM은 "다음에 올 토큰이 뭘지 확률적으로 예측"하는 모델이다.
틀린 정보도 문맥상 자연스럽게 이어지면 높은 확률로 선택될 수 있다.
사실 여부를 확인하는 메커니즘이 기본 구조에 없다.
완화 방법:
- RAG: 근거 문서를 프롬프트에 넣어주면 모델이 그 범위 안에서 답하도록 유도할 수 있다
- 낮은 temperature: 확률 분포를 뾰족하게 만들어 덜 창의적인(= 더 보수적인) 답변을 유도
- 출처 인용 요청: "답변마다 근거 문서를 인용하라"고 지시하면 환각이 줄어드는 경향
- 검증 레이어: LLM 출력을 다른 LLM으로 검증하거나 외부 API로 팩트체크
환각은 현재 LLM의 구조적 한계라서 완전히 제거할 수 없다. 높은 정확성이 요구되는 도메인(법률·의료·금융)에서는 반드시 검증 레이어를 따로 두어야 한다.
9. 함수 호출(Function Calling / Tool Use)
LLM이 외부 시스템과 연동하는 방법.
LLM 자체가 직접 API를 호출하는 게 아니라, LLM이 "어떤 함수를 어떤 인자로 호출해달라"는 JSON을 출력하면, 그걸 받은 코드가 실제 함수를 실행하고 결과를 다시 LLM에 넘기는 방식이다.
흐름:
사용자: "현재 서울 날씨는?"
↓
LLM 출력: { "function": "get_weather", "args": { "city": "서울" } }
↓
코드가 날씨 API 호출 → "맑음, 23°C" 반환
↓
LLM: "서울은 현재 맑고 23°C입니다."
이 패턴이 유용한 이유:
- LLM이 학습 시점 이후의 실시간 데이터(날씨, 주가, 재고 등)에 접근 가능
- 데이터베이스 조회, 외부 서비스 호출, 계산 실행 등 LLM이 직접 할 수 없는 작업을 연결
- 도구(tool)를 여러 개 정의해두고 LLM이 상황에 따라 선택해서 쓰게 할 수 있다
RAG도 넓은 의미에서 "검색 도구를 LLM이 활용하는 패턴"으로 볼 수 있다.
10. JSON 스키마: 출력 형식을 강제하기
LLM의 출력은 기본적으로 자유로운 텍스트다.
그런데 시스템에서 LLM의 답을 코드로 처리하려면 형식이 고정돼 있어야 한다.
그래서 프롬프트에 "이 JSON 스키마 형태로만 답하라"고 명시적으로 지시하고, 모델이 그 형식을 따르도록 유도한다.
모델이 형식을 어기고 설명을 덧붙이거나 마크다운 코드블록으로 감싸서 답하는 경우도 흔해서,
실전에서는 응답을 받은 뒤 그런 잡음을 제거하고 JSON 부분만 추출하는 파싱 로직을 따로 둔다.
파싱이 실패하면(JSON이 아니거나 필드가 빠졌으면) 이를 "신뢰할 수 없는 응답"으로 간주하고 별도 처리(재시도, 에스컬레이션, 폴백)를 하는 게 일반적이다.
11. 배치(batch)와 동시성(concurrency)
LLM API 호출은 비용과 시간이 든다.
항목 하나하나마다 호출하면 비효율적이라, 여러 항목을 한 번의 프롬프트에 묶어서(배치) 한 번의 호출로 처리하는 방식을 쓴다.
다만 배치가 너무 크면 모델의 응답 시간이 길어지고, 일부 추론(reasoning) 특화 모델은 처리시간이 오래 걸려 네트워크 타임아웃에 걸릴 수 있다.
그래서 배치 크기는 모델의 응답속도·타임아웃 제약을 보고 실전적으로 조정한다.
여러 배치를 처리해야 한다면, 순차적으로 하나씩 호출하는 대신 동시에 여러 개를 병렬로 호출(concurrency)해서 전체 처리시간을 줄인다.
다만 동시에 너무 많이 호출하면 API의 속도제한(rate limit)에 걸리므로, 동시 호출 개수에 상한을 두는 게 일반적이다.
12. 정리
- 트랜스포머는 어텐션으로 문장 전체를 한 번에 보며 단어 간 관련도를 계산 — RNN의 정보 희석 문제를 해결
- LLM은 "다음 토큰 확률분포"를 소프트맥스로 만들고, temperature로 그 분포에서 어떻게 뽑을지를 조절
- temperature=0이어도 신경망 연산(문맥 이해, 확률분포 계산)은 그대로 수행됨 — 룰베이스와는 본질적으로 다른 메커니즘
- 출력 형식을 강제(JSON 스키마)하고, 배치·동시성으로 비용·지연을 조절하는 게 실전 운영의 핵심
LLM은 학습된 지식(모델 학습 시점까지의 데이터)만 갖고 있다. 회사 내부 문서나 최신 정책처럼 모델이 모르는 정보를 답변에 반영하려면, 검색을 LLM 호출 앞에 끼워넣어야 한다. 그 설계 패턴이 RAG다.
GitHub 댓글