엑셀에서 CSV 열면 한글이 깨지는 이유
CSV 파일을 엑셀에서 열었더니 한글이 ê°ë 같은 글자로 깨져 있습니다. 메모장에서 열면 멀쩡합니다. 같은 파일인데 왜 프로그램마다 다를까요.
원인은 파일 맨 앞의 세 바이트입니다.
CSV에는 인코딩 정보가 없습니다
CSV는 단순한 텍스트 파일입니다. 쉼표로 칸을 나눈 글자의 나열일 뿐, "이 파일은 어떤 인코딩으로 저장됐다"는 정보를 담는 자리가 없습니다.
엑셀 파일(xlsx)이나 워드 파일(docx)에는 그런 정보가 들어 있습니다. 하지만 CSV에는 없습니다. 그래서 프로그램이 추측해야 합니다.
한글을 표현하는 방식은 크게 두 가지입니다.
| 인코딩 | 특징 |
|---|---|
| UTF-8 | 국제 표준. 웹, 맥, 리눅스, 대부분의 개발 도구가 기본으로 씁니다 |
| CP949 (EUC-KR) | 한국 윈도우의 전통적 방식. 구버전 엑셀이 기본으로 가정합니다 |
같은 "가"라는 글자도 두 방식에서 저장되는 바이트가 다릅니다. UTF-8로 저장한 파일을 CP949로 읽으면, 바이트를 엉뚱하게 해석해서 깨진 글자가 나옵니다.
BOM이라는 표식
여기서 BOM(Byte Order Mark)이 등장합니다.
파일 맨 앞에 EF BB BF라는 세 바이트를 붙여두면, 그건 "이 파일은 UTF-8입니다"라는 표식이 됩니다. 화면에는 보이지 않습니다.
엑셀은 CSV를 열 때 이 세 바이트를 먼저 확인합니다.
- 있으면: UTF-8로 읽습니다 → 한글 정상
- 없으면: 시스템 기본 인코딩(한국 윈도우에서는 CP949)으로 추측합니다 → UTF-8 파일이면 깨짐
메모장에서 멀쩡히 보이는 이유도 여기 있습니다. 메모장은 BOM이 없어도 내용을 분석해 UTF-8일 가능성을 판단합니다. 엑셀보다 관대합니다.
해결 방법
1. BOM을 붙여 저장한다
가장 깔끔합니다. 파일을 만드는 쪽에서 BOM을 넣으면 받는 사람이 아무것도 안 해도 됩니다.
이 사이트의 엑셀 변환 도구에 "엑셀용 / UTF-8" 선택지를 둔 것이 이 때문입니다. 엑셀용을 고르면 BOM이 들어갑니다.
파이썬으로 직접 만든다면 인코딩을 utf-8-sig로 지정하면 됩니다.
df.to_csv('data.csv', encoding='utf-8-sig', index=False)
utf-8이 아니라 utf-8-sig입니다. sig가 BOM을 뜻합니다. 이 한 글자 차이로 한국에서 CSV 문제의 상당수가 해결됩니다.
2. 엑셀에서 인코딩을 지정해 연다
이미 받은 파일이고 다시 만들 수 없다면, 더블클릭 대신 가져오기를 씁니다.
엑셀 2016 이상
1. 데이터 탭 → 텍스트/CSV에서 가져오기
2. 파일 선택
3. 미리보기 창에서 파일 원본을 65001: 유니코드(UTF-8)로 변경
4. 로드
구버전 엑셀 1. 데이터 탭 → 외부 데이터 가져오기 → 텍스트 2. 마법사 1단계에서 원본 파일을 UTF-8로 지정 3. 구분 기호를 쉼표로
3. 메모장으로 다시 저장한다
가장 단순한 방법입니다.
- 메모장으로 CSV 파일을 엽니다 (한글이 정상으로 보일 겁니다)
- 다른 이름으로 저장
- 인코딩을 "UTF-8 (BOM)" 으로 선택
- 저장 후 엑셀에서 열기
윈도우 메모장은 버전에 따라 항목 이름이 "UTF-8"과 "UTF-8 (BOM 포함)"으로 나뉩니다. BOM이 붙은 쪽을 고르시면 됩니다.
반대 방향도 문제입니다
엑셀에서 CSV로 저장하면 기본적으로 CP949로 저장됩니다. 이 파일을 맥이나 리눅스, 또는 개발 도구에서 열면 이번엔 그쪽에서 깨집니다.
방향이 반대일 뿐 같은 문제입니다.
엑셀에서 UTF-8로 내보내려면 "다른 이름으로 저장" 시 파일 형식에서 "CSV UTF-8 (쉼표로 분리)"를 고르면 됩니다. 일반 "CSV (쉼표로 분리)"와 다른 항목이니 주의하시기 바랍니다.
실무에서 겪는 패턴
웹 서비스에서 내려받은 CSV가 깨진다. 대부분의 웹 서비스는 국제 표준인 UTF-8을 씁니다. BOM은 안 붙이는 경우가 많고요. 위의 2번이나 3번 방법이 필요합니다.
동료에게 보낸 CSV만 깨진다. 본인은 맥, 상대는 윈도우인 경우가 흔합니다. BOM을 붙여 다시 보내면 해결됩니다.
일부 글자만 깨진다. 이건 인코딩 문제가 아닐 수 있습니다. CP949는 표현할 수 있는 글자 수가 UTF-8보다 적어서, 이모지나 일부 한자·특수문자가 변환 과정에서 유실됩니다. 이 경우 원본을 UTF-8로 유지하는 것 외에 방법이 없습니다.
쉼표가 들어간 데이터가 칸을 밀어낸다. 인코딩과 무관한 별개 문제입니다. 값 안에 쉼표가 있으면 큰따옴표로 감싸야 하는데("서울시, 강남구"), 그 처리가 빠진 파일입니다.
인코딩은 눈에 보이지 않아 원인을 찾기 어렵지만, 구조를 알고 나면 대응은 단순합니다. 파일을 만드는 쪽에서 BOM을 붙이는 것이 가장 확실한 해법입니다.
아래 도구는 변환할 때 BOM 포함 여부를 고를 수 있습니다. 파일은 브라우저 안에서 처리되며 서버로 전송되지 않습니다.