
transformers 라이브러리의 pipeline("sentiment-analysis")은 코드 3줄이면 감정 분석 결과가 나오는 것으로 유명합니다. 그런데 이 3줄 코드를 한국어 문장에 그대로 쓰면 결과가 이상하게 나오는 경우가 많습니다. 이 글에서는 Hugging Face pipeline 3줄 감정분석이 왜 한국어에서 틀리는지 토크나이저 레벨에서 원인을 확인하고, 실제로 쓸 수 있는 한국어 모델 교체 방법까지 정리합니다.
3줄 감정분석 코드, 한국어를 넣으면 무슨 일이 벌어지나
가장 기본적인 예시부터 보겠습니다. model 인자를 지정하지 않으면 pipeline은 기본 모델인 distilbert-base-uncased-finetuned-sst-2-english를 자동으로 내려받습니다. 이 모델은 이름에서 알 수 있듯 영어 문장 SST-2(Stanford Sentiment Treebank) 데이터셋으로 파인튜닝된 모델입니다.
from transformers import pipeline
classifier = pipeline("sentiment-analysis")
print(classifier("오늘 정말 즐거운 하루였어요"))
print(classifier("최악이었다. 다시는 안 갈 것 같다"))
이 코드를 실행하면 두 문장 모두 POSITIVE 또는 NEGATIVE 라벨과 함께 confidence score가 출력되기는 합니다. 문제는 그 score가 0.5 근처, 즉 모델이 사실상 “찍고 있는” 수준에 머무르는 경우가 많다는 점입니다. 겉으로는 정상 작동하는 것처럼 보이지만, 내부적으로는 모델이 문장을 제대로 이해하지 못한 채 라벨을 뱉어내는 상태입니다. 이 원인을 다음 섹션에서 토크나이저 레벨로 직접 확인해보겠습니다.
원인은 모델이 아니라 토크나이저 어휘집
distilbert-base-uncased-finetuned-sst-2-english가 쓰는 토크나이저는 WordPiece 방식이며, 어휘집(vocab)이 영어 소문자 텍스트를 기준으로 구성되어 있습니다. 한글 음절은 이 어휘집에 아예 등록되어 있지 않기 때문에, 토크나이저가 한국어 문장을 인코딩하는 순간부터 이미 정보 손실이 시작됩니다. 직접 토크나이징 결과를 찍어보면 확인할 수 있습니다.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
tokens = tokenizer.tokenize("오늘 정말 즐거운 하루였어요")
print(tokens)
이 코드를 실행하면 대부분의 토큰이 [UNK](unknown, 미등록 토큰)로 치환되거나, 극히 일부만 의미 없는 서브워드 조각으로 쪼개지는 결과를 확인할 수 있습니다. 모델 입장에서는 “오늘 정말 즐거운 하루였어요”라는 문장이 사실상 [UNK] [UNK] [UNK] [UNK]에 가까운 입력으로 들어오는 셈입니다. 애초에 파인튜닝 데이터인 SST-2 자체가 영어 영화 리뷰 문장으로만 구성돼 있어서, 학습 과정에서 한국어 패턴을 한 번도 본 적이 없다는 점도 근본 원인입니다. 즉 이 문제는 “모델 성능이 낮아서”가 아니라 “애초에 한국어를 처리하도록 만들어진 적이 없어서” 발생하는 구조적인 한계입니다.

해결법 1: 한국어로 파인튜닝된 모델로 교체
가장 직접적인 해결책은 pipeline 생성 시 model 인자에 한국어 데이터로 파인튜닝된 모델을 명시하는 것입니다. Hugging Face Hub에는 NSMC(Naver Sentiment Movie Corpus, 네이버 영화 리뷰 감정 데이터셋)로 학습된 한국어 감정분석 모델들이 공개돼 있습니다. 대표적으로 matthewburke/korean_sentiment는 DistilBERT 계열 아키텍처를 한국어 리뷰 데이터로 파인튜닝한 모델로, 라벨은 LABEL_0(부정), LABEL_1(긍정) 형태로 반환됩니다.
from transformers import pipeline
korean_classifier = pipeline(
"sentiment-analysis",
model="matthewburke/korean_sentiment"
)
print(korean_classifier("오늘 정말 즐거운 하루였어요"))
print(korean_classifier("최악이었다. 다시는 안 갈 것 같다"))
모델을 교체하면 토크나이저도 해당 모델에 맞는 것이 함께 로드되기 때문에, 한글 어휘가 [UNK]로 뭉개지지 않고 의미 단위에 가깝게 분절됩니다. 다만 라벨 이름이 POSITIVE/NEGATIVE가 아니라 LABEL_0/LABEL_1처럼 추상적으로 나오는 모델도 많으므로, 모델 카드(Hub 페이지)에서 각 라벨이 어떤 감정을 의미하는지 반드시 확인 후 매핑 딕셔너리를 만들어 사용하는 것이 안전합니다.
label_map = {"LABEL_0": "부정", "LABEL_1": "긍정"}
result = korean_classifier("오늘 정말 즐거운 하루였어요")[0]
print(label_map[result["label"]], result["score"])
해결법 2: 직접 파인튜닝이 필요한 경우
리뷰 도메인(쇼핑몰 후기, 앱 리뷰 등)이 영화 리뷰와 다르거나, 라벨을 3단계(긍정/중립/부정) 이상으로 세분화하고 싶다면 공개 모델을 그대로 쓰기보다 직접 파인튜닝하는 편이 정확도가 높습니다. 이때 베이스 모델로는 한국어 코퍼스로 사전학습된 beomi/KcELECTRA-base나 monologg/koelectra-base-v3-discriminator 같은 모델을 추천할 수 있습니다. 이들은 애초에 사전학습(pretraining) 단계부터 한국어 텍스트로 학습되어 어휘집 자체가 한글 음절/서브워드를 포함하고 있으므로, 영어 전용 모델을 한국어로 파인튜닝하는 것보다 훨씬 안정적인 출발점이 됩니다.
파인튜닝은 Trainer API를 사용하는 것이 일반적이며, 대략적인 흐름은 다음과 같습니다.
from transformers import AutoModelForSequenceClassification, AutoTokenizer, Trainer, TrainingArguments
model_name = "beomi/KcELECTRA-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)
# train_dataset, eval_dataset은 직접 준비한 라벨링 데이터를 토크나이징한 것
training_args = TrainingArguments(
output_dir="./result",
num_train_epochs=3,
per_device_train_batch_size=16
)
trainer = Trainer(model=model, args=training_args,
train_dataset=train_dataset, eval_dataset=eval_dataset)
trainer.train()

