아티클 목록으로
아티클약 19분 소요

Python과 ChatGPT API로 Excel을 번역하는 방법【2026년판・작동하는 코드 포함】

openpyxl과 OpenAI API로 Excel 파일을 자동 번역하는 방법을 최신 SDK에 맞춘 완전한 코드로 단계별 설명합니다. 수식과 스타일을 깨뜨리지 않는 요령, API 비용을 줄이는 구현까지 함께 소개합니다.

Translate Excel ChatGPT

마지막 업데이트: 2026년 6월 — OpenAI Python SDK v1 계열과 Chat Completions API로 테스트했습니다.

이 튜토리얼은 간단하고 폭넓게 지원되는 Chat Completions API를 사용합니다. 새로 만드는 애플리케이션이라면 OpenAI의 Responses API와 구조화된 출력(structured outputs)도 함께 검토해 보세요.

Excel을 번역하는 두 가지 방법

코드를 한 줄이라도 작성하기 전에, 어느 쪽이 나에게 맞는지 솔직하게 정리해 두면 도움이 됩니다.

  • Python으로 스크립트를 작성한다(본 가이드). 여러 파일을 한꺼번에 번역하거나, 정기적으로 실행하거나, 더 큰 파이프라인에 통합하고 싶다면 가장 적합합니다. OpenAI API 키와 기본적인 Python 지식이 필요합니다.
  • 기성 도구를 사용한다. 지금 당장 스프레드시트 한 개만 번역하면 된다면 — 차트, 수식, 서식까지 자동으로 보존되는 Doc2Lang의 Excel 번역 도구에 업로드하는 편이 더 빠르고, 코드도 전혀 필요 없습니다.

이 가이드는 Python 방식에 초점을 맞추고, 그대로 복사해서 작동하는 완전한 코드를 제공합니다. 아울러 직접 만들 때 정확히 어디서 막히기 쉬운지도 짚어 드리니, 충분히 납득한 뒤 선택할 수 있습니다. 글 후반부에는 전체 비교표도 마련해 두었습니다.

준비물

시작하기 전에 몇 가지를 갖춰야 합니다.

  • Python 기초 지식. 이 글에는 코드가 나옵니다. 기초를 알면 유리하지만, 각 단계는 설명해 드립니다.
  • Python 설치. 아직 설치하지 않았다면 공식 웹사이트에서 내려받으세요.
  • pip. Python 라이브러리를 설치하는 도구입니다. Python 3가 있다면 거의 틀림없이 pip도 함께 사용할 수 있습니다.
  • OpenAI API 키. OpenAI 계정 대시보드에서 발급합니다. 동일한 키로 현행의 모든 모델(gpt-4o, gpt-4o-mini 등)을 사용할 수 있습니다.
  • 번역할 Excel 파일. 번역하려는 .xlsx 파일을 미리 준비해 두세요.

API 키는 코드에 절대 남지 않도록 환경 변수로 설정해 두세요.

macOS / Linux:

export OPENAI_API_KEY="your_api_key_here"

Windows PowerShell:

$env:OPENAI_API_KEY="your_api_key_here"

.xlsx 파일의 구조 (선택, 배경 지식)

Excel에서 .xlsx로 저장한 파일은 사실 여러 개의 파일을 하나로 묶은 아카이브입니다. 이 형식을 OpenXML이라고 부릅니다. 궁금하다면 확장자를 .zip으로 바꿔 압축을 풀어 내부를 들여다볼 수 있습니다.

  • xl/worksheets/ — 시트별 XML 파일(sheet1.xml, sheet2.xml, …). 행, 열, 셀의 실제 데이터가 바로 여기에 들어 있습니다.
  • xl/styles.xml — 워크북에서 쓰이는 모든 스타일. 어느 셀이 굵게 표시되는지, 어느 셀이 파란색인지, 어느 숫자가 통화 서식인지 등이 정의되어 있습니다.
  • xl/sharedStrings.xml — 용량을 아끼기 위해, Excel은 중복되는 문자열을 한 번만 저장하고 쓰이는 곳마다 참조합니다. "Total"이 1,000번 나와도 본체는 단 하나만 저장됩니다.
  • xl/workbook.xml — 일종의 목차입니다. 어떤 시트가 있는지, 그 순서, 시트 보호 같은 속성이 적혀 있습니다.

