개체명 인식
Named Entity Recognition (NER)
텍스트에서 인명(PER), 기관명(ORG), 지명(LOC) 등 특정 의미를 가진 개체를 자동으로 찾아 분류하는 NLP 기술. 정보 추출, 검색 엔진, 챗봇, 문서 분석의 핵심 요소입니다.
Named Entity Recognition (NER)
텍스트에서 인명(PER), 기관명(ORG), 지명(LOC) 등 특정 의미를 가진 개체를 자동으로 찾아 분류하는 NLP 기술. 정보 추출, 검색 엔진, 챗봇, 문서 분석의 핵심 요소입니다.
개체명 인식(Named Entity Recognition, NER)은 텍스트에서 인명(PER), 기관명(ORG), 지명(LOC), 날짜/시간(DATE), 금액(MONEY), 수량(QUANTITY) 등 특정 의미를 가진 개체를 자동으로 찾아 분류하는 자연어 처리 기술입니다. 정보 추출(Information Extraction)의 핵심 요소이며, 검색 엔진, 챗봇, 뉴스 분석, 법률/의료 문서 처리에서 광범위하게 활용됩니다.
NER은 1990년대 MUC(Message Understanding Conference) 평가에서 공식적으로 정의되었습니다. 초기에는 규칙 기반과 사전(Dictionary) 매칭이 주류였으나, 2000년대 CRF(Conditional Random Field)가 표준이 되었고, 2015년 이후 BiLSTM-CRF가 등장했습니다. 현재는 BERT, RoBERTa 등 Transformer 기반 모델이 최고 성능을 보여주며, GPT-4 같은 LLM을 활용한 Zero-shot/Few-shot NER도 연구되고 있습니다.
NER은 시퀀스 레이블링 문제로 정의됩니다. 각 토큰에 BIO 태깅(B-시작, I-내부, O-외부) 또는 BIOES(B, I, O, E-끝, S-단일) 방식으로 레이블을 부여합니다. 예를 들어 "삼성전자 이재용 회장이 서울에서"에서 "삼성전자"는 B-ORG, "이재용"은 B-PER, "서울"은 B-LOC로 태깅됩니다.
실무에서 NER은 계약서 분석(당사자/금액/날짜 자동 추출), 의료 기록 분석(약물명/증상/진단명 추출), 금융 뉴스 모니터링(기업/인물/이벤트 추적), 고객 문의 분석(제품명/서비스명 인식) 등에 필수적입니다. 한국어의 경우 조사 처리, 띄어쓰기 오류, 복합 명사 처리가 추가적인 도전 과제입니다.
주요 한국어 NER 모델 성능 비교 (2025년 1월 기준)
| 모델 | F1 Score | 추론 속도 | 파라미터 | 특징 |
|---|---|---|---|---|
| KoELECTRA-base | 91.2% | ~500 sent/s | 110M | 범용 한국어 NER |
| KoBERT-NER | 89.5% | ~400 sent/s | 92M | SKT 개발 |
| klue/roberta-large | 92.8% | ~150 sent/s | 337M | KLUE 벤치마크 SOTA |
| spaCy ko_core_news | 85.0% | ~2000 sent/s | 15M | 경량/빠른 추론 |
| GPT-4 (Zero-shot) | 88.0% | ~10 sent/s | - | 학습 데이터 불필요 |
| Claude 3.5 (Few-shot) | 90.5% | ~15 sent/s | - | 복잡한 도메인 강점 |
선택 가이드: 대량 처리가 필요하면 KoELECTRA, 최고 정확도가 필요하면 klue/roberta-large, 도메인 특화 데이터가 적으면 LLM Zero/Few-shot을 권장합니다. LLM은 API 비용($0.01-0.06/1K tokens)이 발생합니다.
Hugging Face Transformers를 사용한 한국어 NER 예제입니다.
# pip install transformers torch
from transformers import AutoTokenizer, AutoModelForTokenClassification
from transformers import pipeline
# 한국어 NER 모델 로드
model_name = "Leo97/KoELECTRA-small-v3-modu-ner"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForTokenClassification.from_pretrained(model_name)
# NER 파이프라인 생성
ner_pipeline = pipeline("ner", model=model, tokenizer=tokenizer,
aggregation_strategy="simple")
# 분석할 텍스트
texts = [
"삼성전자 이재용 회장이 서울에서 기자회견을 열었다.",
"2024년 1월 15일 네이버는 신규 AI 서비스를 발표했다.",
"애플의 팀 쿡 CEO가 도쿄에서 열린 행사에 참석했다."
]
# NER 수행
for text in texts:
print(f"원문: {text}")
entities = ner_pipeline(text)
for entity in entities:
print(f" → {entity['word']}: {entity['entity_group']} "
f"(신뢰도: {entity['score']:.2%})")
print()
# 출력 예시:
# 원문: 삼성전자 이재용 회장이 서울에서 기자회견을 열었다.
# → 삼성전자: ORG (신뢰도: 98.45%)
# → 이재용: PER (신뢰도: 99.12%)
# → 서울: LOC (신뢰도: 97.89%)
spaCy를 사용한 빠른 NER 예제입니다.
# pip install spacy
# python -m spacy download ko_core_news_lg
import spacy
# 한국어 모델 로드
nlp = spacy.load("ko_core_news_lg")
text = """
카카오뱅크가 2024년 3월에 서울 강남에서 핀테크 컨퍼런스를 개최한다.
행사에는 김범수 카카오 창업자와 이승건 토스 대표가 참석할 예정이다.
"""
# NER 수행
doc = nlp(text)
# 결과 출력
print("개체명 인식 결과:")
for ent in doc.ents:
print(f" {ent.text}: {ent.label_} (위치: {ent.start_char}-{ent.end_char})")
# 출력 예시:
# 개체명 인식 결과:
# 카카오뱅크: ORG (위치: 1-6)
# 2024년 3월: DATE (위치: 8-16)
# 서울 강남: LOC (위치: 18-24)
# 김범수: PER (위치: 50-53)
# 카카오: ORG (위치: 54-57)
# 이승건: PER (위치: 65-68)
# 토스: ORG (위치: 69-71)
LLM을 활용한 Few-shot NER 예제입니다.
# pip install anthropic
import anthropic
import json
client = anthropic.Anthropic()
def extract_entities_with_llm(text: str) -> dict:
prompt = f"""다음 텍스트에서 개체명을 추출하세요.
개체 유형:
- PER: 인명
- ORG: 기관/회사명
- LOC: 지명
- DATE: 날짜/시간
- MONEY: 금액
예시:
텍스트: "삼성전자 이재용 회장이 2024년 1월 서울에서 10억원 투자를 발표했다."
결과: {{"PER": ["이재용"], "ORG": ["삼성전자"], "LOC": ["서울"], "DATE": ["2024년 1월"], "MONEY": ["10억원"]}}
텍스트: "{text}"
결과:"""
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=500,
messages=[{"role": "user", "content": prompt}]
)
return json.loads(response.content[0].text)
# 사용 예시
text = "LG전자가 2024년 4월 부산 벡스코에서 500억원 규모의 AI 로봇 사업을 공개한다."
entities = extract_entities_with_llm(text)
print(entities)
# 출력: {"PER": [], "ORG": ["LG전자"], "LOC": ["부산 벡스코"], "DATE": ["2024년 4월"], "MONEY": ["500억원"]}
"계약서에서 당사자명과 계약금액을 자동 추출하려면 NER이 필요합니다. 법률 도메인에 특화된 데이터로 KoELECTRA를 파인튜닝하면 F1 95% 이상 나올 거예요. 특히 '을', '갑' 같은 법률 용어 처리가 중요합니다."
"의료 NER 시스템을 구축했습니다. 처방전에서 약물명, 용량, 복용 방법을 추출하는데, BioBERT 기반으로 파인튜닝하여 약물명 인식에서 F1 0.94를 달성했어요. 의약품 데이터베이스와 연동해서 후처리로 정규화도 진행합니다."
"한국어 NER에서 '삼성전자 반도체 사업부'처럼 중첩 개체가 문제예요. 기본 BIO 태깅으로는 안 되고, Span-based 모델이나 Multi-label classification으로 접근해야 해요. 아니면 계층적으로 먼저 전체를 인식하고 다시 분해하는 방법도 있어요."
일반 뉴스로 학습된 모델을 의료/법률/금융 문서에 적용하면 성능이 크게 떨어집니다. 도메인 특화 용어와 표현 방식이 다르기 때문입니다.
"삼성전자 반도체 사업부"처럼 개체가 중첩되는 경우를 처리하지 못하는 모델이 많습니다. 실무에서는 자주 발생하는 패턴입니다.
한국어 NER은 띄어쓰기 오류("서울시" vs "서울 시")와 오타에 민감합니다. 전처리 없이 모델에 넣으면 성능이 저하됩니다.
도메인 특화 데이터로 파인튜닝하고, 맞춤법 검사기로 전처리하세요. 중첩 NER이 필요하면 Span-based 모델을 사용하고, 후처리로 사전 기반 검증과 정규화를 추가하면 정확도가 올라갑니다.
원인: 고객 문의에서 "김민수"를 인명으로 인식했으나, 실제로는 지점명("김민수 지점")이었음. 동명이인 고객 계좌에 잘못 연결
영향: 개인정보 유출, 고객 클레임, 금융감독원 경고
해결: 컨텍스트 기반 검증 강화, "~지점", "~점" 패턴 후처리 규칙 추가
교훈: NER 결과를 그대로 신뢰하지 말고, 특히 금융/의료 등 민감한 도메인에서는 반드시 후처리 검증과 휴먼 리뷰를 병행해야 합니다.
원인: NER이 "이영희"를 단순히 PER로 태깅, 동명이인 구분 없이 유명인 프로필을 자동 연결하여 잘못된 정보 노출
영향: 명예훼손 소송, 기사 삭제, 신뢰도 하락
해결: Entity Linking(개체 연결) 파이프라인 추가, 확신도 낮은 경우 휴먼 리뷰 필수화
교훈: NER은 "무엇이 개체인가"만 알려줄 뿐, "누구인가"는 Entity Linking이 필요합니다. 특히 인명은 동명이인 처리가 필수입니다.
Q1. NER에서 "삼성전자"를 태깅할 때 올바른 BIO 레이블은?
Q2. 다음 중 NER의 성능 평가에 가장 널리 사용되는 지표는?
Q3. "삼성전자 반도체 사업부"처럼 개체가 중첩되는 경우를 처리하기 위한 방법이 아닌 것은?