CSV의 문자 깨짐을 완전히 해결! 문자 코드·BOM·줄바꿈 코드의 기초 지식
CSV 파일을 열었을 때 문자 인코딩이 깨져 있었다는 경험은 개발자라면 누구나 있을 것입니다. 특히 일본어를 포함한 CSV는 문자 인코딩의 차이로 인해 자주 문제가 발생합니다. 이 글에서는 문자 인코딩 손상의 원인을 근본적으로 이해하고 확실하게 해결하기 위한 지식을 정리합니다.
문자 인코딩의 기본: <code>UTF-8</code> vs <code>Shift_JIS</code>
일본어 CSV 파일에서 문제가 되는 문자 인코딩은 주로 다음 2가지입니다.
UTF-8
현재의 웹 표준이며 전 세계의 문자를 다룰 수 있는 유니코드 기반 문자 코드입니다. Linux, macOS, 모던 웹 애플리케이션에서는 UTF-8이 기본값입니다. 문자당 1~4바이트의 가변 길이 인코딩을 사용하며, ASCII 문자는 그대로 1바이트로 표현됩니다.
Shift_JIS(CP932)
Windows의 레거시 애플리케이션 및 구 버전 Excel에서 사용되던 일본어 문자 코드입니다. 정확히는 Windows 환경에서 CP932(Microsoft의 Shift_JIS 확장)가 사용되며, 일부 기종 의존 문자(원숫자, 로마 숫자 등)는 CP932에서만 처리할 수 있습니다.
왜 문자 깨짐이 발생하나요
문자 깨짐의 근본적인 원인은 단순합니다. 파일을 쓸 때의 문자 인코딩과 읽을 때의 문자 인코딩이 일치하지 않기 때문입니다.
예를 들어, 웹 애플리케이션이 UTF-8로 CSV를 내보내고 사용자가 Excel에서 열면 문자가 깨집니다. 이는 Excel이 일본어 환경에서 기본적으로 파일을 Shift_JIS(CP932)로 해석하기 때문입니다.
BOM(Byte Order Mark)의 역할
BOM은 파일의 시작에 붙는 몇 바이트의 마커로, 문자 코드를 나타내는 표시입니다. UTF-8의 BOM은 <code>0xEF 0xBB 0xBF</code>의 3바이트입니다.
중요한 점은 <strong>Excel에서 UTF-8 CSV를 올바르게 열려면 BOM이 필요</strong>하다는 것입니다. BOM 없는 UTF-8 CSV를 Excel에서 열면 Shift_JIS로 해석되어 문자가 깨집니다.
// PHP で BOM 付き UTF-8 CSV を出力する例
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="data.csv"');
// BOM を出力
echo "\xEF\xBB\xBF";
$fp = fopen('php://output', 'w');
fputcsv($fp, ['名前', 'メール', '部署']);
fputcsv($fp, ['田中太郎', 'tanaka@example.com', '開発部']);
fclose($fp);
# Python で BOM 付き UTF-8 CSV を出力する例
import csv
with open('data.csv', 'w', encoding='utf-8-sig', newline='') as f:
writer = csv.writer(f)
writer.writerow(['名前', 'メール', '部署'])
writer.writerow(['田中太郎', 'tanaka@example.com', '開発部'])
그러나 BOM에 대해 주의할 점들이 있습니다. 일부 프로그램이나 셸 스크립트는 BOM을 잘못된 문자로 취급하여 오류의 원인이 될 수 있습니다. API 응답이나 프로그램에서 처리하는 CSV에는 BOM을 붙이지 않는 것이 안전합니다.
줄 바꿈 코드 문제
CSV의 문자 깨짐과 함께 흔히 발생하는 문제가 줄바꿈 코드의 차이입니다.
- <strong>CRLF</strong>(<code>\r\n</code>) — Windows 표준
- <strong>LF</strong>(<code>\n</code>) — Linux / macOS 표준
- <strong>CR</strong>(<code>\r</code>) — 구형 Mac OS (현재 거의 사용되지 않음)
RFC 4180에서는 CSV의 개행 코드를 CRLF로 정하고 있습니다. 하지만 실제로는 많은 도구가 LF만 있는 CSV도 문제없이 처리할 수 있습니다. 문제가 발생하기 쉬운 것은 Excel과 일부 레거시 시스템입니다.
줄 바꿈 코드 확인에는 명령줄 도구가 편리합니다.
# file コマンドで確認
file data.csv
# 出力例: data.csv: UTF-8 Unicode (with BOM) text, with CRLF line terminators
# xxd で先頭バイトを確認(BOM の有無)
xxd data.csv | head -3
실용적인 솔루션 차트
CSV의 용도에 따른 최적의 설정을 다음과 같이 정리합니다.
| 용도 | 문자 인코딩 | BOM | 줄 바꿈 코드 |
|---|---|---|---|
| Excel에서 열기 | UTF-8 | 있음 | CRLF |
| 프로그램으로 처리 | UTF-8 | 없음 | LF |
| 레거시 시스템 연동 | Shift_JIS (CP932) | 없음 | CRLF |
| API 응답 | UTF-8 | 없음 | LF |
테스트용 CSV 파일
자신의 애플리케이션이 다양한 문자 인코딩의 CSV를 올바르게 처리할 수 있는지 확인하려면 DevLab의 테스트 파일을 사용하세요.
- <a href="/ja/files/encoding/">문자 인코딩별 테스트용 CSV 파일</a> — UTF-8 (BOM 포함/미포함), Shift_JIS, EUC-JP 등
- <a href="/ja/files/newline/">줄바꿈 코드별 테스트 파일</a> — CRLF, LF, CR 각종 파일
- <a href="/ja/files/csv/">CSV 테스트 파일 목록</a> — 각종 크기의 CSV 파일
요약
CSV 문자 인코딩 문제는 문자 인코딩, BOM(Byte Order Mark), 줄 바꿈의 세 가지 요소를 올바르게 이해하면 확실하게 해결할 수 있습니다. Excel의 경우 BOM이 있는 UTF-8에 CRLF 줄 바꿈을 사용하는 것이 표준이며, 프로그래밍 처리의 경우 BOM이 없는 UTF-8에 LF 줄 바꿈을 사용합니다. DevLab의 다양한 테스트 파일을 사용하여 애플리케이션이 각 패턴을 올바르게 처리하는지 확인하세요.
이 기사에서 사용할 수 있는 테스트 파일
- → <a href="/ja/files/encoding/" class="text-primary-600 dark:text-primary-400 hover:underline">문자 인코딩별 CSV 테스트 파일 목록 (UTF-8 / Shift_JIS / EUC-JP)</a>
- → <a href="/ja/files/csv/" class="text-primary-600 dark:text-primary-400 hover:underline">CSV 테스트 파일 목록</a>
관련 기사
- → <a href="/ja/blog/file-format-quick-reference/" class="text-primary-600 dark:text-primary-400 hover:underline">개발자를 위한 파일 형식 빠른 참조</a>
- → <a href="/ja/blog/wordpress-upload-limit-fix/" class="text-primary-600 dark:text-primary-400 hover:underline">WordPress 업로드 제한을 높이는 5가지 방법</a>