Servlet/Jsp에서 요청 파라미터값을 읽는 방법
일반적으로 클라이언트가 HTTP 요청시 넘긴 데이터는 다음과 같이 HttpServletRequest의 request.getParameter(String name) 메서드를 통해 얻습니다. HTTP GET방식 요청이든 POST 방식의 요청이든 param이라는 key에 해당하는 값을 넘겼다면 다음와 같이 값을 읽어올것입니다.
String param = request.getParameter("param");                                            
cs



톰캣에서의 요청 파라미터 인코딩 설정
WAS의 사양이나 버전에 따라서는 getParameter() 사용시 데이터를 읽어오는 인코딩 설정이 달라지게 되는데, 톰캣7을 기준으로 보자면 기본적인 인코딩 설정값으로 "ISO-8859-1"를 사용하게 됩니다. 따라서 보통 톰캣을 기준으로 웹 어플리케이션을 개발할때 두가지 작업을 해줍니다.



GET방식 요청일 때
첫번째로는 톰캣의 Connector 설정에서 인코딩 설정을 변경하는것입니다. 톰캣의 server.xml 파일에서 Connector 설정에 다음과 같이 URIEncoding 속성값을 추가 또는 (이미 있는경우)수정합니다. 그러나 이 속성은 GET방식 요청을 통해 넘어온 URI상의 쿼리스트링에 대한 인코딩 설정입니다. 즉 POST 방식등을 통한 BODY로 넘어온 데이터는 인코딩하지 못합니다.
<Connector connectionTimeout="20000"
                    port="8080"
                    protocol="HTTP/1.1"
                    redirectPort="8443"
                    URIEncoding="utf-8"/>                                                
cs



POST방식 요청일 때
두번째로 GET 방식 이외에 HTTP 요청 메시지의 BODY 데이터에 대한 인코딩을 설정하기 위해 다음과 같은 코드가 꼭 따라다니게 됩니다. 바로 HttpServletRequest의 setCharacterEncoding(String charset) 메서드를 사용하는 것입니다. setCharacterEncoding() 메서드는 HTTP 요청 메시지의 BODY에 대한 인코딩을 설정하는 메서드입니다.
request.setCharacterEncoding("utf-8");                                                    
String param = request.getParameter("param");
cs




인코딩 코드의 중복 발생과 해결 방안
GET방식의 경우 설정 한번으로 인코딩을 설정할 수 있다고 해도 POST 방식의 경우에는 getParameter() 메서드를 사용하는 페이지에서 매번 setCharacterEncoding() 메서드를 통해 인코딩 설정을 해주어야 하는 코드 중복 문제가 발생합니다. 그렇게 되면 당연히 코드 변경시에 많은 비용을 소모하게 됩니다. 따라서 이런 경우에는 각각의 페이지에서 인코딩 처리를 하던 중복코드를 필터로 빼주어 관리하는것이 좋습니다.





한글 인코딩 처리 필터 구현
앞서 말했던 인코딩 처리의 중복을 해결하기 위해 JSP나 서블릿을 호출하기에 앞서 인코딩을 처리해줄 필터를 구현하여 사용하면 인코딩 관련 코드 중복을 해결하여 코드 수정에 용이하고 그에 따른 유지보수 비용을 줄일 수 있습니다.

여기서는 아래와 같이 CharsetEncodingFilter를 만들어 모든 요청에 대해 요청 파라미터를 인코딩 처리한 이후 원래의 목적에 맞는 JSP나 서블릿으로 요청을 전달하도록 할것입니다.







예제 소스 구현
먼저 구현에 앞서 예제 프로젝트는 대략 다음과 같이 구성됩니다. 최초 input.html에 접근하여 한글을 입력후 전송을 클릭하면 paramTest.jsp로 POST 방식으로 데이터를 전송하는데, 이때 한글처리 필터에서 인코딩을 처리한 후 요청을 넘겨줍니다. paramTest.jsp에서는 인코딩 처리된 요청파라미터를 얻어 클라이언트에 출력합니다.




