블로그

LunariaJS + Git: 버전 관리 기반 현지화 워크플로우

LunariaJS가 Git을 활용해 현지화 변경 사항을 추적하는 방법을 설명하고, Git 커밋 히스토리로 번역 업데이트를 식별하고, 오래된 콘텐츠를 감지하며, 팀 협업과 완벽하게 통합된 현지화 워크플로우를 구현하는 방법을 배웁니다.

LibDoc Team 2026년 3월 6일 LunariaJS 칼럼 55 분 읽기
#LunariaJS #Git #버전 관리 #워크플로우 #팀 협업

LunariaJS + Git: 버전 관리 기반 현지화 워크플로우

앞선 글들에서는 LunariaJS의 설치, 설정, 대시보드 사용법을 소개했습니다. 이미 눈치채셨을 수도 있지만, LunariaJS의 핵심 특징 중 하나는 Git 기반 워크플로우입니다. 오늘은 LunariaJS가 Git을 활용해 현지화 변경 사항을 추적하는 방법과 효율적인 팀 협업 워크플로우를 설계하는 방법을 깊이 있게 살펴보겠습니다.

💡 공식 문서: LunariaJS 한국어 문서 - Git 워크플로우

왜 Git 통합이 필요한가요?

전통적인 현지화 관리의 딜레마

Git 통합 없이 번역 상태를 관리하려면 보통 다음이 필요합니다:

방식 1: 수동 표 유지

파일중국어일본어한국어
index.md
getting-started.md⚠️⚠️
configuration.md

문제점:

  • 표가 실제 파일과 동기화되지 않기 쉬움
  • “⚠️”가 구체적으로 얼마나 뒤처졌는지 알 수 없음
  • 표 업데이트는 추가 유지보수 부담

방식 2: 번역 플랫폼의 버전 관리 의존

일부 온라인 번역 플랫폼(예: Crowdin)은 자체 버전 관리 시스템이 있습니다.

문제점:

  • 코드 저장소와 분리됨
  • 동기화 메커니즘 설정 필요
  • 버전 불일치 발생 가능

방식 3: 파일에 마커 추가

<!-- TODO: Translate to Chinese -->
<!-- LAST_UPDATED: 2026-02-20 -->
<!-- STATUS: OUTDATED -->

문제점:

  • 파일 내용 오염
  • 마커 업데이트를 잊기 쉬움
  • 일괄 분석 어려움

LunariaJS의 Git 통합 장점

LunariaJS는 다른 길을 선택했습니다: Git 커밋 히스토리를 직접 사용해 번역 상태를 판단합니다.

핵심 장점:

장점설명
추가 마커 불필요파일 자체가 데이터 소스
자동 동기화Git 히스토리가 코드와 완전히 동기화됨
정밀 추적각 변경의 시간과 작성자를 알 수 있음
팀 친화적기존 Git 워크플로우에 통합됨

Git 추적 메커니즘 상세 설명

기본 원리

LunariaJS는 다음 단계를 통해 번역 상태를 판단합니다:

1. 파일 최종 수정 시간 획득

git log 명령어로 각 파일의 최종 수정 커밋을 가져옵니다:

git log -1 --format="%H %ct" -- path/to/file.md

2. 원본 파일과 번역 파일의 타임스탬프 비교

원본 파일 (en/getting-started.md):  2026-02-28 14:30
번역 파일 (ko/getting-started.md): 2026-02-20 10:15

시간 차이: 8일
상태: 오래됨 (Outdated)

3. 상태 보고서 생성

타임스탬프 비교에 따라 각 번역 파일의 상태를 생성합니다.

파일 변경 감지 알고리즘

LunariaJS는 다음 알고리즘으로 파일 변경을 감지합니다:

// 간소화된 알고리즘 로직
function getTranslationStatus(sourceFile: File, translationFile: File): Status {
  // 경우 1: 번역 파일이 존재하지 않음
  if (!translationFile.exists()) {
    return 'missing';
  }

  // 최종 수정 시간 획득
  const sourceLastModified = getLastCommitTime(sourceFile);
  const translationLastModified = getLastCommitTime(translationFile);

  // 경우 2: 번역이 원본보다 새거나 동기화됨
  if (translationLastModified >= sourceLastModified) {
    return 'done';
  }

  // 경우 3: 원본 파일이 번역보다 새로움
  return 'outdated';
}

