Projects About

기술 블로그를 AI로 다국적화하는 자동 발행 파이프라인 구축기

블로그를 영어로도 발행하려다 보니 번역과 발행 과정이 너무 번거로웠다. 그래서 AI와 GitHub Actions로 완전 자동화된 파이프라인을 만들었다. 이 글에서는 어떻게 Claude를 활용해서 콘텐츠를 다국화하고, 여러 플랫폼에 자동 발행하는 시스템을 구축했는지 다룬다.

배경: 무엇을 만들고 있는가

개발 관련 블로그를 한국어로 쓰고 있었는데, 해외 독자들에게도 도달하고 싶었다. 문제는 번역과 발행이 수작업이라는 점이었다. DEV.to, Hashnode, Medium 등 여러 플랫폼에 발행하려면 각각 다른 포맷에 맞춰서 올려야 했다.

이번 작업의 목표는 명확했다:

  • 한국어 글을 영어로 자동 번역
  • 여러 플랫폼에 자동 발행
  • 저품질 콘텐츠는 자동으로 정리
  • 모든 과정을 GitHub Actions로 자동화

AI로 기술 블로그 번역하기 — 톤앤매너가 핵심이다

기술 블로그 번역에서 가장 중요한 건 단순한 언어 변환이 아니라 독자층에 맞는 톤앤매너 변경이다.

효과적인 번역 프롬프트 패턴

이렇게 프롬프트를 구성했다:

“다음 한국어 기술 블로그 글을 영어로 번역해줘. 단순 번역이 아니라 해외 개발자 커뮤니티에 맞는 톤으로 다시 써줘.

조건:

  • 반말을 자연스러운 영어 어투로 바꿔줘 (단정적이지만 친근한 느낌)
  • 한국 특유의 맥락은 글로벌 독자가 이해할 수 있게 설명 추가
  • 코드/CLI 명령어/파일명은 그대로 유지
  • 기술 용어는 번역하지 말고 원어 사용
  • frontmatter의 slug는 영어로, 나머지 메타데이터는 유지

[원문 내용]”

이렇게 쓰면 안 된다:

“영어로 번역해줘”

차이점은 명확하다. 첫 번째 프롬프트는 번역의 목적과 제약 조건을 구체화했다. 특히 기술 블로그의 특성상 코드와 메타데이터 처리 방식을 명시한 게 핵심이다.

Claude Code의 배치 처리 활용

여러 글을 한번에 번역할 때는 Claude Code의 codebase 기능을 활용했다:

find posts -name "*-ko.md" | head -5 | xargs -I {} basename {} -ko.md

이렇게 파일 목록을 뽑은 다음, Claude에게 각 파일을 읽어서 번역하라고 지시했다. 중요한 건 일관성 유지를 위한 제약 조건을 매번 반복해서 제공한 것이다.

각 파일마다 다음 규칙을 적용해:
1. 파일명에서 -ko 제거하고 -en 추가
2. frontmatter의 date는 그대로, slug만 영어로
3. 본문의 톤은 기존 영어 글들과 일치시켜

번역 품질 검증 자동화

번역된 글의 품질을 확인하기 위해 간단한 체크리스트를 만들었다:

“번역된 글을 검토해줘. 다음 항목들을 체크해:

  • 코드 블록이 깨지지 않았는가
  • 링크가 여전히 유효한가
  • frontmatter 형식이 올바른가
  • 전문 용어가 일관되게 사용되었는가
  • 한국어 특유의 표현이 자연스럽게 바뀌었는가”

이 패턴을 쓰니까 번역 후 수정 작업이 대폭 줄어들었다.

GitHub Actions로 플랫폼별 자동 발행 구축하기

각 플랫폼마다 API 특성이 다르다. DEV.to는 간단하지만 Hashnode는 GraphQL이고, Medium은 OAuth 토큰 관리가 복잡하다.

플랫폼별 필터링 전략

모든 글을 모든 플랫폼에 올릴 필요는 없다. 이런 규칙을 적용했다:

- name: Filter posts for platform
  run: |
    # DEV.to: 한국어 글과 build-log는 제외
    find posts -name "*.md" \
      ! -name "*-ko.md" \
      ! -name "*build-log*" \
      -exec echo {} \;

이렇게 필터링하는 이유:

  • 한국어 글은 DEV.to의 주 독자층에 맞지 않음
  • build-log 시리즈는 너무 개인적이어서 글로벌 플랫폼에는 부적절
  • contextual relevance를 고려한 선별적 발행이 engagement 향상에 도움

API 에러 핸들링 패턴

각 플랫폼의 API는 서로 다른 방식으로 에러를 낸다. 공통 패턴을 찾아서 처리 로직을 표준화했다:

