블로그

LunariaJS CI/CD 통합: 현지화 워크플로우 자동화하기

LunariaJS를 GitHub Actions, GitLab CI 등 CI/CD 플랫폼에 통합하여 번역 상태 자동 검사, 대시보드 자동 빌드 및 게시를 구현하고, 현지화 워크플로우를 완전히 자동화하는 방법을 배웁니다.

LibDoc Team 2026년 3월 6일 LunariaJS 칼럼 42 분 읽기
#LunariaJS #CI/CD #GitHub Actions #자동화 #지속적 통합

LunariaJS CI/CD 통합: 현지화 워크플로우 자동화하기

앞선 글들에서는 LunariaJS의 핵심 기능, Git 워크플로우, Astro Starlight 통합을 배웠습니다. 오늘은 현지화 워크플로우를 한 단계 더 높여 CI/CD를 통한 완전한 자동화를 구현해 보겠습니다.

💡 공식 문서: LunariaJS 한국어 문서 - CI/CD

CI/CD 통합의 가치

왜 자동화가 필요한가요?

CI/CD 통합 없이 현지화를 관리하면 다음 문제가 발생합니다:

문제영향
수동으로 번역 상태 확인시간이 많이 걸리고 누락 발생
대시보드 업데이트 불적시팀이 최신 상태를 볼 수 없음
번역 문제 발견 지연출시 후 번역 누락 발견
자동화된 알림 부족기여자가 번역이 필요한지 모름

지속적 현지화 개념

지속적 현지화(Continuous Localization) 는 번역 작업을 CI/CD 파이프라인에 통합하는 실천입니다:

코드 커밋 → 자동 감지 번역 변경 → 대시보드 업데이트 → 관련자 알림 → 게시

핵심 가치:

  • 즉각적 피드백: 매 커밋마다 번역 상태 파악
  • 자동화: 수동 작업 최소화, 효율성 향상
  • 시각화: 팀이 언제든 번역 진행 상황 확인
  • 품질 보장: 출시 전 번역 완전성 확인

GitHub Actions 통합

기본 워크플로우 설정

.github/workflows/lunaria.yml 생성:

name: Lunaria Dashboard

on:
  push:
    branches: [main]
    paths:
      - 'docs/**'
      - 'i18n/**'
      - 'lunaria.config.json'
  pull_request:
    branches: [main]
  workflow_dispatch:  # 수동 트리거

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 전체 Git 히스토리 획득

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build Lunaria Dashboard
        run: npx lunaria build

      - name: Upload dashboard artifact
        uses: actions/upload-artifact@v4
        with:
          name: lunaria-dashboard
          path: lunaria-dashboard/
          retention-days: 7

GitHub Pages에 자동 게시

대시보드를 자동으로 GitHub Pages에 배포합니다:

name: Deploy Lunaria Dashboard

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build main site
        run: npm run build

      - name: Build Lunaria Dashboard
        run: npx lunaria build

      - name: Setup Pages
        uses: actions/configure-pages@v4

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: './dist'

      - name: Deploy to GitHub Pages
        uses: actions/deploy-pages@v4

PR 번역 상태 검사

Pull Request에서 자동으로 번역 상태를 검사합니다:

name: Translation Check

on:
  pull_request:
    branches: [main]

jobs:
  check-translations:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build Lunaria Dashboard
        run: npx lunaria build --silent

      - name: Check for missing translations
        id: check
        run: |
          # 대시보드 데이터 파싱, 새로운 누락된 번역이 있는지 확인
          MISSING=$(node scripts/check-new-missing.js)
          echo "missing=$MISSING" >> $GITHUB_OUTPUT

      - name: Comment on PR
        if: steps.check.outputs.missing != ''
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## 🌙 Translation Status Update\n\n${{ steps.check.outputs.missing }}`
            })

GitLab CI 통합

기본 설정

.gitlab-ci.yml 생성:

# .gitlab-ci.yml
stages:
  - check
  - build
  - deploy

variables:
  NODE_VERSION: '20'

# 캐시 설정
.node-cache:
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/

