paper&honey

엑셀에서 CSV 한글이 깨지는 이유 — 인코딩과 BOM 이야기

은행 거래내역이나 쇼핑몰 주문 목록을 CSV로 내려받아 열었는데 한글이 물음표나 알 수 없는 기호로 바뀌어 있는 경험은 한국에서 컴퓨터를 쓰는 사람이라면 한 번쯤 겪어봤을 일입니다. 신기하게도 같은 파일을 메모장이나 다른 프로그램으로 열면 멀쩡한 경우가 많은데, 유독 엑셀에서만 이런 일이 반복됩니다. 이 글에서는 CSV라는 형식 자체가 왜 이런 문제에 취약한지, 그리고 왜 하필 엑셀이 유독 이 문제를 자주 일으키는지를 배경부터 짚어보겠습니다.

CSV는 인코딩 정보를 담을 자리가 없는 형식입니다

엑셀의 기본 저장 형식인 xlsx는 사실 여러 개의 파일을 압축한 묶음이라, 그 안에 문서 정보와 함께 어떤 방식으로 글자를 저장했는지도 함께 기록할 수 있습니다. 반면 CSV는 값들을 쉼표로 나열한 순수한 텍스트일 뿐입니다. 첫 줄이 제목이든 데이터든, 파일에는 "이 글자들은 어떤 인코딩으로 저장됐다"고 알려주는 자리가 애초에 없습니다. 그래서 CSV 파일을 여는 쪽 프로그램은 매번 바이트만 보고 인코딩을 스스로 짐작해야 하고, 이 짐작이 틀리면 한글이 깨져 보이는 것입니다.

EUC-KR과 CP949는 어느 시절의 유산인가

유니코드가 보편화되기 전, 한국어를 컴퓨터에 담기 위해 만들어진 완성형 인코딩이 EUC-KR입니다. 자주 쓰는 한글 음절을 정해진 표로 묶어 각 글자에 두 바이트를 배정하는 방식입니다. 문제는 한글이 초성·중성·종성 조합으로 훨씬 많은 음절을 만들어낼 수 있는데, EUC-KR 표에는 그중 자주 쓰이는 음절만 들어 있었다는 점입니다. 이름이나 사투리 표현에 쓰이는 드문 음절은 이 표만으로는 표현할 수 없었습니다. 마이크로소프트는 이 빈틈을 메우기 위해 EUC-KR 표에 없던 음절까지 담도록 확장한 자체 코드페이지를 만들었고, 이것이 CP949입니다. 한국어 윈도우가 오래전 기본으로 채택한 이래 CP949는 지금도 전통적인 기본 인코딩 자리를 지키고 있습니다. 즉 CP949는 인터넷과 유니코드가 자리 잡기 전, 한국어 윈도우 생태계 안에서만 통하던 약속이었던 셈입니다. 문제는 이 약속이 웹과 다른 운영체제로 나가는 데이터에는 통하지 않는다는 데 있습니다.

유독 엑셀에서만 문제가 되는 이유

요즘 CSV를 만들어내는 쪽은 대개 웹 서비스입니다. 은행 사이트, 쇼핑몰 관리자 페이지, 설문조사 플랫폼 같은 곳은 국적을 가리지 않고 전 세계 어디서나 통하는 UTF-8로 데이터를 내보내는 경우가 많습니다. 그런데 엑셀은 확장자가 .csv인 파일을 열 때, 파일 안에 명시적인 표시가 없으면 여전히 시스템 로캘, 즉 한국어 윈도우 기준으로는 전통적인 EUC-KR·CP949 계열 인코딩으로 읽는 동작을 기본으로 삼아 왔습니다. 그 결과 UTF-8로 내보낸 최신 CSV를 엑셀은 옛 방식으로 짐작해서 읽는 어긋남이 벌어지고, 이 어긋남이 매번 한글 깨짐으로 나타납니다. 근원이 CSV를 만든 쪽이 아니라 여는 쪽의 오래된 동작에 있다 보니, 파일을 다시 받아도 똑같이 깨집니다.

구글 시트·맥·프로그래밍 언어는 왜 다른가