openpyxl 같은 라이브러리는 이런 세부 사항을 대부분 가려 주지만, 구조를 알아 두면 고급 작업이 필요하거나 문제를 해결해야 할 때 도움이 됩니다.

압축을 푼 report.xlsx의 내용을 보여주는 Windows 탐색기

report.xlsx의 압축을 푼 모습: 워크시트, 공유 문자열, 스타일, 워크북 구조는 모두 zip 안의 XML 파일일 뿐입니다.

openpyxl로 Excel 읽고 쓰기

openpyxl은 Excel 파일(.xlsx, .xlsm, .xltx, .xltm)의 읽기와 쓰기에 특화된 Python 라이브러리입니다. 시트와 셀을 직접 다룰 수 있습니다.

한 가지 미리 분명히 해 둘 점이 있습니다. openpyxl은 셀 단위 작업에는 더없이 훌륭하지만, Excel 레이아웃을 완벽하게 재현하는 엔진은 아닙니다. 도형, 일부 이미지, 차트, 매크로, 한 셀 안의 서식 있는 텍스트(rich text)는 파일을 열었다가 다시 저장할 때 그대로 보존되지 않을 수 있습니다. 매크로가 포함된 .xlsm 파일은 load_workbook(..., keep_vba=True)로 불러와 다시 .xlsm으로 저장해야 하며, 그렇지 않으면 매크로가 사라질 수 있습니다. 이런 한계는 글 끝부분에서 다시 다루겠습니다.

1. openpyxl 설치

pip install openpyxl

2. 핵심 개념

몇 가지 개념이 그대로 openpyxl의 동작과 대응됩니다.

Workbook(워크북) — Excel 파일 전체를 가리킵니다.

from openpyxl import load_workbook
 
workbook = load_workbook(filename="sample.xlsx")

Sheet(시트) — 하나의 워크북에는 하나 이상의 시트가 들어 있습니다.

sheet = workbook.active          # 활성 시트
another_sheet = workbook["Sheet2"]  # 이름으로 지정한 시트

Cell(셀) — 행과 열이 만나는 곳. 데이터가 들어가는 지점입니다.

cell_value = sheet["A1"].value   # 읽기
sheet["B1"] = "Hello, Excel!"    # 쓰기

행과 열 — 손쉽게 반복 처리할 수 있습니다.

for row in sheet.iter_rows(values_only=True):
    for value in row:
        print(value)

OpenAI API로 텍스트 번역하기

openpyxl로 데이터를 읽어 들였다면, 다음 단계는 OpenAI API로 번역하는 것입니다.

1. OpenAI Python 라이브러리 설치

pip install openai

2. 최신 번역 함수 (2026년판)

import os
from openai import OpenAI
 
# 키는 환경 변수에서 읽어 옵니다 — 스크립트에 직접 적어 넣지 마세요.
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
 
def translate_text(text, target_lang="Korean"):
    response = client.chat.completions.create(
        model="gpt-4o-mini",  # 빠르고 저렴함. 최고 품질이 필요하면 "gpt-4o" 사용
        messages=[
            {
                "role": "system",
                "content": (
                    f"You are a professional translator. Translate the user's text "
                    f"into {target_lang}. Return only the translation, with no extra commentary."
                ),
            },
            {"role": "user", "content": text},
        ],
    )
    return response.choices[0].message.content.strip()

참고: 오래된 튜토리얼 상당수는 openai.ChatCompletion.create()model="gpt-4"를 사용합니다. 이는 1.0 이전 SDK의 작성법으로, openai>=1.0에서는 더 이상 작동하지 않습니다. 위 코드는 현행 client.chat.completions.create() 인터페이스를 사용합니다. 비용과 속도를 중시한다면 gpt-4o-mini를, 번역 품질을 최우선으로 한다면 gpt-4o를 선택하세요.

3. 가장 단순한 첫 시도

가장 흔한 튜토리얼 방식은 모든 셀을 순회하며 하나씩 덮어쓰는 것입니다.

from openpyxl import load_workbook
 
workbook = load_workbook(filename="your_file.xlsx")
 
for sheet in workbook.worksheets:
    for row in sheet.iter_rows():
        for cell in row:
            if isinstance(cell.value, str):
                cell.value = translate_text(cell.value)
 
workbook.save("your_translated_file.xlsx")

데모에서는 작동하지만, 실제 스프레드시트에서는 진짜 문제가 생깁니다. 셀마다 API를 한 번씩 호출하니 느리고 비싸며, 수식까지 번역해 망가뜨리고, 레이트 리밋에 대한 보호 장치도 없습니다. 이제 이 모든 문제를 해결해 봅시다.

실무에 쓸 수 있게 다듬기

1. 수식은 번역하지 않기

=SUM(A1:A10) 같은 수식이 들어 있는 셀을 번역하면 스프레드시트가 망가집니다. 수식, 빈 셀, 텍스트가 아닌 값은 건너뛰세요.

def is_translatable(cell):
    # 빈 셀, 숫자, 수식 셀은 건너뜀.
    value = cell.value
    return (
        isinstance(value, str)
        and value.strip() != ""
        and cell.data_type != "f"   # "f" = 수식
    )

openpyxl은 cell.value만 다시 쓰기 때문에, 텍스트가 아닌 셀을 건드리지 않는 한 숫자 서식, 글꼴, 채우기 색 등 대부분의 스타일은 그대로 유지됩니다.

2. 중복 문자열을 캐싱해 비용 줄이기

스프레드시트에는 같은 레이블("Total", "Date", 부서명 등)이 끊임없이 반복됩니다. 동일한 문자열은 딱 한 번만 번역하세요.

cache = {}
 
def translate_cached(text, target_lang="Korean"):
    if text not in cache:
        cache[text] = translate_text(text, target_lang)
    return cache[text]

일반적인 보고서라면 이것만으로도 API 호출 수 — 그리고 요금 — 를 큰 폭으로 줄일 수 있습니다.

3. 여러 셀을 한 번의 요청으로 묶기

느림의 가장 큰 원인은 "셀 1개 = API 호출 1회"입니다. 대신 여러 문자열을 한 번의 요청으로 보내고, 결과를 안정적으로 다시 매핑할 수 있도록 모델에 JSON으로 반환하도록 요청하세요.

import json
 
def translate_batch(texts, target_lang="Korean"):
    numbered = {str(i): t for i, t in enumerate(texts)}
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": (
                    f"You are a professional translator. Translate each value in the "
                    f"JSON object into {target_lang}. Keep the same keys. "
                    f"Return only a JSON object."
                ),
            },
            {"role": "user", "content": json.dumps(numbered, ensure_ascii=False)},
        ],
        response_format={"type": "json_object"},
    )
    result = json.loads(response.choices[0].message.content)
    return [result[str(i)] for i in range(len(texts))]

4. 레이트 리밋 시 재시도 (지수 백오프)

레이트 리밋에 걸려도 멈추지 말고, 대기 시간을 매번 두 배로 늘리며 다시 시도하세요.

import time
 
def with_retry(func, *args, retries=5, **kwargs):
    for attempt in range(retries):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            wait = 2 ** attempt
            print(f"Error: {e}. Retrying in {wait}s...")
            time.sleep(wait)
    raise RuntimeError("Translation failed after several retries.")

5. 신뢰할 수 없는 파일을 안전하게 다루기

다른 사람이 업로드한 Excel 파일을 처리한다면 악의적인 XML로부터 보호해야 합니다. defusedxml을 설치하면 openpyxl이 설치 여부를 감지해 자동으로 사용하며, 파일을 불러오기 전에 크기와 형식도 검증하세요.

pip install defusedxml

직접 만든 파일이라면 굳이 필요하지 않지만, 본인이 만들지 않은 파일을 다룰 때는 강력히 권장합니다.

완성된 작동 스크립트

지금까지의 내용을 하나로 합쳐, 그대로 복사해 실행할 수 있는 스크립트입니다. 고유한 문자열을 모으고, 재시도를 포함해 배치 단위로 번역하며, 결과를 캐싱하고, 수식을 건너뛰고, 새 파일로 저장하므로 원본은 안전하게 남습니다.

import json
import os
import time
from openai import OpenAI
from openpyxl import load_workbook
 
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
 