# 번역 상태 확인
lunaria-check:
  stage: check
  extends: .node-cache
  image: node:${NODE_VERSION}
  script:
    - npm ci
    - npx lunaria build
  artifacts:
    paths:
      - lunaria-dashboard/
    expire_in: 1 week
  only:
    - merge_requests
    - main

# 빌드 및 배포
lunaria-deploy:
  stage: deploy
  image: node:${NODE_VERSION}
  needs:
    - lunaria-check
  script:
    - echo "Deploying Lunaria dashboard..."
  only:
    - main

GitLab Pages 통합

# .gitlab-ci.yml
image: node:20

stages:
  - deploy

pages:
  stage: deploy
  script:
    - npm ci
    - npm run build
    - npx lunaria build
    - mv lunaria-dashboard public
  artifacts:
    paths:
      - public
  only:
    - main

자동화 작업 설계

번역 완전성 검사

사용자 정의 검사 스크립트 scripts/check-new-missing.js 생성:

// scripts/check-new-missing.js
const fs = require('fs');
const path = require('path');

function checkMissingTranslations() {
  const statusPath = path.join('lunaria-dashboard', 'data', 'status.json');

  if (!fs.existsSync(statusPath)) {
    console.log('No status file found');
    return '';
  }

  const status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));

  const missing = [];
  for (const [lang, data] of Object.entries(status.languages)) {
    if (data.missing > 0) {
      missing.push({
        language: lang,
        count: data.missing
      });
    }
  }

  if (missing.length === 0) {
    return '✅ All translations are up to date!';
  }

  let report = '### ⚠️ Missing Translations Found\n\n';
  for (const item of missing) {
    report += `- **${item.language}**: ${item.count} missing files\n`;
  }

  return report;
}

console.log(checkMissingTranslations());

알림 및 보고

Slack 알림

- name: Notify Slack
  if: always()
  uses: slackapi/slack-github-action@v1
  with:
    channel-id: 'C0123456789'
    payload: |
      {
        "text": "Lunaria Dashboard Update",
        "attachments": [
          {
            "color": "${{ job.status == 'success' && 'good' || 'danger' }}",
            "fields": [
              {
                "title": "Status",
                "value": "${{ job.status }}",
                "short": true
              }
            ]
          }
        ]
      }
  env:
    SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

PR 댓글 봇

- name: Comment on PR
  uses: actions/github-script@v7
  with:
    script: |
      const status = require('./lunaria-dashboard/data/status.json');

      let body = '## 🌙 Translation Status\n\n';
      body += '| Language | Done | Outdated | Missing | Progress |\n';

      for (const [lang, data] of Object.entries(status.languages)) {
        const progress = Math.round((data.done / data.total) * 100);
        body += `| ${lang} | ${data.done} | ${data.outdated} | ${data.missing} | ${progress}% |\n`;
      }

      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: body
      });

CI/CD 모범 사례

1. 조건부 트리거

on:
  push:
    branches: [main]
    paths:
      - 'docs/**'
      - 'i18n/**'
      - 'lunaria.config.json'

2. 캐시 최적화

- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

3. 실패 전략

jobs:
  check:
    continue-on-error: true

  deploy:
    needs: check
    if: always() && needs.check.result == 'success'

요약

CI/CD 통합을 통해 LunariaJS는 완전히 자동화된 현지화 워크플로우를 구현할 수 있습니다:

기능구현
자동 감지 번역 변경GitHub Actions / GitLab CI
자동 빌드 대시보드매 커밋 트리거
자동 게시GitHub Pages / GitLab Pages
자동 알림Slack / Email / PR 댓글

핵심 포인트:

  • fetch-depth: 0을 사용해 전체 Git 히스토리 획득
  • 조건부 트리거로 불필요한 빌드 최소화
  • 캐시를 활용해 CI 속도 향상

다음 단계

LunariaJS 입문 시리즈를 완료하신 것을 축하드립니다! 다음 글부터는 심화 편에 들어갑니다:

  • 제 8 편: @lunariajs/core 소스 코드 분석
  • 제 9 편: 고급 설정 및 사용자 정의 전략
  • 제 10 편: 완전한 기업급 실전

기대해 주세요!


💡 추천 읽기: