본문 바로가기
AI API 활용

AI API로 자동 번역기 만들기 - 파파고보다 나은 결과물

by 소개왕 탑백귀 2026. 4. 5.

AI API로 자동 번역기 만들기 - 파파고보다 나은 결과물

2026년 4월 기준 | AI API 활용 · 파이썬 번역기 구현

요약: 파파고, GPT API, Claude API로 동일한 텍스트를 번역하고 품질을 비교했습니다. 기술문서, 구어체, 전문용어 세 가지 유형으로 나눠서 테스트한 결과와, 파이썬으로 배치 번역기를 구현하는 전체 코드를 공유합니다.

파파고 대신 AI API를 쓰게 된 이유

저는 원래 파파고를 많이 썼습니다. 영어 기술 블로그를 읽을 때, 공식 문서를 참고할 때, 파파고 크롬 확장을 켜놓고 드래그 번역을 하면 대부분 해결됐습니다.

문제가 생긴 건 회사에서 API 문서를 한국어로 옮기는 작업을 맡으면서였습니다. 파파고에 넣으면 이런 결과가 나옵니다:

원문: "The endpoint returns a paginated list of resources. Use the cursor parameter to iterate through results."

파파고: "끝점은 페이지로 나뉜 리소스 목록을 반환합니다. 결과를 반복하려면 커서 매개 변수를 사용하십시오."

Claude: "이 엔드포인트는 페이지네이션된 리소스 목록을 반환합니다. cursor 파라미터를 사용해 결과를 순회할 수 있습니다."

차이가 느껴지시나요? 파파고는 "끝점", "매개 변수", "반복하려면"처럼 직역합니다. 개발자가 읽기엔 어색합니다. Claude는 엔드포인트, 파라미터, 순회처럼 개발자가 실제로 쓰는 용어를 그대로 씁니다. 이게 단순 번역기와 LLM 번역의 결정적 차이입니다.

이걸 경험하고 나서 "아, API 문서나 기술 블로그 번역은 AI API가 압도적이겠다"는 확신이 들었고, 실제로 번역 파이프라인을 만들어 쓰기 시작했습니다.

GPT, Claude 번역 코드 구현

라이브러리 설치

pip install openai anthropic

Claude API로 번역하기

먼저 Claude API를 이용한 번역 함수입니다. 핵심은 시스템 프롬프트에 번역 규칙을 명확하게 잡아주는 것입니다.

import anthropic

client = anthropic.Anthropic()  # ANTHROPIC_API_KEY 환경변수 필요

def translate_with_claude(text: str, source: str = "en", target: str = "ko") -> str:
    system_prompt = f"""당신은 전문 기술 번역가입니다.
다음 규칙을 따라 {source}를 {target}로 번역하세요:

1. 개발 용어는 한국 개발자가 실제 사용하는 표현을 씁니다
   - endpoint → 엔드포인트, parameter → 파라미터, deploy → 배포
2. 코드 블록, 변수명, 함수명은 번역하지 않고 원문 유지합니다
3. 마크다운 포맷이 있으면 그대로 유지합니다
4. 존댓말(~합니다)로 통일합니다
5. 번역문만 출력하고, 설명이나 주석을 추가하지 않습니다"""

    message = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        system=system_prompt,
        messages=[
            {"role": "user", "content": text}
        ]
    )
    return message.content[0].text

GPT API로 번역하기

GPT 쪽도 동일한 프롬프트를 사용해서 공정하게 비교합니다.

import openai

gpt_client = openai.OpenAI()  # OPENAI_API_KEY 환경변수 필요