TARGET_LANG = "Korean"
MODEL = "gpt-4o-mini"   # 더 높은 품질이 필요하면 "gpt-4o"
BATCH_SIZE = 40
 
 
def is_translatable(cell):
    value = cell.value
    return (
        isinstance(value, str)
        and value.strip() != ""
        and cell.data_type != "f"   # "f" = 수식
    )
 
 
def translate_batch(texts, target_lang=TARGET_LANG, retries=5):
    numbered = {str(i): t for i, t in enumerate(texts)}
    system = (
        f"You are a professional translator. Translate each value in the JSON object "
        f"into {target_lang}. Keep the same keys. Return only a JSON object."
    )
    for attempt in range(retries):
        try:
            response = client.chat.completions.create(
                model=MODEL,
                messages=[
                    {"role": "system", "content": system},
                    {"role": "user", "content": json.dumps(numbered, ensure_ascii=False)},
                ],
                response_format={"type": "json_object"},
            )
            result = json.loads(response.choices[0].message.content)
            return [result[str(i)] for i in range(len(texts))]
        except Exception as e:
            wait = 2 ** attempt
            print(f"Error: {e}. Retrying in {wait}s...")
            time.sleep(wait)
    raise RuntimeError("Translation failed after several retries.")
 
 
# 1. 워크북 불러오기
workbook = load_workbook(filename="your_file.xlsx")
 
# 2. 번역 대상이 되는 고유한 문자열 모두 모으기
unique_texts = set()
for sheet in workbook.worksheets:
    for row in sheet.iter_rows():
        for cell in row:
            if is_translatable(cell):
                unique_texts.add(cell.value)
unique_texts = list(unique_texts)
 
# 3. 배치로 번역하고 {원문: 번역문} 캐시 만들기
cache = {}
for start in range(0, len(unique_texts), BATCH_SIZE):
    chunk = unique_texts[start:start + BATCH_SIZE]
    cache.update(dict(zip(chunk, translate_batch(chunk))))
 
# 4. 수식과 스타일은 건드리지 않고 번역문만 다시 써넣기
for sheet in workbook.worksheets:
    for row in sheet.iter_rows():
        for cell in row:
            if is_translatable(cell):
                cell.value = cache[cell.value]
 
# 5. 새 파일로 저장
workbook.save("your_translated_file.xlsx")
print("Done!")

100줄도 채 안 되는 분량으로, 빠르고 수식에 안전하며 셀별로 호출하는 버전보다 훨씬 저렴한 실용적인 번역 도구가 완성되었습니다.

선택 사항: 실제 운영 작업을 위한 강화

위 스크립트만으로도 이미 충분히 실용적입니다. 다만 규모가 크거나 반복적으로 돌리는 작업이라면, 세 가지 안전장치를 더해 두면 도움이 됩니다.

모든 예외를 삼키지 마세요. 모든 예외에 대해 재시도하면 잘못된 API 키나 틀린 모델 이름까지 다섯 번이나 재시도하게 됩니다. 레이트 리밋일 때만 재시도하고, 나머지는 즉시 실패시키세요.

from openai import RateLimitError
 
def translate_batch(texts, target_lang=TARGET_LANG, retries=5):
    numbered = {str(i): t for i, t in enumerate(texts)}
    system = (
        f"You are a professional translator. Translate each value in the JSON object "
        f"into {target_lang}. Keep the same keys. Return only a JSON object."
    )
    for attempt in range(retries):
        try:
            response = client.chat.completions.create(
                model=MODEL,
                messages=[
                    {"role": "system", "content": system},
                    {"role": "user", "content": json.dumps(numbered, ensure_ascii=False)},
                ],
                response_format={"type": "json_object"},
            )
            result = json.loads(response.choices[0].message.content)
            missing = [str(i) for i in range(len(texts)) if str(i) not in result]
            if missing:
                raise ValueError(f"Missing translations for keys: {missing}")
            return [result[str(i)] for i in range(len(texts))]
        except RateLimitError:
            wait = 2 ** attempt
            print(f"Rate limited. Retrying in {wait}s...")
            time.sleep(wait)
    raise RuntimeError("Translation failed after several retries.")

이 버전은 모델이 받은 모든 키를 빠짐없이 반환했는지도 검증하므로, 응답이 잘리거나 형식이 어긋났을 때 셀을 조용히 누락하는 대신 분명하게 실패합니다.

