작동 방식

@lingo.dev/compiler는 지능형 코드 분석과 AI 기반 번역을 통해 빌드 시점에 React 애플리케이션을 다국어 앱으로 변환합니다.

빌드 시점 변환

기존 런타임 i18n 라이브러리(i18next, react-intl)는 런타임에 작동합니다. 앱이 실행되는 동안 번역을 로드하고, 값을 삽입하며, 메시지를 포맷합니다. 이는 번들 크기, 런타임 오버헤드 및 복잡성을 증가시킵니다.

@lingo.dev/compiler는 다르게 작동합니다. 빌드 프로세스 중에 코드를 변환합니다. React 컴포넌트는 깔끔하게 유지되며, 번역은 최적화된 번들로 사전 컴파일됩니다.

결과: 런타임 오버헤드 제로, 더 작은 번들, 수동 번역 키 관리 불필요.

프로세스

1. AST 분석

컴파일러는 Babel을 사용하여 React 코드를 추상 구문 트리(AST)로 파싱합니다. JSX를 순회하며 번역 가능한 콘텐츠를 식별합니다:

  • 텍스트 노드(<p>Hello</p>)
  • 문자열 속성(<img alt="Logo" />)
  • 템플릿 표현식의 텍스트(<p>Hello {name}</p>)

컴파일러는 React 컴포넌트 경계를 이해하고 정확한 번역을 위한 컨텍스트 정보를 유지합니다. 기술 식별자, 코드 스니펫 및 번역 불가능한 요소는 자동으로 필터링됩니다.

2. 콘텐츠 추출

각 번역 가능한 문자열에 대해 컴파일러는:

  • 안정적인 해시 기반 식별자를 생성합니다
  • 컴포넌트 컨텍스트(파일, 위치, 주변 요소)를 보존합니다
  • 리치 텍스트 구조를 추출합니다(<strong><em>와 같은 중첩 요소 처리)
  • 삽입 플레이스홀더를 유지합니다

이 메타데이터는 .lingo/metadata.json에 저장됩니다. 이는 앱의 모든 번역 가능한 콘텐츠를 추적하는 버전 관리 파일입니다.

3. 번역 생성

개발 중에 번역 서버는 온디맨드 번역을 처리합니다:

  • 의사 번역기 모드(기본값): 즉각적인 가짜 번역을 생성합니다. API 비용 없이 무엇이 번역되는지 확인하는 데 유용합니다
  • 실제 번역 모드: 구성된 LLM 제공자(Lingo.dev Engine 또는 직접 LLM)를 호출합니다

번역 서비스는 상태를 유지하지 않으며 부분 실패를 우아하게 처리합니다. 일부 번역이 실패하더라도 캐시된 번역은 계속 사용됩니다.

4. 코드 주입

컴파일러는 JSX에 번역 조회를 주입합니다:

// Your source code
<p>Hello {name}</p>

// Transformed code (simplified)
<p>{t('abc123', { name })}</p>

t() 함수는 최적화되어 자동으로 주입됩니다. 미리 로드된 번역 사전에서 해시 기반 조회를 수행합니다.

5. 번들 최적화

빌드 시:

  • 로케일별 번들이 생성됩니다
  • 사용된 번역만 포함됩니다
  • 데드 코드 제거로 사용되지 않는 번역이 제거됩니다
  • 사전은 컴포넌트별로 트리 셰이킹됩니다

개발 워크플로우

개발 모드

{
  dev: {
    usePseudotranslator: true,
  }
}

npm run dev를 실행하면:

  1. 컴파일러가 번역 서버를 시작합니다 (포트 60000-60099 자동 검색)
  2. 앱이 번역을 위해 서버에 요청합니다
  3. 의사 번역기가 즉시 가짜 번역을 생성합니다
  4. 번역은 .lingo/metadata.json에 캐시됩니다
  5. HMR이 정상적으로 작동하며 상태가 유지됩니다

개발 위젯(활성화된 경우)을 사용하면 브라우저에서 번역을 편집하고 실시간으로 변경 사항을 확인할 수 있습니다.