Git 커밋 타임스탬프 분석

# 파일의 최종 수정 커밋 획득
$ git log -1 --format="%H %ct %s" -- docs/en/getting-started.md

abc1234567 1709123400 "Update getting-started documentation"

출력 분석:

  • %H: 전체 커밋 해시
  • %ct: Unix 타임스탬프
  • %s: 커밋 메시지

오래된 번역 감지 원리

타임스탬프 비교 전략

LunariaJS는 “최종 수정 시간” 전략을 사용해 번역이 오래되었는지 판단합니다:

타임라인 예시:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶
         │                      │                    │
      2월20일                2월25일               2월28일
         │                      │                    │
    한국어 번역 업데이트     영어 원본 업데이트     현재 시간
    (commit: def5678)      (commit: abc1234)
         │                      │
         └──────────────────────┘
                시간 차이 8일

             상태: 오래됨 🟡

왜 콘텐츠 비교를 사용하지 않나요?

git diff로 콘텐츠를 직접 비교하면 되지 않나요라고 물으실 수 있습니다.

콘텐츠 비교의 문제점:

  • 계산 비용이 높음 (각 파일을 읽고 파싱해야 함)
  • 구조가 같지만 내용이 다른 경우를 처리할 수 없음
  • 대규모 프로젝트에서 성능 영향이 큼

타임스탬프 비교의 장점:

  • 계산 비용이 낮음 (Git 메타데이터만 읽으면 됨)
  • 파일 크기에 영향받지 않는 안정적인 성능
  • 명확한 의미: 원본 파일이 업데이트되면 번역은 “오래됨”

특수 상황 처리

상황 1: 원본 파일과 번역이 동시에 업데이트됨

# 같은 커밋에서 원본 파일과 번역이 업데이트됨
$ git log --oneline -- docs/en/guide.md docs/ko/guide.md
abc1234 (HEAD) Update guide documentation

결과: 상태는 done

상황 2: 번역 파일만 업데이트됨

# 번역만 업데이트되고 원본 파일은 변경 없음
$ git log -1 -- docs/ko/guide.md
abc1234 (HEAD) Update Korean translation
$ git log -1 -- docs/en/guide.md
def5678 (HEAD~1) Original guide

결과: 상태는 done

상황 3: 포맷 조정이지만 내용에 영향 없음

# 원본 파일이 포맷 조정만 됨
$ git show abc1234 --stat
docs/en/guide.md | 2 +-
# 공백이나 줄바꿈만 조정

결과: 상태는 outdated ⚠️ (보수적 전략)

💡 이것은 LunariaJS의 보수적인 설계 선택입니다. 번역이 여전히 유효하다고 확신한다면 커밋 메시지에 [skip lunaria] 마커를 추가할 수 있습니다.

브랜치 전략과 현지화

메인 브랜치 번역 관리

대부분의 프로젝트는 메인 브랜치(main 또는 master)에서 번역을 관리합니다:

main

  ├── docs/en/           # 원본 언어 (영어)
  │   ├── index.md
  │   └── guide.md

  ├── docs/ko/           # 한국어 번역
  │   ├── index.md
  │   └── guide.md

  └── docs/ja/           # 일본어 번역
      ├── index.md
      └── guide.md

LunariaJS 설정:

{
  "sourceLanguage": "en",
  "languages": ["en", "ko", "ja"],
  "files": [
    {
      "sourcePath": "docs/en/{slug}.md",
      "localizationPath": "docs/{lang}/{slug}.md"
    }
  ]
}

기능 브랜치의 번역 처리

새로운 기능을 개발할 때는 보통 기능 브랜치를 생성합니다:

main

  └── feature/new-api-docs

        └── docs/en/api/new-endpoint.md  # 새 원본 파일

문제: 새로운 기능 브랜치의 번역은 어떻게 처리하나요?

전략 1: 기능 브랜치에서 번역하지 않음

  • 원본 파일은 먼저 기능 브랜치에서 완성
  • 메인 브랜치에 병합한 후 번역 시작
  • 장점: 번역 충돌 방지
  • 단점: 사용자가 누락된 번역을 봄

전략 2: 동시 번역

feature/new-api-docs

  ├── docs/en/api/new-endpoint.md
  ├── docs/ko/api/new-endpoint.md
  └── docs/ja/api/new-endpoint.md
  • 장점: 기능 출시 시 번역도 동시에 완료
  • 단점: 번역 시간 조율 필요