중복 제거 시 순서를 유지하세요. set 대신 순서를 유지하는 중복 제거를 사용하면, 로그와 오류 메시지가 예측 가능하게 유지됩니다.

# 기존: unique_texts = list(unique_texts)  (set() 사용)
unique_texts = list(dict.fromkeys(collected_texts))

Python 스크립트 vs Doc2Lang: 무엇을 선택할까?

직접 스크립트를 작성하는 방식은 강력하지만 분명한 한계가 있습니다. 솔직하게 비교해 보겠습니다.

Python(직접 구현)Doc2Lang
서식・차트직접 처리해야 하며 쉽게 깨짐자동으로 보존
수식건너뛸 조건을 직접 작성자동으로 건너뜀
필요한 것OpenAI API 키 + 코딩파일 업로드만
적합한 대상대량・정기 작업을 자동화하려는 개발자지금 당장 한 파일을 번역해야 하는 누구나
Doc2Lang으로 영어에서 한국어로 번역된, 차트와 서식이 유지된 재무 보고서

영어 재무 보고서를 Doc2Lang으로 한국어로 번역 — 막대 차트와 선 차트, 수식, 숫자 서식, 열 너비까지 모두 그대로 유지됩니다(시트 탭 이름은 원본 언어 그대로 유지되며 번역되지 않습니다).

Excel 번역 도구 사용해 보기 — API 키도, 코드도 필요 없습니다.

대략적인 기준은 이렇습니다. 정기적인 번역 작업을 자동화하고 싶다면 위 스크립트를 만드세요. 코드 없이 지금 당장 스프레드시트를 번역하고 싶다면 Excel 번역 도구를 사용하세요 — 업로드, 번역, 다운로드, 그리고 서식은 그대로 유지됩니다.

관련 가이드

자주 묻는 질문 (FAQ)

레이트 리밋 오류가 나면 어떻게 하나요?
OpenAI는 계정 등급에 따라 레이트 리밋을 적용합니다. 위에서 보여 드린 지수 백오프 재시도를 사용하거나, 배치 크기를 줄이거나, 대량으로 처리한다면 계정 등급을 올리세요.

여러 언어로 동시에 번역하려면 어떻게 하나요?
대상 언어 목록을 순회하며 언어마다 전체 과정을 한 번씩 실행하고, 각 결과를 별도의 파일(예: report_ja.xlsx, report_de.xlsx)로 저장하세요.

OpenAI API를 사용하면 비용이 드나요?
네. 사용한 토큰만큼 비용을 지불합니다. 위에서 소개한 중복 문자열 캐싱과 요청 배치 처리를 사용하면 비용을 낮게 유지할 수 있습니다. 일상적인 번역이라면 gpt-4o-mini는 더 큰 모델보다 훨씬 저렴합니다.

서식과 수식이 그대로 보존되나요?
이 스크립트는 텍스트 셀의 값만 바꾸므로, 기본적인 셀 스타일 — 글꼴, 채우기, 테두리, 정렬, 숫자 서식 — 은 대체로 유지되고 수식은 건너뜁니다. 다만 openpyxl은 Excel 레이아웃을 완벽하게 재현하는 엔진이 아닙니다. 매크로, 도형, 차트, 이미지, 한 셀 안의 서식 있는 텍스트(rich text), 복잡한 워크북 기능은 완벽하게 보존되지 않을 수 있습니다. .xlsm 파일은 keep_vba=True로 불러와 다시 .xlsm으로 저장하세요. 자동화보다 픽셀 단위로 정확한 레이아웃이 더 중요하다면, 전용 도구가 이런 경우를 자동으로 처리해 줍니다.

마치며

openpyxl과 OpenAI API를 사용하면 100줄도 안 되는 코드로 빠르고 수식에 안전한 Excel 번역 도구를 만들 수 있습니다. 대규모로 번역을 자동화해야 할 때 안성맞춤입니다.

자동화보다 레이아웃 보존이 우선이라면, 전용 Excel 번역 도구가 더 나은 선택일 수 있습니다. openpyxl이 다루지 못하는 차트, 도형, 스타일까지 알아서 처리해 주니까요.

코드 없이 Excel 파일 번역하기

공유