← Studio Log
D. 기술 신뢰 (Uy tín)다국어국제화로케일앱 개발베트남 시장

다국어 앱의 로케일 설계: 한국어와 베트남어, 영어를 한 앱에

다국어 앱의 로케일 설계: 한국어와 베트남어, 영어를 한 앱에
글: Yeowubie

번역 파일만 넣어서는 끝나지 않는 이유

다국어 지원을 문자열 교체로 이해하면 출시 직후부터 문제가 쌓입니다. 화면에 보이는 문장은 로케일이 결정하는 여러 값 가운데 하나일 뿐입니다. 날짜 표기, 숫자 구분자, 이름 순서, 주소 입력 순서, 정렬 기준, 알림 발송 시각이 함께 갈라집니다. 번역 파일은 그중 가장 눈에 잘 띄는 한 겹입니다.

실제로 문제가 터지는 지점은 대부분 문장 밖에 있습니다. 한국어 화면에서는 2026년 3월 5일이라고 쓰지만 영어권 사용자는 같은 날짜를 다른 순서로 읽습니다. 베트남에서는 날짜를 일, 월, 연 순서로 씁니다. 서버가 한 가지 순서로만 문자열을 만들어 내려보내면 클라이언트가 손댈 여지가 없습니다. 반대로 서버가 시각을 절대값으로 내려보내고 표기는 클라이언트가 맡으면, 로케일이 늘어나도 서버 코드는 그대로 둡니다. 이 경계를 어디에 그을지가 첫 설계 결정입니다.

정렬도 자주 놓칩니다. 이름 목록을 알파벳 순으로 정렬한다고 할 때, 그 순서는 언어마다 다릅니다. 베트남어는 성조 부호가 붙은 글자를 기본 글자 뒤에 놓는 규칙이 있고, 한국어는 자음 순서를 따릅니다. 데이터베이스 기본 정렬 규칙에 맡겨 두면 사용자 눈에는 무작위로 섞인 목록으로 보입니다. 목록이 짧을 때는 아무도 지적하지 않다가, 데이터가 쌓이면 그때 문의가 들어옵니다.

검색은 한 단계 더 까다롭습니다. 베트남어 사용자는 성조 부호를 빼고 입력하는 경우가 흔합니다. 부호를 그대로 비교하면 사용자가 분명히 존재하는 항목을 못 찾습니다. 그래서 저장할 때 부호를 제거한 보조 색인을 함께 만들어 두는 편이 안전합니다. 한국어에서는 초성 검색을 기대하는 사용자가 있습니다. 이런 기대는 언어별로 다르고, 번역 파일에는 전혀 드러나지 않습니다.

여우비 인터랙션은 한국과 베트남 두 지역에서 함께 일하면서 자체 제품과 고객사 제품을 같이 만듭니다. 그래서 다국어는 옵션이 아니라 기본 조건에 가깝습니다. 출결 관리 서비스인 onSpots는 특정 국가에 묶이지 않은 다국어 서비스로 만들었고, 한국어 학습에서 배우는 사람과 가르치는 사람을 잇는 매칭 도구인 랭토리는 한국어와 베트남어, 영어 로케일을 지원하되 주력을 베트남어에 둡니다. 두 제품 모두 번역 파일보다 그 바깥의 결정에 시간이 더 들었습니다.

정리하면 국제화는 문자열 작업이 아니라 데이터 모델 작업입니다. 어떤 값을 원본으로 저장하고 어떤 값을 표시 시점에 만들어 낼지 정하는 일이 먼저입니다. 이 순서를 뒤집으면 언어를 하나 더할 때마다 코드 여러 곳을 다시 열게 됩니다.

언어와 지역, 통화, 날짜를 분리해서 다루기

로케일을 하나의 값으로 묶어 두면 나중에 반드시 쪼개게 됩니다. 언어, 지역, 통화, 시간대, 날짜 형식은 서로 독립적으로 변합니다. 베트남에 사는 한국인은 한국어 화면을 보면서 베트남 시간과 베트남 동을 씁니다. 이 조합을 표현할 수 없는 구조면 그 사용자는 어느 쪽이든 불편을 감수합니다.

사용자 설정에 언어 하나만 두면 이런 조합이 막힙니다. 최소한 표시 언어와 지역을 따로 저장하고, 시간대는 별도 필드로 두는 편이 좋습니다. 통화는 사용자 선호가 아니라 거래 통화를 따라가야 하는 경우가 많으므로 결제 도메인 쪽에 붙입니다. 이렇게 나눠 두면 이후에 지역별 규칙이 추가돼도 기존 필드를 건드리지 않습니다.

금액 표기에는 별도의 주의가 필요합니다. 베트남 동은 소수점 단위를 사실상 쓰지 않고 자릿수가 큽니다. 한국 원도 소수점 단위가 없습니다. 반면 미국 달러는 소수 두 자리를 씁니다. 통화별 소수 자릿수를 코드에 상수로 박아 두면 통화가 늘어날 때마다 조건문이 붙습니다. 금액은 최소 단위 정수로 저장하고, 통화 코드와 함께 다니게 하고, 표기 자릿수는 통화 메타데이터에서 읽어 오는 편이 오래 갑니다. 자릿수 구분 기호도 지역마다 다릅니다. 점과 쉼표의 역할이 뒤바뀌는 지역이 있어서, 숫자를 직접 문자열로 조립하면 사고가 납니다.

시간은 저장과 표시를 확실히 분리합니다. 데이터베이스에는 시간대를 포함한 절대 시각으로 저장하고, 화면에는 사용자 시간대로 변환해 보여 줍니다. 한국과 베트남은 두 시간 차이가 나므로, 출결이나 마감처럼 시각이 판정 기준이 되는 기능에서는 이 차이가 곧바로 분쟁이 됩니다. 어느 시간대를 기준으로 하루를 자를지도 정책 결정입니다. 사용자 현지 자정인지, 서비스 운영 기준 시간대의 자정인지 문서에 적어 두지 않으면 구현자마다 다르게 만듭니다.

문장 안에 값을 끼워 넣는 방식도 미리 정합니다. 문장을 앞뒤로 잘라 붙이면 어순이 다른 언어에서 무너집니다. 한국어는 서술어가 뒤에 오고, 베트남어는 수식어가 명사 뒤에 붙습니다. 그래서 번역 단위는 자리표시자를 포함한 문장 전체여야 합니다. 널리 쓰이는 국제화 라이브러리는 대부분 이 방식을 지원하지만 세부 문법은 라이브러리마다 다르므로, 도입 전에 실제 문서를 확인하고 팀 규칙을 한 번 정해 두는 편이 낫습니다.

복수형 처리도 언어마다 다릅니다. 영어는 단수와 복수를 나누고, 한국어와 베트남어는 그런 구분을 문법으로 강제하지 않습니다. 영어 기준으로 두 갈래 분기를 코드에 박으면 다른 언어에서 어색한 문장이 나옵니다. 복수 규칙은 번역 자원 쪽에서 언어별로 선언하고 코드는 개수만 넘기는 구조가 안전합니다.

베트남어와 한국어가 레이아웃에 주는 부담

같은 뜻의 문장이라도 언어마다 길이가 다릅니다. 베트남어는 성조 부호 때문에 글자 높이가 늘고, 한국어는 짧게 압축되며, 영어는 그 사이 어딘가에 놓입니다. 버튼과 탭, 카드 제목처럼 폭이 고정된 자리에서 이 차이가 바로 드러납니다. 레이아웃은 가장 긴 언어를 기준으로 검증해야 합니다.

베트남어의 성조 부호는 글자 위와 아래에 붙습니다. 줄 간격을 좁게 잡으면 위쪽 부호가 잘리거나 앞 줄과 붙어 보입니다. 한국어와 영어 화면에서 멀쩡하던 간격이 베트남어에서만 깨지는 이유가 대개 이것입니다. 서체를 고를 때도 베트남어 확장 글자를 제대로 담고 있는지 확인해야 합니다. 담기지 않으면 브라우저나 시스템이 다른 서체로 대체하는데, 그 순간 한 문장 안에서 글자 모양이 섞입니다.

