티스토리 뷰

개발/PHP

ZipArchive Class 한글 인코딩 문제

Jaeyeon Baek 2017. 7. 26. 17:25

지난주 금요일 부터 난해한 문제가 있었는데 charset 관련 된 내용이었다. 요약하면 윈도우에서 만들어진 Zip 파일을 리눅스 서버에서 압축 풀었을 때 이름이 utf8 형식이 아닌 다른 언어셋으로 되어있는 경우에 문자가 깨지는 문제인데, 예를 들면 윈도우에서 만들어진 한글 파일명이 그러했다. 깨지는 이유는 Zip 에는 그 안에 들어있는 파일명에 대한 charset 정보가 없기 때문. 이 문제를 해결하기 위해 세 가지 방법을 생각했다.

1. 서버가 redhat 기반의 리눅스인데 redhat 에서 기본 제공되는 unzip binary 가 아닌 debian 에서 제공되는 unzip bianry 를 가져다 쓴다. 이유는 간단하다. debian 에는 압축을 풀 때 언어셋을 지정하는 옵션이 있다. (버전이 레드햇, 데비안 두 개가 같은데 옵션에만 케릭터 셋 지정하는 차이가 있다.)

- 문제: 데비안 unzip 소스를 찾는게 녹록치 않다. 막상 debian 소스라고 받아서 보면 캐릭터 셋 변환 옵션이 포함 안되어 있다. 그렇다고 unzip 소스를 수정하기에는 일이 산으로 가는 느낌이라 패스.

2. PHP 로 동작하는 서버이기 때문에 코드상으로 문제를 푸는게 제일 좋겠다. ZipArchive 라는 클래스를 사용해서 압축을 푼다

- 문제: 여전히 한글 파일 이름이 깨진다. flags 로 옵션을 설정할 수 있기는 한데 써봐도 의미가 없었다.

3. 이쯤되면 슬슬 이게 간단한 문제가 아니라는 느낌이 죄여온다. PHP 쪽 zip_string.c 소스를 연다 (막 가자는거지). ZipArchive 의 구현 부분을 살피는데 내부적으로 오토 인코딩 하는 함수가 구현되어 있다. 그랬다. 지맘대로 utf8 같은 이상한 형태로 인코딩을 진행한다.. 당장 관련된 구문을 ifdef 로 막아버리고 컴파일 후 테스트. 아. 정상적으로 처리 된다. 한탄.

이대로 PHP 의 extension 인 zip.so 를 교체하는 것으로 마무리 하려다가 코드를 조금 더 보니 아까 그 쓰레기 flags 가 if 조건에 간간히 보인다. 일단 정말 그게 쓰레기인지 확인이 필요해서 앞뒤로 살펴보니 쓰레기는 아니었다. 그래. 함수를 설명하고 있는 PHP 문서가 쓰레기였다 (문서 잘 씁시다. ) 여튼 결국은 ZipArchive 클래스를 호출 하는 쪽에 flags 를 제대로 설정해서 문제를 해결 했다.

항상 새로운 경험은 즐겁다. 단순히 압축을 풀고 다시 묶을 뿐인데 한글이 모조리 깨져버렸을 때의 어이 없음이란. 여튼 iconv 나 mb_convert 그런 함수는 도움이 안된다. 내게 필요한 답은 아니었다. 이미 오토인코딩 되어 있는 상태였기 때문.

사실 이게 100% 정답일 수는 없다. 왜냐면 "모든 언어셋에 대해 과연 대응이 가능한가" 하는 문제가 존재하기 때문. 일단 그건 다시 테스트 해보기로 하고. 사실 남이 압축해 놓은 파일을 검사하겠다고 열고 있는 우리 잘못이 크다(?).

댓글
댓글쓰기 폼