read_csv()로 한글 파일을 열자마자 UnicodeDecodeError가 난다. 같은 CSV가 다른 프로그램에서는 열리니 pandas 문제처럼 보일 수 있지만, 먼저 확인할 것은 파일에 저장된 바이트를 어떤 문자 인코딩으로 읽고 있는가다. UTF-8로 저장한 파일과 CP949로 저장한 파일은 한글 부분의 바이트가 다르다.
UTF-8로 읽을 수 없는 CP949 바이트를 재현한다
도식은 같은 바이트를 UTF-8과 CP949로 해석한 두 결과를 나눈다. UTF-8 경로의 오류는 파일이 손상됐다는 뜻이 아니라, 저장할 때 사용한 문자표와 읽을 때 지정한 문자표가 다르다는 신호일 수 있다.
외부 파일 없이 설명용 CSV를 메모리에서 만든다. 실제 파일을 읽는 상황과 달리 여기서는 인코딩을 우리가 직접 지정했으므로 원인을 알고 있다.
from io import BytesIO
import pandas as pd
raw = "이름,상태\n가,완료\n".encode("cp949")
try:
pd.read_csv(BytesIO(raw))
except UnicodeDecodeError as error:
print(type(error).__name__)
table = pd.read_csv(BytesIO(raw), encoding="cp949")
print(table.to_string(index=False))UnicodeDecodeError
이름 상태
가 완료첫 읽기는 기본 인코딩으로 CP949 바이트를 해석하지 못해 실패한다. 두 번째 읽기는 생성할 때 쓴 인코딩과 같은 cp949를 지정해 한글 열 이름과 값을 얻는다. BytesIO(raw)를 두 번 만든 이유는 각 읽기마다 입력을 처음부터 시작하기 위해서다. 실제 파일에서는 경로를 넘기면 pandas가 새로 열지만, 이미 열어 둔 파일 객체는 읽기 위치를 확인해야 한다.
실제 CSV가 CP949인지 어떻게 확인할까?
오류 메시지의 바이트 위치만 보고 무조건 encoding="cp949"를 붙이지 않는다. 파일을 만든 시스템의 내보내기 옵션, 전달한 쪽의 안내, 같은 배치의 다른 파일을 먼저 확인한다. 아는 테스트 문구가 있다면 작은 샘플을 후보 인코딩으로 읽어 열 이름과 값이 의미 있게 보이는지 대조한다. 코드만 성공해도 글자가 깨져 있다면 맞는 해독이 아니다.
확인한 뒤에는 입력 형식을 코드와 작업 설명에 명시해 다음 실행에서 같은 오류가 반복되지 않게 한다.
table = pd.read_csv("sample.csv", encoding="cp949")
print(table.columns.tolist())
print(table.head(2).to_string(index=False))여기서 sample.csv는 실제 받은 파일명으로 바꿔야 한다. 열 이름과 앞의 두 행을 보는 이유는 읽기 성공 여부뿐 아니라 데이터가 잘못 해석되지 않았는지 확인하기 위해서다. 개인정보가 든 파일이라면 head() 결과를 공유 로그에 그대로 남기지 말고, 비식별 테스트 파일로 재현한다.
깨진 문자를 조용히 넘기는 옵션은 왜 조심할까?
읽기 오류를 무조건 ‘무시’하거나 대체 문자로 바꾸면 파이프라인은 계속 돌 수 있다. 하지만 이름·주소·분류 코드의 일부가 바뀌면 조인 키나 집계 범주도 달라질 수 있다. 중요한 데이터에서는 실패를 눈에 띄게 남기고 원본 파일의 인코딩을 확인한 다음 다시 읽는 편이 안전하다.
반대로 모든 한글 CSV가 CP949인 것도 아니다. UTF-8로 만든 파일은 기본 읽기로 정상일 수 있다. 파일 형식이 섞여 들어오는 배치라면 파일별 출처와 인코딩을 메타데이터로 관리하고, 예상하지 못한 형식은 임의 추측 대신 격리·재확인하는 경계를 둔다. 속도 옵션이나 구분자 옵션을 바꾸기 전에 문자 인코딩 오류를 먼저 분리하면 진단이 짧아진다.
핵심 요약: 저장된 인코딩과 읽는 인코딩을 맞춘다
UnicodeDecodeError는 한글 자체가 잘못됐다는 뜻이 아니라 현재 해독 방식으로 파일 바이트를 읽을 수 없다는 신호다. 파일을 만든 쪽의 인코딩을 확인하고, CP949임이 확인됐으면 encoding="cp949"로 읽는다. 성공 뒤에도 열 이름과 샘플 값이 올바른지 확인해야 한다.
작성자
기초 개념을 구현과 검증, 실제 운영 판단까지 연결해 기록합니다.

