개발 slecs

다국어 페이지 라우팅과 배포 환경 표준화

목차

법인 서비스 영역에서 다국어 지원을 위한 동적 라우팅을 추가하고, 동시에 Prisma ORM의 Linux 엔진을 명시적으로 동봉했다. 언뜻 보기엔 라우팅이 하나, 빌드 설정이 하나—두 개의 독립적 작업으로 보이지만, 사실 팀이 성장하면서 맞닥뜨리는 공통 문제를 푼 결과다.

Next.js catch-all 라우트로 다국어 확장성 확보

이전엔 다국어 페이지가 고정적이었을 테다. 예를 들어 /ko, /en 같은 단순 구조. 하지만 법인 서비스가 늘어나면서 지역별, 서비스별로 다른 URL 체계가 필요했다. 한국 법인, 싱가포르 법인, 글로벌 법인이 각각 다른 경로를 가질 수 있어야 한다는 뜻이다.

이걸 일일이 라우트를 추가하는 방식은 비효율적이었다. 대신 [site]/[...path] 패턴을 도입했다.

// Before (확장성 제한)
/ko/privacy
/en/privacy
/jp/privacy

// After (임의 깊이, 임의 사이트)
/{site}/{...path}
/legal-kr/terms
/legal-kr/privacy/v2
/legal-sg/terms

이렇게 하면 URL 체계를 바꿀 때마다 라우트 파일을 수정할 필요 없다. page.tsx의 로직에서 params.siteparams.path를 받아 콘텐츠를 동적으로 렌더링하면 된다. 확장성 측면에서 큰 승리다.

라우트 변경 후에도 UI 상태 유지

[...path] 라우트가 많아지면, 사용자가 페이지를 이동할 때마다 컴포넌트가 리마운트될 수 있다. ThemeToggle 컴포넌트처럼 사용자 선택(다크 모드, 라이트 모드)을 유지해야 한다면?

해결책은 간단하다—쿠키나 로컬스토리지에 테마 설정을 저장하고, 라우트 변경 후에도 복원하는 것이다. 페이지 로드 시 미리 테마를 읽어서 렌더링하면, 사용자 경험이 끊기지 않는다.

// ThemeToggle.tsx의 전형적 패턴
useEffect(() => {
  const saved = localStorage.getItem('theme') || 'light';
  applyTheme(saved);
}, []);

const toggle = () => {
  const next = currentTheme === 'light' ? 'dark' : 'light';
  localStorage.setItem('theme', next);
  applyTheme(next);
};

CLAUDE.md에 이 패턴을 기록해 둔 것도 의도가 있다. 다음 팀원이 "왜 theme를 localStorage에 저장하나?" 물었을 때, 라우트 수렴 후 상태 유지가 필요하다는 배경을 알 수 있도록.

Prisma Linux 엔진: 배포 환경 일관성의 핵심

여기서 가장 중요한 부분이다. Prisma ORM은 쿼리 엔진을 바이너리로 제공한다. 로컬 개발(Mac arm64)과 프로덕션(Linux x86_64)의 아키텍처가 다르면, 이 바이너리가 달라져야 한다.

과거에는 npm install할 때 자동으로 맞는 바이너리를 받아왔는데, 문제가 있었다:

  • CI/CD 환경에서 로컬과 다른 node_modules를 생성할 수 있다
  • Docker 빌드 시 multistage를 쓰면, 빌드 스테이지와 런타임 스테이지의 Prisma 바이너리가 불일치할 수 있다
  • 캐시 일관성 문제로 "로컬에선 되는데 배포에선 안 돼" 상황이 발생한다

이번엔 명시적으로 prisma/schema.prisma 설정에서 Linux 엔진을 고정했다. 이렇게 하면 CI/CD 빌드 시 일관된 엔진을 사용하고, Docker에서도 예측 가능한 바이너리를 쓰며, 팀원들이 로컬에서 테스트할 때도 프로덕션과 같은 엔진으로 동작시킬 수 있다.

문서화의 중요성: 다음 팀원을 위해

변경 파일을 보면 코드(page.tsx, ThemeToggle.tsx)만큼 CLAUDE.md의 업데이트가 중요했다. 왜냐하면 "왜?"에 대한 답이 코드에만 있으면, 시간이 지날수록 그 맥락이 사라지기 때문이다. 3개월 뒤 다른 개발자(또는 나)가 이 구조를 보고 "이거 정말 필요해?" 물었을 때, commit 메시지만으로는 설득력이 없다.

하지만 CLAUDE.md에 기록해 두면 라우팅 구조를 왜 이렇게 했는지 알 수 있고, Prisma Linux 엔진을 명시한 이유를 이해할 수 있으며, 다음 작업자가 같은 실수를 반복하지 않는다. 팀 리딩 관점에서, 코드 리뷰할 때 항상 확인하는 것 중 하나가 "이 설계 결정을 문서화했나?"다.

회고: 구조와 안정성은 한 몸

이 작업을 하면서 깨달은 것이 하나 있다. 라우팅 구조(확장성)와 배포 안정성(Linux 엔진)은 사실 한 몸이라는 것이다. 라우팅을 유연하게 하려면, 어디서나 같은 방식으로 동작할 수 있어야 하고, 그러려면 빌드 산출물이 일관되어야 한다. Prisma 엔진을 명시하지 않으면, 개발 환경과 배포 환경의 동작이 달라질 수 있고, 그러면 다국어 라우팅이 한곳에선 정상, 다른 곳에선 오류가 날 수 있다. 작은 두 개의 변경이 아니라, 하나의 일관된 시스템 개선이었다는 뜻이다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.