java servlet의 문자 인코딩 문제

들어가며

  • http 통신에 있어서 가장 먼저 부딪히는 것은 문자인코딩 문제이다. http의 통신 과정은 아래와 같다.
  • 클라이언트(브라우져) -> request(get / post) -> 웹서버(was, tomcat) -> response(get / post) -> 클라이언트
  • 위의 모든 과정을 단 한 번의 인코딩으로 정리할 수 있었으면 좋았을테다. 그러나 모든 과정마다 인코딩 문제가 발생한다. browser마다, web container마다 발생한다.

http Get method

  • http표준에서는 get 방식으로 전달하는 파라미터에 대한 인코딩의 규약이 존재하지 않는다.
  • 브라우저에 따라 인코딩 방식이 다르다. 인터넷익스플로러는 MS949를 사용하고, 크롬은 utf-8을 사용한다.
  • url로 전달하는 파라미터의 경우 인코딩과 디코딩에 신경써야 한다.
String value = URLEncoder.encode("안녕", "utf-8");
response.sendRedirect("/content/sayhello.jsp?name="+value);

웹 컨테이너, 클라이언트

  • 웹 컨테이너에 따라 인코딩 방식이 다르다. 톰캣의 경우 버전마다 다르다.
    • 톰캣 7의 경우 ISO-8859-1을 기본 값으로 사용한다.
    • 톰캣 8 이후부터는 UTF-8 기본 값으로 사용한다.
  • 클라이언트 간 기본 인코딩 값이 다르다.
  • 클라이언트 간 바디에 대한 기본 타입이 다르다. 특별한 설정 없이 plain text 파일을 보냈다면
    • 익스플로러 계열은 plain text를 plain text
    • 크롬의 경우 html 형태로 받아드린다.
  • 결론적으로 response를 정의할 때 content type과 인코딩 모두 고려해야 한다.
<!-- jsp 파일 html 설정 -->
<%@ page contentType = "text/html; charset=UTF-8"%>

<!-- jsp 혹은 controller에서 설정 -->
<%
request.setCharacterEncoding("utf-8");
%>
// servlet의 경우는...
public class TestServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		for(int i=0; i<100; i++) {
			out.println(i + ": 안녕!<br>");			
		}
	}	
}

spring web.xml

  • 스프링을 사용하는 경우 web.xml를 이용하여 공통 설정할 수 있다.
  <filter>
   <filter-name>encodingFilter</filter-name>
   <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
   <init-param>
    <param-name>encoding</param-name>
    <param-value>utf-8</param-value>
   </init-param>   
  </filter>
  
  <filter-mapping>
   <filter-name>encodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
  </filter-mapping>