구글 시트는 태생부터 웹 서비스이다 보니 CSV를 업로드할 때 기본적으로 UTF-8을 전제로 처리합니다. 그래서 BOM이 없는 UTF-8 CSV를 올려도 대개 한글이 그대로 보입니다. 파이썬이나 자바스크립트 같은 프로그래밍 언어로 CSV를 읽을 때는 애초에 인코딩을 코드에서 직접 지정해야 하는 경우가 많습니다. 프로그램이 알아서 짐작하기보다는 개발자가 미리 "이 파일은 UTF-8이다"라고 못 박아 두기 때문에 짐작이 틀릴 여지 자체가 줄어듭니다. 엑셀만 유독 문제가 잦은 이유는 프로그램이 사용자 대신 인코딩을 추측해 주는 오래된 편의 기능 때문입니다. 그 추측 기준이 요즘 데이터 생태계의 기본값인 UTF-8이 아니라 옛 로캘 방식에 머물러 있는 것이 근본 원인입니다.

참고로 파일 이름의 인코딩이 어긋나는 문제도 원리는 비슷합니다. 압축 프로그램마다 파일 이름을 어떤 방식으로 기록할지가 통일돼 있지 않아서 벌어지는 현상인데, 이 주제는 zip 파일 한글 깨짐 가이드에서 다른 각도로 다뤘습니다.

BOM은 이 짐작을 없애 주는 표시입니다

BOM(Byte Order Mark)은 파일 맨 앞에 붙는 몇 바이트짜리 표시로, UTF-8로 저장된 파일이라면 EF BB BF라는 세 바이트가 옵니다. 이 세 바이트는 실제 데이터가 아니라 순전히 "이 파일은 UTF-8입니다"라고 알려주는 신호일 뿐이라, 근래의 엑셀은 이 신호를 발견하면 로캘 기준 짐작을 멈추고 UTF-8로 해석합니다. 즉 BOM은 CSV 형식 자체가 갖고 있지 않은 인코딩 정보를, 파일 맨 앞에 억지로라도 끼워 넣어 엑셀의 짐작을 원천적으로 없애 버리는 우회로인 셈입니다.

예방과 해결

CSV를 직접 만들 수 있는 입장이라면, 내보낼 때부터 BOM을 붙인 UTF-8로 저장하는 것이 가장 근본적인 예방책입니다. 반대로 이미 BOM 없는 UTF-8이나 EUC-KR 계열로 만들어진 CSV를 받은 입장이라면, 파일을 열 때마다 새로 만들어 달라고 요청하기보다 받은 쪽에서 인코딩을 바로잡아 여는 편이 빠릅니다. paper&honey의 CSV 한글 깨짐 해결 도구를 쓰면 파일의 인코딩을 자동으로 판별해 미리보기로 확인시켜 주고, 엑셀에서 바로 열리는 UTF-8(BOM 포함) 파일로 다시 저장할 수 있습니다.

자주 묻는 질문

Q. 메모장이나 다른 프로그램에서는 멀쩡한데 왜 엑셀만 깨지나요? 메모장을 비롯한 요즘 텍스트 편집기들은 대부분 UTF-8을 기본 짐작 순서에서 앞쪽에 두거나, 애초에 인코딩을 자동으로 판별하는 로직이 최신 표준에 맞춰져 있습니다. 반면 엑셀은 CSV를 열 때 여전히 시스템 로캘을 우선 기준으로 삼는 오래된 동작을 유지하고 있어서 유독 이 조합에서만 어긋남이 두드러집니다.

Q. CSV를 UTF-8로 저장하기만 하면 항상 해결되나요? BOM 없는 UTF-8이라면 웹이나 구글 시트에서는 문제가 없지만, 엑셀에서 .csv 확장자로 바로 열 때는 여전히 로캘로 짐작해 깨질 수 있습니다. 엑셀에서 안정적으로 열리게 하려면 UTF-8에 BOM까지 붙여야 짐작 과정 자체를 건너뛸 수 있습니다.

Q. 엑셀 안에서 인코딩을 지정해서 열 방법은 없나요? 엑셀의 텍스트 가져오기 기능(버전에 따라 데이터 탭의 "데이터 가져오기 및 변환" 등 이름이 조금씩 다릅니다)을 쓰면 인코딩을 직접 골라 지정할 수 있습니다. 다만 파일을 더블클릭해서 바로 여는 일상적인 방식은 이 과정을 거치지 않고 로캘 짐작에 맡겨지므로, 매번 가져오기 메뉴를 거치기보다는 파일 자체를 BOM 포함 UTF-8로 바꿔 두는 편이 번거로움이 적습니다.