euc-kr 과 자바스크립트. 파라미터 전달에 한글이 깨져요? 개발자로서의 Berry

  웹 개발을 하다보면 문자셋 이라는 거대한 똥덩어리에 자주 부딪히게 됩니다. Java기반의 Servlet, JSP는 덜한편이며 구버전의 PHP에서는 거의 죽음입니다. 아무튼 PHP는 언어상으로는 유니코드에 대한 올바른 지원을 하지 않으니까요. 그 세계에서 문자열은 그저 배열일 뿐입니다. PHP에서 한글 '가나다'의 문자열 길이를 측정하면 3을 반환하는 것이 아니라 무려 6에서 9를 반환해줍니다! iconv와 같은 모듈이 귀찮은 문자셋 문제에 대해 우리를 도와주긴 하지만 그것만으로 석연치 않아 유니코드를 UTF-8로 전환하는 함수를 짜던 기억이 나는군요. 

  자바스크립트는 기본적으로 유니코드로 문자열을 취급합니다. 범세계적이죠. 그런데 euc-kr 인코딩을 사용하는 우리네 서버에서는 귀찮은 문제들이 발생하게 됩니다. 주로 AJAX나 자바스크립트를 통한 파라미터 전달시 이런 문제를 볼 수 있는데 이런 문제와 전혀 마주치지 않는 분들도 계실겁니다. 간혹은 대충 때려 맞춰도 통하는 법이죠. 그런데 euc-kr은 도무지 엉망진창입니다. 아름다운 우리 한글 쀍도 올바르게 표현하지도 못합니다. 규칙이라곤 찾아볼 수 없는 CP949님에게 손을 빌려야만 비로서 쀍을 나타낼 수 있습니다. 이 더러운 EUC-KR에 대한 저의 한탄이 또다른 글에 있으니 기회가 되시면 한 번 보셔도 좋습니다.(http://thinkberry.co.kr/1532 : 네 개념을 체크해제 하세요? URL을 항상 UTF-8로 보냄) 아무튼 EUC-KR 웹서버에서 AJAX로 통신할 때 한글이 깨지는 것은 너무나 당연합니다. AJAX는 UTF-8로 파라미터를 전송하거든요.

  인터넷에서 AJAX를 하는데 한글이 깨져요, 자바스크립트에서 한글을 보낼때 깨지지 않게 보내고 싶어요. 라고 검색을 하면 아주 친절한 답변들이 많이 나옵니다. "encodeURI, encodeURIComponent, escape라는 내장 함수가 있는데요 escape는 역사속 퇴물이니 이제 그만 사용하시구 encodeURI로 인코딩해서 보내면 되요"  아주 줄기차게 나오지요. 하하하 Copy&Paste족 여러분! 저 함수가 하는 일이 뭔지는 아십니까? 

  혹시 유니코드를 모르는 분 계신가요? 유니코드는 기본적으로 2바이트로 전세계 문자를 표현하는 범세계 문자셋입니다. 사실 양키들은 7비트면 모든 글자를 표현하고 남아돌아 특수문자도 집어넣는데 짱개들은 혼자써도 2바이트도 모자라죠. 자바스크립트는 바로 이 유니코드가 기반입니다. 따라서 페이지의 인코딩타입이 EUC-KR일지라도 한글 문자열을 유니코드로 취급합니다. 대단하죠? 이제 자바스크립트에서 encodeURI함수의 역할을 설명하면 유니코드형식의 문자들을 (1)UTF-8로 변환하여 (2)각 바이트별로 16진수로 쪼갠다음 (3)그 앞에 %기호를 붙여서 반환. 입니다. 한마디로 encodeURI함수의 결과 값은 %붙여놓은 16진수형식의 UTF-8이다 라는 이야깁니다.


   가나다 를 유니코드로 나타내면 이렇습니다.(16진수) AC00 BC98 B2E4
   이를 UTF-8로 변환하면 이렇게 되겠죠. EAB080 EB8298 EB8BA4

  위키에 보시면 UTF-8에 대해 아주 잘나와있으니 기회가 되면 검색해보시기 바랍니다.


    UTF-8이라는 친구는 양키놈의 언어는 1바이트로 쫀쫀하게 표현하지만 한글은 3바이트라는 관대함으로 표현하니 2바이트의 유니코드보다는 길이가 조금 길어집니다. 그럼 가나다를 자바스크립트 encodeURI 함수로 인코딩해보겠습니다.

   가나다(UTF-8) => EAB080 EB8298 EB8BA4
   encodeURI("가나다") => %EA%B0%80%EB%82%98%EB%8B%A4


  어때요. 이제 느껴지시나요?  그런데 UTF-8 이라는 문자셋은 unicode에 대한 또다른 표현이지만 우리 웹 페이지는 대부분 어떤 문자셋을 이용하죠? 바로 euc-kr이지요! 완성형 문자셋의 대명사 euc-kr과 범세계 공통 문자셋 unicode는 호환이 될까요 안될까요? 될리가 없지않습니까?
   
   참고로 가나다를 EUC-KR로 표현하면 이렇습니다. B
0A1 B3AA B4D9   

답이 나왔습니다. UTF-8과 EUC-KR은 서로다른 문자 인코딩 방식이므로 호환이 되지 않습니다. EUC-KR은 유니코드나 UTF-8과는 전혀 무관한 별개의 문자셋입니다. 도무지 호환이 될 구멍이 없죠. 그런데 AJAX의 핵심객체인 XMLHttpRequest는 무조건, 무조건. 무조건! UTF-8로 파라미터를 전송합니다. 이것은 페이지의 문자셋이나 파일의 인코딩 방식과 전혀 상관없습니다. 이는 지극히 정상인데 범세계 표준 인터넷 문자셋은 UTF-8이기 때문입니다. 그래서 EUC-KR서버에 자꾸 UTF-8 파라미터가 넘어오니까 한글이 깨지는 겁니다.



  문제의 원인은 알았습니다. 이제 솔루션을 제시해야죠. AJAX와 EUC-KR 문자셋 서버간에 호환할 방법은 없는 걸까요? 2가지 방법이 있겠네요.

   1) 자바스크립트에서 UTF-8 문자열을 EUC-KR로 변환하여 서버로 넘긴다.
   2) 서버상에서 UTF-8로 넘겨받은 파라미터를 직접 EUC-KR로 변환한다.

  1번 방법은 좀 어려워 보입니다. 자바스크립트에서는 애초에 컨버트 함수를 지원하지도 않기 때문에 직접 매핑테이블을 만들어야 하는데 자바스크립트의 용량이 너무 커져 웹 페이지 로딩이 길어지기 때문입니다. 2번은 조금 더 쉬워보이는데요. 대부분의 언어는 컨버트 함수를 지원합니다. php만해도 iconv라는 함수를 통해 UTF-8 인코딩을 euc-kr로 쉽게 전환할 수 있습니다. 

  2)번 방법을 사용할때는 주의하세요. euc-kr은 모든 unicode를 표현하지 못합니다. 경우에 따라 에러가 날 수도 있습니다. 하지만 보편적인 경우라면 큰 문제 없이 사용할 수 있을 겁니다. 

 하지만 가장 좋은 방법은 3번, 웹 서버에서도 그냥 UTF-8 문자셋을 이용하는 겁니다! 페이지 파일을 UTF-8로 저장하고, META태그의 문자셋 값을 UTF-8로 지정한다면 바로 이것이 표준을 지향하고 똥덩어리도 피하는 가장 좋은 방법입니다.




THinkBerry의 생각열매를 함께 나눠요. ThinkBerry.co.kr
TAG

Leave Comments


profileThinkberry에 오신것을 환영해요~ 

Recent Trackback

오늘:
167
어제:
135
전체:
76,325