def translate_with_gpt(text: str, source: str = "en", target: str = "ko") -> str:
    system_prompt = f"""당신은 전문 기술 번역가입니다.
다음 규칙을 따라 {source}를 {target}로 번역하세요:

1. 개발 용어는 한국 개발자가 실제 사용하는 표현을 씁니다
   - endpoint → 엔드포인트, parameter → 파라미터, deploy → 배포
2. 코드 블록, 변수명, 함수명은 번역하지 않고 원문 유지합니다
3. 마크다운 포맷이 있으면 그대로 유지합니다
4. 존댓말(~합니다)로 통일합니다
5. 번역문만 출력하고, 설명이나 주석을 추가하지 않습니다"""

    response = gpt_client.chat.completions.create(
        model="gpt-4o",
        temperature=0,
        max_tokens=4096,
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": text}
        ]
    )
    return response.choices[0].message.content

번역 품질을 좌우하는 프롬프트 설계

번역 품질의 80%는 프롬프트에서 결정됩니다. 제가 수십 번 시행착오를 거치면서 찾은 핵심 포인트를 공유합니다.

1. 용어집(Glossary)을 프롬프트에 포함시키기

이게 가장 효과가 큽니다. 번역 일관성이 확 올라갑니다.

glossary = {
    "authentication": "인증",
    "authorization": "인가",
    "middleware": "미들웨어",
    "dependency injection": "의존성 주입",
    "rate limiting": "요청 제한",
    "payload": "페이로드",
    "schema": "스키마",
    "deprecated": "지원 중단 예정",
}

glossary_text = "\n".join([f"- {k} → {v}" for k, v in glossary.items()])

system_prompt = f"""전문 기술 번역가로서 번역하세요.

[용어집 - 반드시 아래 번역을 따르세요]
{glossary_text}

용어집에 없는 기술 용어는 한국 개발자 커뮤니티에서
통용되는 표현을 사용하세요."""

용어집 없이 번역하면 같은 문서 안에서 "인증"과 "인가"가 뒤섞이거나, "authentication"이 어떤 문단에서는 "인증"이고 다른 문단에서는 "확인"으로 바뀌는 일이 생깁니다. 용어집을 넣으면 이 문제가 거의 사라집니다.

2. 번역 대상의 맥락을 알려주기

같은 영어 단어라도 맥락에 따라 번역이 달라져야 합니다. "table"이 데이터베이스 문맥이면 "테이블"이고, HTML 문맥이면 "표"입니다. 프롬프트에 문서의 분야를 명시하면 정확도가 올라갑니다.

system_prompt = """이 텍스트는 PostgreSQL 공식 문서의 일부입니다.
데이터베이스 관련 용어는 한국 DBA 커뮤니티에서 통용되는
표현을 사용하세요.
- query → 쿼리
- table → 테이블
- index → 인덱스
- constraint → 제약조건
- transaction → 트랜잭션"""

3. 구어체 번역은 톤을 지정하기

기술문서가 아니라 유튜브 자막이나 블로그 글을 번역할 때는 톤이 중요합니다.

system_prompt = """친근한 개발 블로그 글을 번역합니다.
- 딱딱한 경어 대신 '~해요' 체를 사용하세요
- 영어 감탄사(Oh, Well, Actually)는 한국식으로 바꾸세요
  예: "Well, actually..." → "사실은요,"
- 유머나 비유가 있으면 한국 독자에게 통하도록 의역하세요
- 원문의 가벼운 톤을 유지하세요"""

이 프롬프트를 쓰면 "Well, this is where things get interesting"이 "자, 여기서부터 재밌어져요"로 번역됩니다. 파파고에 넣으면 "글쎄, 여기서 상황이 흥미로워집니다"가 되죠. 어느 쪽이 블로그 글에 어울리는지는 명확합니다.

파파고 vs GPT vs Claude 번역 품질 비교

말로만 하면 설득력이 없으니, 실제로 세 가지 유형의 텍스트를 번역해서 비교했습니다.

테스트 1: 기술문서 번역

"To implement rate limiting, configure the middleware with a sliding window algorithm. The default threshold is 100 requests per minute per API key. Exceeding this limit returns a 429 status code with a Retry-After header."

