[68일차] 자연어 처리 기초와 토큰화

송정근·2026년 9월 14일

자연어 처리(Natural Language Processing, NLP)는 컴퓨터가 사람이 사용하는 언어를 분석하고 이해하며 생성할 수 있게 만드는 인공지능 분야다. 컴퓨터는 문장을 그대로 이해하지 못하므로, 텍스트를 토큰(Token)으로 나누고 숫자 ID로 바꾸는 전처리 과정을 거친다.

이번에는 자연어 처리의 기본 단위인 Corpus, Document, Token, Vocabulary를 살펴보고, 직접 만든 사전과 Hugging Face의 klue/bert-base 토크나이저를 비교한다.


1. 자연어와 자연어 처리

자연어는 사람이 일상에서 말하고 쓰는 언어다. 문법과 어휘뿐 아니라 문맥, 표현 방식, 뉘앙스처럼 규칙만으로 처리하기 어려운 요소를 포함한다.

자연어 처리는 텍스트 또는 음성 데이터를 모델이 다룰 수 있는 형태로 바꾸고, 그 안에서 의미 있는 결과를 찾거나 새로운 문장을 만드는 기술이다.

활용 분야설명
텍스트 분류문서를 뉴스, 스포츠, 경제처럼 범주로 나눈다.
감정 분석리뷰나 댓글의 긍정·부정 성향을 분석한다.
문서 요약긴 문서에서 핵심 내용을 짧게 정리한다.
기계 번역한 언어의 문장을 다른 언어로 변환한다.
질의응답질문에 맞는 답변을 찾거나 생성한다.
정보 검색사용자의 검색어와 관련된 문서를 찾는다.
챗봇·문장 생성사용자 입력에 맞춰 자연스러운 문장을 생성한다.
RAG·LLM Agent외부 문서를 검색하거나 도구를 사용해 답변을 보완한다.

최근에는 텍스트뿐 아니라 이미지, 음성, 영상과 결합하는 멀티모달 AI로도 확장되고 있다.


2. Corpus와 Document

Corpus

Corpus(말뭉치)는 자연어 처리 모델을 분석하거나 학습하기 위해 모은 전체 텍스트 데이터 집합이다.

예를 들어 영화 리뷰 10만 개를 모았다면, 리뷰 10만 개 전체가 하나의 Corpus가 된다.

Document

Document는 Corpus를 구성하는 개별 텍스트 하나다. 반드시 긴 글일 필요는 없다.

Corpus: 영화 리뷰 10만 개
 ├── Document 1: "재미있고 배우들의 연기가 좋다."
 ├── Document 2: "전개가 느려서 아쉬웠다."
 └── Document 3: "다시 보고 싶은 영화다."

뉴스 기사 하나, 리뷰 하나, 댓글 하나, 짧은 문장 하나도 모두 Document가 될 수 있다.


3. Tokenization: 텍스트를 모델의 입력 단위로 나누기

Tokenization(토큰화)은 텍스트를 모델이 처리할 수 있는 작은 단위인 Token으로 나누는 과정이다.

"자연어 처리를 공부합니다."
            ↓ Tokenization
["자연", "##어", "처리", "##를", "공부", "##합니다", "."]
            ↓ Token ID 변환
[3941, 2051, 4211, 2138, 4244, 11800, 18]
            ↓ Tensor 변환
tensor([3941, 2051, 4211, 2138, 4244, 11800, 18])

토큰은 항상 단어 하나와 같지 않다. 단어 전체일 수도 있고, 단어의 일부, 구두점, 공백과 관련된 단위일 수도 있다.

단순 공백 기준 토큰화

가장 간단한 방법은 공백을 기준으로 문장을 나누는 것이다.

text = "나는 자연어를 공부한다"
tokens = text.split()

print(tokens)
['나는', '자연어를', '공부한다']

이 방식은 이해하기 쉽지만, 한국어의 조사나 어미를 분리하지 못하고 구두점 처리도 세밀하지 않다. 예를 들어 자연어를은 하나의 Token으로 남고, 처음 보는 단어는 사전에 없을 가능성이 커진다.


4. Vocabulary와 Token ID

