어텐션(Attention) 메커니즘을 공부할 때 가장 처음 마주치는 난관이자, 가장 헷갈리는 개념이 바로 Q(Query), K(Key), V(Value)입니다.
이 글에서는 복잡한 수식 대신, 우리가 매일 사용하는 구글 검색과 도서관 시스템에 비유하여 이 3가지 개념을 직관적으로 정리해보겠습니다.
어텐션의 작동 원리는 검색 엔진과 놀랍도록 닮아 있습니다. 여러분이 구글에서 자료를 찾는 상황을 상상해 보세요.
예: "맛있는 사과 고르는 법"
예: "사과 재배법", "아이폰 수리", "백설공주 줄거리", "맛있는 과일 고르기"
예: 클릭했을 때 나오는 글 본문
다음과 같은 문장이 있다고 가정해 봅시다.
"나는 [강]가에서 낚시를 했다."
여기서 "강"이라는 단어가 문맥을 파악하기 위해 어텐션을 수행하는 과정입니다. (한국어에서 '강'은 River일 수도, 성씨 Kang일 수도 있으니까요.)
"강"이 질문을 던집니다.
"내 주변 단어들아, 나랑 관련된 애 누구야? 나 지금 River인지 Surname인지 헷갈려."
주변 단어들이 자신의 명찰(Key)을 보여줍니다.
Q("강")는 K("낚시를")와 계산했을 때 가장 높은 매칭 점수를 기록합니다.
점수가 가장 높은 "낚시를"의 Value(V)를 중점적으로 가져옵니다.
그냥 단어 벡터 하나로 다 계산하면 안 될까요? 안 됩니다. 역할이 다르기 때문입니다.
소개팅을 한다고 가정해 봅시다.
내가 상대를 찾는 기준(Q)과, 남에게 보여주는 내 특성(K)은 다를 수 있습니다. 학습 효율을 위해 이를 분리합니다.
어텐션 점수를 계산할 때는 매칭에 특화된 벡터(K)를 쓰고, 정보를 섞을 때는 의미 전달에 특화된 벡터(V)를 쓰는 것이 효율적입니다.

| 개념 | 역할 | 비유 (검색 엔진) | 비유 (문장 속 단어) |
|---|---|---|---|
| Query (Q) | 질문하는 역할 | 검색창에 친 검색어 | 현재 단어: "나랑 친한 애 누구야?" |
| Key (K) | 대조되는 역할 | 검색 결과의 제목 | 다른 단어들: "난 이런 단어야." (매칭용) |
| Value (V) | 제공되는 정보 | 클릭하면 나오는 내용 | 다른 단어들: "매칭됐으니 내 정보를 줄게." (내용물) |
이제 Transformer 논문(Attention Is All You Need)의 수식이 조금 더 친근하게 느껴지실 겁니다.
class SelfAttention_v2(nn.Module):
def __init__(self, d_in, d_out, qkv_bias=False):
super().__init__()
self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
def forward(self, x):
keys = self.W_key(x)
queries = self.W_query(x)
values = self.W_value(x)
attn_scores = queries @ keys.T
attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
context_vec = attn_weights @ values
return context_vec
torch.manual_seed(789)
sa_v2 = SelfAttention_v2(d_in, d_out)
print(sa_v2(inputs))