전략 3: 초안 마커 사용

---
title: New API Endpoint
draft: true  # 초안으로 표시, 공개 사이트에 표시하지 않음
---
  • 원본 파일 완성 후 초안 마커 제거
  • 번역 파일도 초안 마커 사용 가능

병합 시 번역 충돌 해결

원본 파일 업데이트와 번역 업데이트가 충돌할 때:

# 시나리오: 메인 브랜치에서 원본 파일이 업데이트되고, PR 브랜치에서 번역이 업데이트됨
$ git merge feature/update-ko-translation
CONFLICT (content): Merge conflict in docs/ko/guide.md

해결 단계:

  1. 충돌 내용 식별
<<<<<<< HEAD
이것은 메인 브랜치의 업데이트된 내용입니다
=======
이것은 번역 브랜치의 내용입니다
>>>>>>> feature/update-ko-translation
  1. 충돌 성격 평가

    • 번역 관련 콘텐츠인가요?
    • 원본 파일에 어떤 변경이 있었나요?
  2. 충돌 해결

    • 번역 업데이트인 경우: 번역 브랜치의 내용 유지
    • 원본 파일에 새 콘텐츠가 있는 경우: 병합 후 다시 번역
  3. 번역 일관성 검증

# 대시보드 빌드로 상태 확인
npx lunaria build --verbose

팀 협업 워크플로우

번역 기여자 워크플로우

시나리오: 커뮤니티 기여자가 번역을 돕고 싶음

단계 1: 대시보드 확인

프로젝트의 LunariaJS 대시보드에 접속하여 번역이 필요한 파일을 찾습니다.

단계 2: Fork하고 브랜치 생성

# 프로젝트 Fork 후
git clone https://github.com/your-username/project-name.git
cd project-name
git checkout -b translate/ko-guide

단계 3: 파일 번역

# 번역 파일 생성 또는 업데이트
# docs/ko/guide.md

단계 4: 커밋하고 PR 생성

git add docs/ko/guide.md
git commit -m "Translate guide to Korean"
git push origin translate/ko-guide

단계 5: PR 리뷰

유지보수자가 번역 품질과 정확성을 리뷰합니다.

코드 리뷰에서의 번역 검사

PR 리뷰 시 번역 상태 검사를 추가할 수 있습니다:

# .github/workflows/translation-check.yml
name: Translation Check