파인튜닝에는 라벨링된 학습 데이터와 GPU 자원이 필요하기 때문에, 우선은 해결법 1의 공개 모델로 베이스라인을 만들고 오분류 사례를 모아 자체 데이터셋을 구축한 뒤 파인튜닝을 진행하는 순서가 효율적입니다.
모델 선택 비교
세 가지 접근을 정리하면 다음과 같습니다.
| 구분 | 기본 pipeline (영어 모델) | matthewburke/korean_sentiment | 직접 파인튜닝 (KcELECTRA 등) |
|---|---|---|---|
| 코드 난이도 | 매우 쉬움 (3줄) | 쉬움 (model 인자만 추가) | 높음 (데이터셋·학습 필요) |
| 한국어 처리 | 사실상 불가 ([UNK] 다발) | 가능 (NSMC 기반) | 가능 (도메인 맞춤) |
| 라벨 커스터마이징 | 불가 | 제한적 (2단계 고정) | 자유로움 |
| 적합한 상황 | 영어 텍스트 전용 | 빠른 프로토타입 | 서비스용 정밀 분류 |
이 표에서 보듯이 한국어 프로젝트에서 기본 pipeline("sentiment-analysis")을 그대로 쓰는 것은 사실상 선택지가 아닙니다. 최소한 model 인자로 한국어 모델을 명시하는 단계는 반드시 거쳐야 합니다.
정리 및 다음 단계
Hugging Face pipeline 3줄 감정분석은 영어 텍스트에서는 빠르고 편리하지만, 한국어에서는 토크나이저 어휘집 자체에 한글이 없어 [UNK] 토큰으로 뭉개지고, 애초에 학습 데이터도 영어 전용이라 정확한 판단이 불가능합니다. 지금 바로 실행해볼 수 있는 다음 단계는 이렇습니다. 첫째, AutoTokenizer.from_pretrained()로 현재 쓰고 있는 모델의 토크나이징 결과를 직접 찍어 [UNK] 비율을 확인합니다. 둘째, pipeline(model="matthewburke/korean_sentiment")처럼 한국어 모델로 교체해 베이스라인을 만듭니다. 셋째, 서비스 도메인에 맞는 정확도가 필요하다면 beomi/KcELECTRA-base 같은 한국어 사전학습 모델을 베이스로 자체 데이터를 모아 파인튜닝을 진행합니다. 자세한 파이프라인 옵션은 Hugging Face 공식 pipeline 문서에서 확인할 수 있습니다.
자주 묻는 질문(FAQ)
Q1. model 인자 없이 pipeline("sentiment-analysis")만 써도 한국어가 아예 안 되나요?
A. 완전히 에러가 나지는 않고 라벨과 점수가 출력되기는 합니다. 다만 토크나이저가 한글 어휘를 대부분 [UNK]로 처리하기 때문에 결과를 신뢰할 수 없고, score가 0.5 근처에 몰리는 경향을 보입니다. 실제 서비스에는 사용하지 않는 것이 안전합니다.
Q2. 라벨이 LABEL_0, LABEL_1로 나오는데 어떤 게 긍정인지 어떻게 확인하나요?
A. Hugging Face Hub에서 해당 모델 페이지(모델 카드)의 설명을 확인해야 합니다. 모델마다 라벨 순서가 다를 수 있으므로, 명확한 예문 몇 개를 직접 넣어 결과를 눈으로 검증한 뒤 매핑 딕셔너리를 만드는 방법이 가장 확실합니다.
Q3. 감정을 긍정/부정 2단계가 아니라 긍정/중립/부정 3단계로 나누고 싶으면 어떻게 하나요?
A. 공개된 2단계 모델을 그대로 쓸 수는 없고, 3단계로 라벨링된 데이터를 직접 준비해 num_labels=3으로 설정한 뒤 파인튜닝해야 합니다. 이 글의 “직접 파인튜닝이 필요한 경우” 섹션의 Trainer 예시 코드가 출발점이 될 수 있습니다.