Vocabulary는 토크나이저가 사용할 수 있는 Token의 집합이다. 모델은 문자열 자체가 아니라 Vocabulary에 등록된 정수 ID를 입력으로 받는다.

vocab = {
    "<PAD>": 0,
    "<UNK>": 1,
    "나는": 2,
    "자연어를": 3,
    "공부한다": 4,
}

text = "나는 자연어를 공부한다"
tokens = text.split()

token_ids = [vocab.get(token, vocab["<UNK>"]) for token in tokens]
input_ids = torch.tensor(token_ids, dtype=torch.long)

print("원문:", text)
print("Token:", tokens)
print("Token ID:", token_ids)
print("PyTorch Tensor:", input_ids)
print("dtype:", input_ids.dtype)

실행 결과는 다음과 같다.

원문: 나는 자연어를 공부한다
Token: ['나는', '자연어를', '공부한다']
Token ID: [2, 3, 4]
PyTorch Tensor: tensor([2, 3, 4])
dtype: torch.int64

2, 3, 4라는 숫자 자체에는 언어적 의미가 없다. 이 숫자는 Vocabulary 안에서 특정 Token을 찾기 위한 식별자다. 이후 모델은 이 ID를 Embedding 층에 전달해 학습 가능한 벡터로 바꾼다.

Special Token

Token의미용도
<PAD>Padding Token문장 길이를 맞출 때 빈자리를 채운다.
<UNK>Unknown TokenVocabulary에 없는 Token을 나타낸다.
[CLS]Classification TokenBERT 계열에서 문장 전체를 대표하는 특별한 시작 Token이다.
[SEP]Separator Token문장 또는 문장 쌍의 경계를 구분한다.

모델은 보통 한 번에 여러 문장을 Batch로 처리한다. 문장 길이가 다르면 Tensor 모양을 맞추기 어려우므로 짧은 문장 뒤에 <PAD>를 추가한다.

문장 A: [2, 3, 4]
문장 B: [2, 4]

Padding 후
문장 A: [2, 3, 4]
문장 B: [2, 4, 0]  # 0은 <PAD>

5. OOV 문제와 <UNK>

OOV(Out-Of-Vocabulary)는 입력된 Token이 Vocabulary에 존재하지 않는 상황이다.

vocab = {
    "<PAD>": 0,
    "<UNK>": 1,
    "나는": 2,
    "파이토치를": 3,
    "공부한다": 4,
}

tokens = ["나는", "트랜스포머를", "공부한다"]
token_ids = [vocab.get(token, vocab["<UNK>"]) for token in tokens]

print(token_ids)
[2, 1, 4]

트랜스포머를은 Vocabulary에 없으므로 <UNK>의 ID인 1로 바뀐다. 단어 단위 사전만 사용하면 새로운 단어, 오타, 활용형을 자주 <UNK>로 처리하게 되어 정보가 사라질 수 있다.

노트북 원본은 tokens를 중괄호 {}로 만든 set으로 작성했다. set은 순서를 보장하지 않으므로, 문장의 Token 순서를 유지해야 할 때는 위 예제처럼 대괄호 []를 사용하는 list가 알맞다.


6. Subword Tokenization

현대 NLP 모델은 OOV 문제를 줄이기 위해 Subword Tokenization을 많이 사용한다. 단어 전체를 하나로만 처리하지 않고, 자주 등장하는 부분 단위로 나눈다.

"자연어 처리를 공부합니다."
        ↓
['자연', '##어', '처리', '##를', '공부', '##합니다', '.']

##는 BERT 계열 WordPiece 토크나이저에서 앞 Token에 이어 붙는 부분이라는 표시다. 예를 들어 자연과 ##어를 합치면 자연어가 되고, 공부와 ##합니다를 합치면 공부합니다가 된다.

처음 보는 단어라도 이미 알고 있는 부분 Token의 조합으로 표현할 가능성이 높다. 이 때문에 단어 전체만 사용하는 방식보다 <UNK> 발생을 줄일 수 있다.


7. Hugging Face AutoTokenizer 사용하기

Hugging Face는 자연어 처리뿐 아니라 이미지, 음성, 멀티모달 모델과 관련 도구를 제공하는 생태계다. AutoTokenizer를 사용하면 모델 저장소에 맞는 Tokenizer 설정과 Vocabulary를 불러올 수 있다.

