제2의 비엔지니어 인생관을 꿈꾸며

Posted
Filed under Study

웹 문서 인코딩의 시련
웹 개발에  있어 인코딩의 문제는, 아직도  헛갈리거나,  그때그때? 구글링을 통해서 해결 하곤 한다.
(그리고 또 다시 문제에 봉착하면, 또 다시 구글링을 통해 해결한다.  본인이 그렇타 ㅠ)

웹은 '페이지' 이고 '문서' 이다.  문서 한 페이지 한 페이지 마다,  페이지 속성에서 언어설정이 가능하다. 유니코드가 표준화(?) 되면서, 기존에 euc-kr 을 고수하던 페이지들은 유니코드로 많이 변경되었다. 나름  유니코드로 자리잡아가는 과도기가 끝을 지나고 있기는 하다. 하지만,  아직도 업무적으로 또는 기존 솔루션의 유지,  PG사 리턴값 , 서드파티 업체에서는 제공되는 API 나 서브밋 페이지들에서 넘어오는  정보들이 인코딩(특히 한글)이
 맞지 않아  깨진 문자들때문에 고생했던 경험들이 한 두번씩 있으리라 생각된다.

그래서 이번기회에 완전히 이해하고 넘어 가고자 정리했다. (찾아보고, 정리하면서 본인도 공부가 되어 좋다.)


웹에서 전달되는 인코딩의 종류
웹 페이지는 특성한 클라이언트 페이지에서 서버로 전달하는 구조를 가지고있다. 그게 아작스건 일반 웹폼이던 뭐든  기본구조이다. 그래서 인코딩은 크게 클라이언트 인코딩 / 서버인코딩으로 나눌 수 있다.  이미 알고있는 이야기이지만, 클라이언트 단은 javascript  , 서버단은 asp , asp.net jsp , php 기타 등의 서버 페이지들 이다. 클라이언트에서 전달된 text 정보들이 서버단으로 넘어가면서 서로 다른 인코딩 페이지로 구성되어 있다면 깨지기 마련이다. 그래서 항상 그렇게 이야기를  많이한다. "Url 인코딩" 또는 "인코딩" 해너 넘겨주세요.

ㆍJavascript(클라이언트) Encode/Decoding


javascript 에서의 3가지 인코딩 함수가 있다.

(아래설명에 있지만 escape는 더 이상  사용하지 않는 함수로 구분되어있다.)

- escape (
unescape)
- encodeURI(decodeURI)
- encodeURIComponent(≠decodeURIComponent)

참고로 테스트 문자열은 영/숫/한글 혼영 + 특수문자 + URL 문자열로 일부 넣어봤다. (아래참조)
테스트 문자열 "test__@__$__#__&__/__?__;__=__\__1234_한글"

뒤에서 따로 디인코딩을 해보겟지만 (≠unescape) 이런식으로 디코딩 함수를 표기해 두었었으니 참고하자. 복잡한건없다. 아래코드를 작성하여 실행해보자.

<!DOCTYPE Html>
<html>
<body>
 
<script language="javascript">
 
      var str = "test__@__$__#__&__\__/__1234_한글";
  
      document.write("<B>원본 : </B>" + str );
      document.write("<BR><BR><BR>");
      document.write("<B>escape :</B> " + escape(str)); 
      document.write("<BR><BR><BR>");
      document.write("<B>encodeURI :</B> " +encodeURI(str));
      document.write("<BR><BR><BR>");
      document.write("<B>encodeURIComponent : </B>" + encodeURIComponent(str));
 
 </script>
</body>
</html>


[결과]
사용자 삽입 이미지