on: [pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 전체 히스토리 획득

      - name: Build Lunaria Dashboard
        run: |
          npm ci
          npx lunaria build

      - name: Check Translation Status
        run: |
          # 새로운 누락된 번역이 있는지 확인
          node scripts/check-new-missing.js

번역 업데이트 PR 흐름

자동화된 흐름:

원본 파일 업데이트


CI가 오래된 번역 감지


번역 업데이트 Issue 생성


번역 기여자가 작업 할당


번역 업데이트 PR 제출


리뷰 및 병합


대시보드 업데이트 ✅

Issue 자동 생성 예시

다수의 오래된 번역이 감지되면 자동으로 Issue를 생성할 수 있습니다:

## 🌙 번역 동기화 알림

### 개요
- 오래된 번역 수: 12
- 영향받는 언어: 한국어 (5), 일본어 (4), 중국어 (3)

### 업데이트가 필요한 파일

| 파일 | 언어 | 뒤처진 일수 |
|------|------|----------|
| getting-started.md | 한국어 | 8 |
| configuration.md | 일본어 | 5 |
| api/overview.md | 중국어 | 3 |

### 조치
각 번역 기여자분은 관련 번역을 할당받아 업데이트해 주세요.

---
*이 Issue는 LunariaJS에 의해 자동 생성되었습니다*

Git 통합 모범 사례

1. 적절한 커밋 단위 유지

추천 방식:

# 각 번역 파일을 별도로 커밋
git add docs/ko/guide.md
git commit -m "Translate guide to Korean"

# 또는 관련 파일을 함께 커밋
git add docs/ko/
git commit -m "Update Korean translations for v2.0"

비추천:

# 소스 코드와 번역을 혼합한 커밋
git add .
git commit -m "Various updates"

2. 의미 있는 커밋 메시지 사용

추천 형식:

[i18n/ko] Translate guide.md

- Translate introduction section
- Update code examples
- Fix terminology consistency

Related: #123

3. Git Blame으로 번역 히스토리 추적

# 번역 파일의 수정 히스토리 보기
git blame docs/ko/guide.md

# 특정 라인의 최종 수정 보기
git blame -L 10,20 docs/ko/guide.md

4. Git Hooks로 자동화

# pre-commit hook
#!/bin/bash

# 원본 파일이 업데이트되었지만 번역이 업데이트되지 않았는지 확인
npm run lunaria:check-outdated

if [ $? -ne 0 ]; then
  echo "Warning: Some translations are outdated!"
  echo "Run 'npx lunaria build' to see details."
fi

5. .gitattributes 설정

# .gitattributes
# 번역 파일의 언어 표시
docs/ko/*.md linguist-language=Markdown
docs/ja/*.md linguist-language=Markdown

# git diff에서 변경 사항을 더 잘 표시
*.md text eol=lf

고급 Git 통합 팁

1. Git 별칭으로 작업 단순화

# ~/.gitconfig
[alias]
    lunaria = "!f() { npx lunaria \"$@\"; }; f"
    i18n-status = "!f() { npx lunaria build && npx lunaria preview; }; f"

사용:

git lunaria build
git i18n-status

2. 다중 저장소 번역 관리

Monorepo 프로젝트의 경우:

{
  "files": [
    {
      "sourcePath": "packages/core/docs/{slug}.md",
      "localizationPath": "packages/core/i18n/{lang}/{slug}.md"
    },
    {
      "sourcePath": "packages/cli/docs/{slug}.md",
      "localizationPath": "packages/cli/i18n/{lang}/{slug}.md"
    }
  ]
}

3. 서브모듈로 번역 관리

# 번역 서브모듈 추가
git submodule add https://github.com/org/translations.git i18n

# 번역 업데이트
git submodule update --remote i18n

4. 번역 브랜치 전략

main

  ├── i18n/ko    # 한국어 번역 브랜치

  ├── i18n/ja    # 일본어 번역 브랜치

  └── i18n/zh-cn # 중국어 번역 브랜치

각 번역 브랜치는 해당 언어 유지보수자가 관리하며, 정기적으로 메인 브랜치에 병합됩니다.

일반적인 문제와 해결 방법

Q1: Git 히스토리가 불완전하여 상태 오류

문제: 얕은 복제(shallow clone)에 전체 히스토리가 없음.

해결 방법:

# 전체 히스토리 획득
git fetch --unshallow

# 또는 CI에서 설정
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # 전체 히스토리

Q2: 대용량 파일 번역 추적 성능 문제

문제: 프로젝트 파일이 너무 많아 빌드가 느림.

해결 방법:

{
  "files": [
    {
      "sourcePath": "docs/{slug}.md",
      "localizationPath": "i18n/{lang}/docs/{slug}.md",
      "include": ["**/*.md"],
      "exclude": ["**/draft/**", "**/internal/**"]
    }
  ]
}

Q3: 파일 이름 변경 후 상태 손실

문제: 파일 이름 변경 후 Git 히스토리 추적이 끊김.

해결 방법:

# git mv를 사용해 히스토리 보존
git mv docs/old-name.md docs/new-name.md

요약

LunariaJS와 Git의 깊은 통합은 강력한 현지화 관리 능력을 제공합니다:

특성가치
타임스탬프 비교오래된 번역 자동 감지
추가 마커 불필요파일을 깔끔하게 유지
팀 협업기존 워크플로우에 통합
히스토리 추적각 변경을 추적 가능
CI/CD 통합자동화된 번역 검사

핵심 포인트:

  • Git 커밋 시간은 번역 상태를 판단하는 핵심 기준
  • 의미 있는 워크플로우로 브랜치와 병합 처리
  • CI/CD로 자동화된 번역 상태 검사 활용
  • 추적을 위해 좋은 커밋 습관 유지

다음 단계

다음 글에서는 LunariaJS와 Astro Starlight의 완벽한 통합을 살펴보고, 다음 방법을 배우겠습니다:

  • @lunariajs/starlight 설치 및 설정
  • 문서 사이트에 대시보드 임베드
  • 삼국어 문서 사이트 구축 실전
  • 일반적인 통합 문제 해결

기대해 주세요!


💡 추천 읽기: