Field Log · Entry

BERT와 GPT 차이: Encoder·Decoder를 RAG 부품으로 이해하기 (8/10)

BERT encoder의 양방향 attention과 GPT decoder의 causal attention을 RAG 검색 재정렬 생성 역할로 비교

오늘의 결론

  • BERT는 양쪽 문맥을 함께 보는 encoder이고, GPT 계열 LLM은 미래를 가린 decoder입니다.
  • BERT의 대표 pretraining은 masked language modeling, GPT의 핵심은 next-token prediction입니다.
  • “BERT embedding”을 그대로 평균내면 항상 좋은 retrieval vector가 되는 것은 아닙니다.
  • RAG에서는 encoder가 후보를 찾고·재정렬하며, decoder LLM이 근거를 바탕으로 답을 생성하는 분업이 흔합니다.

BERT와 GPT는 모두 Transformer를 사용하지만 정보 흐름과 학습 목표가 다릅니다. 이를 단순히 “BERT는 옛날 모델, GPT는 최신 모델”로 이해하면 RAG architecture를 잘못 고르게 됩니다.

검색에서는 문서를 미리 encoding하고 빠르게 비교해야 하며, reranking에서는 질문과 문서의 세밀한 상호작용이 필요합니다. 답변 단계에서는 새로운 token을 순차 생성해야 합니다. 서로 다른 목적에는 서로 다른 Transformer 사용법이 맞습니다.

BERT와 GPT의 attention mask 및 RAG 역할 비교

그림 1. BERT형 encoder는 전체 입력을 양방향으로 표현하고, GPT형 decoder는 왼쪽 context만 보며 다음 token을 생성한다.


같은 Transformer, 다른 Mask

문장 [E17, 원인은, 냉각수, 저하]가 있다고 합시다.

BERT형 encoder의 self-attention은 기본적으로 모든 유효 위치를 서로 볼 수 있습니다.

                E17  원인은  냉각수  저하
E17              ○      ○       ○     ○
원인은           ○      ○       ○     ○
냉각수           ○      ○       ○     ○
저하             ○      ○       ○     ○

“원인은” 위치도 오른쪽의 “냉각수 저하”를 참고해 문맥화됩니다.

GPT형 decoder는 causal mask를 사용합니다.

                E17  원인은  냉각수  저하
E17              ○      ×       ×     ×
원인은           ○      ○       ×     ×
냉각수           ○      ○       ○     ×
저하             ○      ○       ○     ○

각 위치는 왼쪽과 자기 자신만 봅니다. 그래야 inference에서 아직 생성되지 않은 미래 token 없이도 같은 조건으로 다음 token을 예측할 수 있습니다.

BERT: 빈칸을 양쪽 문맥으로 맞힌다

BERT의 핵심 pretraining objective는 Masked Language Modeling(MLM)입니다.

입력: E17 알람은 [MASK] 유량 저하로 발생한다.
정답: 냉각수

mask 위치를 맞힐 때 왼쪽 “E17 알람은”과 오른쪽 “유량 저하로 발생한다”를 모두 사용할 수 있습니다. 이 양방향성은 classification, named-entity recognition, 문장 쌍 판단처럼 전체 입력 이해가 필요한 task에 잘 맞습니다.

원 BERT 논문은 Next Sentence Prediction(NSP)도 함께 사용했습니다. 이후 RoBERTa 연구는 NSP를 제거하고 데이터·batch·학습 시간을 조정해 성능을 개선할 수 있음을 보였습니다. 따라서 “모든 BERT 계열은 반드시 NSP를 쓴다”고 외우면 안 됩니다.

GPT: 왼쪽 문맥으로 다음 token을 맞힌다

decoder-only GPT 계열은 causal language modeling을 사용합니다.

입력: E17 알람은 냉각수 유량
정답: 저하

이 목표를 모든 위치에 적용하고, 생성 시 선택한 token을 다시 context 뒤에 붙입니다. 별도 decoder head를 붙이지 않아도 pretraining과 같은 형태로 자유로운 text를 생성할 수 있습니다.

규모가 커진 autoregressive language model은 prompt 안의 instruction과 example을 context로 받아 다양한 task를 수행하는 능력을 보였습니다. 하지만 generation 능력과 외부 지식의 최신성·정확성은 별개입니다.

입출력 관점에서 비교하기

항목BERT형 EncoderGPT형 Decoder
기본 attention양방향causal, 왼쪽→오른쪽
대표 목표masked token 복원next-token prediction
기본 출력각 입력 token의 contextual vector각 위치의 next-token logits
강한 용도분류, 추출, 표현, 문장 쌍 점수생성, 대화, 코드, tool call
새 문장 생성기본 목적 아님기본 목적
RAG 역할embedding, rerankinganswer generation, agent control

이는 절대적인 규칙이 아니라 대표적인 설계입니다. encoder-decoder 모델, prefix language model, unified architecture 등 변형도 있습니다.

BERT의 CLS가 곧 좋은 문장 Embedding은 아니다

BERT 입력 앞에는 보통 CLS special token을 둡니다. classification fine-tuning에서는 CLS 위치의 final hidden state를 classifier에 넣을 수 있습니다.

하지만 pretraining된 BERT의 CLS vector를 그대로 cosine search에 사용한다고 semantic retrieval에 최적인 것은 아닙니다. BERT는 원래 문장 embedding의 cosine geometry를 retrieval에 맞게 학습한 모델이 아니기 때문입니다.

Sentence-BERT는 siamese/triplet 구조로 문장을 독립 encoding하고 cosine으로 효율적으로 비교할 수 있게 학습했습니다. 실무에서 “BERT 기반 embedding”이라고 말할 때는 backbone뿐 아니라 pooling과 contrastive training objective를 확인해야 합니다.

