Backend/Http+Servlet

한글 인코딩과 new String, getBytes

findmypiece 2021. 7. 16. 22:59
728x90

http 통신에서 한글을 사용한다면 인코딩은 필수이다. 기본적으로 일부 한글과 특수문자, 공백 등의 문자들은 그대로 http 프로토콜에 포함될 수 없고 별도로 인코딩을 해서 보내야 한다.

일반적으로 인터넷 브라우저나 코드상에서 사용하는 RestTemplate 같은 RestClient 에서는 이러한 인코딩을 자동으로 해준다.

인코딩된 데이터를 받는 쪽에서는 역시 디코딩이 필요하다. 이는 일종의 통신규약으로 인코딩과 디코딩의 기준이 되는 문자셋(ISO-8859-1, EUC-KR, UTF-8)은 서로 동일해야 하고 한글을 사용한다면 EUC-KR 또는 UTF-8을 문자셋으로 선택해야 한다.

참고로 ISO-8859-1는 알파벳과 일부 특수기호만을 처리할 수 있고 한글은 처리할 수 없다.

결국 시작은 인코딩인데 POST 방식 통신에서는 Request Content-Type 헤더에 charset 키로 문자셋을 포함하고 서버에서는 이를 토대로 디코딩을 진행한다. 하지만 GET 방식에는 기본적으로 Content-Type도 Request에 포함되지 않기 때문에 인코딩한 문자셋을 전달할 방법이 없고 이를 위해 서버에서는 GET방식 데이터의 디코딩을 위한 문자셋을 미리 지정해놔야 한다.

Tomcat을 예로 들면 server.xml 파일의 아래와 같은 설정이 바로 그것이다.

<Connector port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8" /> <Connector port="8001" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8" />

기본적으로 Tomcat8 의 경우 기본적으로 GET방식으로 넘어온 데이터를 UTF-8로 디코딩하도록 되어 있지만 그 이전 버전은 ISO-8859-1을 기본 디코딩 문자셋으로 사용하고 UTF-8 이 사용되게 하려면 위와 같이 별도로 지정을 해줘야 한다.

이런 이유로 Tomcat8 이전 버전에서 위와 같이 URIEncoding="UTF-8" 를 지정해주지 않았다면 보내는 곳에서 한글처리를 위해 UTF-8 로 인코딩을 했더라도 디코딩을 ISO-8859-1 로 하다보니 한글을 정상적으로 표현할 수 없게 된다.

이 경우 코드에서 new String, getBytes 를 이용해서 아래와 같이 처리할 수 있다.

String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8");

이는 ISO-8859-1 로 디코딩 되어 있는 문자열을 다시 ISO-8859-1 로 인코딩해서 원상태(UTF-8 인코딩)로 되돌린뒤 뒤에 다시 UTF-8로 디코딩 하라는 말이다.

그런데 URIEncoding="UTF-8" 설정이 되어 있는데도 한글이 깨지는 경우가 있다. 인코딩된 URL이 다른 서버를 거치는 경우가 그런데 디코딩 설정이 UTF-8 로 되어 있는 A서버가 있고, ISO-8859-1 로 되어 있는 B서버가 있다고 가정해보자.

클라이언트에서는 A서버로 접근하는 URL에 한글이 포함되어 있어 URL을 UTF-8 로 인코딩했다. 그런데 해당 URL을 B서버에 GET방식 Parameter로 전달했다가 B서버에서 해당 URL을 호출해야 하는 상황이 바로 그것이다.

B서버에서 UTF-8로 인코딩된 URL을 ISO-8859-1로 디코딩했고 이것을 가지고 A서버를 호출하게 되는 셈이다. A서버에서는 UTF-8로 디코딩을 하겠지만 이미 ISO-8859-1로 디코딩된 상태라 추가로 변환되는 것은 없다.

이 상황은 java에서 기본적으로 제공되는 URLEncoder, URLDecoder 로 아래와 같이 재현해볼 수 있다.

String iso = URLEncoder.encode("한글 입니다만???", "UTF-8"); 

iso = URLDecoder.decode(iso, "ISO-8859-1"); //B서버에서 디코딩 
System.out.println(iso); 

iso = URLDecoder.decode(iso, "UTF-8"); //A서버에서 디코딩 
System.out.println(iso); 

//A서버 정상적으로 한글을 표현하기 위해서는 코드에서 아래와 같이 해야함. 
System.out.println(new String(iso.getBytes("ISO-8859-1"), "UTF-8"));


우리가 많이들 사용하고 있는 카카오톡 오픈그래프가 현재 위와 같이 되어 있다. 때문에 og:title 이나 og:description 항목에 한글을 포함하고 GET방식 Parameter 로 전달받아 다이나믹하게 나타내기 위해서는 서버에서 위와 같이 new String, getByte 설정을 추가로 해줘야 한다.

728x90

'Backend > Http+Servlet' 카테고리의 다른 글

URL 에 포함된 한글 파라미터 처리  (0) 2021.11.17
Contents-Type, Accept  (0) 2021.04.20
서버에서 클라이언트 Cookie 셋팅하기  (0) 2021.03.29
JSESSIONID  (0) 2021.03.29
response.sendRedirect 에 대한 오해  (2) 2021.03.16