본문 바로가기

etc

URI encoding

반응형

encodeURIComponent는 javascript에서 string을 UTF-8로 인코딩해주는 함수이다.

보통 http 로 주소를 전송할 때, 넘겨야 하는 변수 값 중간에 &나 #이 있으면 변수값이 제대로 전달되지 않기 때문에

인코딩을 해줘야 할 필요성이 생기는데, javascript에서 인코딩 하는 방식은 몇가지가 더 있지만,

서버에서 해석이 가능한 인코딩은 encodeURIComponent 함수를 이용하는 방법 뿐이다.

그러나 서버의 기본 문자 인코딩 타입이 UTF-8이라면 아무런 문제 없이 한글이 깨지지 않지만,

그 외의 인코딩 타입이 기본 문자셋이라면 한글이 깨지게 된다. (특히 서버가 MS949로 되어있는 경우-)

왜 깨지는 것일까-? 복원할 방법은 없는 것일까.. 를 고민했다.

문자가 깨지는 상황을 재현하기 위해 테스트 파일을 만들어봤다.

 

public void test() throws UnsupportedEncodingException {

  String a = "건강·의학";
  a = URLEncoder.encode(a, "UTF-8");
  log.info("encode : " + a);  //%EA%B1%B4%EA%B0%95%C2%B7%EC%9D%98%ED%95%99
  
a = URLDecoder.decode(a, "MS949");
  log.info("decode : " + a);  //嫄닿컯쨌?쓽?븰
  a = URLEncoder.encode(a, "MS949");
  log.info("encode : " + a);  //%EA%B1%B4%EA%B0%95%C2%B7%3F%9D%98%3F%95%99
  a = URLDecoder.decode(a, "UTF-8");
  log.info("decode : " + a);  //건강·??????

}

 

처음에 UTF-8로 인코딩 한 상태가 javascript에서 encodeURIComponent함수를 이용하여 인코딩한 결과와 같다.

그리고 서버에서는 MS949로 디코딩을 자동으로 수행하게 된다. (서버의 기본 캐릭터 셋이 MS949일 때)

그래서 결국 "건강·의학"이라는 글자는 "嫄닿컯쨌?쓽?븰" 이라는 알 수 없는 알 수 없는 글자로 깨지게 되고,

이를 다시 복구하기 위해 MS949로 인코딩을 해보았지만,

처음 javascript에서 encodeURIComponent 함수를 이용하여 인코딩 한 결과와 정확히 일치하지 않는다.(위에 빨간글자)

UTF-8로 인코딩한 한글 문자열을 MS949로 디코딩할 때는 이미 캐릭터의 byte값이 알 수 없는 정보로 저장되며,

다시 인코딩을 한다고 해서 원복이 되지 않는 것 같다.

 

해결방법은 아래 3가지이다.

1. UTF-8로 인코딩 하지 않고 그냥 전송한다.

  이 방법은 변수의 값을 온전하게 전송할 수 없기 때문에 문제가 된다.

2. MS949로 인코딩하여 전송한다.

  불행히도 javascript에서는 MS949인코딩을 지원하지 않는다.

  구글링을 해보면 개인적으로 javascript의 인코딩을 지원해주는 유틸들을 만들어서 배포한 걸 볼 수 있는데, 완벽하지 않다. 잘못 쓰면 낭패본다.;; 

  서버에서 MS949로 인코딩하여 내려보내주고, 그 데이터를 활용하면 되지만,

  html에서 script로 동적으로 생성되는 문자열을 인코딩해야 한다면, ajax를 활용해서 서버로부터 MS949변환된 문자열을 가져와야 한다.

  하지만 매번 ajax 호출이 힘든 환경도 있을 것이다..

3encodeURIComponent 함수를 두번 사용하여 UTF-8로 두번 인코딩 한 후에 서버에서 UTF-8로 한번 더 인코딩을 한다.

  아래 코드를 참고한다.

 

 public void test() throws UnsupportedEncodingException {

  String a = "건강·의학";
  a = URLEncoder.encode(a, "UTF-8");
  a = URLEncoder.encode(a, "UTF-8");
  log.info("encode : " + a);//%25EA%25B1%25B4%25EA%25B0%2595%25C2%25B7%25EC%259D%2598%25ED%2595%2599
  a = URLDecoder.decode(a, "MS949");
  log.info("decode : " + a); //%EA%B1%B4%EA%B0%95%C2%B7%EC%9D%98%ED%95%99
  a = URLDecoder.decode(a, "UTF-8");
  log.info("decode : " + a); //건강·의학

}

 

두번 인코딩을 하기 때문에 변수 명도 길어지고, 받는 쪽에서도 디코딩을 한번은 해야 하기 때문에 그다지 나이스한 방법은 아니지만,

어쨌든 문제 해결은 되고, 코드 복잡도는 적은 편이며, 왜 이런 행위를 했는지만 잘 적어놓으면 된다. -_-;;

위와 같은 꽁수가 통하는 이유는, 영문과 숫자, %로만 이뤄진 문자열을 UTF-8로 인코딩한 문자열은

MS949로 디코딩하나, UTF-8로 디코딩하나 결과는 동일하기 때문이다.

 

인코딩의 세계는 쉽지 않다;;

반응형

'etc' 카테고리의 다른 글

jQuery Mobile  (0) 2011.08.17
dev blog  (0) 2011.08.17
User Context  (0) 2011.08.16
http://code.google.com/p/explorercanvas/  (0) 2011.08.14
GIS  (0) 2011.08.08