한국어에는 줄바꿈 문제가 따로 있습니다. 웹 기본 동작에서 한국어는 단어 중간에서 잘려 다음 줄로 넘어갑니다. 두 글자짜리 단어가 한 글자씩 나뉘어 두 줄에 걸치면 읽는 사람은 곧바로 어색함을 느낍니다. 이건 미관 문제로 보이지만 실제로는 가독성과 신뢰의 문제입니다. 줄바꿈이 단어 단위로 일어나도록 스타일에서 명시해 두어야 하고, 헤드라인처럼 줄 나눔이 의미를 좌우하는 자리에서는 브라우저 자동 줄바꿈에 맡기지 말고 줄을 직접 나눠 배치하는 편이 낫습니다. 이 처리는 개발자가 알고 있지 않으면 누구도 지적해 주지 않습니다. 한국어를 모르는 리뷰어에게는 그냥 정상으로 보이기 때문입니다.

문장 길이 차이는 설계로 흡수합니다. 버튼 라벨을 한 줄에 맞추려고 번역을 억지로 줄이면 뜻이 흐려집니다. 대신 버튼이 두 줄까지 늘어날 수 있게 하거나, 최소 높이를 잡아 두고 내용에 따라 늘어나게 합니다. 표 형태 화면은 특히 취약합니다. 열 폭을 고정한 표는 한 언어에서만 맞고 나머지에서는 잘리거나 남습니다. 좁은 화면에서 표를 카드 목록으로 바꾸는 방식이 다국어에서도 유리하게 작동합니다.

검증 방법도 정해 둡니다. 화면을 만들 때마다 세 언어로 실제 렌더 화면을 보고, 데스크톱과 모바일 양쪽에서 확인합니다. 타입 검사를 통과했다는 사실은 레이아웃 확인이 아닙니다. 가장 긴 문자열을 임시로 넣어 보는 방법도 씁니다. 번역이 아직 안 나왔다면 원문을 늘려 붙인 더미 문자열로 폭을 먼저 시험합니다.

말줄임 처리는 마지막 수단으로 남깁니다. 잘린 문장은 정보가 사라진 상태이고, 사용자는 무엇이 잘렸는지 알 수 없습니다. 특히 이름과 주소, 가게 상호처럼 사용자에게 중요한 값은 잘리면 곤란합니다. 어떤 값이 잘려도 되는지, 어떤 값은 반드시 다 보여야 하는지 화면 설계 단계에서 구분해 두면 개발 중에 다투지 않습니다.

기본 언어와 폴백 규칙 정하기

기본 언어와 폴백 규칙을 정하지 않으면 빈 화면이나 키 이름이 그대로 노출됩니다. 결정할 항목은 셋입니다. 첫 방문자에게 무엇을 보여 줄지, 번역이 없을 때 어느 언어로 내려갈지, 사용자가 직접 고른 선택을 얼마나 오래 존중할지입니다. 이 셋은 코드가 아니라 정책입니다.

첫 화면 언어는 브라우저나 기기 설정을 참고하되 그대로 따르지 않는 편이 낫습니다. 베트남에서 판매되는 기기가 영어로 설정된 경우가 흔하고, 한국 사용자가 영문 운영체제를 쓰기도 합니다. 기기 설정과 접속 지역, 그리고 서비스의 주력 시장을 함께 놓고 우선순위를 정합니다. 랭토리는 세 언어를 지원하지만 주력을 베트남어에 두었으므로 판단이 애매한 구간에서는 베트남어로 기울입니다. 이런 결정은 제품마다 다르고, 문서에 근거를 적어 두어야 나중에 다시 논쟁하지 않습니다.

사용자가 언어를 직접 바꾸면 그 선택이 가장 강한 신호입니다. 이후 접속에서 기기 설정이 무엇이든 사용자 선택을 우선합니다. 로그인 사용자는 계정에 저장하고, 비로그인 사용자는 브라우저 저장소에 남깁니다. 여기서 흔한 실수는 로그인 순간에 계정 값이 현재 선택을 덮어써 화면 언어가 갑자기 바뀌는 것입니다. 어느 쪽이 이기는지 미리 정하고 한 곳에서 처리합니다.

폴백은 단계로 만듭니다. 특정 지역 변형이 없으면 상위 언어로, 상위 언어도 없으면 지정한 기준 언어로 내려갑니다. 기준 언어는 번역 누락이 절대 없도록 관리하는 한 언어여야 합니다. 세 언어를 모두 동등하게 두면 어느 쪽도 완전하지 않은 상태가 됩니다. 기준 언어에서조차 키가 없으면 화면에 키 문자열이 노출되므로, 빌드 단계에서 누락 키를 검사해 실패시키는 장치를 두는 편이 낫습니다.

