제목을 입력해주세요..png

"글로벌 시장으로 진출합니다!"

기획팀의 야심 찬 선언과 함께 제 자리엔 '다국어 지원(i18n)'이라는 묵직한 과제가 떨어졌습니다. 새로 만드는 프로젝트라면 참 좋았겠지만, 현실은 이미 수많은 유저들이 매일 사용하고 있는 **'라이브 서비스'**였습니다.

개발자들 사이에서 가장 악명 높은 작업 중 하나인 "달리는 기차의 바퀴 바꾸기"가 시작된 순간이었죠.

기차를 멈추지 않고(무중단), 승객들이 멀미를 느끼지 않게(SEO 및 기존 URL 유지), 그러면서도 바퀴를 튼튼한 다국어용으로 교체해야 했습니다. 이 험난했던 여정, 그리고 라이브러리의 밑바닥을 파헤치며 깨달았던 사투의 기록을 공유합니다.


🚨 1번 선로: 절대로 멈출 수 없는 두 가지 조건 (SEO & Legacy URL)

새 바퀴를 갈아 끼우기 전에 절대로 건드려선 안 될 성역이 있었습니다.

  1. SEO (검색 엔진 최적화): 현재 서비스는 구글과 네이버 검색을 통해 유입되는 유저가 많습니다. 다국어를 도입한다고 한국어 페이지의 점수가 깎이거나 검색 결과에서 사라지면 절대 안 됩니다.
  2. 기존 URL 체계 유지: 수많은 유저들이 이미 특정 링크를 즐겨찾기 해두거나 공유해 두었습니다. 다국어 도입한다고 이 링크들이 404로 바뀌면 대참사입니다.

처음엔 간단하게 ?lang=en 같은 쿼리 파라미터 방식을 생각했습니다. 기존 URL을 건드리지 않으니까요. 하지만 검색 엔진은 URL 경로(/en/...) 형태를 훨씬 선호하며, 그래야 각 언어별 페이지로 명확히 인지하기 때문입니다.

스크린샷 2026-03-27 오후 4.10.27.png

구글의 공식 문서를 기반하여 결국 Sub-path 방식(/[locale]/...)을 택했습니다. 달리는 기차 아래로 기어들어 갈 준비를 마쳤습니다.

image.png


🧠 2번 선로: 전역 상태(Context)의 함정과 '쿠키'라는 구원자

경로 구조를 잡고 나니 프론트엔드 개발자로서 근본적인 의문이 들었습니다.

"엥? 결국 JSON 파일에서 다국어 텍스트를 가져와서 전체 화면에 뿌려주려면, Zustand나 React Context 같은 전역 상태(Global State)로 현재 언어(lang)를 관리해야 하는 거 아닌가?"

기존 React (SPA) 방식에 익숙했던 저의 오판이었습니다. 만약 최상단에서 Context Provider로 언어 상태를 관리하게 되면, 앱 전체가 클라이언트 사이드 렌더링(CSR)으로 동작하게 되어 기껏 지키려 했던 SEO와 초기 로딩 속도(TTFB)가 다 박살 나버리기 때문입니다.

이 딜레마를 안고 next-intl 라이브러리의 동작 원리를 파헤치기 시작했고, 이 녀석이 전역 상태 대신 '쿠키(Cookie)'와 '미들웨어(Middleware)'를 기가 막히게 활용한다는 사실을 깨달았습니다.