from transformers import AutoTokenizer

# Hugging Face Hub의 klue/bert-base 토크나이저 불러오기
tokenizer = AutoTokenizer.from_pretrained("klue/bert-base")

text = "자연어 처리를 공부합니다."
tokens = tokenizer.tokenize(text)
token_ids = tokenizer.convert_tokens_to_ids(tokens)

print("Token:", tokens)
print("Token ID:", token_ids)

실행 결과는 다음과 같다.

Token: ['자연', '##어', '처리', '##를', '공부', '##합니다', '.']
Token ID: [3941, 2051, 4211, 2138, 4244, 11800, 18]

klue/bert-base의 Vocabulary 크기와 주요 Special Token ID는 다음과 같이 확인했다.

print("Vocabulary 크기:", tokenizer.vocab_size)
print("[PAD] ID:", tokenizer.pad_token_id)
print("[UNK] ID:", tokenizer.unk_token_id)
print("[CLS] ID:", tokenizer.cls_token_id)
print("[SEP] ID:", tokenizer.sep_token_id)
Vocabulary 크기: 32000
[PAD] ID: 0
[UNK] ID: 1
[CLS] ID: 2
[SEP] ID: 3

노트북에서는 [PAD] ID를 출력할 때 tokenizer.pad_token_type_id를 사용했다. 이 값은 이 모델에서 우연히 0으로 출력되지만, PAD Token의 Vocabulary ID를 확인하려면 의미에 맞는 tokenizer.pad_token_id를 사용해야 한다.

tokenize()와 모델 입력 만들기의 차이

tokenizer.tokenize()는 사람이 확인하기 좋은 Token 문자열 목록을 반환한다. 실제 모델 입력을 만들 때는 보통 토큰화와 ID 변환, Special Token 추가, Padding, Attention Mask 생성을 한 번에 처리한다.

encoded = tokenizer(
    "자연어 처리를 공부합니다.",
    return_tensors="pt",
)

print(encoded["input_ids"])
print(encoded["attention_mask"])

input_ids는 모델에 전달할 Token ID이고, attention_mask는 실제 Token과 Padding 위치를 구분하는 값이다. 이처럼 모델용 입력을 만들 때는 tokenizer(...) 호출이 더 편리하다.


8. PyTorch Tensor와 실행 장치

Token ID는 정수 인덱스이므로 torch.long, 즉 일반적으로 torch.int64 자료형 Tensor로 만든다.

input_ids = torch.tensor(token_ids, dtype=torch.long)

노트북에서는 실행 장치를 다음 순서로 선택했고, 현재 환경에서는 mps가 선택됐다.

if torch.cuda.is_available():
    DEVICE = torch.device("cuda")
elif torch.backends.mps.is_available():
    DEVICE = torch.device("mps")
elif torch.xpu.is_available():
    DEVICE = torch.device("xpu")
else:
    DEVICE = torch.device("cpu")

print(DEVICE)
mps

mps는 Apple Silicon Mac의 GPU 가속을 위한 PyTorch 장치다. 학습이나 추론 시 모델과 입력 Tensor를 같은 장치에 올려야 한다.


9. 전체 흐름 정리

Corpus
  ↓
Document 선택
  ↓
Tokenization
  ↓
Vocabulary에서 Token ID 조회
  ↓
Padding·Attention Mask 생성
  ↓
PyTorch Tensor로 변환
  ↓
NLP 모델 입력
  • Corpus는 학습·분석에 사용하는 전체 텍스트 집합이고, Document는 그 안의 개별 텍스트다.
  • Token은 모델이 다루는 입력 단위이며, 단어 하나와 항상 같지 않다.
  • Vocabulary는 Token과 정수 ID의 대응표다.
  • <UNK>는 사전에 없는 Token을 처리하지만, Subword Tokenization은 OOV 문제를 줄이는 데 도움이 된다.
  • AutoTokenizer는 모델에 맞는 Vocabulary와 Tokenization 규칙을 불러온다.
  • 세밀한 NLP 모델 입력에는 Token ID뿐 아니라 Special Token, Padding, Attention Mask도 함께 필요하다.
profile
기록하며 성장하는 개발자

0개의 댓글