서비스 번역 결과 점수
파파고 속도 제한을 구현하려면 슬라이딩 윈도우 알고리즘으로 미들웨어를 구성합니다. 기본 임계값은 API 키당 분당 100개의 요청입니다. 이 제한을 초과하면 Retry-After 헤더가 포함된 429 상태 코드가 반환됩니다. 6/10
GPT-4o 요청 제한을 구현하려면 슬라이딩 윈도우 알고리즘을 사용하여 미들웨어를 설정하세요. 기본 임계값은 API 키당 분당 100회 요청입니다. 이 한도를 초과하면 Retry-After 헤더가 포함된 429 상태 코드가 반환됩니다. 8/10
Claude 요청 제한(Rate Limiting)을 구현하려면, 슬라이딩 윈도우 알고리즘으로 미들웨어를 설정합니다. 기본 임계값은 API 키당 분당 100건입니다. 이 제한을 초과하면 Retry-After 헤더가 포함된 429 상태 코드가 반환됩니다. 9/10

분석: Claude가 "Rate Limiting"을 병기한 것이 눈에 띕니다. 기술문서를 읽는 사람은 원문 용어도 같이 보고 싶어하는데, 이걸 자동으로 해줍니다. 또한 코드 관련 용어(429, Retry-After)를 코드 포맷으로 처리한 것도 좋습니다.

테스트 2: 구어체 (개발 블로그)

"Honestly, I was skeptical about Rust at first. Like, why would I give up the convenience of Python's garbage collector? But after rewriting our hot path in Rust, the latency dropped by 40%. I'm a convert now."

서비스 번역 결과 점수
파파고 솔직히 처음에는 Rust에 대해 회의적이었습니다. Python의 가비지 컬렉터의 편리함을 왜 포기하겠습니까? 하지만 핫 경로를 Rust로 다시 작성한 후 지연 시간이 40% 감소했습니다. 저는 이제 전향자입니다. 4/10
GPT-4o 솔직히 처음에는 Rust에 대해 회의적이었어요. Python의 가비지 컬렉터가 주는 편리함을 왜 포기해야 하죠? 하지만 핫 패스를 Rust로 다시 작성하고 나니, 레이턴시가 40% 줄었어요. 이제 완전히 전향했습니다. 7/10
Claude 솔직히 처음엔 Rust를 반신반의했어요. Python 가비지 컬렉터의 편안함을 뭐하러 버리나 싶었거든요. 그런데 핫 패스를 Rust로 다시 짜고 나니 레이턴시가 40%나 줄더라고요. 지금은 완전히 넘어갔습니다. 9/10

분석: 구어체에서 차이가 극적입니다. 파파고의 "왜 포기하겠습니까?"는 논문 톤이고, "전향자입니다"는 어색합니다. Claude는 "뭐하러 버리나 싶었거든요", "줄더라고요"처럼 실제 한국어 구어체를 자연스럽게 구사합니다.

테스트 3: 전문용어가 밀집된 텍스트

"The CI/CD pipeline triggers on every push to main. It runs unit tests, performs SAST scanning, builds a Docker image, pushes it to ECR, and rolls out a blue-green deployment on EKS."

서비스 번역 결과 점수
파파고 CI/CD 파이프라인은 메인으로 푸시할 때마다 트리거됩니다. 단위 테스트를 실행하고, SAST 스캐닝을 수행하고, Docker 이미지를 빌드하고, ECR에 푸시하고, EKS에 블루-그린 배포를 롤아웃합니다. 7/10
GPT-4o CI/CD 파이프라인은 main 브랜치에 푸시할 때마다 실행됩니다. 유닛 테스트를 실행하고, SAST 정적 분석을 수행하며, Docker 이미지를 빌드한 뒤 ECR에 푸시하고, EKS에서 블루-그린 배포를 진행합니다. 8/10
Claude CI/CD 파이프라인은 main 브랜치에 푸시할 때마다 트리거됩니다. 유닛 테스트 실행, SAST(정적 애플리케이션 보안 테스트) 스캔, Docker 이미지 빌드, ECR 푸시를 거쳐 EKS에서 블루-그린 배포를 수행합니다. 9/10

