-
Seq2Seq의 한계를 넘어서: Attention 메커니즘AI 2026. 2. 23. 20:54
기존의 Seq2Seq 모델은 인코더가 입력 문장을 하나의 고정된 벡터(Context Vector)로 압축합니다. 그 결과물을 디코더에게 '밀어 넣어주는' 구조입니다. 여기서 두 가지 치명적인 문제가 발생하죠.
- 정보 손실 (Information Loss): 문장이 길어지면 그 많은 정보를 하나의 벡터에 다 담지 못하고 앞부분 내용을 잊어버립니다. (Long-term Dependency 문제)
- 기울기 소실 (Vanishing Gradient): 역전파 과정에서 문장 앞쪽까지 신호가 제대로 전달되지 않습니다.

해결책:
"디코더가 단어를 뱉을 때마다, 인코더의 전체 문장을 다시 한 번 훑어보자! 단, 지금 필요한 부분에만 집중(Attention)해서!", 즉 입력으로 들어온 단어들과 compatibility(궁합)을 본다.
인코더는 압축 파일을 만들어서 넘겨주지 않습니다. 대신 '데이터베이스' 역할을 합니다. 컨텍스트 벡터는 디코더가 단어를 만들 때마다 실시간(On-the-fly)으로 직접 계산합니다.
- 인코더의 역할: 각 단어를 처리할 때 생기는 모든 중간 결과물(Hidden States, $h_1, h_2, ..., h_T$)을 메모리에 유지합니다. (넘겨주지 않고 펼쳐 놓음)
- 디코더의 역할:
- 단어를 하나 뱉을 때마다, 현재 자기 상태($s_t$)와 인코더의 모든 데이터($h_1 \sim h_T$)를 대조합니다. 매 타임스텝마다..
- "지금 어떤 데이터가 제일 중요하지?"를 계산해서 어텐션 가중치를 구합니다.
- 이 가중치를 인코더 데이터들에 곱해서 합친 '맞춤형 컨텍스트 벡터'를 그 자리에서 직접 생산(Production)합니다.
즉, 어텐션은 입력 시퀀스의 각 위치에 대해 가중치를 부여하여 중요한 정보에 집중하는 메커니즘입니다.
어텐션의 3요소: Query, Key, Value
어텐션을 이해하는 가장 좋은 방법은 '유연한 검색 시스템'으로 보는 것입니다. 파이썬의 dict와 비교해 볼까요?
- Query (Q): 질문하는 주체. "지금 'crispy'를 번역하려는데 원문의 어디를 참고해야 할까?" (디코더의 현재 시점 Hidden State)
- Key (K): 검색 대상의 인덱스. "나는 '바삭한'이라는 의미의 정보를 가지고 있어." (인코더의 모든 시점 Hidden State들)
- Value (V): 실제 데이터 알맹이. "그 정보의 실체는 바로 이 벡터값이야." (인코더의 모든 시점 Hidden State들)

"바삭한 치킨 너겟"을 번역할 때
나는 바삭한 치킨너겟이에요 -> I am a crispy chicken nugget.직접 작성한 노트를 바탕으로, 번역 모델 내부에서 $Q, K, V$가 어떻게 정의되는지 구체적으로 매칭해 보겠습니다.
요소 정의 (노트 내용) 실제 예시 (번역 상황) Query (Q) 내가 지금 상황에서 알고 싶은 것 "I am a..." 다음에 출력해야 할 시점이 되었을 때 내뱉는 질문. (아직 'crispy'라고 단어를 정한 상태는 아닙니다.) 디코더의 현재 은닉상태 Key (K) 쿼리와 비교해서 답을 유용하게 찾을 수 있는 정보 비교 대상이 되는 한국어 원문의 모든 단어 ("나는", "바삭한", "치킨", "너겟이에요"). 인코더셀의 은닉상태 Value (V) 키의 결과값 :궁합이 잘 맞는다고 판단된 한국어 단어의 실제 정보(은닉 상태 값) Dot-Product Attention
아래 그림은 어텐션 메카니즘을 설명합니다.
디코더의 세번째 LSTM 셀은 출력 단어를 예측하기 위해서 인코더의 모든 입력 단어들의 정보를 다시 한번 참고하고자 합니다.
"누구에게 더 집중할까?" (빨간 직사각형의 의미)
현재 디코더(오른쪽 초록색 부분)는 "I am a student"를 프랑스어인 "je suis étudiant"으로 번역하고 있습니다. 마지막 단어인 'étudiant'을 예측해야 하는 상황이죠.
- 이때 디코더는 입력된 영어 단어들(I, am, a, student)을 모두 다시 살펴봅니다.
- 빨간 직사각형은 그 '궁합(유사도)' 점수를 시각화한 것입니다. 'étudiant(학생)'이라는 단어를 뱉기 위해서는 입력값 중 'student'가 가장 중요하겠죠?
- 그래서 그림을 보시면 'student' 위에 있는 빨간 직사각형이 가장 크게 그려져 있습니다. 이것이 바로 해당 단어에 주는 강조(Weight)입니다. 바로 Attend한다라는 의미입니다.

