콘텐츠가 바뀌면 이제 서비스 중인 모든 로캘에 반영되어야 합니다. 교육 모듈에 새 강의가 추가됩니다. CMS 항목이 저장됩니다. 제품 설명이 수정됩니다. 그러면 번역은 독일어, 프랑스어, 일본어는 물론 그 밖의 수많은 언어로 퍼져나가야 하고, 그동안 앱이 멈춰 있어서는 안 됩니다.
비동기 로컬라이제이션 API는 바로 이런 순간을 위해 만들어졌습니다. 요청 한 번으로 모든 로캘을 처리하고, 결과는 완료되는 즉시 받아볼 수 있습니다. 대상 로캘과 함께 콘텐츠를 한 번 POST하면 즉시 202가 반환되고, 플랫폼은 각 로캘을 독립적인 백그라운드 작업으로 번역합니다. 용어집, 브랜드 보이스, 모델 구성은 그대로 유지되며, 동기 API와 같은 엔진을 사용하면서 재시도는 더 이상 직접 관리하지 않아도 됩니다.
이 페이지에서 다루는 내용
문제#
교육 플랫폼, 콘텐츠 관리 시스템, 이러닝 도구는 콘텐츠가 생성되거나 업데이트되는 즉시 수십 개 언어로 번역해야 하는 경우가 많습니다. 동기 로컬라이제이션 API로도 가능하지만, 규모가 커지면 피할 수 없는 트레이드오프가 생깁니다.
예를 들어 영어로 작성된 교육 모듈을 14개 언어의 학습자에게 제공해야 한다고 해보겠습니다. 동기 API를 쓰면 선택지는 두 가지뿐이고, 어느 쪽이든 대가가 따릅니다.
14개의 병렬 호출 실행 – 대상 로캘마다 하나씩 요청을 보내고, 각 요청에는 동일한 소스 페이로드가 들어갑니다. 각 언어 결과를 도착하는 대로 표시할 수는 있지만, 중복 데이터를 포함한 14번의 네트워크 왕복을 관리해야 하고 그중 하나라도 실패하면 재시도 로직도 직접 책임져야 합니다.
14개 언어를 하나의 동기 호출로 모두 번역 – 왕복 횟수는 줄어들지만, 이번에는 가장 느린 로캘이 끝날 때까지 어떤 언어도 보여줄 수 없습니다.
어느 쪽이든 번역이 처리되는 동안 애플리케이션은 붙잡히게 됩니다. 서버가 처리 도중 재시작되면 진행 중이던 번역은 사라집니다. 한 언어라도 실패하면 부분 실패 처리도 직접 맡아야 합니다. 게다가 두 방식 모두 사용자에게 번역이 진행 중이라는 깔끔한 신호를 주지 못합니다.
비동기 API는 이 트레이드오프를 없앱니다. 한 번의 요청으로 대상 로캘마다 하나의 작업을 담은 작업 그룹이 생성됩니다. 각 작업은 로컬라이제이션 엔진을 거치는 내구성 있는 백그라운드 워크플로로 독립적으로 실행되므로, 사용자 측 서버가 재시작되어도 잃는 것은 없습니다. 작업이 사용자 프로세스 안에서 실행되는 것이 아니기 때문입니다. 결과는 각 로캘이 완료되는 즉시 로캘별로 전달됩니다. 앱은 계속 응답성을 유지합니다. 실패는 서로 격리됩니다. 재시도와 전달은 플랫폼이 맡습니다.
로캘이 하나고 잠깐 기다릴 수 있나요? 그럼 sync를 쓰세요.
비동기 API는 로캘이 많거나, 콘텐츠가 길거나, UI에 진행 상황을 보여줘야 할 때 진가를 발휘합니다. 로캘 쌍이 하나뿐이고 한 번의 왕복을 기다릴 수 있다면 동기 Localize 엔드포인트가 더 단순한 선택입니다. 요청 한 번이면 응답에서 번역된 데이터를 바로 받고, 웹훅 엔드포인트도 운영할 필요가 없습니다. 작업이 너무 크거나, 너무 오래 걸리거나, 로캘이 너무 많아 기다릴 수 없을 때 비동기를 선택하세요.
작동 방식#
단계는 세 가지이고, 이 중 요청/응답 사이클 안에서 일어나는 것은 첫 번째뿐입니다. 나머지 두 단계는 플랫폼이 자체적으로 처리합니다.
요청 한 번으로 제출
콘텐츠와 대상 로캘을 /jobs/localization로 POST하세요. API는 페이로드를 검증하고, 로캘별로 하나씩 작업이 담긴 작업 그룹을 만든 뒤, 그룹 ID와 작업 요약이 포함된 202를 반환합니다. 애플리케이션은 즉시 다음 작업을 계속할 수 있습니다. 이 호출 안에서는 실제 번역이 수행되지 않습니다. 전체 요청 및 응답 형식은 작업 생성에서 확인하세요.
플랫폼이 각 로캘을 독립적으로 처리
결과는 완료되는 즉시 수신
로캘 하나가 완료되는 순간, 플랫폼은 그 결과를 사용자의 webhook URL로 전달합니다. UI에서 실시간 진행 상황을 보여주고 싶다면, 예를 들어 작업이 완료될 때마다 업데이트되는 "14개 중 3개 준비 완료" 카운터를 표시하려면 그룹의 WebSocket에 연결하세요. 직접 가져오고 싶다면 일정 간격으로 그룹을 폴링할 수도 있습니다.
작업 그룹 모델#
한 번 제출하면 대상 로캘마다 하나의 작업을 담은 하나의 그룹이 생성됩니다. 이 구조가 바로 전체 개념 모델이며, 까다로운 질문들에 답할 수 있게 해주는 핵심이기도 합니다.
눈썰미 있는 독자라면 벌써 이런 질문을 떠올렸을 겁니다. 특정 로캘이 실패하면 어떻게 될까? 그리고 이 모든 작업이 진행되는 동안 내 앱은 어떻게 될까? 그룹 모델은 그 두 질문 모두에 답합니다.
- 실패는 격리됩니다. 각 로캘이 독립된 작업이기 때문입니다. 독일어는 성공하고 일본어는 실패하더라도, 독일어 번역은 정상적으로 전달되고 일본어 작업은 자체
errorMessage를 가집니다. 그룹은partial를 보고하며, 성공한 작업은 그대로 배포할 수 있습니다. 한 로캘의 실패가 이미 완료된 다른 로캘을 롤백할 수는 없습니다. 전체 상태 의미 체계는 작업 그룹 추적에서 확인할 수 있습니다. - 진행 중인 작업은 재시작 후에도 살아남습니다. 사용자 프로세스에서 실행되지 않기 때문입니다. 각 작업은 플랫폼 위에서 실행되는 내구성 있는 백그라운드 워크플로입니다. 서버가 재부팅되어도 진행 중인 작업은 사라지지 않습니다. 다시 연결하거나 폴링하면 그룹은 중단된 지점 그대로 남아 있습니다.
- 그룹은 UI에 연결할 수 있는 진행 모델이기도 합니다.
202에서 받은groupId를 저장한 다음, webhook 전달이나 WebSocket 스냅샷을 바탕으로 진행 표시기를 구성하세요. "14개 언어 중 3개 준비 완료"는 그룹의 하위 작업 수를 세는 카운터입니다.
이 모델에도 분명한 비용은 있습니다. 동기 호출에서는 필요 없는 소규모 통합 작업을 맡아야 합니다. 결과를 받으려면 HTTPS 웹훅 엔드포인트를 운영하거나 서버 측 WebSocket 연결을 유지해야 하고, 하나의 응답에서 번역 데이터를 바로 읽는 대신 각 로캘이 도착할 때마다 처리해야 합니다. 그 대신 플랫폼이 재시도, 실패 격리, 결과 전달을 맡고, 앱은 번역 때문에 멈추지 않습니다.
이것이 바로 비동기 API가 만들어진 이유입니다. 요청 한 번으로 모든 로캘을 처리하고, 결과는 완료되는 즉시 받아볼 수 있습니다. 다음 페이지에서는 이 문장을 구성하는 동작들을 하나씩 살펴봅니다.