RAG 검색의 Bi-Encoder

bi-encoder 또는 dual-encoder는 query와 document를 따로 encoding합니다.

q = QueryEncoder("E17 원인은?")
d = DocumentEncoder("E17은 냉각수 유량 저하...")

score = similarity(q, d)

문서 vector는 offline에 미리 계산해 저장할 수 있습니다. 요청 시 query vector 하나를 만들고 ANN index에서 가까운 문서를 찾으므로 대규모 후보 생성에 적합합니다.

offline:  모든 document → embeddings → vector index
online:   query → embedding → ANN top-k

DPR은 question과 passage를 두 BERT encoder로 표현하는 dense retrieval을 open-domain QA에 적용했습니다. query encoder와 passage encoder는 구조가 같아도 parameter를 공유할지, 별도로 둘지는 모델 설계에 따라 다릅니다.

RAG 재정렬의 Cross-Encoder

cross-encoder는 query와 document를 하나의 sequence로 붙여 함께 읽습니다.

[CLS] E17 원인은? [SEP] E17은 냉각수 유량 저하... [SEP]
→ Transformer
→ relevance score

모든 layer에서 query token과 document token이 attention으로 상호작용할 수 있어 세밀한 relevance 판단에 강합니다. 대신 문서마다 모델 forward가 필요합니다.

방식문서 사전 계산query-document 상호작용대규모 전체 검색
bi-encoder가능마지막 vector score에서만적합
cross-encoder불가능모든 Transformer layer너무 비쌈

그래서 흔한 pipeline은 bi-encoder로 top-100 후보를 찾고 cross-encoder로 top-10을 다시 정렬합니다.

Late Interaction은 그 사이 어디쯤인가

ColBERT는 query와 document를 따로 encoding해 문서 token vector를 미리 저장하면서, 마지막에 query token과 document token의 MaxSim을 계산합니다.

bi-encoder:       vector 하나 ↔ vector 하나
ColBERT:          token vectors ↔ token vectors, late interaction
cross-encoder:    query+document를 처음부터 함께 encoding

속도·저장 공간·상호작용 품질 사이의 중간 지점을 만듭니다. 이미 블로그의 ColBERT Late Interaction 해설에서 수치 예제와 함께 더 자세히 볼 수 있습니다.

Generator는 왜 Decoder인가

검색 결과를 바탕으로 길이가 정해지지 않은 답을 새로 만들어야 하므로 autoregressive decoder가 자연스럽습니다.

context:
  질문: E17 알람 점검 순서는?
  근거 1: ...
  근거 2: ...
  지시: 근거에 없는 내용은 추측하지 말 것

decoder:
  첫 token → 다음 token → ... → EOS

decoder는 검색 문서를 “학습”하지 않습니다. 한 요청의 왼쪽 context로 읽고 다음 답 token 분포를 조건화합니다.

BERT와 LLM 중 하나만 고르는 문제가 아니다

RAG 하나에 여러 model이 들어갈 수 있습니다.

단계입력출력적합한 모델 예
candidate retrievalquery 또는 document 각각고정 길이 vectorretrieval encoder
rerankingquery-document 쌍relevance scalarcross-encoder
generationquestion + evidenceanswer tokensdecoder LLM
claim verificationclaim-evidence 쌍entailment/scoreencoder 또는 LLM

비용이 중요한 경우 reranker를 생략할 수 있고, corpus가 작으면 cross-encoder를 더 넓게 적용할 수도 있습니다. 핵심은 모델 이름이 아니라 각 단계의 입력·출력과 latency budget입니다.

10분 실습: 내 RAG 모델 역할표 만들기

현재 시스템의 각 model을 아래처럼 적어 보세요.

retriever:
  model: "..."
  architecture: "encoder / decoder / unknown"
  input: "query or passage"
  output: "dimension ... vector"
  pooling: "..."
  normalization: "..."

reranker:
  model: "none / ..."
  input: "query + passage"
  output: "relevance score"

generator:
  model: "..."
  input: "instruction + question + evidence"
  output: "answer tokens"

“unknown” 칸이 있으면 model card와 code에서 확인합니다. 특히 retriever의 query/document prefix, pooling, normalize 설정은 검색 결과를 직접 바꿉니다.

자주 하는 오해

“BERT는 생성하지 못하고 GPT는 이해하지 못한다.”

두 모델의 대표 목적과 mask가 다르다는 뜻이지 인간 능력처럼 이분법으로 나눌 수는 없습니다. encoder도 token prediction을 하고 decoder도 context 표현을 학습합니다.

“더 큰 generator를 쓰면 retrieval도 좋아진다.”

retriever가 별도 encoder라면 generator 교체가 후보 검색 recall을 직접 개선하지 않습니다. 단계별 model과 metric을 따로 봐야 합니다.

“Cross-encoder가 정확하니 vector DB 없이 모든 문서를 비교하면 된다.”

문서 수가 커지면 query마다 모든 pair를 forward해야 해 확장하기 어렵습니다. 후보 생성과 재정렬을 분리하는 이유입니다.

스스로 확인하기

  1. BERT와 GPT의 attention mask는 어떻게 다른가?
  2. MLM과 causal LM의 label은 각각 어떻게 만들어지는가?
  3. bi-encoder는 왜 document embedding을 미리 계산할 수 있는가?
  4. cross-encoder를 전체 corpus 검색에 바로 쓰기 어려운 이유는 무엇인가?

다음 글에서는 decoder LLM이 실제 요청을 처리할 때 일어나는 prefill·decode·sampling·KV cache를 살펴봅니다.

참고자료