압축 풀면 한글 파일명이 깨지는 이유
한글.txt가 ÇѱÛ.txt가 되는 원리. 왜 ZIP만 깨지고 7Z는 멀쩡한지, 받은 쪽과 보내는 쪽이 각각 무엇을 하면 되는지.
회사에서 받은 압축파일을 풀었더니 한글보고서.hwp가 ÇÑ±Û 같은 글자가 뒤섞인 외계어 이름이 되어 있다. 맥에서 만든 압축을 윈도우에서 열었더니 이번엔 ë³´ê³ ì„œ 같은 게 나온다. 파일 내용은 멀쩡한데 이름만 외계어다. 버그처럼 보이지만 사실 ZIP이라는 형식이 태어날 때부터 안고 있던 문제이고, 원리를 알면 왜 어떤 프로그램에서는 멀쩡하고 어떤 프로그램에서는 깨지는지까지 설명이 된다.
ZIP은 파일명을 "그냥 바이트"로 저장한다
ZIP은 1989년, MS-DOS 시절에 만들어진 형식이다. 그 시절 컴퓨터는 글자를 저마다의 문자표(코드페이지)로 저장했다. 같은 바이트 0xC7 0xD1이 한국 컴퓨터에서는 '한'이고, 다른 나라 컴퓨터에서는 전혀 다른 글자였다. ZIP 규격은 파일명을 저장할 자리만 만들어 두고 "이 이름이 어느 문자표로 적혔는지"를 기록하는 자리를 만들지 않았다. 미국식 문자표(CP437)를 쓴다고 가정했을 뿐이다.
세월이 흘러 2006년에야 규격에 "이 파일명은 UTF-8이다"라고 표시하는 플래그(11번 비트)가 추가됐다. 그런데 여기서 두 번째 문제가 생긴다. 플래그를 세우는 건 압축을 만드는 프로그램의 몫인데, 지키지 않는 프로그램이 아주 많다.
깨지는 경로는 두 방향이다
한국에서 겪는 파일명 깨짐은 거의 전부 다음 둘 중 하나다.
- 윈도우에서 만든 ZIP을 맥·리눅스에서 열 때 — 윈도우 압축 프로그램들은 한글 파일명을 한국어 윈도우의 문자표(CP949)로 적으면서 UTF-8 플래그를 세우지 않는 경우가 많다. 받는 쪽은 표시가 없으니 UTF-8이나 CP437로 읽고,
한글.txt는?ѱ?.txt나╟╤▒█.txt가 된다. 맥의 기본 압축 해제와 터미널의unzip도 똑같이 깨뜨린다. - 맥에서 만든 ZIP을 윈도우에서 열 때 — 맥은 파일명을 UTF-8로 적는데, 역시 플래그를 세우지 않는다. 한국어 윈도우의 기본 압축 해제는 표시가 없는 이름을 CP949로 읽어버리고, 이번엔
ë³´ê³ ì„œ처럼 라틴 문자가 뒤섞인 형태로 깨진다.
정리하면 이렇다. 쓰는 쪽은 자기 문자표로 적고, 읽는 쪽은 자기 문자표로 읽는다. 중간에 "어느 문자표인지"를 전달하는 다리가 끊겨 있다. 어느 한쪽의 잘못이라기보다, 30년 넘은 형식과 각자 다른 관행이 만든 합작이다.
왜 어떤 프로그램은 안 깨질까
반디집이나 7-Zip 같은 프로그램에서는 같은 파일이 멀쩡하게 풀리는 경우가 많다. 마법이 아니라 추측이다. 플래그가 없는 파일명을 만나면 바이트 배열을 여러 문자표로 해석해 보고, 가장 "말이 되는" 결과를 고른다. 판별에 쓸 수 있는 강력한 단서가 하나 있는데, UTF-8은 문법이 엄격해서 아무 바이트나 유효한 UTF-8이 되지 않는다는 점이다. 예컨대 CP949로 적힌 '한'(C7 D1)은 UTF-8 문법에 어긋나는 바이트 조합이라, "UTF-8로 읽어보고 문법 오류 없이 읽히면 UTF-8, 아니면 CP949일 가능성이 높다"는 식의 판정이 꽤 정확하게 작동한다.
참고로 7Z나 RAR에서는 이 문제가 아예 없다. 두 형식은 처음부터 파일명을 유니코드로 저장하도록 정해져 있어서, 어느 문자표인지 추측할 필요가 없다. "ZIP만 깨지고 7z는 멀쩡하다"는 경험칙의 정체가 이것이다.
__MACOSX 폴더와 .DS_Store는 또 뭔가
맥에서 만든 ZIP을 열면 시킨 적 없는 __MACOSX 폴더와 .DS_Store, ._파일명 같은 항목이 따라온다. 맥이 파일마다 함께 관리하는 부가 정보(아이콘 위치, 미리보기 캐시 등)를 ZIP 안에 같이 담은 것으로, 맥이 아닌 곳에서는 쓸모가 없다. 지워도 원본 파일에는 아무 영향이 없으니 무시하면 된다. 윈도우 쪽에도 같은 부류로 Thumbs.db가 있다.
그래서 어떻게 하면 되나
- 받은 파일이 깨졌을 때: 파일 내용은 손상되지 않았다. 파일명을 어느 문자표로 읽을지 지정할 수 있는 프로그램으로 다시 풀면 이름이 돌아온다. 압축 풀기 도구는 파일명의 원본 바이트를 직접 읽어 문자표를 자동 판별하고, 틀리면 한국어·일본어·중국어 중에서 직접 고를 수 있다. 파일이 서버로 올라가지 않으니 사내 문서에도 쓸 수 있다.
- 보내는 쪽일 때: 상대가 어떤 환경인지 모른다면 ZIP 대신 7Z로 보내는 것이 가장 확실하다. 파일명이 유니코드로 저장되니 어디서 열어도 깨지지 않는다. 받은 ZIP을 압축 풀기 도구에 넣고 "묶어서 받기"로 7Z를 만들어 전달해도 된다.
- 계속 주고받는 사이라면: 양쪽 모두 반디집·7-Zip처럼 UTF-8 플래그를 제대로 쓰는 프로그램으로 압축하는 습관이 근본 해결이다. 운영체제 기본 압축 기능이 문제의 진원지인 경우가 많다.
기억할 것 하나
파일명이 깨져도 내용물은 무사하다. 깨진 것은 이름표뿐이고, 이름표는 올바른 문자표로 다시 읽으면 복구된다. 압축을 다시 받거나 보낸 사람을 탓하기 전에, 문자표를 바꿔 읽어볼 수 있는 도구에 한 번 넣어보면 대부분 거기서 끝난다.