참조 사이트
- SKALA 4기 - LLM과 Transformer 아키텍처 (SK AX SKALA)
- Attention Is All You Need (Vaswani et al., 2017)
- The Illustrated Transformer (Jay Alammar)
개요

지난 [LLM Pipeline 3]에서는 데이터로더로부터 전달받은 [Batch, Time] (이하 [B, T]) 정수 토큰 배치를 고차원 의미 공간의 밀집 좌표로 변환하고 어순 감각을 부여하는 토큰 임베딩(Token Embedding)과 위치 인코딩(Positional Encoding & RoPE)을 살펴보았다.
임베딩과 위치 정보 결합을 거친 결과물은 단어의 고유 의미와 위치 정보가 결합된 [Batch, Time, Dimension] (이하 [B, T, D]) 형태의 3차원 입력 밀집 텐서이다. 하지만 이 텐서는 아직 주변 단어들과 어떠한 상호작용도 거치지 않은 고립된 단어 임베딩에 가깝다.
이번 글에서는 트랜스포머 아키텍처의 핵심 축이자, 단어들이 문맥 속에서 서로 정보를 교환하며 동적인 의미 표현을 완성해 나가는 어텐션(Attention) 메커니즘의 수학적 원리(Q, K, V 수식 분해)와 주요 4대 어텐션 유형에 대해 깊이 있게 다룬다.

1. 어텐션(Attention)이란 무엇인가?
① 문맥에 따른 동적 의미 표현 (Dynamic Representation)
어텐션은 "문장 속에서 특정 단어를 해석할 때, 주변의 어떤 단어들에 가중치를 두고 결합할 것인지 수학적으로 계산하는 기술"로 정의할 수 있다.
사람이 문장을 읽을 때 모든 단어를 동일한 비중으로 읽지 않고 문맥적으로 연관된 단어들에 시선을 집중하듯이, 모델 역시 단어 간의 상호 유사도(가중치)를 계산하여 단어 벡터에 반영한다.

- 예시 문장 A: "그 은행에 가서 돈을 찾고 예금을 넣었다."
- 예시 문장 B: "가을이 되니 은행나무에 은행이 노랗게 열렸다."
사전에서 정의된 단일 벡터 상태의 '은행'은 금융기관을 의미하는지 나무 열매를 의미하는지 구분하기 어렵다.
- 문장 A에서는 '돈', '예금'이라는 단어와의 어텐션 가중치를 강하게 계산하여, 임베딩 벡터가 금융기관의 문맥 정보를 갖도록 실시간으로 업데이트된다.
- 문장 B에서는 '가을', '나무', '열렸다'라는 단어와의 유사도를 크게 연산하여, 나무 열매의 의미적 표현에 부합하도록 업데이트된다.
즉, 어텐션은 고정된 단어 고유의 초깃값에 주변 단어들의 문맥적 의미를 반영하여 가장 알맞은 의미 표현을 구성하는 연산 과정이다.
💡 용어 사전: 셀프 어텐션(Self-Attention)
문장 내부의 모든 토큰 쌍 간의 연관성을 확률로 계산하여, 단어가 문맥 속에서 주변 단어들과 맺는 관계 정보를 동적으로 표현 벡터에 반영하는 메커니즘이다.
② RNN과의 비교: 순차 병목에서 직접 연결로
트랜스포머 이전의 NLP 분야를 이끌던 RNN 기반 구조는 단어를 앞에서부터 순차적으로 처리해야 했기 때문에 다음과 같은 구조적인 제약을 가지고 있었다.
- 장기 의존성(Long-Term Dependency) 정보 손실: 문장의 길이가 길어질수록 초반에 들어온 단어 정보가 뒤로 갈수록 희석되는 고질적인 한계가 존재했다.
- 순차 연산 병목 (O(T) 연산 흐름): 번째 단어를 계산하기 위해서는 반드시 t−1번째 단어의 연산이 선행되어야 하므로 GPU 병렬 연산의 성능을 온전히 활용하기 어려웠다.

트랜스포머의 셀프 어텐션은 문장 내 모든 단어 쌍 사이의 상호 관계를 단 한 번의 행렬곱(O(1)의 최대 경로 거리)으로 직접 계산하여, 거리가 먼 단어들 간의 관계도 정보 손실 없이 연결하며 완전한 병렬 연산을 실현했다.
2. Query, Key, Value의 수학적 및 개념적 정의
트랜스포머는 입력 임베딩 텐서 X ∈ ℝ^(T × D)에 학습 가능한 3개의 가중치 행렬 W_Q, W_K, W_V ∈ ℝ^(D × D)를 곱하여, 각 단어마다 서로 다른 역할을 담당하는 3가지 분신 벡터를 생성한다.