정보를 하나로 모으기" (초록색 삼각형)
소프트맥스를 통해 나온 이 가중치(0~1 사이의 확률값)들을 각 단어의 정보와 곱해서 합치면, 초록색 삼각형으로 표현된 컨텍스트 벡터(Context Vector)가 만들어집니다.
- 이 삼각형 안에는 "지금 단어를 예측할 때 'student'의 정보를 80%, 'am'의 정보를 5%... 이런 식으로 참고해!"라는 핵심 요약 정보가 담겨 있습니다.
- 단순히 마지막 단어의 정보만 쓰는 게 아니라, 입력 문장 전체에서 필요한 부분만 쏙쏙 골라 담은 주머니라고 생각하시면 됩니다.
- 텍스트 벡터(초록색 삼각형)는 고정된 값이 아니라, 디코더가 단어를 하나씩 출력(Sequence)할 때마다 매번 새롭게 계산됩니다.
- 이 매번 새로 계산하는 과정이 번거롭고 느려서, "한 번에 모든 단어의 궁합을 계산해버리자!"라고 나온 것이 바로 트랜스포머(Transformer)의 핵심 아이디어입니다.
1) Attention Score
디코더가 현재 시점 $t$에서 정답을 맞히기 위해, "인코더가 넘겨준 단어들($h_1, h_2, h_3, h_4$) 중에서 지금 나한테 가장 중요한 게 뭐야?"를 수치로 나타낸 값입니다.

- 인코더의 은닉 상태 ($h_1, h_2, h_3, h_4$): 입력 단어 'I', 'am', 'a', 'student' 각각에 대한 정보를 담은 벡터입니다.
- 디코더의 현재 은닉 상태 ($s_t$): 지금까지 출력한 단어들('je', 'suis')을 바탕으로 "이제 다음 단어는 뭘까?"를 고민하고 있는 상태의 벡터입니다.

