애플포럼에 WebDAV를 사용함에 있어서 애로사항에 대한 글을 보고 요즘 관심사이기에 문제를 해결하는 패치를 만들어 올려 봅니다.

WebDAV( Web-based Distributed Authoring and Versioning) (웹기반 분산형 저작 및 버전관리)는 기존의 HTTP프로토콜을 확장해서 웹서버에 있는 파일을 관리(목록 조회, 수정, 삭제, 이동 등)할 수 있게 하는 확장된 프로토콜 셋입니다. Apache웹서버에서도 이 기능을 mod_dav란 확장 모듈을 통해서 지원합니다. 자세한 소개는 커피닉스님의 소개글과 한컴사의 남동선님글을 참고하세요

OS X에서 항상 한글등의 풀어쓰기로 표현이 되는 문자들에서 문제가 되는 Unicode Normalization이 여기에서도 관심사가 됩니다.

만약 OS X에다 아파치 웹서버를 운영하고 mod_dav를 사용하면 결국 접속하는 클라이언트들은 애플에서만 유일하다시피 사용중인 NFD(Normalization Form Decomposed)(풀어쓰기로 최대한 나타내는 형태)로 표현된 유니코드 UTF-8 문자열을 보게 됩니다. 그렇게 되면 NFD를 제대로 표시하지 못하는 운영체제나 WebDAV클라이언트에서는 한글이나 기타 풀어쓰기 문자들이 죄다 망가져 보이거나 풀어헤쳐져 보이게 됩니다. 여기에서만 문제가 있는게 아니라 이 파일을 자신의 컴퓨터에 복사하면 한 폴더에 같은 이름을 가지는 두개의 파일이 생길 수도 있습니다.( 같은 글자이지만 풀어쓰기 모아쓰기된 유니코드의 섞임때문에 )

사실 유니코드 영역에 풀어쓰기와 모아쓰기글자영역이 모두 있는 언어의 경우에 이들(완성된글자 '한' = 초성ㅎ+중성ㅏ+종성ㄴ) 사이를 같은 글자로 볼 것인가 다른 글자로 볼 것인가에 대해서 Unicode consortium과 국제 표준을 규정하는 ISO/IEC 간에 의견차이가 있다고 하던데 정확히는 모르겠네요. 하지만 실제적으로 사용상에 다르게 본다면 앞문단 끝부분에 적었듯이 문제꺼리가 됩니다.

애플에서도 이런 사항에 대해 몇가지 관련 링크가 있습니다.그 중 하나인 커널레벨에서 인코딩 변환을 위한 자료인Text Encodings in VFS를 가지고 위 문제를 해결했습니다. 추가로 맥에서 제공하는 iconv에서도 자신들의 풀어쓰기 인코딩을 'UTF-8-MAC'이라는 이상야릇한 비공식적인 이름으로 지원합니다. 마찬가지로 여기서도 위 링크의 커널레벨 변환을 이용하여서 구현했더군요. 현재 위 링크의 vfs_utfconv.c란 소스코드는 받을 수 없는데 다행히 공개된 OS X의 xnu소스코드안에 찾아보면 파일이 있습니다. 실제 구현은 HFS+에서 사용하는 인코딩 표를 그대로 배열로 만들어서 1:1변환합니다.

본론으로 돌아와서 패치를 어떻게 한 것인지에 대한 내역을 적습니다. 먼저 아래 그림을 보면 mod_dav와 mod_encoding의 메시지 흐름을 볼 수 있습니다.
mod_dav layer

