트랜스포머(Transformer)란 무엇인가
GPT, BERT 등 현대 LLM의 근간인 트랜스포머 아키텍처를 셀프 어텐션부터 인코더-디코더 구조까지 직관적으로 이해합니다.
지난 글에서 신경망이 어떻게 학습하는지 살펴봤습니다. 입력을 받아 가중합을 계산하고, 활성화 함수를 통과시키고, 역전파로 가중치를 조정하는 과정이었죠.
그런데 실제 언어를 처리할 때는 한 가지 문제가 있습니다. “나는 어제 친구와 함께 영화를 봤고 정말 재미있었다”라는 문장에서 “재미있었다”는 “영화”와 연관된 것인지 신경망이 어떻게 알 수 있을까요?
이 문제를 해결하기 위해 등장한 것이 트랜스포머(Transformer) 입니다. 2017년 구글이 발표한 논문 “Attention Is All You Need” 로 세상에 나온 이후, GPT, BERT, Claude 등 오늘날의 모든 대형 언어 모델이 이 구조를 기반으로 만들어졌습니다.
이전 방식의 한계
트랜스포머 이전에는 RNN(순환 신경망) 과 LSTM 이 언어 처리의 주류였습니다.
RNN은 문장을 왼쪽에서 오른쪽으로 한 단어씩 순차 처리합니다.
"나는" → "어제" → "친구와" → "함께" → "영화를" → "봤고" → ...
이 방식에는 두 가지 큰 문제가 있습니다.
첫째, 느립니다. 단어 하나를 처리해야 다음 단어를 처리할 수 있어 병렬화가 불가능합니다. GPU가 수천 개의 연산을 동시에 처리할 수 있어도 순서대로 줄을 서야 합니다.
둘째, 멀리 있는 단어를 잊어버립니다. “나는 … 재미있었다” 처럼 연관 단어들이 멀리 떨어져 있으면 앞에서 처리한 정보가 뒤로 전달되는 과정에서 흐릿해집니다. 이를 기울기 소실(Vanishing Gradient) 이라고 합니다.
LSTM이 이 문제를 일부 완화했지만, 근본적인 해결책은 아니었습니다.
트랜스포머의 핵심 아이디어
트랜스포머는 발상을 바꿉니다.
“순서대로 처리하는 대신, 모든 단어를 한 번에 보고
서로가 서로를 얼마나 중요하게 참조하는지 계산하면 어떨까?”
이것이 셀프 어텐션(Self-Attention) 입니다. 모든 단어가 서로를 동시에 참조하므로 병렬화가 가능하고, 거리에 상관없이 중요한 단어끼리 직접 연결됩니다.
“재미있었다”는 “영화”를 직접 참조할 수 있습니다. 거리가 아무리 멀어도요.
셀프 어텐션: Q, K, V로 이해하기
셀프 어텐션을 이해하는 가장 좋은 비유는 도서관 검색 시스템입니다.
- Query (Q, 질의) — “내가 찾고 싶은 것은 무엇인가?”
- Key (K, 색인) — “이 책은 어떤 내용을 담고 있나?”
- Value (V, 내용) — “실제로 꺼내 읽을 책의 본문”
단어 하나하나는 입력에서 세 가지 벡터를 생성합니다: Q, K, V.
그런 다음 이렇게 계산합니다.
1. 나의 Query × 모든 단어의 Key = 관련성 점수
2. 점수에 softmax 적용 → 어텐션 가중치 (합산 = 1.0)
3. 가중치 × 각 단어의 Value → 가중합 = 최종 출력
수식으로는 이렇습니다.
Attention(Q, K, V) = softmax( Q · Kᵀ / √dₖ ) · V
√dₖ 로 나누는 이유는 벡터 차원이 커질수록 내적 값이 폭발적으로 커지는 것을 막기 위해서입니다.
아래는 “나는 고양이를 정말 좋아해”라는 문장에서 각 토큰이 서로를 얼마나 참조하는지 시각화한 것입니다.
“좋아해”라는 단어가 “고양이를”에 40%의 어텐션을 집중하는 것을 볼 수 있습니다. 무엇을 좋아하는지 파악하려면 목적어를 봐야 하니까요. 이것이 트랜스포머가 언어의 의미적 관계를 포착하는 방식입니다.
멀티헤드 어텐션
어텐션을 한 번만 수행하면 한 가지 관점밖에 못 봅니다. 멀티헤드 어텐션(Multi-Head Attention) 은 이 계산을 여러 번 병렬로 수행합니다.
헤드 1: 문법적 관계 파악 (동사-주어)
헤드 2: 의미적 관계 파악 (사물-속성)
헤드 3: 지시어 해소 (그것 → 실제 대상)
헤드 4: ...
각 헤드는 서로 다른 Q, K, V 행렬을 학습합니다. 헤드 수는 보통 8, 12, 16 등으로 설정하며, 최종 출력은 모든 헤드의 결과를 이어붙여(concatenate) 선형 변환한 값입니다.
GPT-3는 96개의 헤드를 사용합니다.
위치 인코딩: 순서를 알려주는 방법
셀프 어텐션은 모든 단어를 동시에 보기 때문에 순서 정보를 잃어버립니다. “나는 고양이를 좋아해”와 “고양이는 나를 좋아해”를 같은 단어의 집합으로 인식할 수 있는 것이죠.
이를 해결하기 위해 각 단어의 임베딩 벡터에 위치 인코딩(Positional Encoding) 을 더합니다.
원래 트랜스포머 논문에서는 사인(sin)과 코사인(cos) 함수를 사용했습니다.
# 개념적 표현
embedding("고양이를") + positional_encoding(위치=2)
위치 인코딩 덕분에 같은 단어라도 문장에서의 위치가 다르면 다른 벡터로 인식됩니다. 현대 모델들은 이 방식을 개선한 RoPE(Rotary Position Embedding) 나 ALiBi 같은 더 정교한 방법을 사용합니다.
인코더-디코더 구조
원래 트랜스포머는 번역 과제를 위해 만들어졌습니다. “한국어 문장 → 영어 문장”처럼 입력과 출력이 다른 경우입니다. 이를 위해 두 가지 블록을 사용합니다.
인코더 (Encoder)
- 입력 문장 전체를 읽고 압축된 맥락 벡터를 생성합니다
- 셀프 어텐션 + FFN (Feed-Forward Network)
- 과거/미래 모든 단어를 자유롭게 참조
디코더 (Decoder)
- 인코더의 맥락 벡터를 받아 출력을 한 단어씩 생성합니다
- 마스크드 셀프 어텐션 + 크로스 어텐션 + FFN
- 미래 단어를 미리 보지 못하도록 마스킹 처리
아래 다이어그램은 전체 구조를 보여줍니다.
인코더와 디코더 사이의 점선이 크로스 어텐션입니다. 디코더가 출력을 생성할 때 인코더의 맥락 정보를 참조하는 경로입니다.
각 블록 안의 “Add & Norm”은 잔차 연결(Residual Connection) 과 레이어 정규화입니다. 깊은 네트워크에서 기울기가 사라지는 문제를 막는 역할을 합니다.
GPT vs BERT: 목적에 따른 구조 선택
트랜스포머의 두 블록을 어떻게 사용하느냐에 따라 모델의 특성이 달라집니다.
| 모델 계열 | 구조 | 학습 방식 | 강점 |
|---|---|---|---|
| BERT | 인코더만 | 마스크된 단어 예측 | 텍스트 이해, 분류 |
| GPT | 디코더만 | 다음 단어 예측 | 텍스트 생성 |
| T5, BART | 인코더 + 디코더 | 텍스트→텍스트 변환 | 번역, 요약 |
| Claude, GPT-4 | 디코더만 (개선) | 다음 토큰 예측 + RLHF | 대화형 생성 |
GPT 계열이 “다음 단어 예측”만으로 강력한 언어 이해 능력을 갖추는 것이 흥미롭습니다. 방대한 데이터로 이 단순한 목표를 최대한 잘 수행하다 보면 언어의 깊은 패턴을 학습하게 됩니다.
왜 트랜스포머가 이렇게 강력한가
트랜스포머가 언어 처리를 지배하게 된 이유를 정리하면 이렇습니다.
| 특성 | RNN/LSTM | 트랜스포머 |
|---|---|---|
| 처리 방식 | 순차 (느림) | 병렬 (빠름) |
| 장거리 의존성 | 약함 | 강함 |
| 확장성 | 한계 있음 | 파라미터 수 무한 확장 |
| GPU 활용 | 낮음 | 매우 높음 |
특히 확장성이 결정적이었습니다. 파라미터를 늘릴수록, 데이터를 늘릴수록 성능이 계속 좋아진다는 사실이 밝혀지면서 GPT-3(175B), GPT-4, Claude 같은 초대형 모델이 등장할 수 있었습니다.
정리
- 트랜스포머 = 순차 처리 대신 병렬 어텐션으로 언어를 이해하는 구조
- 셀프 어텐션 = Q·Kᵀ 내적으로 토큰 간 관련성 계산, V 가중합으로 출력 생성
- 멀티헤드 어텐션 = 여러 관점의 어텐션을 병렬 수행해 다양한 관계 포착
- 위치 인코딩 = 순서 정보를 임베딩에 더해 위치 감각을 부여
- 인코더 = 입력 전체를 읽어 맥락 벡터 생성
- 디코더 = 맥락 벡터와 이전 출력을 보며 다음 토큰 생성
오늘날의 LLM은 대부분 디코더만 사용하며, 이 구조의 단순하지만 강력한 아이디어 위에 놀라운 성능을 쌓아 올리고 있습니다.
다음 글: 프롬프트 엔지니어링 — LLM에게 잘 말을 거는 방법
읽어주셔서 감사합니다. 😊