이 스코어 값을 구하기 위해 를 전치(transpose)하고 각 은닉 상태와 내적(dot product)을 수행합니다. 즉, 모든 어텐션 스코어 값은 스칼라입니다
- 디코더의 은닉 상태 $s_t$를 전치($s_t^T$)하여 인코더의 각 은닉 상태($h_1, h_2, h_3, h_4$)와 내적(Dot Product)을 수행합니다.
- 수식으로는 $score(s_t, h_i) = s_t^T \cdot h_i$ 로 표현됩니다.
- 내적의 의미: 앞서 말씀하신 것처럼 '궁합'을 재는 것입니다. 두 벡터가 비슷할수록 내적 값(스코어)이 크게 나옵니다.
$$e_t = [s_t^T h_1, ..., s_t^T h_N]$$
- 시점 $t$에서의 어텐션 스코어 모음(벡터)
2) Attention Distribution
앞서 구한 어텐션 스코어 $e_t$는 단순히 숫자들의 나열일 뿐입니다. 소프트맥스를 적용해서 모든 값을 합하면 1이 되는 확률 분포를 얻어낸 값이 Attention Deistribution입니다.
- 계산 식: $\alpha_t = \text{softmax}(e_t)$
- Attention Weight: 소프트맥스를 거치면 모든 성분의 값이 0과 1 사이가 되며, 전체 합은 항상 1이 됩니다. 각각의 값을 어텐션 가중치라고 한합니다.
- 의미: "현재 단어를 예측할 때, 입력 문장의 각 단어가 몇 %나 중요한가?"를 나타내는 지표가 됩니다
디코더 t시점에서의 어텐서 분포를 $\alpha_t$라고 할때 정의는 아래와 같습니다.$$\alpha_t = \text{softmax}(e_t)$$3) Attention Value
어텐션의 최종 결과값을 얻기 위해서 각 인코더의 은닉 상태와 어텐션 가중치값들을 곱하고, 최종적으로 모두 더합니다.
이 가중합(Weighted Sum)을 통해 계산된 결과값이 바로 어텐션 값(Attention Value, $a_t$)입니다.
$$a_t = \sum_{i=1}^{N} \alpha_{ti} h_i$$
- 어텐션 가중치($\alpha_{ti}$)를 다시 인코더의 은닉 상태($h_i$)에 곱하는 이유는 "관련이 깊은 단어의 정보는 크게 가져오고, 관련 없는 정보는 작게 가져와서 합치자!"라는 가중합(Weighted Sum)을 하기 위함입니다.
$a_t$ 은 종종 인코더의 문맥을 포함하고 있다고하여, 컨텍스트 벡터(context vector)라고 합니다. seq2seq의 마지막 은닉상태도 context Vector라고 합니다.
4) Concatenate(결합)
우리는 앞선 과정에서 두 가지 중요한 벡터를 얻었습니다.
- $s_t$ (디코더 은닉 상태): "나는 지금 'je suis' 다음에 올 단어를 찾아야 해"라는 디코더의 현재 상태 정보입니다.
- $a_t$ (어텐션 값): "인코더를 훑어보니 지금 'student'라는 단어의 정보가 가장 중요해"라고 요약된 인코더의 정보입니다.
이 두 벡터를 단순히 더하는 것이 아니라, 옆으로 나란히 붙여서(Concatenate) 더 긴 하나의 벡터 $v_t$를 만듭니다.