먼저 input.html입니다. 단순히 입력창 하나와 전송버튼 하나를 가지고 있는 폼태그이며 전송을 누를실 post 방식으로 paramTest.jsp에 입력한 한글을 전송합니다.

input.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>한글입력페이지</title>
</head>
<body>
     <form action="paramTest.jsp" method="post">
           한글입력 : <input type="text" name="param"><br>                                
           <input type="submit" value="전송">
     </form>
</body>
</html>
cs



두번째로는 paramTest.jsp입니다. 요청받은 파라미터를 얻어 그대로 출력합니다.

paramTest.jsp
<%@ page contentType="text/html; charset=utf-8" session="true"%>                        
 
 
<html>
<head>
</head>
<body>
<%
     String param = request.getParameter("param");
%>
<h1><%= param %></h1>
</body>
</html>
cs



지금 구현된 상태로 테스트를 진행해보겠습니다.



전송을 클릭했더니 paramTest.jsp페이지를 요청했지만 input.html에서 입력했던 한글이 깨져서 출력됩니다. paramTest.jsp에는 파라미터를 인코딩하는 부분이 없기 때문입니다.




인코딩 Filter 작성
이제 필터를 작성하고 web.xml에 설정할 차례입니다.
package com.dololak.filter;
 
 
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
 
public class CharsetEncodingFilter implements Filter {
     private String encoding;
     
     @Override
     public void doFilter(ServletRequest request,  ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
           
           request.setCharacterEncoding(encoding);
           chain.doFilter(request, response);
     }
 
 
     @Override
     public void init(FilterConfig fConfig) throws  ServletException {
           encoding = fConfig.getInitParameter("encoding");
           
           //인코딩을 따로 지정하지 않은 경우 기본값 세팅
           if(encoding == null) {
                encoding = "utf-8";
           }
     }
 
 
     @Override
     public void destroy() {
     }
}
cs


필터가 구현되었다면 web.xml을 통해 등록하고 서버를 기동합니다. 여기서는 모든 URL에 대해 CharsetEncodingFilter를 거치도록 설정하였습니다.
     <filter>
           <filter-name>encodingFilter</filter-name>
          <filter-class>com.dololak.filter.CharsetEncodingFilter</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>
cs


필터에 대해 간략하게 설명을 하자면 웹컨테이너가 기동되는 과정에서 필터가 생성되고 init() 메서드를 통해 초기화될 때 개발자가 web.xml에 설정한 인코딩 값을 가져와 멤버변수인 encoding에 할당합니다. 만약 설정한 값이 따로 없다면 기본값으로 utf-8로 설정합니다.

이런식으로 웹어플리케이션에 사용되는 특정 설정값을 web.xml과 같은 설정파일을 통해 관리하도록 하면 유지보수시에 인코딩 값이 바뀌어도 코드를 컴파일 하지 않고 web.xml만 수정하면 되는 이점이 있습니다. 실무환경에서는 웹 어플리케이션의 규모가 크고 사용자들이 이미 사용중인 운영환경인 경우가 많기 때문에 컴파일에 걸리는 시간과 그것을 서버에 다시 적용하는 시간이 많이 소모되기 때문입니다.
     public void init(FilterConfig fConfig) throws  ServletException {                    
           encoding = fConfig.getInitParameter("encoding");
           
           //인코딩을 따로 지정하지 않은 경우 기본값 세팅
           if(encoding == null) {
                encoding = "utf-8";
           }
     }
cs


이후 특정 요청이 있을때 필터에서는 doFilter() 메서드에서 설정된 인코딩값을 setCharacterEncoding() 메서드를 통해 미리서 셋팅 한 후 chain.doFilter()를 통해 요청을 전달하게 됩니다. 따라서 이후 전달된 요청에 대해서는 다른 JSP 페이지나 서블릿에서 인코딩에 대해 신경쓸 필요가 없게 되는것입니다.


필터를 구현한 이후에는 인코딩 처리가 잘 된것을 볼 수 있습니다.



참고글

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,