WebDAV표준에 근거해 mod_dav가 UTF-8 인코딩으로 파일명을 보네달라는 요청에도 로컬 인코딩으로 응답하는 클라이언트의 문제 해결을 위해서 일본에서 mod_enconding 모듈이 만들어 졌습니다. 모듈을 올리면 mod_dav가 파일생성등의 요청을 받기전 먼저 가로채서 클라이언트의 로컬 인코딩을 UTF-8로 바꾸어 전달해주는 방식입니다. 하지만 반대의 상황, 즉 그림에서 역시나 보이듯이 mod_dav가 클라이언트에게 파일이름을 전달하는 경우에는 mod_encoding이 작동하지 않습니다. 그래서 이것을 해결하기 위해서 mod_encoding에서 받아들인 요청에 대한 클라이언트 인코딩 설정을 기록하고 이를 mod_dav에 전달해서 mod_dav가 응답을 할 때 제대로 인코딩을 맞추어 주도록 패치를 만들었습니다.

바꾼 내용은 많지 않습니다. 일본에서 맥용으로 만든 패치가 있는데 이것을 기본으로 해서 단순히 NFD -> NFC로만 바꾸는게 아니라 mod_encoding에서 설정한 인코딩으로 다시 변경을 하여 보내도록 요청된 페이지 정보에 추가 인코딩 정보를 넣어서 mod_dav모듈에서 인코딩이 무엇인지 알 수 있게 만들어 vfs_utfconv.c 혹은 libiconv로 인코딩을 바꾸어 주게 만들었습니다. 그렇게 되면 httpd.conf의 mod_encoding.c 에서 설정한 클라이언트별 인코딩 변경이 서버->클라이언트로도 적용 됩니다. 그러면 표준을 따르지 않던 클라이언트에서도 제대로 파일명을 보고 파일을 만들 수 있습니다.

애플포럼에 첨부파일 용량이 작아서 이곳에 백업 및 좀 더 자유스러운 다운로드가 되게 하기 위해 올립니다. 아무래도 모듈 업그레이드가 되면 업데이트 되어야 하므로 소스의 변경 부분만 diff로 만들어서 나중 적용이 쉽게 해 놓았습니다.

소스코드는 mod_encoding 사이트와 애플의 공개 소스코드 사이트에서 받아 왔습니다. 수정이 필요하다면 소스쪽의 라이센스에 따라 자유롭게 사용하시면 됩니다.

같이 첨부한 모듈 바이너리는 10.5.8에서 컴파일한 유니버설 바이너리 모듈입니다. /usr/libexec/apache2에 mod_dav.so, mod_encoding.so 파일을 넣고 httpd.conf 설정을 아래 예제와 비슷하게 해 주면 됩니다.



/etc/apache2/httpd.conf... # 모듈 로드 설정부 LoadModule dav_module libexec/apache2/mod_dav.so LoadModule encoding_module libexec/apache2/mod_encoding.so ... # mod_encoding 옵션 설정부분 <IfModule mod_encoding.c> EncodingEngine on # 인코딩 변경 활성화 여부 SetServerEncoding UTF-8 # 기본 서버측 인코딩 NormalizeUsername on #윈도우처럼 '워크그룹\아이디'형식의 사용자명을 아이디만 걸러줍니다. DefaultClientEncoding UTF-8 CP949 # 아래에 클라이언트별 인코딩 설정이 없는 경우 기본 인코딩을 적용할 값 # AddClientEncoding "UserAgent를 매칭할 문자열 정규식" "하나이상의 여러 시도할 인코딩" AddClientEncoding "Microsoft-WebDAV*" UTF-8 CP949 # MS Windows XP AddClientEncoding "RMA/*" CP949 # RealPlayer AddClientEncoding "DataFreeway/.*" CP949 # datafree client AddClientEncoding "WebDAVFS/*" UTF-8-MAC # OS X 인코딩 변환을 무시할 것은 이렇게 인코딩을 지정해도 됩니다. </IfModule> ...


추가로 UTF-8-MAC 인코딩을 다룰 수 있게 패치한 리눅스에서 컴파일되는 libiconv도 함께 올립니다. 단 libiconv의 중간 변형단계를 거치는 특성상 유니코드 Surrogate pair의 변환이 되지 않으므로 U+10000 이상의 문자를 변환시도시 실패하게 됩니다.
Posted by trip2me
,