트랜스포머 구조 이해하기: 어텐션이 문맥을 읽는 방법
트랜스포머가 토큰을 벡터로 바꾸고 어텐션으로 서로를 참조해 문맥을 만드는 과정을 단계별로 설명합니다. 셀프 어텐션, 멀티헤드, 층을 쌓는 이유까지 다룹니다.

이 글의 목차
오늘날 쓰이는 거의 모든 대규모 언어 모델은 트랜스포머(Transformer) 라는 구조를 바탕으로 합니다. 2017년에 제안된 이 구조는 이전 방식과 달리 문장을 순서대로 하나씩 처리하지 않고, 모든 위치를 동시에 보면서 서로를 참조하게 만들었습니다. 이 변화가 오늘의 모델들을 가능하게 했습니다.
트랜스포머를 제대로 설명하려면 수식이 필요하지만, 핵심 아이디어는 수식 없이도 전달할 수 있습니다. 이 글에서는 "단어들이 서로를 쳐다보면서 자기 의미를 갱신한다" 는 하나의 비유를 축으로, 입력이 들어와 출력이 나오기까지의 흐름을 따라가겠습니다.
LLM의 동작 원리에서 모델이 다음 토큰의 확률 분포를 계산한다고 설명했습니다. 이 글은 그 계산이 내부에서 어떻게 이루어지는지를 다룹니다.
순서대로 읽는 방식의 한계
트랜스포머 이전에는 순환 신경망(RNN) 계열이 주로 쓰였습니다. 문장을 앞에서부터 한 단어씩 읽으면서 "지금까지의 요약"을 갱신해 나가는 방식입니다. 사람이 글을 읽는 방식과 비슷해 직관적이지만 두 가지 문제가 있었습니다.
첫째, 병렬 처리가 불가능합니다. 두 번째 단어를 처리하려면 첫 번째 처리가 끝나야 합니다. 문장이 길수록 시간이 선형으로 늘고, GPU의 병렬 연산 능력을 활용할 수 없습니다.
둘째, 멀리 떨어진 관계가 약해집니다. 요약을 계속 덮어쓰다 보면 앞쪽 정보가 흐려집니다. "어제 서점에서 산 책이 정말 재미있었다"에서 "재미있었다"의 주어가 "책"임을 연결하려면 그 사이의 모든 단계를 거쳐야 합니다.
트랜스포머는 이 두 문제를 "순서대로 읽기를 포기하고, 모든 위치가 모든 위치를 직접 참조하게 하기" 로 해결했습니다.
1단계: 토큰을 벡터로 바꿉니다
입력 텍스트는 먼저 토큰으로 쪼개집니다(토큰과 토크나이저 참고). 각 토큰에는 고유 번호가 붙어 있고, 이 번호로 임베딩 테이블에서 벡터를 찾아옵니다. 임베딩은 토큰 하나를 수백에서 수천 개의 숫자로 표현한 것입니다. 개념 자체는 임베딩과 벡터 검색에서 더 자세히 다룹니다.
이 시점의 벡터는 문맥과 무관한 사전적 의미에 가깝습니다. "밤"이라는 토큰은 시간을 뜻하는지 먹는 것을 뜻하는지 아직 구분되지 않은 상태입니다.
여기에 위치 정보를 더합니다. 트랜스포머는 모든 토큰을 동시에 보기 때문에, 위치 정보를 따로 넣어 주지 않으면 "개가 사람을 물었다"와 "사람이 개를 물었다"를 구분할 수 없습니다. 위치를 벡터에 인코딩해 더하거나, 어텐션을 계산할 때 상대적 거리를 반영하는 방식이 쓰입니다.
2단계: 셀프 어텐션 — 서로를 쳐다봅니다
트랜스포머의 핵심입니다. 각 토큰이 문장 안의 다른 모든 토큰을 살펴보고, 자기에게 중요한 것들로부터 정보를 끌어와 자기 벡터를 갱신합니다.
이를 위해 각 토큰의 벡터로부터 세 가지를 만듭니다.
| 이름 | 역할 | 비유 |
|---|---|---|
| 쿼리(Query) | 내가 찾는 것 | "나를 꾸며 주는 말이 어디 있지?" |
| 키(Key) | 내가 제공하는 것의 표지 | "나는 명사입니다" |
| 밸류(Value) | 실제로 전달할 내용 | 그 토큰이 가진 정보 |
계산은 이렇게 진행됩니다. 어떤 토큰의 쿼리를 다른 모든 토큰의 키와 비교해 유사도 점수를 냅니다. 점수를 확률처럼 정규화해 가중치를 만들고, 그 가중치로 각 토큰의 밸류를 섞어 더합니다. 결과가 그 토큰의 새 벡터입니다.
이 연산 덕분에 "재미있었다"의 벡터에는 "책"의 정보가 섞여 들어갑니다. 문맥과 무관했던 초기 벡터가 문맥을 반영한 벡터로 바뀌는 것입니다. 앞서 예로 든 "밤"도 주변에 "달"이 있는지 "껍질"이 있는지에 따라 다른 방향으로 갱신됩니다.
중요한 점은 이 참조가 거리와 무관하다는 것입니다. 100 토큰 떨어진 단어든 바로 옆 단어든 똑같이 한 번에 참조합니다. RNN의 두 번째 문제가 여기서 해결됩니다. 그리고 모든 토큰의 계산이 서로 독립적이므로 행렬 곱 한 번으로 병렬 처리할 수 있습니다. 첫 번째 문제도 해결됩니다.
참고
글을 생성하는 모델에서는 각 토큰이 자기보다 뒤에 있는 토큰을 보지 못하도록 가립니다(마스킹). 다음 단어를 예측해야 하는데 정답을 미리 보면 학습이 되지 않기 때문입니다.
3단계: 멀티헤드 — 여러 관점으로 동시에
문장 안의 관계는 한 종류가 아닙니다. 주어-서술어 관계, 수식 관계, 대명사가 가리키는 대상, 문체와 어조 같은 것들이 동시에 존재합니다. 어텐션을 한 번만 계산하면 이 모든 관계를 하나의 가중치에 욱여넣어야 합니다.
그래서 어텐션을 여러 벌 동시에 계산합니다. 각각을 헤드(head) 라고 부르며, 헤드마다 다른 쿼리·키·밸류 변환을 학습합니다. 어떤 헤드는 문법적 관계에, 다른 헤드는 의미적 유사성에 반응하는 식으로 역할이 자연스럽게 나뉩니다. 각 헤드의 결과를 이어 붙이고 한 번 더 변환하면 멀티헤드 어텐션의 출력이 됩니다.
헤드가 정확히 무엇을 담당하는지는 사람이 지정하지 않습니다. 학습 과정에서 저절로 분화하며, 사후 분석으로 일부 헤드의 역할을 해석할 수 있는 경우가 있을 뿐입니다.
4단계: 피드포워드 — 각자 정리합니다
어텐션이 "다른 토큰에서 정보를 가져오는" 단계라면, 그다음의 피드포워드 신경망(FFN) 은 각 토큰이 가져온 정보를 혼자서 소화하는 단계입니다. 토큰마다 독립적으로, 같은 가중치를 써서 벡터를 한 번 늘렸다가 다시 줄입니다.
단순해 보이지만 모델 파라미터의 상당 부분이 여기에 있습니다. 학습된 지식의 많은 부분이 이 층에 저장된다고 보는 연구들이 있습니다. 어텐션이 "관계"를 담당하고 FFN이 "지식"을 담당한다고 거칠게 나눠 볼 수 있습니다.
5단계: 같은 블록을 여러 번 쌓습니다
어텐션과 피드포워드를 묶은 것이 트랜스포머 블록 하나입니다. 실제 모델은 이 블록을 수십 개 이상 쌓습니다. 한 블록의 출력이 다음 블록의 입력이 되는 구조입니다.
층을 쌓으면 표현이 점점 추상화됩니다. 앞쪽 층은 품사나 구문 같은 표면적 패턴에, 뒤쪽 층은 의미나 논리 관계 같은 추상적 정보에 반응하는 경향이 관찰됩니다. 사람이 그렇게 설계한 것이 아니라 학습 결과로 나타나는 현상입니다.
깊게 쌓으려면 두 가지 장치가 필요합니다. 잔차 연결(residual connection) 은 각 블록의 입력을 출력에 그대로 더해, 깊어져도 원래 정보가 소실되지 않게 합니다. 정규화(normalization) 는 값의 크기를 일정 범위로 유지해 학습을 안정시킵니다. 둘 다 없으면 깊은 신경망은 제대로 학습되지 않습니다.
마지막 블록을 지난 벡터는 어휘 사전 크기의 점수로 변환되고, 정규화를 거쳐 다음 토큰의 확률 분포가 됩니다. 이 분포에서 토큰 하나를 고르는 방법이 temperature와 top-p에서 다루는 샘플링입니다.
인코더와 디코더
원 논문의 트랜스포머는 번역을 위해 설계되어 두 부분으로 나뉘어 있었습니다. 인코더는 입력 문장 전체를 읽어 표현을 만들고, 디코더는 그 표현을 참조하며 출력을 한 토큰씩 생성합니다.
이후 용도에 따라 갈라졌습니다. 문장을 이해하고 분류하거나 임베딩을 만드는 작업에는 인코더만 쓰는 구조가, 글을 생성하는 작업에는 디코더만 쓰는 구조가 적합했습니다. 오늘날의 대화형 LLM은 대부분 디코더 계열입니다.
흔한 오해
"어텐션은 모델이 무엇에 주목했는지 보여 준다." 어텐션 가중치는 정보가 섞이는 비율일 뿐, 모델이 그 판단을 내린 근거와 일치한다고 보기는 어렵습니다. 가중치 시각화를 설명(explanation)으로 받아들이는 데는 신중해야 합니다.
"층이 많을수록 똑똑하다." 깊이는 성능에 영향을 주는 여러 요인 중 하나입니다. 층 수, 벡터 크기, 학습 데이터의 양과 질, 학습 방법이 함께 작용하며, 깊이만 늘린다고 좋아지지 않습니다.
"트랜스포머는 문장을 순서대로 읽는다." 읽지 않습니다. 모든 위치를 동시에 처리하고, 순서는 위치 정보로만 알려 줍니다. 생성할 때 한 토큰씩 나오는 것은 자기회귀 방식 때문이지 내부 처리가 순차적이어서가 아닙니다.
정리
- 트랜스포머는 순서대로 읽는 대신 모든 토큰이 모든 토큰을 직접 참조하게 만들어 병렬 처리와 장거리 의존성을 동시에 해결했습니다.
- 셀프 어텐션은 쿼리·키·밸류로 가중치를 만들고, 그 가중치로 정보를 섞어 문맥이 반영된 벡터를 만듭니다.
- 멀티헤드는 여러 종류의 관계를 동시에 포착하기 위한 장치입니다.
- 피드포워드 층은 토큰별로 정보를 정리하며, 학습된 지식의 상당 부분을 담습니다.
- 잔차 연결과 정규화 덕분에 블록을 깊게 쌓을 수 있고, 층이 깊어질수록 표현이 추상화됩니다.
- 오늘날의 대화형 LLM은 대부분 디코더 계열 구조를 사용합니다.
참고 자료
- Attention Is All You Need — 트랜스포머를 제안한 원 논문
- Hugging Face LLM Course — Transformer Architectures — 인코더·디코더 계열 정리
- Google Machine Learning Crash Course — Transformers — 어텐션 개념 강의