LunariaJS + Git: 버전 관리 기반 현지화 워크플로우
LunariaJS가 Git을 활용해 현지화 변경 사항을 추적하는 방법을 설명하고, 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
해결 단계:
- 충돌 내용 식별
<<<<<<< HEAD
이것은 메인 브랜치의 업데이트된 내용입니다
=======
이것은 번역 브랜치의 내용입니다
>>>>>>> feature/update-ko-translation
-
충돌 성격 평가
- 번역 관련 콘텐츠인가요?
- 원본 파일에 어떤 변경이 있었나요?
-
충돌 해결
- 번역 업데이트인 경우: 번역 브랜치의 내용 유지
- 원본 파일에 새 콘텐츠가 있는 경우: 병합 후 다시 번역
-
번역 일관성 검증
# 대시보드 빌드로 상태 확인
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 설치 및 설정
- 문서 사이트에 대시보드 임베드
- 삼국어 문서 사이트 구축 실전
- 일반적인 통합 문제 해결
기대해 주세요!
💡 추천 읽기: