배민 다국어 서비스 — 5년 백로그를 LLM으로 19일에 끝낸 이야기
5년 된 백로그
2026년 1월 14일, 배민 팀이 다국어 서비스 개발을 시작했다. 2월 3일에 끝냈다. 19일이다. 5년 동안 아무도 못 건드린 일이었다.
왜 5년이 걸렸을까. 번역 대상이 너무 많았다. 수십만 개의 가게 정보, 수천만 개의 메뉴. 각 메뉴는 영어, 일본어, 중국어로 번역돼야 하고, 가게가 메뉴를 바꿀 때마다 실시간으로 반영돼야 한다. 사람이 하면 인력이 감당이 안 되고, 기존 번역 API는 퀄리티가 문제였다. LLM이 이 방정식을 바꿨다.
기술 스택
| 구성 요소 | 기술 | 역할 |
|---|---|---|
| LLM | Amazon Nova 2 Lite | 메뉴/가게명 번역 |
| 인프라 | AWS Bedrock | LLM API 호스팅 |
| 프레임워크 | Spring AI Bedrock | Java 서버에서 LLM 연동 |
| 데이터 허브 | FDH (Food Data Hub) | 가게/메뉴 데이터 원천 |
| UI 문구 | i18n | 정적 문구 1,600개 이상 관리 |
처음에는 Claude Haiku로 시작했다. 번역 품질은 좋았지만 비용과 속도 측면에서 Amazon Nova 2 Lite로 전환했다. 실제 배민 서비스처럼 수천만 건을 처리할 때는 단가와 처리량이 더 중요해진다.
[💡 잠깐! 이 용어는?] FDH (Food Data Hub): 배민 내부 플랫폼으로, 가게·메뉴 정보를 통합 관리하는 데이터 허브. 번역 파이프라인의 입력 데이터를 여기서 받는다.
파이프라인 구조
두 개의 파이프라인으로 나뉜다.
번역 파이프라인 (이벤트 기반)
가게나 메뉴 데이터가 변경될 때 이벤트가 발행된다. 파이프라인이 이벤트를 받아 LLM에게 번역을 요청하고, 결과를 언어별 메타데이터로 저장한다.
FDH 데이터 변경 이벤트
→ 번역 파이프라인 트리거
→ Amazon Nova 2 Lite API 호출
→ 영어/일본어/중국어 번역 결과 수신
→ 역번역으로 품질 검증
→ 언어별 메타데이터 저장
역번역 검증이 핵심이다. "짜장면" → "Jajangmyeon" → 다시 번역 → "짜장면"이 나오면 품질이 확보된 것으로 간주한다. 완벽하진 않지만 명백한 번역 실패를 걸러낸다.
응답 처리 파이프라인
사용자 요청이 들어오면 Accept-Language 헤더를 분석해서 언어를 판별하고, 저장된 번역 메타데이터를 매핑해서 응답한다. 번역은 이미 완료된 상태라 런타임 비용이 없다.
HTTP 요청
→ Accept-Language 헤더 파싱
→ 언어별 메타데이터 조회
→ 번역된 가게/메뉴 정보 응답
정적 문구는 i18n으로 분리
LLM 번역은 동적 콘텐츠(가게명, 메뉴명)에만 쓴다. "주문하기", "장바구니", "결제" 같은 UI 고정 문구 1,600개 이상은 i18n으로 관리한다.
이 분리가 중요하다. UI 문구를 LLM으로 번역하면 매 배포마다 번역 결과가 달라질 수 있다. "장바구니"가 어떤 날은 "Shopping Cart"이고 어떤 날은 "Cart"가 되면 사용자 혼란이 생긴다. 정적 문구는 i18n 파일에 고정, 동적 콘텐츠는 LLM 자동화로 역할을 나눈 것이다.
19일이 가능했던 이유
기술보다 흥미로운 건 속도다. 팀은 기획서 없이 PoC 먼저 만들었다. "이게 돼요"를 말로 설득하는 대신, 실제로 동작하는 걸 보여주고 의사결정을 얻었다. 그 다음이 구현이었다.
범위 최소화도 결정적이었다. "오픈하는 데 반드시 필요한 것"만 구현했다. 번역 품질 UI, 번역 수정 기능, 상세 오류 처리 — 이것들은 전부 이후 태스크다. MVP에 집중하지 않으면 "다 되면 오픈하겠다"는 식으로 계속 미뤄진다.
마무리
이 프로젝트의 기술적 교훈은 하나다. LLM이 번역 파이프라인의 "다시 시도할 만한" 수준이 됐다는 것이다. 예전 번역 API로는 퀄리티 문제 때문에 포기했던 일을 다시 꺼낼 수 있게 됐다. 역번역 검증처럼 간단한 품질 보증 레이어를 얹으면 실서비스에서 쓸 수 있는 수준이 된다.
5년 백로그를 19일에 끝낸 건 LLM 덕분이기도 하지만, "지금 당장 오픈할 수 있는 최소한"을 정한 팀의 판단력 덕분이기도 하다.
참고:
관심 있을 만한 포스트
Renderify — LLM이 생성한 JSX를 빌드 없이 브라우저에서 바로 실행하는 런타임 UI 엔진
Renderify가 @babel/standalone과 JSPM CDN을 이용해 LLM 생성 JSX/TSX를 zero-build로 실행하는 방식과 보안 모델, 스트리밍 렌더링 구조를 분석한다.
신입사원을 에이스로 — Netflix가 LLM Post-Training을 대규모 엔지니어링으로 만든 과정
Pre-training이 LLM에 넓은 언어 능력을 주지만, post-training이 실제 의도와 도메인 제약에 맞추는 단계. Netflix의 스케일링 접근법.
Zustand 소프트 삭제 — enumerable:false로 컴포넌트 크래시 없이 처리하기
JavaScript property descriptor의 enumerable 플래그를 활용해 삭제된 엔티티를 투명하게 처리하는 Zustand 패턴을 소개한다.
SVG 아이콘 — 코드 배포 없이 프로덕트 팀이 직접 관리하는 법
CSS mask-image와 S3를 조합해 개발자 개입 없이 아이콘을 교체하는 패턴을 소개한다.
VS Code 1.116 — 에이전트 디버깅, 포그라운드 터미널, 내장 Copilot
2026년 4월 VS Code 1.116이 에이전트 경험, 터미널, Chat UX, 내장 브라우저를 개선한 핵심 변경사항을 정리한다.
Naver FE News 2026년 4월 — 49MB 웹 페이지부터 Temporal Stage 4까지
Naver FE News 2026년 4월호에서 프론트엔드 개발자가 주목할 6가지 소식을 선별해 정리한다.
VS Code 에이전트 — 실전 개발에서 쓸 수 있게 만드는 세 가지 축
VS Code 1.110이 도입한 컨텍스트 관리, 에이전트 제어, 확장성 기능이 AI 에이전트를 실무에 투입 가능하게 만든 방식을 분석한다.
node:vfs — Node.js에 가상 파일 시스템이 필요한 이유
Matteo Collina가 제안한 node:vfs 모듈이 해결하려는 4가지 문제와 아키텍처를 분석한다.