먼저 "__" 언더바 2개로 문자를 각각 구분하였다.(언더바는 영문자와 같이, 인코딩이 따로 되지않아서, 데이터를 육안으로 구분하기 쉽게 하게 위해넣었다.


● escape 와 encdoeURI (encodeURIComponent) 

크게보면 두 가지의 경우  인코딩 방식이 다르다. 
첨언하자면, escape는 더 이상 표준(?)함수가 아닌, 하위호환성을 위해 유지되고있는 함수일뿐이므로, 사라질 수도있으니 encodeURI 관련 함수를 이용하도록 하자

escape는 유니코드 인코딩 방식이고 , 
encodeURI (encodeURIComponent) URI 인코딩 방식이다.

1234 숫자뒤에 한글이인코딩된것을 보면 알수있다. escape 의경우  한글과 일부 특수문자들을 인코딩 하는것을  알 수 있다. 영문, 일부특수문자 , 숫자등 모두 인코딩 하지않는다. 그대로 전송한다. 자세히 히보면  $ 나 # 의 1byte 문자의경우 %23 한글처럼 2byte의 경우 한 %uD55C 로 인코딩되는 것을 알수있다.
(ASCII 코드를 유니코드로 인코딩 한다.)


encdoeURI 와 encodeURIComponent 경우 한글을 인코딩하는 방식은 같으나. encdoeURI 는 URL 에 사용되는 몇가지 특수문자(아래참조) 를 제외하고 인코딩 되며, encodeURIComponent 는 그것을 포함한 문자들을
인코딩 한다.
구분 인코딩 안되는 문자
encodeURI
      ; , / ? : @ & = + $ – _ . ! ~ * ‘ ( ) # a-z 0-9
encodeURIComponet

 – _ . ! ~ * ‘ ( ) a-z 0-9

솔직히 저런거 외우는사람 몇이나 될까? 그냥 URL 쿼리 전송시 사용되는 
.aspx?a=1&b=c&#aaa  에서 ?,&,# 등이 인코딩 안되는건 encodeURI 모두 인코딩되는건 encodeURIComponent 라고 생각하면 간편하다. :)

여담으로,  회원가입/로그인시  Ajax(UTF-8) 처리로 인해 서브밋(EUC-KR) 페이지 인코딩이 맞지 않는다면 encodeURIComponent 로 인코딩하는것이 좋다. 패스워드에는 특수문자를 이용할 확률이 높기때문이다.
encodeURI를 사용 할 경우 몇몇의 특수문자들은  웹서버가 인코딩하기때문에 원하지 않는 문자열이 저장된다.


 ㆍAsp , Asp.net (서버) Encode/Decoding


ASP 와 ASP.Net 은 또다른 인코딩 방식으로 출력값을 리턴한다.
ASP 의 경우 javascript 인코딩된 (위의 3가지) 값들을 디코딩하는 함수가(내장함수) 사실없다. 만들어써야한다. 대신 runat="server" 로 javascript 함수를 그대로 쓸수있다.


ㆍ먼저 ASP.Net을 살펴보자.
(화면이 깨지는관계로 이미지로 대체했고, 소스는 다운받게해두었다.)
사용자 삽입 이미지
asp.net 인코디/디코딩 소스

 

(일단 주석은 무시하고 인코딩만 해보자)


[ Asp.net 결과 ]
사용자 삽입 이미지







javascript 결과와 다른방식으로 인코딩한다.


ㆍ ASP(classic ASP) 방식을 살펴
<% Response.Write(server.urlencode("test__@__$__#__&__/__?__;__=__\__1234_한글")) %>



[ classic ASP 결과]
사용자 삽입 이미지




 

서버측에서 인코딩된 문자열을 클라이언트측에서 디코딩할수 있는 함수는없다(내장함수로는안된다)
단 클라이언트 측에서 인코딩된 문자열을 서버측에서는 가능한다.
ASP.Net 의 경우 HttpUtility.UrlDecode 함수 하나면 unescape  / decodeURI / decodeURIComponent 를 모두 대체가 가능하다. classic ASP 의 경우 ruat=server 속성을 이용해
자바스크립함수를 서버함수로 따로 각각 3개다 모두 만들어줘야한다.

ㆍ마지막으로 classic ASP 와 ASP.Net 의 디코딩 화면을 확인하면서 마치기로 하자

 Asp.net 에서 HttpUtility.UrlDecode함수의 활용

사용자 삽입 이미지
(위에 asp.net 소스를 다운받아 주석을 풀면 디코딩이 된다.)

[ 결과 ]
사용자 삽입 이미지










javascript 으로 인코딩된 3가지 값들이 함수 1가지로 모두 디코딩 되는것을 볼 수 있다.




ㆍ ASP(classic ASP) 방식을 살펴보자 
    Classic ASP 에서는 Runat=server 를 활용하여 javascript  함수를 서버용으로 만들어줘야한다.
 <%
      <script language="javascript" runat="server">
             function  asp_unescape(s) {    return unescape(s);  }
             function  asp_decodeURI(s) {    return decodeURI(s);  }
             function  asp_decodeURIComponent(s) {    return decodeURIComponent(s);  }
      </script>
      <%
         Response.write("asp_unescape" & _
                                    asp_unescape("test__@__%24__%23__%26__/__%3F__%3B__%3D____1234_%uD55C%uAE00") &  _
                                    "<BR><BR>")
         Response.write("asp_decodeURI" & _
                                    asp_decodeURI("test__@__$__#__&__/__?__;__=____1234_%ED%95%9C%EA%B8%80") & _
                                    "<BR>
 <BR>")
        Response.write("asp_decodeURIComponent" & _
                                       asp_decodeURIComponent("test__%40__%24__%23__%26__%2F__%3F__%3B__%3D____" & _      
                                      "1234_%ED%95%9C%EA%B8%80")& "<BR><BR>")

%>

<결과>
사용자 삽입 이미지
  runat 서버로 추가된 javascript 함수들이 asp 내에서 정상적으로 작동하는것을 볼수있다

2018/11/30 10:47 2018/11/30 10:47