Microsoft 社는 2022년 6월 15일 Internet Explorer 11의 지원을 종료했습니다.

request.getParameter 와 인코딩(Graha 라이브러리의 처리방법을 중심으로)

제목

request.getParameter 와 인코딩(Graha 라이브러리의 처리방법을 중심으로)

1. request.getParameter 의 인코딩에 영향을 주는 요소

1.1. file.encoding

WAS 를 기동할 때, "-Dfile.encoding=iso-8859-1" 과 같이 명령행 파라미터를 추가하지 않았다면, file.encoding 은 WAS 를 기동할 때의 환경변수에 의해 결정된다.

명령행 파라미터를 추가하기 위해서 Apache Tomcat 계열은 startup.sh 실행하기 전에 다음과 같이 JAVA_OPTS 환경변수를 설정하면 된다.

WAS 에 따라 방법이 다를 수 있다. 과거를 돌이켜 보면 startup.sh 와 같은 WAS 기동 script 에 하드코딩되어 있는 경우도 있었다.

export JAVA_OPTS="-Dfile.encoding=iso-8859-1"
export JAVA_OPTS="-Dfile.encoding=euc-kr"
export JAVA_OPTS="-Dfile.encoding=UTF-8"

Windows 에서 테스트한 프로그램을 Unix 로 이식한 이후에 한글이 깨지는 경우는 file.encoding 과 관련이 있을 가능성이 높다.

이 설정은 다음과 같이 확인할 수 있다.

System.getProperty("file.encoding");

1.2. request.setCharacterEncoding

request.setCharacterEncoding 를 통해 UTF-8 이나, EUC-KR 과 같은 charset 을 지정할 수 있는데 예외는 있다.

Apache Tomcat 을 기준으로 7 ~ 10 버전을 살펴보면, Apache Tomcat 7 버전의 GET 요청에서는 request.setCharacterEncoding 은 효과가 없다.

GET 요청이라고 했지만, URL 에 붙어 있는 파라미터를 의미하고, POST 요청에서도 요청 URL 자체에 파라미터를 붙일 수 있기 때문에, Graha 라이브러리는 범용적인 방법의 처리가 필요하다.

2. 시스템 설정과 무관하게 파라미터를 UTF-8로 받는 방법

2.1. Apache Tomcat 7

Apache Tomcat 7 에서 request.setCharacterEncoding("ISO-8859-1"); 은 POST 에 한해서 적용된다.

Apache Tomcat 7 에서는 request.setCharacterEncoding 에 UTF-8 따위를 지정하게 되면, 파라미터가 GET 인지 POST 인지에 따라 처리를 달리해야 하므로, UTF-8 파라미터를 범용적으로 처리하기 위해서는 다음과 같이 해야 한다.

request.setCharacterEncoding("ISO-8859-1");
String param = request.getParameter("param");
param = new String(param.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

Apache Tomcat 7 의 방식은 다른 상위 버전과도 호환될 것으로 생각된다.

2.2. Apache Tomcat 8 이상

Apache Tomcat 8 이상의 버전에서는 다음으로 충분하다.

request.setCharacterEncoding("UTF-8");
String param = request.getParameter("param");

2.3. Graha 라이브러리의 처리방법

많은 WAS 를 대상으로 테스트 할 생각은 없고, Apache Tomcat 은 표준 구현체나 다름없으므로, 표준을 준수하는 다른 WAS 들도 동일한 구현일 것으로 전제하고, 다음과 같이 처리하기로 하였다.

  • Server API 3.0 까지는 Apache Tomcat 7 의 방식으로 처리하고,
  • Server API 3.1 부터는 Apache Tomcat 8 의 방식으로 처리한다.
if(
request.getServletContext().getMajorVersion() < 3
|| (
request.getServletContext().getMajorVersion() == 3
&& request.getServletContext().getMinorVersion() == 0
)
) {
request.setCharacterEncoding("ISO-8859-1");
String param = request.getParameter("param");
param = new String(param.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
} else {
request.setCharacterEncoding("UTF-8");
String param = request.getParameter("param");
}

전체 소스는 QueryImpl.java 의 parameter 메소드를 참조하면 된다.

3. 테스트를 위한 소스코드

action.jsp 의 request.setCharacterEncoding 의 주석을 순차적으로 풀어보면서 테스트 한다.

3.1. form.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="utf-8"/>
<meta
name="viewport"
content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width"
/>
<title>Parameter Encoding</title>
</head>
<body>
<h3>POST 전송</h3>
<form method="post" action="action.jsp">
<input type="text" name="param" value="한글">
<input type="submit" value="전송">
</form>
<h3>GET 전송</h3>
<form method="get" action="action.jsp">
<input type="text" name="param" value="한글">
<input type="submit" value="전송">
</form>
</body>
</html>

3.2. action.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8" %><%
//request.setCharacterEncoding("UTF-8");
//request.setCharacterEncoding("EUC-KR");
//request.setCharacterEncoding("ISO-8859-1");
%>
<html>
<head>
<meta charset="utf-8"/>
<meta
name="viewport"
content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width"
/>
<title>Parameter Encoding</title>
</head>
<body>
<ol>
<li>request.getParameter("param") : <%=request.getParameter("param")%></li>
<li>request.getMethod() : <%=request.getMethod()%></li>
<li>request.getServletContext().getMajorVersion() = <%=request.getServletContext().getMajorVersion()%></li>
<li>request.getServletContext().getMinorVersion() = <%=request.getServletContext().getMinorVersion()%></li>
<li>file.encoding = <%=System.getProperty("file.encoding")%></li>
<li>java.nio.charset.Charset.defaultCharset = <%=java.nio.charset.Charset.defaultCharset()%></li>
<li>request.getCharacterEncoding() = <%=request.getCharacterEncoding()%></li>
</ol>
</body>
</html>

4. 여담

개발서버에서 개발 및 테스트를 완료했다고 하더라도, 개발서버와 운영서버의 환경이 서로 다르다면, 운영서버로 이전 한 이후에, 한글이 깨지는 등의 외관상 치명적으로 보이는 문제가 발생할 수 있다.

이런 일은 완전하게 방어할 수 있는 성질의 것이 아니지만, 최소한 다음 3개의 환경은 동일하게 유지할 것을 권한다.

  • JDK 버전
  • WAS 의 버전
  • file.encoding 파라미터
제목

첨부파일