이 글의 배경이 되는 이야기는 15화: 감칠맛 조미료의 정체에서 읽을 수 있습니다.
이 글을 읽으면 알 수 있는 것
- 첨가물 화학명을 일상어로 번역하는 문제의 규모
- 수작업 번역 100건으로 커버리지 85%를 달성한 이유
- LLM 번역 파이프라인의 설계: 프롬프트, 검증, 적재
- AI 번역에서 “공포 조장 금지”를 어떻게 강제했는지
문제: “L-글루탐산나트륨”을 이해하는 사람
식약처 원재료 사전에는 약 3,800종의 첨가물이 등록되어 있습니다. 이 이름들은 대부분 화학 명칭입니다.
- L-글루탐산나트륨
- 카르복시메틸셀룰로스나트륨
- 5’-리보뉴클레오티드이나트륨
- 파라옥시안식향산에틸
이 이름을 성분표에서 보고 “아, 이건 MSG구나”라고 바로 알 수 있는 사람은 많지 않습니다.
서비스의 목표는 “이 첨가물이 뭔지, 왜 들어가 있는지” 알려주는 것이었습니다. 두 가지 정보가 필요했습니다.
- 용도 분류: 감미료, 보존료, 유화제 등 (왜 들어가 있는지)
- 일상어 번역: “MSG (감칠맛 조미료)” 같은 쉬운 이름 (뭔지)
1단계: 수작업 번역 100건
3,800종 전부를 사람이 번역하는 것은 비현실적이었습니다. 하지만 전부 할 필요가 없었습니다.
첨가물의 출현 빈도는 극단적으로 편중되어 있습니다. 상위 100개 첨가물이 실제 제품 데이터의 약 85%를 커버합니다.
그래서 가장 많이 등장하는 첨가물부터 우선순위를 두었습니다.
수작업 번역에서 가장 신경 쓴 원칙이 있었습니다.
“공포가 아니라 이해.”
# 이렇게 쓰지 않습니다
"유해한 보존료"
"위험한 착색료"
# 이렇게 씁니다
"미생물 번식을 억제하여 보존 기간을 늘리는 보존료"
"식품에 색을 입히는 착색료"
첨가물이 좋은지 나쁜지는 이 서비스가 판단할 문제가 아닙니다. 식약처가 안전성을 평가해서 허가한 것이고, 서비스는 “이게 뭔지, 왜 들어가 있는지”만 알려줍니다.
2단계: LLM으로 나머지 확장
수작업 100건으로 85.3%를 커버했지만, 나머지 14.7%도 채워야 했습니다. 여기서 LLM(Gemini)을 도입했습니다.
입력 설계
LLM에게 제공하는 정보:
- 표준명: 폴리소르베이트80
영문명: Polysorbate 80
대분류: 식품첨가물(B)
출현 빈도: 2,847회
표준명만 주면 LLM이 추측해야 할 부분이 많습니다. 영문명, 대분류, 출현 빈도까지 함께 제공하여 맥락을 풍부하게 했습니다.
출력 강제
LLM의 응답에 세 가지 강제 조건을 두었습니다.
- 용도 분류 Enum 강제: 식약처 공식 31개 분류 + 가공보조제, 이 목록에 없는 분류를 쓰면 거부
- 금지 표현 목록: “유해”, “위험”, “독성”, “암 유발”, “과다 섭취 시…” 등을 시스템 프롬프트에서 명시적으로 금지
- JSON 스키마 강제: 자유 텍스트가 아닌 구조화된 JSON으로 응답
[절대 금지]
- "유해", "위험", "독성", "암 유발" 등 공포 조장 표현
- "과다 섭취 시..." 등 부작용/경고성 멘트
- "화학적", "인위적인" 등 비하 표현
이 규칙이 없으면, LLM은 인터넷에서 학습한 “첨가물 = 나쁜 것” 편향을 반영할 가능성이 있습니다.
검증 파이프라인
LLM이 반환한 결과는 자동 검증을 거칩니다.
- 필수 필드 누락 확인 (
plain_name,purpose_category,one_line_desc) purpose_category가 허용된 Enum 목록에 있는지 확인one_line_desc길이 체크 (50자 초과 시 경고)- 검증 통과한 건만 DB에 적재,
is_verified=False로 표시
is_verified=False가 핵심입니다.
LLM이 생성한 번역은 “초안”이며, 사람이 검수하기 전까지 사용자에게 노출되지 않습니다.
갈림길: 왜 전부 LLM으로 하지 않았는가
| 방법 | 장점 | 단점 |
|---|---|---|
| 전체 LLM 생성 | 빠름 | 검수 부담 큼, 톤 일관성 보장 어려움 |
| 전체 수작업 | 품질 확실 | 3,800종은 비현실적 |
| 수작업 기반 + LLM 확장 | 핵심은 사람이, 롱테일은 AI가 | 두 단계 관리 필요 |
수작업 100건은 단순히 번역 결과만이 아니라, LLM에게 “이런 톤과 수준으로 작성하라”는 참고 기준이기도 했습니다.
운영 구조
실제 적재는 두 단계로 나뉘어 있습니다.
- 시드 데이터 적재: 수작업 번역 + 가공보조제 94종 포함,
source='manual',is_verified=True - LLM 생성 적재: 미번역 B코드 첨가물 대상,
source='llm',is_verified=False
LLM 호출에는 Rate Limit 대응(지수 백오프 재시도)과 API 키 없이도 JSON 파일에서 로드할 수 있는 우회 경로가 포함되어 있습니다.
결과
| 항목 | 수치 |
|---|---|
| 전체 첨가물 | ~3,800종 |
| 수작업 번역 (시드) | ~200건 (일반 + 가공보조제) |
| LLM 생성 번역 | ~421건 |
| 합계 | ~621건 |
| 실제 제품 커버리지 | ~96.0% |
3,800종 중 621건만 번역했는데 96%를 커버하는 이유는, 나머지 3,200종 대부분이 실제 제품에 거의 등장하지 않기 때문입니다.
한계
LLM 번역의 검수가 아직 완료되지 않았습니다.
is_verified=False 상태의 번역이 남아 있습니다.
검수 완료 전까지는 사용자에게 노출되지 않습니다.
가공보조제의 번역은 사실상 불필요할 수 있습니다. 가공보조제는 최종 제품에 잔류하지 않는 성분입니다. 성분표에 거의 등장하지 않으므로 번역 우선순위가 낮지만, 완전성을 위해 포함했습니다.
한 줄 교훈
AI 번역의 핵심은 “빠르게 초안을 만드는 것”이 아니라 “틀린 것이 사용자에게 도달하지 않게 하는 것”입니다.
is_verified=False라는 한 줄이 서비스 품질을 지킵니다.