분석: Claude가 SAST를 풀어서 "(정적 애플리케이션 보안 테스트)"를 병기한 것이 좋습니다. 약어가 많은 DevOps 문서에서 이렇게 한 번 풀어주면 가독성이 올라갑니다. 파파고는 "메인으로 푸시"라고 했는데, "main 브랜치에 푸시"가 더 정확합니다.

종합 비교표

비교 항목 파파고 GPT-4o Claude Sonnet
기술문서 번역 6/10 8/10 9/10
구어체 번역 4/10 7/10 9/10
전문용어 처리 7/10 8/10 9/10
용어 일관성 5/10 7/10 9/10
자연스러운 한국어 5/10 7/10 9/10
원문 포맷 유지 8/10 8/10 9/10
평균 5.8 7.5 9.0

배치 번역기 구현 - 파일 단위로 한번에

한두 문장 번역은 위 함수로 충분하지만, 실무에서는 마크다운 파일 수십 개를 한번에 번역해야 하는 경우가 많습니다. 이를 위한 배치 번역기를 만들어봤습니다.

import os
import time
import anthropic
from pathlib import Path

client = anthropic.Anthropic()

SYSTEM_PROMPT = """전문 기술 번역가로서 영어를 한국어로 번역하세요.
- 개발 용어는 한국 개발자가 실제 사용하는 표현 사용
- 코드 블록, 변수명, 함수명은 원문 유지
- 마크다운 포맷 유지
- 존댓말(~합니다) 통일"""


def translate_file(file_path: str) -> str:
    """단일 파일을 번역하고 결과를 반환합니다."""
    text = Path(file_path).read_text(encoding="utf-8")

    # 긴 문서는 청크로 나눠서 번역
    chunks = split_by_heading(text)
    translated_chunks = []

    for i, chunk in enumerate(chunks):
        print(f"  번역 중: {i+1}/{len(chunks)} 청크")

        message = client.messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=4096,
            system=SYSTEM_PROMPT,
            messages=[{"role": "user", "content": chunk}]
        )
        translated_chunks.append(message.content[0].text)
        time.sleep(0.5)  # Rate limit 방지

    return "\n\n".join(translated_chunks)


def split_by_heading(text: str, max_chars: int = 3000) -> list:
    """마크다운 헤딩 기준으로 텍스트를 분할합니다."""
    lines = text.split("\n")
    chunks = []
    current_chunk = []
    current_length = 0

    for line in lines:
        if line.startswith("#") and current_length > max_chars:
            chunks.append("\n".join(current_chunk))
            current_chunk = []
            current_length = 0
        current_chunk.append(line)
        current_length += len(line)

    if current_chunk:
        chunks.append("\n".join(current_chunk))

    return chunks


def batch_translate(input_dir: str, output_dir: str):
    """디렉토리 내 모든 .md 파일을 번역합니다."""
    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    md_files = list(input_path.glob("*.md"))
    print(f"총 {len(md_files)}개 파일 발견")

    for i, md_file in enumerate(md_files):
        print(f"\n[{i+1}/{len(md_files)}] {md_file.name} 번역 시작")

        translated = translate_file(str(md_file))

        out_file = output_path / f"{md_file.stem}_ko.md"
        out_file.write_text(translated, encoding="utf-8")
        print(f"  저장 완료: {out_file.name}")

    print(f"\n번역 완료! {output_dir}에서 확인하세요.")


# 실행
batch_translate("./docs/en", "./docs/ko")