이해를 돕기 위해 Q, K, V의 개념을 검색 시스템과 도서관 대출 과정의 비유로 정리할 수 있다.
| 요소 | 비유 | 도서관 비유 | 수학 및 문맥적 역할 |
| Query (Q) | 검색창에 입력한 검색어 | 도서 대출 요청서 | "내가 지금 찾고자 하는 질문/기준" (현재 단어의 입장에서 상대방을 탐색하는 주체) |
| Key (K) | 동영상의 해시태그/메타데이터 | 책 표지의 도서 분류 표지 | "각 단어가 가지고 있는 식별 정보" (Query와 매칭하여 가중치를 매기기 위한 대상) |
| Value (V) | 동영상의 실제 내용물 | 책 내부의 진짜 본문 지식 | "각 단어가 내포하고 있는 정보의 실제 알맹이" (어텐션 확률에 따라 가중합되는 대상) |
💡 용어 사전: 쿼리(Query, Q)
어텐션 연산에서 '질문(검색어)' 역할을 하는 벡터로, 현재 토큰이 문맥 속 다른 토큰들과 얼마나 강하게 연결되는지 확인하는 연산의 주체이다.
💡 용어 사전: 키(Key, K)
어텐션 연산에서 '색인(Index)' 역할을 하는 벡터로, Query 벡터와의 유사도를 계산하기 위해 각 토큰이 내세우는 대표적인 식별 속성을 대변한다
💡 용어 사전: 밸류(Value, V)
어텐션 연산에서 '실제 값(본문 지식)' 역할을 하는 벡터로, 계산된 어텐션 확률 가중치에 따라 최종적으로 가중합되어 출력 텐서의 정밀한 문맥 정보가 되는 정보의 알맹이다.
3. Scaled Dot-Product Attention 연산의 4단계 공정

트랜스포머의 핵심 어텐션 수식은 다음과 같다.
Attention(Q, K, V) = softmax( (Q·Kᵀ) / √d_k ) · V
이 수식은 모델 내부적으로 아래와 같이 4단계의 정밀한 텐서 연산 공정을 거치게 된다.
[Step 1: Q × K^T] 검색어(Q)와 라벨(K)의 내적 ➔ 단어 간 '연관도 원시 점수표' [T × T] 생성
▼
[Step 2: ÷ √d_k] 차원 크기로 나누기 ➔ Softmax 기울기 소실 방지 (스케일 정규화)
▼
[Step 3: Softmax] 점수를 행 단위 합이 1.0(100%)인 'Attention 확률 가중치'로 변환
▼
[Step 4: × V] 확률 비율대로 각 단어의 알맹이(V)를 가중합하여 문맥 벡터 완성
① 1단계: 행렬 내적 (Q·Kᵀ) ➔ 단어 간 유사도 맵 생성
- Q ∈ ℝ^(T × d_k)와 Kᵀ ∈ ℝ^(d_k × T)를 행렬곱하면 d_k 축이 축약되면서 [T, T] 크기의 정방행렬이 생성된다.
- 이 [T, T] 행렬의 (i, j) 원소는 "i번째 단어(Query)가 j번째 단어(Key)와 의미적으로 얼마나 밀접한지"를 나타내는 원시 내적 점수(Dot-Product Score)가 된다.
② 2단계: 스케일링 (÷ √d_k) ➔ 기울기 소실(Gradient Vanishing) 방지
- 왜√d_k로 나누어 주는가?
- 헤드별 임베딩 차원 d_k(예: LLaMA-3-8B 기준 128)가 커질수록, 내적 결과값(Q·Kᵀ)의 분산 역시 차원 크기에 비례하여 증가한다.
- 값이 지나치게 커진 상태로 Softmax 함수를 통과시키면, 출력이 특정 원소에 극단적으로 치우치게(0 또는 1에 근접) 된다.
- 이는 역전파(Backpropagation) 과정에서 Softmax의 미분 기울기가 0에 가까워져 가중치 학습이 정체되는 기울기 소실(Gradient Vanishing) 문제를 유발한다.
- 따라서 √d_k로 나누어 분산을 1로 정규화함으로써 수치적 안정성을 확보한다.
③ 3단계: Softmax ➔ 확률 분포화 (주목도 확률 지도 완성)
- 스케일링된 점수표의 행(Row) 단위로 Softmax 함수를 취한다.
- 각 행의 점수값들의 합이 정확히 1.0(100%)으로 변환되며, ii번째 단어가 전체 문맥 속에서 다른 단어들을 각각 몇 %의 비중으로 바라보고 집중해야 하는지(Attention Weights)를 보여주는 확률 지도가 완성된다.
④ 4단계: 가중합 (× V) ➔ 문맥 정보가 반영된 벡터 생성
- 계산된 확률 가중치 [T, T] 행렬과 실제 단어가 지닌 지식 정보인 V ∈ ℝ^(T × d_v) 행렬을 행렬곱한다.
- 확정된 확률 비중만큼 각 단어의 Value 벡터를 선형 결합(가중합)하여, 최종적으로 고립된 표현을 탈피하고 문맥 정보가 융합된 [T, d_v] (전체 배치 및 다중 헤드 기준 [B, T, D]) 출력 텐서를 생성한다.
💡 [심화 분석] 셀프 어텐션의 연산 복잡도와 O(T²) 병목
셀프 어텐션의 Q·Kᵀ 연산은 시퀀스 길이 T에 대해 T × T 정방행렬을 생성하므로, 시간 및 공간 복잡도가 모두 O(T²·d)를 따른다. 즉, 컨텍스트 길이(T)가 2배 늘어나면 연산량과 메모리 점유율은 4배(T²)로 증가한다. 현대 LLM에서 FlashAttention이나 GQA 같은 최적화 기법을 적극적으로 도입하는 이유가 바로 이 2차 복잡도에 따른 GPU 메모리 오버헤드를 완화하기 위함이다.
4. 주요 4대 어텐션 유형 및 특성

