On Encoding URI with Non-ASCII characters

History of Standards concerning URI with Non-ASCII characters

1994년의 URI를 정의하는 RFC1630 ë˜ëŠ” URL을 정의하는 RFC1738을 ë³´ë©´ 알 수 있듯이, ì´ˆê¸°ë¶€í„° URI는 Non-ASCII 문자를 포함할 수 없다. 현재 우리가 Percent Encoding이라고 부르는 escaping 방식은 단지 공백이나 ì œì–´ 문자들 그리고 7bit 범위를 넘어서는 unsafe  문자들을 표현하기 위해 정의 되어있었으나, 어떤 문자 인코딩을 사용해야하는지는 정의되지 않았으며, I18N에 대해서 명확하게 언급하지는 않았다.

1998년, IETF Policy on Character Sets and Languages (RFC2277)에서 I18N을 위해 모든 프로토콜에서 모든 문자 데이터는 문자셋(charset)을 명시해야하며, UTF-8 문자집합과 인코딩을 사용할 수 있어야 한다고 명시됨으로써 인터넷 프로토콜들에 대한 ê¸°ë³¸ì ì¸ I18N 가이드라인이 만들어졌다. 그럼에도 불구하고, 이후에 업데이트된 URI를 정의하는 1998년의 RFC2396은 Escaped Encoding에 관해서 좀 더 자세하고 정밀하게 설명하고 있지만 역시 Escaped Encoding을 적용할 때 어떤 character encoding에 대한 언급은 없었다. 다행히 1999년의 W3C에서 출판한 HTML 4.01의 Appendix에서는 Non-ASCII 문자를 UTF-8로 표현하도록 ‘권장’하게 되었다. 2001년에 역시 W3C쪽 멤버 한 사람이 19th IUC(International Unicode Conference)에서 Non-ASCII 문자에 대한 UTF-8ê³¼ Percent Encoding 사용을 공식화하는 IRI (Internationalized URI)에 관한 발표를 했고, 이는 IRI specification 작업으로 이어졌다. IRI의 결과가 RFC로 결실을 맺은 것은 2005년의 RFC3986이었다. 이 때에서야 scheme-specific한 문자 인코딩에 관한 언급과 함께 새로운 scheme이 UCS로 된 텍스트를 정의할 때는 UTF-8ê³¼ Percent Encoding을 사용해야한다는 언급이 들어가게 되었다. (http scheme은 Generic URI를 사용하므로 UTF-8로 인코딩되어야함을 의미하는 것으로 해석하는 것이 적절할 것이다.)

Web Browser’s Perspective

한편, 웹페이지들의 수가 증가하고, Non-ASCII 문자들을 포함한 URI들이 한국을 포함한 비영어권의 ë§Žì€ 웹페이지들에 들어가면서, 브라우저는 이들을 어떻게 처리해야할지 고민해야만 했다. 일반적으로, 웹브라우저는 사용자가 페이지 내의 URI을 클릭했을 때, ê·¸ URL에 해당하는 페이지를 보여주기 위해서, URI에 명시되어있는 서버로 URI을 보내야한다. 브라우저가 이 URI들을 어떤 형태로 서버로 보내느냐에 따라 ì„¸ê°€ì§€ì˜ 방식으로 나눌 수 있다.

  1. Non-ASCII 문자들을 웹페이지의 인코딩대로 인코딩된 채 (그대로 포함한 채) URL를 웹서버로 보낸다.
  2. Non-ASCII 문자들을 웹페이지의 인코딩을 사용하여 Percent Encoding한 후 웹서버로 보낸다.
  3. Non-ASCII 문자들을 정해진 인코딩 (e.g. UTF-8) 을 사용하여 Percent Encoding한 후 웹서버로 보낸다.

1번안의 방식은 Non-ASCII 문자가 URI에 들어가서는 안된다는 표준에 직접적으로 배치될 뿐만 아니라,

  • 웹서버 또는 CGI 등의 웹 어플리케이션이 웹페이지의 문자 인코딩과 같은 문자 인코딩을 사용해서 URI를 디코딩하도록 ì„¤ì •ë˜ì–´ 있거나,
  • 우연찮게도 파일시스템 등에서도 같은 인코딩을 사용하고 있어야한다는 제약이 있다. (즉, 디코딩을 아예 하지 않음)

웹서버가 인코딩에 대한 지원이 빠져있는 trivial한 구현인 경우 후자의 경우가 ë°œìƒí•˜ê²Œ 된다. 이를테면 EUC-KR 웹페이지에서 나온 EUC-KR URI를 웹서버에서 그대로 넘겨주더라도 ë‹¤í–‰ížˆ EUC-KR 파일 시스템이라서 제대로 웹페이지가 보여졌을뿐, 파일시스템의 인코딩을 UTF-8로 변경하려면, 웹페이지의 인코딩까지 바꿔야한다.

2번안의 경우는 1번안의 경우와 비슷하나, 1번안에서의 후자와 같은 경우는 발생할 수 없다. 제대로 구현된 웹서버라면 URI의 해석이 íŠ
¹ì • 인코딩(Encoding A)으로 설정되어있거나 페이지의 인코딩을 따른다고 하더라도, 서버의 파일시스템이 어떤 인코딩(Encoding B)인지 인지한 후 적절하게 인코딩을 변환(A->B)해줄 것이다. 하지만, 현실적으로 웹서버에서 이러한 두가지 인코딩을 모두 명시하는 것은 상당한 복잡도를 야기시킨다. 또다른 문제는, ì´ëŸ° 웹서버로 Non-ASCII 문자를 포함한 URI를 생성해서 보내줄 때는 웹서버가 어떤 인코딩을 사용하는지 클라이언트 즉, 웹브라우저나 웹사용자가 인지하고 있어야한다는 것이다. URI가 웹페이지에서만 클라이언트에게 주어진다면 웹페이지의 인코딩을 자동적으로 따름으로서 이러한 문제를 해결할 수 있으나, URI의 interoperatibility를 크게 떨어뜨린다. í´ë¼ì´ì–¸íŠ¸ê°€ Non-ASCII 문자로 URI를 생성하는 일이 힘들어질 뿐만 아니라, 서버측의 문자 인코딩으로 인코딩된 URI를 클라이언트 측에서 디코딩해서 보여줄 수도 없게된다. (trivial한 클라이언트라면 서버측의 인코딩을 무시하고 클라이언트의 인코딩을 사용해서 디코딩함으로써 부분적으로 보여주는 시도를 할 수도 있을 것이다.) 

3번안의 경우에는 드디어 URI는 í´ë¼ì´ì–¸íŠ¸ì¸¡ì˜ 인코딩, 서버측의 인코딩과는 독립적이고, 클라이언트와 서버 모두 ì¶”가적인 정보없이 URI를 인코딩하고 디코딩할 수 있게된다. 따라서, 부가적인 설정이 필요하지도 않을 뿐더러, URI를 사용자에게 친숙한 형태로 디코딩해서 보여주기도 쉬울 것이다. 2번안에 비해서 크게 추가되는 비용도 없다.

One Character Encoding To Rule Them All

여기서 핵심은 RFC3986의 2.5절에서 언급하듯이, URI의 생성과 전송과정에서는 하나 이상의 문자인코딩이 관여할 수 있다는 것이다. 이를 해결하기 위한 가장 직관적인 방법들은 바로 ë¬¸ìž 인코딩을 명시하거나, 하나의 통일된 문자 인코딩을 정하는 것이다. 현재의 표준 명세상 URI에 문자 인코딩을 명시할 수 있는 메커니즘이 존재하지 않기 때문에 실현 가능한 것은 후자의 방식이고, 하나의 통일된 문자 인코딩은 바로 UTF-8이 되는 것이다. ê·¸ë¦¬ê³  그것이 3번안이 우리가 ë³´ê³  있는 해답인 이유다.

Internet Explorer 7 vs. mod_url

Internet Explorer ì˜µì…˜ì„ 세심하게 들여다보지 않았더라도, Internet Explorer가 URI들을 UTF-8로 인코딩하도록 하는 옵션이 존재한다는 사실은 한국인들에게는 잘 알려져있을 것이다. ì•„마도, 대부분의 사람들은 이 옵션을 꺼야 한국의 웹페이지들을 정상적으로 브라우징í•
  수 있었던 경험을 가지고 있을 것이다. 물론, 특히 URI에서 Non-ASCII 문자, 즉 한글을 사용하는 경우 말이다. 이유는 위에서 설명한 1번 방식이나 2번 방식에 해당하는 ì›¹ë¸Œë¼ìš°ì €, 웹서버들이 웹을 지배하고 있었기 때문이다. 적어도 Internet Explorer 5 부터 이 옵션이 있지만, Non-ASCII 문자를 포함하는 URI들을 위해서는 이 옵션을 끄도록 권장하고 있다.

내 기억으로는 이 옵션이 처음 등장했을 때는 (아마도 한글판에서만?) ê¸°ë³¸ì ìœ¼ë¡œ 꺼져있었던 것 같다. 그런데 언젠가부터인가 이 옵션이 기본적으로 켜지면서 많은 한국 사이트들에 문제가 발생했고 이 때 mod_url이 등장했다. mod_url은 UTF-8로 인코딩되어 웹서버로 들어오는 URI를 원하는 인코딩 (e.g. EUC-KR)로 변환하여 redirect 시킴으로써 웹 브라우저가 강제로 특정 인코딩을 사용하도록 만드는 일종의 트릭이었다. 이러한 방식이 Internet Explorer 6까지는 잘 동작했지만, Internet Explorer 7가 redirect된 URI도 UTF-8로 인코딩하게 ë˜ë©´ì„œ 이 트릭은 동작하지 않게 ë˜ì—ˆë‹¤. ê²°êµ­, mod_url을 사용해 문제를 해결했던 웹서버들에 다시 문제가 발생하게 되었다. (mod_url의 자세한 ë™ìž‘ 방식이나 IE 7ê³¼ 관련한 문제에 대해서는 mod_urlê³¼ IE7이라는 글과 ie7 utf-8 bug 한글주소 요청 버그라는 글을 참고하라.) Internet Explorer 7의 이러한 변경을 ‘버그’로 부르는 것은 잘못된 것이다. Internet Explorer 7은 좀 더 표준에 호환되는 조치를 취했을 뿐이고, 기존의 문제를 트릭으로 해결한 곳들만 문제가 발생한 것이다.

Internet Explorer 7 vs. Firefox

현재 Internet Explorer 7은 기본적으로 URI를 UTF-8로 Percent Encoding한다. Firefox는 Percent Encoding은 하지만, UTF-8로 하는 것이 아니라, 실행되는 환경의 기본 인코딩 (예를 들어, 한국어 Windows라면 EUC-KR, 현대의 리눅스 환경이라면 UTF-8)으로 Percent Encoding을 한다. 반면에, Percent Encoding을 하는 부분에서도 두 브라우저는 차이가 난다. Firefox는 URI 전체를 Percent Encoding하지만, Internet Explorer 7은 ? 이후의 부분 즉 query 부분은 Percent Encoding하지않고 그대로 보낸다. ê²°êµ­, 한글이 query에 포함되고, 이에 대한 인코딩을 EUC-KR로 가정하고 개발한 웹애플리케이션이 있다면, 리눅스에서 실행된 Firefox에서는 오동작할 거란 얘기다. 물론 두 브라우저 모두 애초에 제대로 인코딩 되어있는 URL은 그대로 처리하기 때문에, 이 문제를 피하기 위한 방법은 애초에 링크를 Percent Encoding하는 것이지만, 그런 정도로 신경을 쓴다면 애초에 이런 문제가 발생하지는 않았을 것이다. ê²°êµ­, Internet Explorer의 차기버전, IE8이나 IE9 ì¦ˆìŒì—ì„œ 이 동작도 표준 호환되게 변경되면 그제서야 사람들은 IE를 욕하면서 제대로 대처할 것이다.