이 코드의 핵심 포인트를 짚어보면:

  • 청크 분할: 긴 문서를 마크다운 헤딩 기준으로 나눕니다. 임의의 위치에서 자르면 문맥이 끊기니까, 섹션 단위로 나누는 것이 번역 품질에 좋습니다.
  • Rate limit 대응: API 호출 사이에 0.5초 간격을 둡니다. Claude API의 기본 Rate limit은 분당 60건이므로 이 정도면 충분합니다.
  • 파일 단위 처리: 원본 파일명에 _ko 접미사를 붙여서 저장합니다. 원본과 번역본을 쉽게 매칭할 수 있습니다.

비용 비교 - 얼마나 들까

번역 품질이 아무리 좋아도 비용이 과하면 의미가 없습니다. 실제 비용을 계산해봤습니다.

A4 한 장 분량 (약 2,000 토큰) 기준

서비스 입력 비용 출력 비용 A4 1장 비용 A4 100장 비용
파파고 API 글자당 과금 - 약 20원 약 2,000원
GPT-4o $2.5/1M tokens $10/1M tokens 약 35원 약 3,500원
Claude Sonnet $3/1M tokens $15/1M tokens 약 43원 약 4,300원

파파고가 가장 저렴하고, Claude가 가장 비쌉니다. 하지만 A4 100장을 번역해도 4,300원 정도입니다. 커피 한 잔 값으로 100페이지짜리 기술문서를 고품질로 번역할 수 있다는 뜻입니다.

비용 절감 팁

  • Haiku 모델 활용: 간단한 번역은 Claude Haiku로도 충분합니다. Sonnet 대비 비용이 1/10 수준입니다.
  • 캐싱 활용: 동일한 시스템 프롬프트를 반복 사용하면 Anthropic의 프롬프트 캐싱으로 입력 비용이 90% 절감됩니다.
  • GPT-4o mini 활용: OpenAI 쪽에서는 GPT-4o mini가 비용 대비 품질이 좋습니다. 기술문서 번역에서는 Sonnet에 약간 뒤처지지만, 일반 텍스트 번역은 무난합니다.

프롬프트 캐싱을 적용하는 방법도 보여드리겠습니다:

# Claude 프롬프트 캐싱 적용
message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=4096,
    system=[
        {
            "type": "text",
            "text": SYSTEM_PROMPT + "\n\n" + glossary_text,
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[{"role": "user", "content": text_to_translate}]
)

시스템 프롬프트에 cache_control을 붙이면, 동일한 프롬프트가 캐시되어 두 번째 호출부터 입력 비용이 크게 줄어듭니다. 배치 번역에서는 매 호출마다 같은 시스템 프롬프트를 쓰므로 효과가 큽니다.

실전 팁과 주의사항

1. 번역 후 검수 자동화

AI 번역도 완벽하지 않습니다. 특히 조심해야 할 패턴이 있습니다:

  • 숫자 변환 오류: 드물지만 "100ms"를 "100밀리초"로 바꾸면서 숫자가 바뀌는 경우가 있습니다.
  • URL/링크 변형: 마크다운 링크 안의 URL이 번역되거나 깨지는 경우가 있습니다.
  • 코드 블록 침범: 코드 안의 주석까지 번역하면서 코드가 깨지기도 합니다.

간단한 검수 스크립트를 돌려서 이런 문제를 잡을 수 있습니다:

import re

def validate_translation(original: str, translated: str) -> list:
    """번역 결과를 검수하고 문제점을 리스트로 반환합니다."""
    issues = []

    # 1. URL이 보존되었는지 확인
    orig_urls = set(re.findall(r'https?://\S+', original))
    trans_urls = set(re.findall(r'https?://\S+', translated))
    missing_urls = orig_urls - trans_urls
    if missing_urls:
        issues.append(f"누락된 URL: {missing_urls}")

    # 2. 코드 블록 수가 동일한지 확인
    orig_blocks = original.count("```")
    trans_blocks = translated.count("```")
    if orig_blocks != trans_blocks:
        issues.append(f"코드 블록 수 불일치: 원본 {orig_blocks}개, 번역 {trans_blocks}개")

    # 3. 숫자가 보존되었는지 확인
    orig_nums = re.findall(r'\b\d+\.?\d*\b', original)
    trans_nums = re.findall(r'\b\d+\.?\d*\b', translated)
    if sorted(orig_nums) != sorted(trans_nums):
        issues.append("숫자 불일치 감지 - 수동 확인 필요")

    return issues

2. 언어 감지를 넣으면 양방향 번역이 됩니다

입력 텍스트의 언어를 자동 감지해서 한영/영한을 자동 전환하는 것도 간단합니다:

def detect_and_translate(text: str) -> str:
    """언어를 감지하고 자동으로 반대 언어로 번역합니다."""
    # 한글 비율로 언어 감지
    korean_chars = len(re.findall(r'[가-힣]', text))
    total_chars = len(re.findall(r'\w', text))

    if total_chars == 0:
        return text

    is_korean = (korean_chars / total_chars) > 0.3

    if is_korean:
        return translate_with_claude(text, source="ko", target="en")
    else:
        return translate_with_claude(text, source="en", target="ko")

3. 파파고가 더 나은 경우도 있습니다

솔직하게 말하면, 모든 상황에서 AI API가 우월한 건 아닙니다:

  • 짧은 단어/문장: "사과" 같은 단어 번역은 파파고가 빠르고 정확합니다. LLM은 오히려 과도하게 맥락을 추론해서 이상한 번역을 할 때가 있습니다.
  • 일상 회화: 여행 가서 간단한 문장 번역할 때는 파파고 앱이 더 실용적입니다. API 호출 시간이 2~3초 걸리는 것도 실시간 소통에는 느립니다.
  • 대량 단순 번역: 제품 설명 수천 개를 기계적으로 번역할 때는 파파고 API가 비용 면에서 압도적입니다.

결국 맥락이 중요한 번역은 AI API, 단순하고 대량인 번역은 파파고가 유리합니다. 저는 둘 다 쓰고 있고, 용도에 따라 분기하는 함수를 만들어 놨습니다.

4. GPT vs Claude, 번역에서는 어떤 걸 쓸까

제 경험상 번역 작업에서의 차이는 이렇습니다:

  • Claude가 나은 경우: 한국어 자연스러움, 긴 문서 번역, 마크다운 포맷 유지, 전문용어 병기
  • GPT가 나은 경우: JSON 구조화 출력이 필요한 경우, Function Calling과 연계할 때
  • 비슷한 경우: 일반적인 기술문서 번역, 짧은 텍스트 번역

번역 품질만 놓고 보면 Claude가 약간 우위에 있다고 느낍니다. 특히 한국어 문체 자연스러움에서 차이가 납니다. 하지만 이건 프롬프트로 상당 부분 보정할 수 있어서, 이미 OpenAI 인프라를 쓰고 있다면 GPT-4o로도 충분히 좋은 번역 품질을 얻을 수 있습니다.

정리

  • 기술문서, 블로그 글 번역은 AI API가 파파고보다 확실히 자연스럽습니다
  • 프롬프트에 용어집과 맥락을 넣으면 번역 품질이 크게 올라갑니다
  • 배치 번역기를 만들어두면 문서 수십 개를 한번에 처리할 수 있습니다
  • A4 100장 번역해도 5,000원 이하이므로 비용 부담이 적습니다
  • 프롬프트 캐싱을 활용하면 비용을 추가로 절감할 수 있습니다
  • 번역 후 자동 검수 스크립트를 돌려서 URL, 숫자, 코드 블록이 깨지지 않았는지 확인하세요

위 코드를 그대로 복사해서 자신의 프로젝트에 적용해보세요. 처음에는 짧은 텍스트로 프롬프트를 조정하면서 품질을 확인하고, 만족스러우면 배치 번역기로 확장하는 순서를 추천합니다.