툴박스 가이드는 W3C·MDN·국제 표준 문서(RFC/ISO)와 한국인터넷진흥원(KISA) 등 공신력 있는 기관의 공개 자료를 기반으로 작성·검토합니다.편집 방침 보기
엑셀로 은행 거래내역 CSV를 열었더니 화면 가득 "占쏙옙占쏙옙"만 나오거나, 오래된 웹페이지에서 "가나다"처럼 알파벳이 뒤엉킨 글자를 본 적이 있을 것이다. 파일 내용이 손상된 게 아니다. 글자를 저장한 인코딩과 읽는 인코딩이 다를 때 생기는 현상, 이른바 '한글 깨짐(모지바케, mojibake)'이다. 영문은 멀쩡한데 한글만 깨지는 이유, 깨진 모양만 보고 원인을 역추적하는 법, 그리고 상황별 복구 절차까지 인코딩의 실무를 한 번에 정리한다.
왜 영문은 멀쩡한데 한글만 깨질까
컴퓨터는 글자를 숫자(바이트)로 바꿔 저장한다. 이 규칙표가 '문자 인코딩'이다. 영문 알파벳·숫자·기본 기호는 ASCII라는 128자짜리 표에 담기는데, 거의 모든 인코딩이 이 128자를 똑같은 1바이트로 표현한다. 그래서 어떤 인코딩으로 읽어도 영문은 안 깨진다.
문제는 한글이다. 한글은 ASCII에 없어서 인코딩마다 다른 방식으로 여러 바이트에 나눠 담는다. UTF-8은 한글 한 글자를 3바이트로, EUC-KR·CP949는 2바이트로 저장한다. 저장할 때와 읽을 때의 규칙표가 어긋나면, 프로그램은 엉뚱한 바이트 묶음을 다른 글자로 해석해 깨진 문자를 뱉는다.
간단히 계산해 보자. "안녕하세요"는 한글 5글자다.
- UTF-8로 저장 → 5 × 3바이트 = 15바이트
- EUC-KR로 저장 → 5 × 2바이트 = 10바이트
- 영문 "Hello"는 어느 쪽이든 5 × 1바이트 = 5바이트
같은 글자인데 파일 크기가 다른 이유가 여기 있다. 텍스트 도구를 다룰 때 이 기본기가 없으면 원인을 못 찾는다. 다양한 텍스트 유틸리티는 kimgoon 라이프스타일 도구 모음에서 함께 볼 수 있다.
문자 인코딩 3형제 비교: UTF-8·EUC-KR·CP949
한국에서 마주치는 인코딩은 사실상 넷으로 좁혀진다. 아래 표로 한 번에 정리했다.
| 인코딩 | 한글 1자 크기 | 지원 문자 | 주 사용처 | 비고 |
|---|---|---|---|---|
| ASCII | 미지원 | 영문·숫자·기호 128자 | 영문 전용 시스템 | 한글 저장 불가 |
| EUC-KR | 2바이트 | 완성형 한글 2,350자 | 2000년대 이전 웹·문서 | 옛한글·일부 글자 누락 |
| CP949 | 2바이트 | 한글 11,172자 | 구형 윈도우 기본 | EUC-KR을 확장한 상위호환 |
| UTF-8 | 3바이트(가변) | 전 세계 모든 문자 | 웹 표준·현재 기본 | 이모지·다국어 지원 |
핵심은 UTF-8과 CP949(EUC-KR)의 충돌이다. 국제 표준화기구(WHATWG) 인코딩 표준과 W3C는 웹 문서 기본 인코딩을 UTF-8로 규정하고 있고(UTF-8은 RFC 3629로 표준화), 현재 만들어지는 거의 모든 파일이 UTF-8이다. 반면 윈도우 메모장이나 구형 엑셀은 여전히 CP949를 기본으로 가정하는 경우가 많다. 이 세대차가 한글 깨짐의 90% 이상을 만든다.
참고로 완성형 한글은 유니코드 'Hangul Syllables' 영역(U+AC00~U+D7A3)에 정확히 11,172자가 배정돼 있다. CP949는 이 중 실사용 글자를 담고, EUC-KR은 그보다 적은 2,350자만 담기 때문에 "쀓" 같은 희귀 조합은 EUC-KR에서 아예 깨진다.
깨진 모양만 보고 원인 역추적하기
깨진 글자의 '모양'은 원인을 알려주는 지문이다. 아무 규칙 없이 깨지는 게 아니라, 어떤 인코딩을 어떤 인코딩으로 오해석했는지에 따라 패턴이 정해진다.
| 깨진 모양 예시 | 실제 원인 | 흔한 상황 |
|---|---|---|
| 占쏙옙, 굞, 뷁 | UTF-8 파일을 CP949로 읽음 | 메모장·구형 엑셀에서 UTF-8 CSV 열기 |
| 가나다, 안녕 | UTF-8을 Latin-1(서유럽)로 읽음 | charset 선언 없는 웹페이지 |
| °¡³ª´Ù | EUC-KR을 Latin-1로 읽음 | 구형 이메일·해외 서버 |
| ᅮ← (네모·물음표◆) | 대상 인코딩에 없는 글자 | DB 저장 시 charset 불일치 |
| ?????? | 변환 실패로 정보 손실 | 잘못 저장 후 재저장 |
특히 알아둘 것은, "占쏙옙"류로 깨진 경우는 원본 바이트가 살아있을 가능성이 높아 복구가 되지만, "??????"나 네모(�, U+FFFD)로 깨진 경우는 바이트가 이미 소실돼 복구가 불가능하다는 점이다. 잘못 열린 파일을 그 상태로 '다시 저장'하는 순간 손실이 확정되므로, 깨진 파일은 절대 덮어쓰지 말고 원본을 따로 보관해야 한다.
상황별 한글 깨짐 진단과 해결
실무에서 자주 만나는 다섯 상황을 원인·해결로 묶었다.
| 상황 | 증상 | 원인 | 해결책 |
|---|---|---|---|
| 엑셀에서 CSV 열기 | 한글 전체 깨짐 | 엑셀이 CSV를 CP949로 가정 | 파일을 'UTF-8 (BOM 포함)'으로 저장하거나, 엑셀 [데이터]→[텍스트/CSV]로 인코딩 지정해 가져오기 |
| 메모장 저장 후 타 프로그램 | 한쪽에서만 깨짐 | 저장·읽기 인코딩 불일치 | 저장 시 인코딩을 UTF-8로 통일 |
| 웹페이지 접속 | 본문 전체 깨짐 | <meta charset> 누락 또는 불일치 | HTML <head>에 <meta charset="utf-8"> 선언 |
| 압축(ZIP) 파일명 | 파일명만 깨짐 | 윈도우가 CP949로 압축 → 맥/리눅스가 UTF-8로 해제 | 압축 시 'UTF-8 파일명' 옵션 사용 |
| DB 조회 결과 | 물음표·네모 | 커넥션/컬럼 charset 불일치 | 컬럼·커넥션을 utf8mb4로 통일 |
가장 흔한 엑셀 CSV 문제는, 은행이나 관공서에서 받은 UTF-8 CSV를 윈도우 엑셀이 CP949로 읽어서 생긴다. 예를 들어 자취 가계부 예산 관리를 위해 거래내역 CSV를 정리할 때 이 문제를 자주 만나는데, 파일을 UTF-8 BOM 형식으로 다시 저장하면 엑셀이 자동으로 UTF-8로 인식한다.
깨진 한글 복구 5단계
- 원본부터 백업한다. 깨진 파일을 복사해 두고 사본으로만 작업한다. 재저장 한 번에 복구 기회가 사라진다.
- 깨진 모양으로 원인을 특정한다. 위 지문 표에서 어떤 오해석인지 파악한다. "占쏙옙"이면 UTF-8↔CP949, "ê°€"류면 UTF-8↔Latin-1이다.
- 읽기 인코딩만 바꿔 다시 연다. 파일 내용(바이트)은 그대로 두고, 여는 쪽 인코딩만 원래 저장 인코딩에 맞춘다. VS Code라면 우하단 인코딩 표시 → 'Reopen with Encoding'으로 바로 확인할 수 있다.
- 온라인 인코딩 변환기로 교차 검증한다. 짧은 텍스트라면 인코딩 변환기에 붙여넣어 여러 인코딩으로 바꿔가며 정상 출력을 찾는다.
- 정상으로 보이면 UTF-8로 통일 저장한다. 앞으로의 깨짐을 막으려면 최종본은 UTF-8(가급적 BOM 없는 UTF-8, CSV만 예외적으로 BOM 포함)로 저장한다.
BOM이 만드는 또 다른 함정
BOM(Byte Order Mark)은 파일 맨 앞에 붙는 3바이트(EF BB BF) 신호로, "이 파일은 UTF-8입니다"라고 알려주는 표식이다. 유용해 보이지만 양날의 검이다.
- BOM이 도움 되는 경우: 윈도우 엑셀은 CSV에 BOM이 있으면 UTF-8로 자동 인식한다. 그래서 엑셀용 CSV는 'UTF-8 BOM 포함'으로 저장하는 게 정답이다.
- BOM이 해가 되는 경우: 웹 서버 설정 파일, 셸 스크립트, JSON, 프로그램 소스 코드에 BOM이 있으면 맨 앞에 보이지 않는 문자가 끼어 오류가 난다. PHP 페이지 상단에 정체불명의 공백이 생기거나, JSON 파싱이 실패하는 원인이 대부분 BOM이다.
즉 CSV는 BOM 포함, 그 외 코드·설정 파일은 BOM 없이 저장하는 것이 실무 원칙이다. 파일 맨 앞에 안 보이는 문자가 의심되면 보이지 않는 문자·텍스트 디버깅 가이드의 방법으로 잡아낼 수 있다.
개발자를 위한 인코딩 체크리스트
코드로 텍스트를 다룬다면 네 곳의 인코딩을 모두 UTF-8로 맞춰야 깨짐이 사라진다.
- HTML:
<head>최상단에<meta charset="utf-8">. HTTP 응답 헤더Content-Type: text/html; charset=utf-8도 함께 맞춘다. - 데이터베이스(MySQL): 컬럼·테이블·커넥션을 모두
utf8mb4로. 옛utf8(사실상 3바이트)은 이모지를 못 담으니utf8mb4(4바이트)를 쓴다. - Python: 파일 열 때
open(path, encoding='utf-8')을 명시한다. 인코딩을 생략하면 OS 기본값(윈도우는 CP949)을 따라가 깨진다. - JavaScript/Node.js: 내부 문자열은 UTF-16이지만 파일 입출력은
fs.readFile(path, 'utf-8')처럼 인코딩을 지정한다.
Base64·URL 인코딩처럼 '문자 인코딩'과 헷갈리기 쉬운 데이터 인코딩은 별개 주제다. 둘의 차이가 궁금하면 Base64·URL·HTML 엔티티 인코딩 가이드를 참고하자.
자주 묻는 질문
엑셀에서 CSV 한글이 깨지는데 어떻게 열어야 하나요? 파일을 그냥 더블클릭하지 말고, 엑셀에서 빈 통합문서를 연 뒤 [데이터] → [텍스트/CSV 가져오기]로 불러오세요. 이때 원본 인코딩을 '65001: 유니코드(UTF-8)'로 지정하면 정상 표시됩니다. 또는 파일을 UTF-8 BOM 포함으로 다시 저장하면 더블클릭으로도 열립니다.
UTF-8과 EUC-KR 중 뭘 써야 하나요? 특별한 이유가 없다면 무조건 UTF-8입니다. 웹 표준이자 다국어·이모지를 모두 지원하고, 현재 거의 모든 시스템의 기본값입니다. EUC-KR·CP949는 구형 시스템과 호환이 꼭 필요할 때만 예외적으로 씁니다.
한 번 깨진 한글을 원래대로 되돌릴 수 있나요? "占쏙옙"처럼 특정 패턴으로 깨졌고 아직 재저장하지 않았다면 읽기 인코딩만 바꿔 대부분 복구됩니다. 하지만 물음표(?)나 네모(�)로 바뀌었다면 원본 바이트가 이미 소실돼 복구가 불가능합니다. 깨진 파일은 덮어쓰지 말고 원본을 보관하세요.
메모장에서 저장할 때 어떤 인코딩을 골라야 하나요? 최신 윈도우 메모장은 저장 대화상자 하단에서 인코딩을 고를 수 있습니다. 대부분의 경우 'UTF-8'을 선택하면 됩니다. 엑셀에서 열 CSV라면 'UTF-8(BOM)'을 고르세요.
웹페이지 한글이 깨지는데 서버 문제인가요?
대개 HTML의 <meta charset> 선언이 없거나 실제 파일 인코딩과 다른 경우입니다. HTML 파일을 UTF-8로 저장하고 <head>에 <meta charset="utf-8">를 넣으면 해결됩니다. 서버가 보내는 Content-Type 헤더의 charset도 UTF-8로 맞추면 더 확실합니다.
관련 가이드
참고한 표준·공식 자료
본 글은 다음 표준·문서의 공개 자료를 바탕으로 정리·검토되었습니다. 최신 사양은 각 표준 문서를 함께 확인해 주세요.
- MDN Web Docs ↗웹 표준·HTML/CSS/JS 공식 문서
- W3C ↗웹 국제 표준 권고안
- IETF RFC Editor ↗인터넷 프로토콜·인코딩 표준 원문
- 한국인터넷진흥원(KISA) ↗보안·암호·개인정보 가이드
잘못된 정보나 갱신이 필요한 부분을 발견하셨다면 contact@kimgoon.kr로 알려주세요. 툴박스 편집 방침을 함께 참고하실 수 있습니다.