- 정보의 공존: $v_t$ 안에는 '내가 지금까지 한 말($s_t$)'과 '내가 참고해야 할 원문의 정보($a_t$)'가 동시에 공존하게 됩니다.
- 다각도 분석: 이렇게 합쳐진 벡터를 출력층(Dense Layer)에 통과시키면, 모델은 두 정보를 함께 고려하여 "아, 'je suis' 다음에는 인코더의 'student' 의미를 담은 'étudiant'이 정답이겠구나!"라고 훨씬 정확한 판단을 내릴 수 있습니다.
4) 출력층 연산
앞서 결합(Concatenate)하여 만든 벡터 $v_t$는 디코더의 상태 $s_t$와 인코더의 요약본 $a_t$가 단순히 옆으로 붙어있는 상태입니다.
- 정보의 융합: 두 정보를 단순히 붙여놓기만 하면 정보 사이의 유기적인 관계가 부족할 수 있습니다.
- 신경망 연산 ($W_c$): 가중치 행렬 $W_c$와 곱하고 $\tanh$ 함수를 통과시키는 과정은, 이질적인 두 정보($s_t, a_t$)를 하나의 고차원적인 의미를 가진 새로운 벡터 $\tilde{s}_t$로 녹여내는 작업입니다.
$\tilde{s}_t$는 아래와 같은 수식으로 구해집니다.$$\tilde{s}_t = \tanh(W_c [a_t; s_t] + b)$$- s_t: 이는 단순한 숫자 나열이 아니라, 신경망이 학습하기 가장 좋은 형태의 '고차원적 특징(Feature)'으로 가공되었다는 뜻입니다.
- $[a_t; s_t]$: 인코더 정보와 디코더 정보를 결합한 벡터입니다.
- $W_c$: 모델이 학습하면서 스스로 최적화하는 '필터'입니다. 어떤 정보에 더 무게를 둘지 결정합니다.
- 차원 맞추기 및 통합: 결합(Concatenate)된 벡터 $[a_t; s_t]$는 원래 벡터보다 길이가 두 배로 깁니다. $W_c$는 이 긴 벡터를 곱해줌으로써 다시 적절한 크기로 줄이면서 두 정보 사이의 관계를 추출합니다.
- 중요도 필터링: $W_c$ 내의 수많은 숫자값들은 학습을 통해 "인코더 정보($a_t$)에서 무엇을 더 강조하고, 디코더 상태($s_t$)에서 무엇을 덜어낼지"를 결정하게 됩니다.
- 최종 판단의 근거: 결과물인 $\tilde{s}_t$는 $W_c$를 거치면서 단순한 데이터의 나열이 아니라, "인코더의 맥락이 완벽히 녹아든 디코더의 최종 생각"으로 변하게 됩니다.
- 고차원적 특징(Feature)
- $\tanh$: 비선형 함수를 추가하여 모델이 더 복잡한 문맥적 의미를 파악할 수 있도록 돕습니다.
6) 최종 출력 ($\hat{y}_t$)
이렇게 정제된 $\tilde{s}_t$를 드디어 출력층으로 보냅니다.
- 계산: $\hat{y}_t = \text{Softmax}(W_y \tilde{s}_t + b_y)$
- 결과: 모델은 모든 단어 중 가장 확률이 높은 단어(예: 'étudiant')를 최종 선택하게 됩니다
- 확률분포 $$\hat{y}_t = [0.01, 0.02, 0.95, 0.02]$$
$W_y$를 곱하는이유는
- 차원 맞추기 (Dimension Mapping)
- $\tilde{s}_t$ (입력): 어텐션과 결합하여 정제된 벡터입니다. 보통 128, 256, 512 같은 특정 차원의 숫자 뭉치입니다.
- 단어장 (Vocabulary): 우리가 번역해야 할 단어는 수만 개(예: 30,000단어)입니다.
- $W_y$의 역할: 512차원의 벡터를 30,000차원의 벡터로 확장해주는 통로 역할을 합니다. $W_y$를 곱해야만 각 단어(사과, 학교, 학생...)마다 하나씩 점수를 매길 수 있는 형태가 됩니다.
- 2단어별 점수 매기기 (Logits 생성)
$W_y$의 각 행(Row)은 특정 단어에 대한 '필터'와 같습니다.- 연산: $W_y \tilde{s}_t$를 하면, 현재의 문맥 벡터($\tilde{s}_t$)가 'student'라는 단어의 필터와 얼마나 일치하는지, 'apple'이라는 단어의 필터와 얼마나 일치하는지를 계산해서 각각 점수를 냅니다.
- 결과: "이번 차례에 'student'는 15.5점, 'apple'은 -2.1점!" 같은 로짓(Logits) 값이 나옵니다.
- 확률로 변환 (Softmax와의 협업)
$W_y$가 매긴 점수들을 Softmax에 넣으면 비로소 확률이 됩니다.- 최종 결과: "student일 확률 98%, apple일 확률 0.01%..."
- 여기서 가장 높은 확률을 가진 단어를 선택하는 것이 우리가 보는 최종 번역 결과입니다.
Seq2Seq 어텐션의 $Q, K, V$ 매핑
Query (Q): "지금 내(디코더)가 필요한 게 뭐야?"
- 실체: 디코더의 현재 시점 은닉 상태 ($s_t$)
- 역할: 인코더의 모든 단어에게 질문을 던집니다. "나 지금 다음 단어 뱉어야 하는데, 너희들 중에 나랑 관련 있는 놈 누구야?"
Key (K): "나(인코더)는 이런 정보를 담고 있어 (찾기용 주소)"
- 실체: 인코더의 모든 시점 은닉 상태들 ($h_1, h_2, ..., h_n$)
- 역할: Query가 들어왔을 때 자기랑 얼마나 비슷한지 비교 대상이 되어줍니다.
Value (V): "나랑 비슷하면 내 실제 데이터($h_i$)를 가져가!"
- 실체: 인코더의 모든 시점 은닉 상태들 ($h_1, h_2, ..., h_n$)
- 특이점: Seq2Seq에서는 Key와 Value가 동일한 $h_i$입니다. (찾기 위한 기준점도 $h_i$이고, 가져갈 실제 값도 $h_i$이기 때문입니다.)
동작 메커니즘 (Step-by-Step)
이 3가지가 어떻게 맞물리는지 엔지니어링 흐름으로 보시죠.
- 점수 계산 ($Q \cdot K$):
디코더의 현재 상태($Q$)와 인코더의 모든 상태($K$)를 하나씩 내적(Dot Product) 합니다.
결과: 각 단어별 '유사도 점수'가 나옵니다. - 가중치 확정 ($\text{softmax}$):위에서 나온 점수들에 소프트맥스를 씌웁니다.결과: [0.05, 0.9, 0.05] 처럼 합이 1인 가중치($\alpha$)가 나옵니다.
- 최종 데이터 추출 ($\alpha \cdot V$):
이 가중치($\alpha$)를 실제 인코더의 값($V$)에 다시 곱해서 모두 더합니다. - 결과: 2번째 단어($h_2$)의 정보가 90% 반영된 문맥 벡터(Context Vector)가 탄생합니다.
💡 마치며: 왜 seq2seq + Attention을 넘어 Transformer인가?
우리는 흔히 Attention이 모든 문제를 해결했다고 생각하지만, 사실 seq2seq + Attention 구조에도 치명적인 약점이 존재합니다. 이 한계를 이해해야 왜 지금의 AI가 Transformer로 대통합되었는지 알 수 있습니다.
seq2seq + Attention의 한계: "여전히 RNN이다"
Attention이 인코더의 정보를 직접 들여다보며 '정보 희석'을 줄여주었지만, 그 밑바탕인 인코더 자체가 RNN(LSTM/GRU)이라는 점이 발목을 잡습니다.
- 히든 스테이트의 오염: 인코더는 여전히 단어를 순차적으로 읽으며 이전 기억과 현재 단어를 섞습니다. 어텐션이 특정 시점($h_2$)을 보러 가도, 이미 그 $h_2$ 안에는 앞선 단어들의 정보가 '짬뽕'되어 있어 아주 선명한 특징을 찾기 어렵습니다.
- Context Vector의 병목: 아무리 어텐션을 써도 결국 디코더로 넘겨주는 초기값은 하나의 고정된 Context Vector입니다. 이 하나의 벡터에 문장 전체의 의미를 욱여넣어야 하는 병목 현상은 여전합니다.
- 병렬 연산의 불가능: RNN은 $t$ 시점의 계산을 위해 반드시 $t-1$ 시점이 끝나야 합니다. 즉, GPU를 아무리 좋은 걸 써도 한 번에 한 단어씩 순차적으로 처리해야 하므로 학습 속도가 매우 느립니다.
Transformer의 혁신: "섞지 말고 그대로 둬라"
Transformer는 "정보가 섞여서 무의미해지는 문제"를 아예 구조적으로 뿌리 뽑았습니다.
- RNN의 퇴출: 옆으로 정보를 밀어내며 섞는 RNN을 아예 버렸습니다. 모든 단어를 한꺼번에 입력받아 각자의 위치에 독립적으로 고정합니다.
- 선명한 특징 보존: 단어들이 서로 섞이지 않으니, 어텐션이 특정 단어를 참조할 때 그 단어 고유의 정보를 가장 선명한(Raw) 상태로 읽어올 수 있습니다.
- Self-Attention: "이전 기억"을 물려받는 대신, 문장 안의 모든 단어가 서로를 직접 쳐다보게 하여 관계를 파악합니다. 이것이 훨씬 빠르고 정확하게 맥락을 짚어냅니다.
seq2seq + Attention의 한계: "피할 수 없는 순차 연산"
Attention이 '정보 희석'은 어느 정도 줄여주었지만, 인코더와 디코더가 모두 순차적(Sequential) 방식으로 동작한다는 근본적인 한계는 그대로입니다.
- 인코더의 순차적 학습: 100단어로 된 문장을 넣으면, 인코더는 1번 단어부터 100번 단어까지 100번의 스텝을 순서대로 밟아야 합니다. 앞 단어 처리가 끝나야 다음 단어를 볼 수 있어 GPU의 병렬 연산 능력을 제대로 쓰지 못합니다.
- 디코더의 훈련 시 정체: 학습할 때 정답을 미리 다 알고 있음에도 불구하고, 디코더는 여전히 한 단어씩 순차적으로 뱉어보며 학습해야 합니다. (연산 속도의 치명적 저하)
- 히든 스테이트의 오염: 정보를 순차적으로 밀어내며 섞다 보니, 어텐션이 특정 시점($h$)을 보러 가도 이미 앞선 정보들과 '짬뽕'되어 있어 단어 고유의 선명한 특징을 찾기 어렵습니다.
'AI' 카테고리의 다른 글
[NLP 아키텍처 연대기] 통계에서 트랜스포머까지: 언어 이해의 여정 (1) 2026.03.02 Transformer (0) 2026.02.24 LSTM(Long Short-Term Memory) (1) 2026.02.22 순환 신경망(RNN)의 개념 (0) 2026.02.22 통계적 언어 모델(SLM)과 N-gram (0) 2026.02.22