publish_to_devto() {
  response=$(curl -s -w "%{http_code}" \
    -H "api-key: $DEVTO_API_KEY" \
    -H "Content-Type: application/json" \
    -d "$payload" \
    https://dev.to/api/articles)
  
  http_code="${response: -3}"
  body="${response%???}"
  
  if [ "$http_code" -ge 400 ]; then
    echo "DEV.to API error: $body"
    return 1
  fi
}

중요한 건 각 API의 rate limiting과 중복 체크 로직을 이해하는 것이다. DEV.to는 같은 제목의 글이 있으면 업데이트하고, Hashnode는 새 글을 만든다.

메타데이터 동기화

발행된 글의 URL을 다시 원본 파일에 기록하는 로직이 필요했다:

# 발행 후 URL을 frontmatter에 추가
sed -i "/^published_urls:/d" "$file"
echo "published_urls:" >> "$file"
echo "  devto: $devto_url" >> "$file"  
echo "  hashnode: $hashnode_url" >> "$file"

이렇게 하면 나중에 어떤 글이 어디 발행됐는지 추적할 수 있다.

콘텐츠 품질 관리 — 데이터 기반 정리 전략

블로그가 늘어나면서 저품질 콘텐츠도 쌓인다. 이걸 수동으로 관리하기엔 너무 번거로워서 자동화했다.

성과 기반 콘텐츠 정리

DEV.to API로 글의 조회수와 반응을 가져와서 기준 이하 글들을 자동으로 unpublish한다:

cleanup_low_performance() {
  articles=$(curl -s -H "api-key: $DEVTO_API_KEY" \
    "https://dev.to/api/articles/me/published")
  
  echo "$articles" | jq -r '.[] | 
    select(.page_views_count < 50 and .positive_reactions_count < 5) | 
    select(.title | contains("build-log") or contains("news")) |
    .id' | while read id; do
      unpublish_article "$id"
  done
}

이 로직의 핵심은 카테고리별 다른 기준 적용이다. build-log나 news 글은 시의성이 중요해서 조회수가 낮으면 빨리 정리하고, 기술 튜토리얼은 롱테일 효과가 있어서 보존한다.

AI로 콘텐츠 품질 평가

Claude에게 글의 품질을 평가하게 하는 프롬프트도 만들었다:

“다음 기술 블로그 글을 평가해줘:

기준:

  • 기술적 정확성 (1-10)
  • 실용성 (1-10)
  • 가독성 (1-10)
  • 시의성 (1-10)

7점 미만 항목이 2개 이상이면 ‘CLEANUP’ 추천 그 외에는 ‘KEEP’ 추천

[글 내용]”

아직 완전 자동화하지는 않고 참고용으로만 쓰지만, 나중에는 이 평가도 자동 정리 기준에 포함할 계획이다.

더 나은 방법은 없을까

현재 파이프라인을 구축하면서 발견한 개선점들이 있다.

번역 품질 향상

Anthropic의 최신 문서를 보면 few-shot prompting이 번역 일관성에 더 좋다고 한다. 현재는 zero-shot으로 번역하는데, 좋은 번역 사례 2-3개를 프롬프트에 포함하면 품질이 올라갈 것 같다.

또한 Claude의 Constitutional AI를 활용해서 번역 과정에서 편향이나 부적절한 표현을 자동으로 걸러낼 수 있다:

번역 시 다음 원칙을 지켜줘:
1. 성별/국가/문화에 대한 편향 없이
2. 포용적인 언어 사용
3. 접근성을 고려한 표현

플랫폼 API 최적화

현재는 각 플랫폼을 순차적으로 처리하는데, parallel publishing으로 시간을 단축할 수 있다. GitHub Actions의 matrix strategy를 쓰면 된다:

strategy:
  matrix:
    platform: [devto, hashnode, medium]

다만 API rate limiting 때문에 너무 aggressive하게 하면 안 된다.

MCP 서버 활용

Claude의 Model Context Protocol을 쓰면 더 정교한 콘텐츠 관리가 가능하다. 예를 들어 Git 히스토리를 분석해서 어떤 글이 자주 수정되는지 파악하고, 그런 글들을 우선적으로 번역하는 로직을 만들 수 있다.

성과 분석 고도화

현재는 단순한 조회수 기반이지만, Google Analytics나 각 플랫폼의 상세 메트릭을 종합해서 더 정교한 성과 평가를 할 수 있다. 특히 conversion rate(글 읽기 → 팔로우/구독)를 추적하면 콘텐츠 전략에 더 도움이 될 것이다.

정리

이번 작업에서 배운 핵심 포인트들:

  • AI 번역은 단순 언어 변환이 아니라 톤앤매너 적응이 핵심이다
  • GitHub Actions로 복잡한 multi-platform 발행도 충분히 자동화할 수 있다
  • 콘텐츠 품질 관리는 수동이 아닌 데이터 기반 자동화가 효율적이다
  • 각 플랫폼의 API 특성을 이해하고 맞춤형 전략을 세워야 한다
이번 작업의 커밋 로그

fab9e97 — chore: update published articles [skip ci] a0152a7 — fix: 제목에 한국어 포함되면 DEV.to 발행 스킵 38d0fc8 — post: contextzip launch - Claude Code built its own tool ece75e5 — post: build logs 2026-03-19 (2 posts, en) 244fbcf — post: build logs 2026-03-19 (2 posts, en) e4c1443 — chore: update published articles [skip ci] 3067d14 — chore: update published articles [skip ci] e14fd1b — post: build logs 2026-03-19 (2 posts, en) be69eca — chore: update published articles [skip ci] b872ce0 — post: build logs 2026-03-19 (2 posts, en) be9979b — chore: update published articles [skip ci] 3ffefc9 — fix: DEV.to에 한국어(-ko.md) 파일 발행 스킵 05e904e — post: build logs 2026-03-18 (2 posts, en) 4de9884 — post: build logs 2026-03-18 (2 posts, en) 2bb1330 — post: build logs 2026-03-18 (2 posts, en) d455bdf — chore: update published articles [skip ci] 2ac70e2 — chore: update published articles [skip ci] 1a019c3 — post: build logs 2026-03-18 (2 posts, en) 7f105fb — chore: update published articles [skip ci] 0665de4 — post: build logs 2026-03-17 (2 posts, en) 90f8079 — chore: update published articles [skip ci] d307780 — post: build logs 2026-03-17 (1 posts, en)

Comments 0

0 / 1000