순서대로 읽지 않고, 한 번에 보고 집중한다
RNN·LSTM은 문장을 앞에서부터 순서대로 읽는다. 문장이 길어지면 앞부분의 정보가 옅어지는 장기 의존성 문제를 완전히 벗어나지 못했다. Transformer는 착안점을 바꿨다 — “모든 단어를 다 보되, 중요한 단어에 더 집중하면 되지 않을까?” 문장을 읽으며 마지막에 정리하는 대신, 읽는 동안 중요한 단어에 형광펜을 긋듯 가중치를 매기는 것이 Attention이고, 이 메커니즘을 잘 쓰기 위해 만든 아키텍처가 Transformer다.
Self-Attention: 문장 안에서 서로를 참고한다
Self-Attention은 문장 내 각 단어가 다른 모든 단어와 얼마나 관련 있는지를 계산한다. “고양이가 창문에서 햇살을 받으며 잔다”라는 문장에서, 잔다는 문장 속 다른 단어와의 관계를 계산하면서 특히 고양이가와 강하게 연결된다 — 누가 자는지를 알아야 “잔다”의 의미가 완성되기 때문이다. RNN이 순서대로 처리하는 것과 달리, Self-Attention은 문장 내 모든 단어를 동시에(병렬로) 처리한다는 점도 중요한 차이다.
Query, Key, Value: 관련성을 숫자로 계산하는 방법
요소 | 역할 | 비유 |
|---|---|---|
Query (질문) | 현재 단어가 다른 단어들과 얼마나 연관 있는지 묻는 값 | “잔다”가 “누가 자는지”를 묻는 질문 |
Key (단서) | 각 단어가 “나는 이런 단어야”라고 스스로 소개하는 값 | “고양이가”의 Key는 “나는 주어야, 잠을 잘 수 있는 대상이야” |
Value (정보) | 그 단어가 실제로 담고 있는 의미 자체 | “고양이가”가 선택됐을 때 “잔다”에게 넘겨줄 “주어=고양이”라는 내용 |
계산 흐름은 세 단계다. ① Query와 모든 단어의 Key를 비교해 관련성 점수(유사도)를 구하고, ② 그 점수를 Softmax로 합이 1인 가중치로 바꾼 뒤, ③ 이 가중치로 각 단어의 Value를 가중합해 최종 표현을 만든다. 이 과정 전체를 Scaled Dot-Product Attention이라 부른다 — 벡터 차원이 커지면 점수(내적, Dot-Product)도 함께 커져 Softmax가 한쪽으로 쏠리기 쉬운데, 이를 완화하려고 벡터 차원의 제곱근으로 나눠(Scaled) 점수를 조정한다.
코드로 Attention 가중치 계산해보기
실제 학습된 벡터는 아니지만, 메커니즘을 체감하기 위해 “고양이가/창문에서/햇살을/받으며/잔다” 5개 토큰에 임의의 Key·Value 벡터를 부여하고, “잔다”의 Query가 “고양이가”의 Key와 가깝게 설계된 상황을 계산해본다.
import numpy as np
np.random.seed(3)
tokens = ["고양이가", "창문에서", "햇살을", "받으며", "잔다"]
d = 4 # 벡터 차원
K = np.random.randn(5, d) # 각 단어의 Key 벡터
V = np.random.randn(5, d) # 각 단어의 Value 벡터
# '잔다'의 Query를 '고양이가'의 Key와 관련 있게 설계 (실제로는 학습으로 정해짐)
q_sleep = K[0] * 0.9 + K[4] * 0.5 + np.random.randn(d) * 0.15
scores = (q_sleep @ K.T) / np.sqrt(d) # Query-Key 유사도, Scaled
weights = np.exp(scores - scores.max())
weights = weights / weights.sum() # Softmax
for token, w in zip(tokens, weights):
print(f"{token}: {w:.3f}")
print("가중치 합:", round(weights.sum(), 3))
고양이가: 0.743
창문에서: 0.055
햇살을: 0.007
받으며: 0.061
잔다: 0.134
가중치 합: 1.0
“잔다”가 만드는 새 표현은 “고양이가”의 Value를 74.3% 반영하고, 나머지 단어는 조금씩만 반영한다. 이렇게 만들어진 “잔다”의 새 표현에는 “고양이가 잔다”라는 문맥이 녹아든다 — 이것이 Self-Attention이 문맥을 이해하는 방식이다.
Multi-Head Attention: 여러 관점에서 동시에 본다
문장 안의 중요한 관계가 하나뿐인 것은 아니다. “고양이가 창문에서 햇살을 받으며 잔다”에서 “잔다”는 “고양이가”(누가)와도, “받으며”(어떻게)와도 관계가 있을 수 있다. Multi-Head Attention은 서로 다른 Query·Key·Value 조합(Head)을 여러 개 두어 각 Head가 다른 종류의 관계에 집중하게 하고, 그 결과를 모두 이어붙여(Concat) 더 풍부한 문맥 표현을 만든다.
문장을 생성하는 Decoder에서는 여기에 Masked Multi-Head Attention이 더해진다 — 다음 단어를 만들 때 아직 만들어지지 않은 미래 단어를 미리 참고하면 안 되므로, 가림막(Mask)으로 미래 위치에는 가중치가 가지 않도록 막는다.
Transformer 구조 한눈에 보기
구성 | 역할 |
|---|---|
Encoder | 입력 문장을 읽고 Multi-Head Self-Attention과 Feed-Forward로 문맥을 압축한 정보를 만든다 |
Decoder | Masked Self-Attention으로 지금까지 생성한 부분만 보고, Encoder의 정보를 참고(Cross-Attention)해 다음 단어를 생성한다 |
Positional Encoding | 모든 단어를 동시에 처리하다 보니 순서 정보가 사라지는 것을 보완하기 위해, 각 단어에 위치 정보를 더해준다 |
RNN처럼 순서대로 처리하지 않고 모든 단어를 병렬로 처리하기 때문에, 학습 속도와 긴 문맥 처리 모두에서 이득을 얻는다. 다만 모든 단어 쌍의 관계를 계산해야 해서, 문장 길이가 n일 때 연산량이 O(n²)로 늘어난다는 비용도 함께 따라온다.
정리
Transformer는 순차 처리 대신 Self-Attention으로 문장 내 모든 단어 쌍의 관계를 한 번에 계산해, RNN·LSTM의 장기 의존성 문제와 순차 처리로 인한 속도 한계를 함께 풀었다. Query·Key·Value로 관련성을 계산하고, Multi-Head로 여러 관점을 동시에 보며, Positional Encoding으로 순서 정보를 보완한다. 이 구조가 다음 글에서 다룰 BERT와 GPT 계열의 공통 기반이 된다.
참고 자료
Attention Is All You Need — Vaswani et al. (2017) — Transformer와 Self-Attention을 처음 제안한 원 논문 (2026-08-07 확인)
댓글 0
댓글을 불러오는 중…