트랜스포머 아키텍처는 적용 목적과 데이터 처리 방향에 따라 어텐션의 연산 방식을 4가지 형태로 변형하여 설계에 반영한다.
① Self-Attention (자체 어텐션)
- 동일한 문장 내부의 토큰들이 서로 대조되며 Query, Key, Value 역할을 동시에 수행해 맥락을 연산한다.
- 문장 내 대명사가 가리키는 실제 핵심 주어를 식별하거나, 주어와 동사 간의 의미적 호응 관계를 포착하는 데 특화되어 있다.
② Multi-Head Attention (다중 헤드 어텐션)
- Q, K, V의 의미 차원 전체를 한 번에 연산하는 대신, h개의 독립적인 저차원 헤드(Head, d_k = D/h) 영역으로 분할하여 병렬로 개별 어텐션을 실행한다. 이후 도출된 모든 출력물을 연결(Concat)하고 가중치 행렬 W_O를 곱해 복원한다.
- 한 번에 하나의 단면만 찍는 단일 렌즈 대신, 여러 각도의 다른 정보를 포착하는 멀티 렌즈 카메라(8~32개)를 사용하는 원리와 유사하다. 문법 구조, 대조 관계, 문장 내 의미적 유사성 등을 다각도로 병렬 탐지한다.
③ Masked Causal Self-Attention (인과적 마스크 자체 어텐션)
- GPT 계열의 디코더 및 LLM 생성 모델의 표준 어텐션 기법이다.
- 모델이 현재 토큰을 기준 삼아 다음 단어를 예측할 때, 뒤이어 올 미래 시점 단어를 미리 참조하는 정보 유출(Information Leakage)을 방지해야 한다. 이를 위해 어텐션 스코어 맵의 오른쪽 위 삼각 영역(미래 위치)을 -∞로 치환하여 Softmax 연산 시 주목 확률을 0으로 소거하는 마스킹 메커니즘을 적용한다.
④ Cross-Attention (교차 어텐션)
- 번역 모델(T5, Transformer 인코더-디코더)이나 이종 모달리티 생성 모델(Whisper, Stable Diffusion)에서 중추적인 연결 통로로 작동한다.
- Query(Q) 벡터는 타겟 문장을 추론하는 디코더 정보에서 가져오고, Key(K)와 Value(V) 벡터는 조건 원문을 담고 있는 인코더의 최종 출력에서 가져와 결합한다. 디코더가 문장을 생성하면서 인코더가 전달한 원문 맥락의 특정 지점을 참조하도록 정렬한다.
💡 엔지니어링 트렌드] Multi-Head Attention(MHA)에서 GQA(Grouped-Query Attention)로의 진화
최신 LLM(LLaMA-3, Mistral 등)에서는 추론 시 KV Cache가 차지하는 GPU 메모리 점유율을 줄이기 위해 GQA를 표준으로 채택한다.
• MHA (Multi-Head Attention): Q, K, V 헤드 수가 동일 (1:1 매칭)
• MQA (Multi-Query Attention): K, V 헤드를 단 1개만 두고 모든 Q 헤드가 공유
• GQA (Grouped-Query Attention): Q 헤드를 여러 그룹으로 묶고, 그룹당 1개의 K, V 헤드를 공유하여 성능 저하 없이 KV Cache 메모리 사용량을 대폭 절감
5. 4대 어텐션 방식 핵심 비교
| 어텐션 유형 | Q의 출처 | K, V의 출처 | 주요 적용모델 | 핵심 역할 및 기능 |
| Self-Attention | 현재 입력 문장 | 현재 입력 문장 | Transformer, BERT | 문장 내 단어 간 의미적·구조적 인과성 계산 |
| Multi-Head Attention | 현재 문장 (헤드 단위 분할) | 현재 문장 (헤드 단위 분할) | 현대 모든 LLM 모델 공통 | 서로 다른 가중치 공간에서 문맥 다각화 학습 |
| Masked Causal Attention | 현재 입력 문장 | 현재 문장 (과거~현재 위치) | GPT 계열, LLaMA, Gemma 등 | 우상단 어텐션 맵 마스킹으로 미래 정보 유출 차단 |
| Cross-Attention | 디코더 입력 상태 | 인코더의 출력 상태 텐서 | T5, Whisper, Diffusion 계열 | 입력 조건(Condition) 정보와 출력 시퀀스 교차 매핑 |
6. PyTorch 기반 Multi-Head Self-Attention 클래스 구현
인과적 마스킹(Causal Mask)을 포함하는 Multi-Head Self-Attention의 PyTorch 구현 코드와 텐서 차원의 실시간 흐름은 다음과 같다.
① PyTorch Multi-Head Attention 모듈 클래스 정의
import torch
import torch.nn as nn
import math
class CausalMultiHeadSelfAttention(nn.Module):
def __init__(self, d_model, n_heads):
super().__init__()
assert d_model % n_heads == 0, "d_model은 n_heads의 배수여야 합니다."
self.d_model = d_model
self.n_heads = n_heads
self.d_k = d_model // n_heads
# Q, K, V 선형 매핑 레이어 정의
self.W_q = nn.Linear(d_model, d_model, bias=False)
self.W_k = nn.Linear(d_model, d_model, bias=False)
self.W_v = nn.Linear(d_model, d_model, bias=False)
# 병합된 최종 헤드를 원본 의미 차원으로 복원하는 레이어
self.W_o = nn.Linear(d_model, d_model, bias=False)
def forward(self, x):
B, T, D = x.shape
# 1. 임베딩 입력에 선형 결합을 곱해 Q, K, V 변환 생성 [B, T, D]
q = self.W_q(x)
k = self.W_k(x)
v = self.W_v(x)
# 2. 다중 헤드 h와 헤드별 차원 d_k 단위로 분할 후 전치 [B, h, T, d_k]
q = q.view(B, T, self.n_heads, self.d_k).transpose(1, 2)
k = k.view(B, T, self.n_heads, self.d_k).transpose(1, 2)
v = v.view(B, T, self.n_heads, self.d_k).transpose(1, 2)
# 3. Scaled Dot-Product 연산으로 어텐션 점수 행렬 도출 [B, h, T, T]
scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.d_k)
# 4. 미래 토큰 위치를 무력화하는 인과적 마스크(Causal Mask) 주입
mask = torch.triu(torch.ones(T, T), diagonal=1).bool().to(x.device)
scores = scores.masked_fill(mask, float('-inf'))
# 5. Softmax 함수를 통과시켜 시선 집중 확률 분포화 [B, h, T, T]
attention_weights = torch.softmax(scores, dim=-1)
# 6. 구한 확률 분포 비중대로 실제 알맹이(Value) 벡터 가중합 진행 [B, h, T, d_k]
out = torch.matmul(attention_weights, v)
# 7. 분산된 헤드를 합산 복원 후 contiguous() 메모리 재배열 [B, T, D]
out = out.transpose(1, 2).contiguous().view(B, T, D)
# 8. 마지막 가중치 곱 연산 적용 후 최종 텐서 변환 완료
output = self.W_o(out)
return output, attention_weights
② 실제 가상 입력 구동을 통한 텐서 흐름 검증
# 차원 검증을 위한 하이퍼파라미터 설정
batch_size = 2 # B: 동시에 학습 연산 중인 배치 크기
seq_len = 4 # T: 입력 시퀀스 토큰 개수
d_model = 768 # D: 단어 의미 임베딩 차원수
n_heads = 8 # h: 설계된 병렬 카메라 헤드 개수
# 1. 가상 정수 텐서가 임베딩을 통과한 형태 모사 [B, T, D] -> [2, 4, 768]
x = torch.randn(batch_size, seq_len, d_model)
print("1. 입력 텐서 차원 (X):", x.shape)
# 2. 어텐션 모델 가동 및 전방향 전파 수행
mha = CausalMultiHeadSelfAttention(d_model=d_model, n_heads=n_heads)
output, attn_weights = mha(x)
print("\n2. 가중치 프로젝션 분할 차원:")
print(" - Query (Q) shape:", f"[B, h, T, d_k] = [2, 8, 4, {d_model//n_heads}]")
print("\n3. 어텐션 가중치 확률 텐서 차원 (softmax(QK^T/sqrt(d_k))):", attn_weights.shape)
print(" - 어텐션 맵 shape: [B, h, T, T] = [2, 8, 4, 4]")
print("\n4. 최종 복원된 출력 텐서 차원 (Output):", output.shape)
print(" - [B, T, D] = [2, 4, 768] 문맥 업데이트 완성")
③ 텐서 변환 실행 결과 출력 로그
1. 입력 텐서 차원 (X): torch.Size([2, 4, 768])
2. 가중치 프로젝션 분할 차원:
- Query (Q) shape: [B, h, T, d_k] = [2, 8, 4, 96]
3. 어텐션 가중치 확률 텐서 차원 (softmax(QK^T/sqrt(d_k))): torch.Size([2, 8, 4, 4])
- 어텐션 맵 shape: [B, h, T, T] = [2, 8, 4, 4]
4. 최종 복원된 출력 텐서 차원 (Output): torch.Size([2, 4, 768])
- [B, T, D] = [2, 4, 768] 문맥 업데이트 완성
실행 결과를 살펴보면, [B, T, D] 형태의 고정된 입력 임베딩 텐서가 어텐션 연산 내부에서 독립된 소형 헤드로 분할된 후 마스킹 및 연산을 거쳤음에도, 출력단에서는 입력 차원과 동일한 [B, T, D] 형태로 보존되어 다음 트랜스포머 레이어로 전달될 구조를 유지함을 확인할 수 있다.
요약 및 다음 단계
- 어텐션의 본질: 고정 단어 의미 벡터에 주변 다른 토큰들의 문맥적 단서 비중을 가중합하여, 매 실행 순간마다 동적으로 단어의 표상을 업데이트하는 핵심 구조이다.
- Q·K·V 상호 역학: 쿼리(Q)가 키(K)라는 색인에 내적을 취해 유사도 지도를 만들고, Softmax 정규화 스케일링을 거쳐 확보한 주목도 비중대로 밸류(V)를 가중 취합한다.
- 병렬 다각화와 정보 차단: 단어를 다각도 공간에서 관측하는 Multi-Head Attention과 미래 정답 유출을 차단하는 Masked Causal 어텐션을 정립함으로써 디코더 기반 언어 모델의 핵심 엔진이 완성된다.
다음 [LLM Pipeline 5]에서는 어텐션을 거치며 풍부한 문맥 정보로 변환된 [B, T, D] 실수 밀집 텐서가 신경망의 비선형 표현력을 확장하는 피드포워드 네트워크(FFN; Feed-Forward Network)와 심층 학습의 수렴 안정성을 담당하는 잔차 연결(Residual Connection) 및 LayerNorm을 통과하며 트랜스포머 블록을 완성하는 과정을 다룬다.
틀린 부분이 있거나 인용한 부분에 대해 문제가 있을 시
댓글로 알려주시면 감사하겠습니다.