Representing URIs as Decoded Form

사이트 내의 한글을 포함한 URI들을 UTF-8로 인코딩하는 작업을 하게되면 사용자들은 ê²°êµ­ 읽기 힘든 URI들만 보게 된다. Internet Explorer의 상태표시줄에는 디코딩된 형태의 URI를 보여주긴 하지만, 아무도 그곳은 보지 않는다. 만약 웹 브라우저들이 사람들이 URI를 ê°€ìž¥ 자주 접하는 ì£¼ì†Œí‘œì‹œì¤„에 디코딩된 형태의 URI를 보여준다면, 브라우징 경험은 상당히 향상될 것이다. http://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD보다는 http://ko.wikipedia.org/wiki/대한민국이 좋지 않은가. 이미 구글과 같은 검색엔진에서는 검색 결과를 보여줄 때 디코딩된 형태로 보여주고 있다. (검색 ê²°ê³¼ anchor의 URI는 인코딩된 형태)

Closing

아직 I18N-aware하지 않는 시스템들이 많지만 개발자라면 ì´ì œë¶€í„°ë¼ë„ I18Nê³¼ 인코딩에 대해서 잘 이해하고 있어야한다. 문자 인코딩에 관한 이해가 부족한 개발자들을 너무나 자주 ë³¼ 수 있다. 상대방이 문자 인코딩에 관해 모른다면 어떻게 URI 인코딩에 대해 설명을 하겠는가. ê·¸ 사람은 과연 위의 문제들을 트릭 이외의 것으로 해결할 수 ìž
ˆì„까. 개발자에 있어서 의외로 언어나 라이브러리의 사용법은 중요하지 않다. 쉽게 배울 수 있기 때문이다. 언어나 라이브러리 ì¡°ì°¨ 혼자 공부하지 못한다면 개발자라는 직업은 그만두라고 하고 싶다. ì „에 언급했던대로 프로그래머에게 가장 중요하고, 교육 과정에서는 강조되면서도 쉽게 얻어지지는 않고, 또 인터뷰에서는 아무도 신경안쓰는 것은 바로 Abstraction에 관한 것들이다. 기본적인 개념들을 이해하지 못하고, 새로운 개념들을 만들어낼 수 없다면, 동작하는 것을 잘 만드는 인센티브를 많이 받는 개발자는 될 수 있어도, 다른 개발자들에게 인정받는 훌륭한 개발자는 될 수 없다. 물론 자기만족이 어디에서 나오는지에 관한 개개인의 선택이겠지만.

한편, URI 인코딩에 관한 여러가지 문제들을 ë³´ë©´ 웹 브라우저와 같은 중요한 애플리케이션은 제대로 동작하는 것도 중요하지만, 표준의 준수도 중요하다는 것을 느낄 수 있다. 비표준적인 형식을 한가지 허용할 때마다 얼마나 많은 사람들이 í˜¸í™˜ì„± 문제 때문에 골머리를 앓고 비용을 낭비했을까. 애초에 동작하는 버전을 만들 수 있었다면 아무 문제가 없었을텐데 말이다. 중요한 애플리케이션일 수록 표준 준수 여부는 면밀하게 관찰되어야하고 준수되지 않는 것은 비판되어야 마땅하다.

“On Encoding URI with Non-ASCII characters”에 대한 2개의 생각

  1. Firefox의 URI encoding 방식

    On Encoding URI with Non-ASCII chracters 글에 오류가 있었습니다. Firefox는 현재 (2.0) URI를 UTF-8로 Percent-encoding하지 않습니다. (이 사실은 윤묵형이 지적해주셨습니다.) Firefox의 about:config 페이지를 보면 URI encoding에 관한 두개의 옵션이 있습니다. network.standard-url.encode-utf8: HTTP 요청으로 전달되는 URI를…

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.