프로덕션 모드

{
  buildMode: "cache-only",
}

npm run build를 실행하면:

  1. 번역 서버가 시작되지 않습니다
  2. .lingo/metadata.json의 캐시된 번역만 사용됩니다
  3. 번역이 누락된 경우 명확한 오류와 함께 빌드가 실패합니다
  4. API 호출이 이루어지지 않으며 API 키가 필요하지 않습니다

왜 캐시 전용인가요? 프로덕션에서는 결정론적 빌드를 원합니다. 번역은 프로덕션 빌드 중이 아닌 CI(API 키가 있는 곳)에서 생성되어야 합니다.

권장 워크플로우

로컬 개발:

  • 의사 번역기 사용
  • 빠른 피드백 루프
  • API 비용 없음

CI/CD:

{
  buildMode: "translate",
  dev: {
    usePseudotranslator: false,
  }
}
  • 실제 번역 생성
  • 배포당 한 번 실행
  • .lingo/ 변경 사항 커밋

프로덕션 빌드:

{
  buildMode: "cache-only",
}
  • 사전 생성된 번역 사용
  • API 키 불필요
  • 빠르고 결정론적인 빌드

아키텍처

컴파일러는 명확한 관심사 분리를 중심으로 구성되어 있습니다:

메타데이터 관리자

  • .lingo/metadata.json에 대한 CRUD 작업
  • 파일 잠금을 통한 스레드 안전성
  • 번역을 위한 해시 기반 식별자

번역 서비스

  • 번역 워크플로우 조율
  • 캐시 전략 처리
  • 부분 실패 관리
  • 성공한 번역과 오류 모두 반환

번역기 (무상태)

  • Pseudotranslator: 즉각적인 가짜 번역
  • LCP Translator: Lingo.dev 엔진 통합
  • LLM Translators: 직접 제공자 통합
  • 내장 캐싱 없음—서비스 레이어에서 처리

번역 서버

  • 개발용 HTTP 서버
  • 실시간 위젯 업데이트를 위한 WebSocket 지원
  • 자동 포트 관리
  • 배치 요청 처리

구현 세부 사항은 소스 코드 아키텍처 문서를 참조하세요.

프레임워크 통합

Next.js

컴파일러는 withLingo() 래퍼를 통해 통합됩니다:

  • Webpack과 Turbopack 모두 지원
  • React Server Components와 호환
  • 지연 플러그인 로딩을 위한 비동기 설정
  • 자동 로케일 기반 라우팅 (설정된 경우)

Vite

컴파일러는 lingoCompilerPlugin를 통해 통합됩니다:

  • Unplugin 기반 (Vite, Webpack, Rollup과 호환)
  • 완전한 HMR 지원
  • 효율적인 개발 서버 통합
  • 자동 가상 모듈 생성

자주 묻는 질문

Server Components와 호환되나요? 네. Next.js에서 컴파일러는 Server와 Client Components를 모두 변환합니다. 번역 조회는 동형적으로 작동합니다.

코드 분할은 어떻게 되나요? 번역은 컴포넌트와 함께 자동으로 분할됩니다. 각 청크는 필요한 번역만 포함합니다.

번역은 어떻게 캐시되나요? 모든 번역은 .lingo/metadata.json에 저장됩니다. 이 파일은 버전 관리되며 번역 캐시 역할을 합니다. 컴파일러는 콘텐츠 해시를 사용하여 새로운 텍스트나 변경된 텍스트만 재번역을 트리거합니다.

번역이 실패하면 어떻게 되나요? 서비스는 부분 결과를 반환합니다. 성공한 번역은 캐시되어 사용되며, 오류는 디버깅을 위한 컨텍스트와 함께 기록됩니다. 앱이 중단되지 않고 캐시된 번역이나 원본 텍스트로 대체됩니다.

변환된 코드를 볼 수 있나요? 네. 빌드 출력에서 변환된 파일을 확인할 수 있습니다. 변환은 최소한으로 이루어지며, 해시 기반 조회를 사용하는 t() 함수 호출만 포함됩니다.

다음 단계