폴백은 텍스트에만 적용되지 않습니다. 이미지 안에 글자가 들어간 배너, 언어별로 다른 약관 문서, 언어별 고객 응대 창구도 같은 규칙을 따릅니다. 베트남어 화면에서 한국어 약관으로 연결되면 사용자는 그 시점에 신뢰를 잃습니다. 법적 효력이 필요한 문서는 어느 언어본이 기준인지도 명시해야 합니다. 이 부분은 서비스 성격에 따라 별도 확인이 필요합니다.

주소 표시줄 구조도 초기에 정합니다. 언어를 경로에 넣을지, 하위 도메인으로 나눌지, 아니면 같은 주소에서 헤더로 판단할지에 따라 검색 노출과 공유 경험이 달라집니다. 같은 주소가 방문자마다 다른 언어를 보여 주면 검색 엔진이 어떤 언어를 색인할지 판단하기 어렵고, 링크를 공유받은 사람이 다른 언어를 보게 됩니다. 언어마다 고유 주소를 주고 서로를 가리키는 표시를 붙이는 구조가 다루기 쉽습니다.

콘텐츠 운영까지 이어지는 다국어

다국어는 배포로 끝나지 않습니다. 공지, 상품 설명, 도움말, 푸시 알림은 출시 뒤에도 계속 생깁니다. 세 언어를 채우는 사람과 순서, 그리고 한 언어가 비었을 때 무엇을 보여 줄지 정해 두지 않으면 시간이 지날수록 언어 사이 내용이 어긋납니다. 운영 규칙이 코드만큼 중요합니다.

콘텐츠 모델부터 다르게 잡습니다. 하나의 항목 아래 언어별 본문을 붙이는 구조여야 번역 상태를 항목 단위로 추적할 수 있습니다. 언어마다 별도 항목을 만들면 어느 것이 원본인지, 원본이 수정됐을 때 어느 번역이 낡았는지 알 수 없습니다. 각 언어 본문에 상태 값을 붙여 초안인지 검수 대기인지 발행됐는지 구분하면, 미완성 번역이 사용자에게 새어 나가는 사고를 막습니다.

번역 자체는 기계 번역으로 초안을 만들고 사람이 다듬는 방식이 현실적입니다. 다만 손대야 하는 지점이 정해져 있습니다. 제품 고유 용어, 법적 문구, 사용자 행동을 유도하는 문장은 사람이 봐야 합니다. 용어집을 따로 관리하면 같은 개념이 화면마다 다른 단어로 번역되는 현상을 막을 수 있습니다. 용어집은 번역가에게 주는 자료이면서 동시에 팀 내부 합의 문서 역할을 합니다.

알림은 별도로 다룹니다. 발송 시점의 사용자 언어 설정을 읽어 본문을 고르고, 시각 표기도 사용자 시간대로 맞춰야 합니다. 미리 만들어 큐에 넣어 둔 알림이 사용자가 언어를 바꾼 뒤 발송되면 예전 언어로 나갑니다. 발송 직전에 언어를 확정하는 구조가 안전합니다. 발송 시각도 지역을 고려합니다. 한국 기준 오전 아홉 시는 베트남 기준 오전 일곱 시입니다.

검색 노출도 운영 항목입니다. 언어별 제목과 요약을 각각 관리하고, 한 언어에서 잘 통하는 표현을 그대로 옮기지 않습니다. 베트남어 검색어와 한국어 검색어는 같은 주제라도 형태가 다릅니다. 번역된 제목이 아니라 그 언어 사용자가 실제로 입력하는 표현을 기준으로 다시 씁니다. 이 작업은 개발이 아니라 콘텐츠 운영의 몫이고, 담당자를 정해 두지 않으면 아무도 하지 않습니다.

마지막은 점검 주기입니다. 분기에 한 번쯤 세 언어 화면을 나란히 놓고 비교하면 어긋난 지점이 드러납니다. 한 언어에만 남아 있는 옛 안내, 한 언어에서만 빠진 새 기능 설명, 언어마다 다른 문의 창구 같은 것들입니다. 다국어 제품에서 품질은 처음 만들 때가 아니라 이런 점검에서 갈립니다. 언어를 늘리는 결정보다 늘린 언어를 유지하는 비용을 먼저 계산해 보시길 권합니다.