주요글: 도커 시작하기
반응형
톰캣 3.2.3, 톰캣 3.3, 톰캣 4.0.1에서의 한글 처리 문제를 원리적으로 해결하는 방법을 살펴본다.

한글처리 방안 준비

자바를 기반으로 하는 서블릿과 JSP를 사용하여 웹 어플리케이션을 개발하는 개발자들을 짜증나게 만드는 문제중의 하나를 꼽으라면 바로 한글 처리 문제일 것이다. 그 만큼 한글 처리 문제는 서블릿이 처음 생겨난 이후 최근에 서블릿 2.3/JSP 1.2 규약이 발표되기까지 한국의 개발자들이 한두번 정도는 경험하게 되는 고질병이라고도 할 수 있다.

하지만 서블릿/JSP 규약을 올바르게 이해하고 있고, 또 자신이 사용하는 서블릿/JSP 엔진의 특징을 조금만 파악하고 있다면 매우 간단하게 해결할 수 있는 것이 한글 문제이기도 하다. 이번 글에서는 개발자들이 많이 사용되는 엔진중의 하나인 톰캣에서 한글 파라미터를 알맞게 처리하는 방법에 대해서 버전별로 살펴보고 그리고 오라클과 MySQL에서 한글을 처리하는 방법에 대해서도 살펴보도록 하자.

기본적으로 알아야 하는 내용

한글 처리 문제에 대해서 살펴보기 이전에 기본적으로 알아야 하는 내용은 서블릿 2.2/JSP 1.1 스펙은 HTTP 요청 파라미터의 캐릭터셋을 "ISO-8859-1"로 가정하고 읽어온다는 점이다. 우리가 흔히 톰캣 3.x 버전을 사용할 때 클라이언트로부터 읽어온 값을 오라클 DB에 저장할 때 캐릭터 셋을 "ISO-8859-1"에서 "EUC-KR"로 변환하곤 하는데, 이렇게 캐릭터 셋을 변환하는 이유는 바로 톰캣 3.x 버전은 서블릿 2.2 규약을 따르고 있으며 따라서 파라미터를 "ISO-8859-1"로 읽어오기 때문이다. (오라클과 톰캣 사이에서의 한글 처리 문제에 대해서는 뒤에서 보다 자세히 다루도록 하겠다.)

또한, 서블릿과 JSP에서 한글을 처리하는 방식이 달라질 수 있다는 점이다. 서블릿의 경우는 우리가 컴파일한 클래스가 그대로 사용되는 것이지만 JSP의 경우는 개발자가 작성한 JSP 코드를 JSP 엔진이 서블릿 소스 코드로 변환한 후 다시 서블릿 클래스로 컴파일한다. JSP 엔진에 따라 JSP 소스 코드를 서블릿 소스 코드로 변환하는 과정에서 캐릭터 셋을 변환하기도 하며 또한 컴파일하는 과정에서 캐릭터셋을 변환하기도 한다. 이 얘기는 같은 JSP 코드라도 사용하는 JSP 엔진에 따라서 한글 처리가 달라질 수도 있다는 점이다.

이런 기본적인 상식을 알아두면 차후에 한글 문제를 보다 빠르게 대처할 수 있을 것이다. 그럼, 이제부터 톰캣에서 한글 문제를 처리하는 방법에 대해서 본격적으로 살펴보도록 하자.

사용할 예제 코드

사용할 예제 코드 목록은 다음과 같다.

소스코드 설명 톰캣버전
HanTestSetCharsetServlet.java response.setContentType("text/html; charset=euc-kr")을 사용하여 컨텐츠 타입 지정 3.2.3/3.3/4.0.1
HanTestNoCharsetServlet.java 컨텐츠 타입 지정하지 않음 3.2.3/3.3/4.0.1
HanTestSetCharset23Servlet.java response.setContentType("text/html; charset=euc-kr")을 사용하여 컨텐츠 타입을 지정하고 request.setCharacterEncoding("euc-kr")로 지정하여 파라미터의 캐릭터 셋 지정 4.0.1
hanTestSetCharset.jsp <%@ page contentType="text/html; charset=euc-kr" %>로 컨텐츠 타입 지정 3.2.3/3.3/4.0.1
hanTestNoCharset.jsp contentType 지정하지 않음 3.2.3/3.3/4.0.1
hanTestSetCharset12.jsp <%@page pageEncoding="euc-kr" %>를 지정 4.0.1

예를 들어, HanTestSetCharsetServlet.java는 다음과 같다.

    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import javax.servlet.ServletException;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class HanTestSetCharsetServlet extends HttpServlet {
        
        public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
            response.setContentType("text/html; charset=euc-kr");
            
            PrintWriter pw = new PrintWriter(response.getWriter());            
            pw.println("<html><head><title>한글테스트</title></head>");
            pw.println("<body>");
            pw.println("파라미터1(캐릭터셋변환 X)="+
                        request.getParameter("param1"));
            pw.println("<br>");
            pw.println("파라미터2(캐릭터셋변환 O)="+
                        CharsetUtil.fromUStoKR(request.getParameter("param2")) );
            pw.println("</body></html>");
            pw.flush();
            pw.close();
    
            System.out.println("파라미터1(캐릭터셋변환 X)="+
                                request.getParameter("param1"));
            System.out.println("파라미터2(캐릭터셋변환 O)="+
                                CharsetUtil.fromUStoKR(request.getParameter("param2")) );
        }
    }

테스트를 위한 서블릿 클래스들은 모두 위와 비슷하다. 차이점이 있다면 response.setContentType() 메소드를 호출하는지의 여부와 request.setCharacterEncoding() 메소드를 호출하는지의 여부뿐이다. 참고적으로 위 코드에서 System.out을 사용하여 콘솔에 메시지를 출력하는 request.getParameter() 메소드를 사용하여 읽어온 파라미터 값이 어떤 값인지 알아보기 위해서이다.

JSP 코드 역시 서블릿 코드와 비슷하다. 예를 들어, hanTestSetCharset.jsp는 다음과 같다.

    <%@ page contentType="text/html; charset=euc-kr" %>    <html>
    <head>
    <title>한글테스트</title>
    </head>
    <body>
    파라미터1(캐릭터셋변환 X)=<%= request.getParameter("param1") %>
    <br>
    파라미터2(캐릭터셋변환 O)=<%= CharsetUtil.fromUStoKR(request.getParameter("param2")) %>
    </body>
    </html>
    <%
        System.out.println("파라미터1(캐릭터셋변환 X)="+
            request.getParameter("param1"));
        System.out.println("파라미터2(캐릭터셋변환 O)="+
            CharsetUtil.fromUStoKR(request.getParameter("param2")) );
    %>

모든 테스트 코드는 관련 링크의 소스 코드를 통해서 구할 수 있으니 참고하기 바란다. 참고적으로 모든 서블릿 소스 코드는 컴파일할 때 -encoding 옵션을 사용하지 않았다.

톰캣에서의 한글 처리 문제

현재 자카르타(http://jakarta.apache.org) 홈페이지에 들어가보면 3 종류의 톰캣 버전이 존재하는 데 그 버전은 4.0.1, 3.3, 3.2.3 이다. 따라서 이 글에서는 4.0.1, 3.3, 3.2.3 버전의 서블릿/JSP 한글 처리 방법에 대해서 살펴볼 것이다.

톰캣 3.2.3과 한글

톰캣 3.2.3에서 서블릿과 JSP 페이지를 차례대로 수행한 결과를 살펴보도록 하자. 앞에서 HanTestSetCharsetServlet.java 파일을 살펴보면 "param1" 파라미터는 읽어온 값을 그대로 출력하고 "param2" 파라미터는 캐릭터셋을 "ISO-8859-1"에서 "EUC-KR"로 변환한 값을 출력한다는 것을 알 수 있다. HanTestSetCharsetServlet.java 뿐만 아니라 다른 서블릿 클래스도 같은 방법으로 "param1" 파라미터와 "param2" 파라미터의 값을 출력한다.

참고적으로 이 글에서는 HTTP 요청 파라미터인 "param1"과 "param2"의 값으로 "한글"을 사용하였다.

먼저 서블릿 HanTestSetCharsetServlet을 수행한 결과는 다음과 같다.


콘솔에는 다음과 같은 값이 출력된다.

    파라미터1(캐릭터셋변환 X)=??±?
    파라미터2(캐릭터셋변환 O)=한글

이제 HanTestNoCharsetServlet을 실행한 결과를 살펴보자. 웹 브라우저에는 다음과 같은 결과가 출력된다.


콘솔에는 다음과 같은 값이 출력된다.

    파라미터1(캐릭터셋변환 X)=??±?
    파라미터2(캐릭터셋변환 O)=한글

위 두 서블릿의 테스트 결과를 분석해보도록 하자. 먼저 response.setContent("text/html; charset=euc-kr")을 사용하여 응답 결과의 컨텐츠타입의 캐릭터셋을 "EUC-KR"로 지정한 HanTestSetCharsetServlet은 PrintWriter 를 사용하여 출력한 한글이 올바르게 출력된 반면에 컨텐츠타입의 캐릭터셋이 "ISO-8859-1"로 지정되어 있는 경우에는 PrintWriter를 사용하여 출력한 한글이 올바르게 출력되지 않고 '?'와 같이 깨져서 출력되는 것을 알 수 있다.

파라미터의 출력 결과를 보면 HanTestSetCharsetServlet에서는 파라미터값을 ISO-8859-1에서 EUC-KR로 변환해야 올바르게 출력되는 것을 알 수 있으며, HanTestNoCharsetServlet의 경우에는 캐릭터셋을 변환하지 않을 때에 올바르게 출력되는 것을 알 수 있다. 하지만, 두 경우 모두 콘솔에 출력할 때에는 ISO-8859-1에서 EUC-KR로 변환해야 올바르게 출력된다는 것을 알 수 있다.

여기서 우리가 알아야 하는 것은 톰캣 3.2.3의 경우 서블릿 클래스에서 읽어오는 파라미터의 값은 ISO-8859-1 캐릭터셋으로 읽혀진다는 것이며(콘솔에 출력된 값을 통해서 알 수 있다!), response.setContent("text/html; charset=euc-kr")를 사용하여 컨텐츠 타입의 캐릭터셋을 지정하지 않을 경우 response.getWriter()는 ISO-8859-1 캐릭터셋으로 구성된 String을 올바르게 출력한다는 점이다.(HanTestNoCharsetServlet의 출력 결과인 그림2를 통해서 알 수 있다.) 서블릿 2.2 규약에서 응답 메시지의 캐릭터셋을 지정하지 않는 한 기본적으로 "ISO-8859-1"을 사용하도록 하고있고 톰캣 3.2.3이 서블릿 2.3 규약을 철저하게 따른다는 점을 생각해보면 당연한 결과라 할 수 있다.

이제 JSP에서 한글 처리가 어떻게 되는 지 살펴보자. 먼저 hanTestSetCharset.jsp의 출력 결과는 다음과 같다.


콘솔에는 다음과 같은 값이 출력된다.

    파라미터1(캐릭터셋변환 X)=??±?
    파라미터2(캐릭터셋변환 O)=한글

이제 마지막으로 hanTestNoCharset.jsp의 결과를 살펴보자. 그 결과는 다음과 같다.


콘솔에는 다음과 같은 값이 출력된다.

    Æ?¶?¹???1(?³¸???¼?º??? X)=??±?
    Æ?¶?¹???2(?³¸???¼?º??? O)=한글

JSP의 경우 서블릿과 약간 다른 출력 결과를 보이기도 하지만 콘솔에 출력되는 값을 통해서 우리가 알 수 있는 것은 파라미터값은 서블릿의 경우와 마찬가지로 JSP에서도 ISO-8859-1 캐릭터셋으로 읽혀진다는 점이다. 또한, page 디렉티브의 contentType 속성을 통해서 응답결과의 캐릭터셋을 EUC-KR로 지정한 경우에 내용이 알맞게 출력된다는 것을 알 수 있다.

위 결과에서 주목해서 봐야 할 부분은 콘솔에 출력된 값이다. hanTestSetCharset.jsp는 System.out.println()을 사용하여 출력한 한글이 올바르게 출력된 반면에 hanTestNoCharset.jsp는 한글이 무참히 깨져서 출력된 것을 알 수 있다. 하지만, 두 JSP 모두 파라미터의 값은 ISO-8859-1에서 EUC-KR로 변환한 경우에 올바르게 출력되었다. 이런 기현상(?)을 이해하기 위해서는 톰캣 3.2.3이 JSP를 서블릿으로 변환하는 과정에서 발생하는 인코딩 변환에 대해서 이해해야 한다.

톰캣 3.2.3의 경우 page 디렉티브의 contentType에 지정한 charset의 값에 따라서 JSP 소스 코드를 .java 소스 코드로 변환할 때 글자를 다르게 인코딩변환한다. 예를 들어, hanTestSetCharset.jsp와 hanTestNoCharset.jsp는 다음과 같은 코드를 갖고 있는데,

    파라미터2(캐릭터셋변환 O)=<%= CharsetUtil.fromUStoKR(request.getParameter("param2")) %>

<%@ page contentType="text/html; charset=euc-kr" %>를 포함하고 있는 hanTestSetCharset.jsp를 서블릿 코드로 변환한 .java 파일에는 위 코드가 다음과 같이 변환되며

    out.write("\r\n<br>\r\n???誘명?2(罹?┃?곗?蹂??O)=");
    out.print( CharsetUtil.fromUStoKR(request.getParameter("param2")) );
    

반면에 hanTestNoCharset.jsp에서는 다음과 같이 변환된다.

    out.write("\r\n<br>\r\n??쨋처쨔???2(?쨀쨍짱??쩌?쨘짱?짱 O)=");
    out.print( CharsetUtil.fromUStoKR(request.getParameter("param2")) );

<%@ page contentType="text/html; charset=euc-kr" %>이 있느냐 없느냐의 차이만 있을 뿐인데, JSP 페이지를 서블릿의 소스 코드로 변환한 결과 파일의 경우에는 서로 다른 인코딩을 사용하여 변환된 것을 알 수 있다. 이는 톰캣 3.2.3이 page 디렉티브의 contentType에 따라서 인코딩을 변환하기 때문인 것으로 보인다. 이러한 차이는 결국 .java 파일을 컴파일한 서블릿 클래스, 즉 JSP가 변환된 서블릿 클래스에도 영향을 미치게 되며, 그 차이점은 콘솔에 출력된 한글의 깨짐여부를 통해서 확인할 수 있다.

톰캣 3.3과 한글

톰캣 3.3의 경우 톰캣 3.2.3과 거의 모든 경우에 웹브라우저의 출력 결과와 콘솔에 출력된 문자열이 같다. 다른 경우는 hanTestNoCharset.jsp를 실행한 경우이다. 먼저 새롭게 웹브라우저를 실행한 다음에 폼을 출력하는 HTML을 사용하여 hanTestSetCharset.jsp에 파라미터값을 전달해보자. 그러면 그림3과 같은 결과가 출력될 것이다. 이 다음에 곧바로 hanTestNoCharset.jsp에 파라미터를 전달해보자. 그러면 4와 같은 결과가 출력되기 보다는 다음과 같은 결과가 출력될 것이다.


그림4와 일부 다른 것을 알 수 있다. 콘솔의 출력결과도 다른데, 톰캣3.3에서 hanTestSetChar.jsp를 실행한 후 hanTestNoCharset.jsp를 실행하면 다음과 같은 내용이 출력된다.

    Æ?¶?¹???1(?³¸???¼?º??? X)=한글
    2001-11-20 13:08:42 - DecodeInterceptor: Charset from session euc-kr    Æ?¶?¹???2(?³¸???¼?º??? O)=??

위 메시지에서 주목할 부분은 DecodeInterceptor를 통해서 파라미터의 캐릭터셋이 자동으로 변환된다는 점이다. 이는 톰캣 3.3에 새롭게 추가된 기능으로서 이전에 출력한 내용의 캐릭터 셋을 세션에 저장하고 있다가 다음번 요청 때 세션으로부터 캐릭터 셋을 읽어와 파라미터의 값을 자동으로 변환해준다. 실제로 웹브라우저에서 리로딩을 해서 파라미터값을 재 전송해보면 다음과 같은 메시지가 출력된다. (즉, 실행순서가 hanTestSetCharset.jsp->hanTestNoCharset.jsp->hanTestNoCharset.jsp)

    Æ?¶?¹???1(?³¸???¼?º??? X)=??±?
    2001-11-20 13:22:32 - DecodeInterceptor: Charset from session ISO-8859-1
    Æ?¶?¹???2(?³¸???¼?º??? O)=한글

이러한 파라미터값의 캐릭터셋의 자동변환 기능은 DecodeInterceptor를 통해서 이루어진다. DecodeInterceptor에 대한 기본 설정은 톰캣의 설정 파일인 server.xml 파일에 <DecodeInterceptor /> 태그를 통해서 이루어진다. 이 태그의 useSessionEncoding 속성의 값을 false로 지정하면 가장 최근에 응답한 컨텐츠의 캐릭터셋을 다음에 오는 요청 파라미터 값의 캐릭터셋으로 지정해주는 기능을 사용하지 않게 된다. 예를 들어, server.xml 파일에 다음과 같이 <DecodeInterceptor> 태그를 지정했다고 해 보자.

    <DecodeInterceptor defaultEncoding="iso-8859-1" useSessionEncoding="false" />

이렇게 지정할 경우 지금 이 글에서 테스트하고 있는 서블릿과 JSP의 출력 결과가 톰캣 3.2.3과 같게 나오게 된다. 따라서 톰캣 3.3을 사용하는 한글 사이트의 경우 다음과 같이 <DecodeInterceptor> 태그를 지정하면 파라미터값을 특별히 캐릭터셋 변환하지 않고서도 EUC-KR로 읽어올 수 있게 된다.

    <DecodeInterceptor defaultEncoding="euc-kr" useSessionEncoding="false" />

톰캣 4.0.1과 한글

톰캣 4.0.1은 서블릿 2.3/JSP 1.2 규약을 지원하는 콘테이너이다. 서블릿 2.3 규약에는 ServletRequest 인터페이스에 파라미터의 캐릭터셋을 지정해주는 setCharacterEncoding() 메소드가 추가되었으며 또한 JSP 1.2 규약에는 페이지의 캐릭터셋을 지정해줄 수 있는 pageEncoding 속성이 page 디렉티브에 새롭게 추가되었다. 따라서 이렇게 새롭게 추가된 기능을 사용하면 보다 편리하게 한글 처리를 할 수 있게 된다.

하지만 서블릿 2.3/JSP 1.2 규약 역시 요청 파라미터의 기본 캐릭터셋을 ISO-8859-1로 지정하고 있다. 따라서 이 글에서는 먼저 서블릿 2.2/JSP 1.1 규약에 따라 작성된 HanTestSetCharsetServlet, HanTestNoCharsetServlet, hanTestSetCharset.jsp, hanTestNoCharset.jsp의 출력 결과를 살펴본 다음에 새롭게 추가된 기능을 사용하는 HanTestSetCharset23Servlet과 hanTest12.jsp의 출력 결과에 대해서 살펴보도록 하자.

예상을 한 사람도 있겠지만, HanTestSetCharsetServlet, HanTestNoCharsetServlet, hanTestSetCharset.jsp, hanTestNoCharset.jsp의 출력 결과는 톰캣 3.2.3에서의 출력 결과와 완전히 동일하다. 이는 서블릿 2.3/JSP 1.2에서 파라미터값의 기본 캐릭터셋으로 ISO-8859-1로 사용한다는 점을 생각해보면 당연한 결과라고 할 수 있겠다.

이제 ServletRequest.setCharacterEncoding() 메소드를 사용하여 파라미터의 캐릭터셋을 지정한 경우에 파라미터의 값이 어떻게 처리되는 지 살펴보도록 하자. HanTestSetCharset23Servlet 클래스는 doGet() 메소드의 가장 앞 부분에 다음과 같이 setCharacterEncoding() 메소드를 사용하여 요청 파라미터의 캐릭터셋을 지정하는 코드가 추가되어 있다.

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        request.setCharacterEncoding("euc-kr");
        response.setContentType("text/html; charset=euc-kr");
        
        PrintWriter pw = new PrintWriter(response.getWriter());
        
        ...
    }
    

HanTestSetCharSetServlet과 차이점은 단 한줄 뿐이지만, 출력 결과는 다음과 같이 다르다.


콘솔에는 다음과 같은 내용이 출력된다.

    파라미터1(캐릭터셋변환 X)=한글
    파라미터2(캐릭터셋변환 O)=??

위의 웹브라우저 화면과 콘솔에 출력된 내용을 통해서 우리는 request.setCharacterEncoding("euc-kr")를 통해서 파라미터값의 캐릭터셋을 변환시키지 않아도 한글을 올바르게 읽어올 수 있다는 점을 알 수 있다.

이제 page 디렉티브에 pageEncoding 속성을 사용한 hanTestSetCharset12.jsp를 실행해보자. hanTestSetCharset12.jsp는 다음과 같다.

    <%@ page pageEncoding="euc-kr" %>
    <%@ page import = "CharsetUtil" %>
    <html>
    <head>
    <title>한글테스트</title>
    </head>
    <body>
    파라미터1(캐릭터셋변환 X)=<%= request.getParameter("param1") %>
    <br>
    파라미터2(캐릭터셋변환 O)=<%= CharsetUtil.fromUStoKR(request.getParameter("param2")) %>
    </body>
    </html>
    <%
        System.out.println("파라미터1(캐릭터셋변환 X)="
            +request.getParameter("param1"));
        System.out.println("파라미터2(캐릭터셋변환 O)="
            +CharsetUtil.fromUStoKR(request.getParameter("param2")) );
    %>

hanTestSetCharset12.jsp는 보다시피 contentType도 지정하지 않았고 request의 setCharacterEncoding() 메소드도 사용하지 않았다. hanTestSetCharset12.jsp에 파라미터를 전송한 결과는 다음과 같다.


위 결과화면은 마치 그림2와 비슷하다. 하지만, 한글이 깨져 나온다는 것은 문제가 있다 할 수 있다. 또한 pageEncoding의 값을 "EUC-KR"로 지정한다고 해서 요청 파라미터의 캐릭터셋이 EUC-KR로 되는 것은 아니며, 요청 파라미터는 여전히 ISO-8859-1 캐릭터셋으로 읽혀진다.

따라서 톰캣 4.0.1에서는 pageEncoding 속성을 사용한다 해도 한글을 올바르게 출력하기 위해서는 contentType 속성의 값을 "text/html; charset=euc-kr"로 지정해주어야 한다. 또한, 파라미터의 캐릭터셋을 EUC-KR로 하고 싶은 경우에는 request.setCharacterEncoding() 메소드를 사용해야만 한다.

오라클과 한글 처리 문제

지금까지는 파라미터의 값이 실제로 어떻게 읽혀지는지에 대해서 살펴보았는데, 이제부터는 웹 프로그래밍에서 데이터베이스에 데이터를 저장할 때 발생하는 한글 문제에 대해서 살펴보도록 하자. 먼저 살펴볼 DBMS는 오라클이다.

흔히들 서블릿/JSP에서 오라클에 데이터를 저장할 때는 ISO-8859-1에서 EUC-KR(또는 KSC5601)로 캐릭터셋을 변환하여 저장해야 하고, 오라클에서 서블릿/JSP로 값을 읽어올 때는 EUC-KR에서 ISO-8859-1로 변환해야 한다고 알고 있다. 이 방법이 비교적 대부분의 경우에 알맞게 적용되긴 하지만 모든 경우에 알맞게 처리되는 것은 아니다.

오라클에 데이터를 저장하거나 오라클로부터 데이터를 읽어올 때에는 오직 한가지 사실만 알고 있으면 모든 문제를 해결할 수 있다. 그 사실은 바로 "오라클에 저장되는 값의 캐릭터셋은 반드시 EUC-KR(KSC5601)이어야 하며, 오라클로부터 읽혀오는 모든 값의 캐릭터셋은 EUC-KR 이다"라는 것이다.

이 얘기를 듣는 순간 지금까지 왜 그렇게 캐릭터셋을 변환해야 했는지 이해가 되는 사람도 있겠지만, 그렇지 못한 분들을 위해서 부가설명을 해 보자.

앞에서 파라미터 값을 살펴볼 때 서블릿 2.2 규약이든 서블릿 2.3 규약이든 기본적으로 파라미터값을 ISO-8859-1로 읽어온다고 하였다. 즉, 웹브라우저에서 전송한 파라미터의 값이 "한글"이라고 할 지라도, 서블릿이나 JSP에서 사용하는 파라미터에는 그 값이 EUC-KR 캐릭터셋인 "한글"이 아닌 ISO-8859-1 캐릭터셋인 "??±?"이 되는 것이다. 따라서, 톰캣 3.2.3이나 (DecodeInterceptor를 <DecodeInterceptor defaultEncoding="iso-8859-1" useSessionEncoding="false" />로 지정한) 톰캣 3.3에서 클라이언트가 전송한 파라미터 값을 오라클 DB에 한글깨짐 현상없이 올바르게 저장하기 위해서는 ISO-8859-1인 파라미터값을 EUC-KR로 변환한 후에 저장해야 하는 것이다.

마찬가지로 오라클에서 읽어온 데이터를 출력할 때도 비슷한 현상이 발생한다. 오라클에서 읽어온 데이터는 EUC-KR 인코딩을 갖는다. 따라서, 서블릿이나 JSP가 EUC-KR을 올바르게 출력하는 경우에는 캐릭터셋 변환을 하지 않아도 무방하며, 서블릿이나 JSP가 ISO-8859-1 캐릭터셋을 올바르게 출력하는 경우에는 오라클에서 읽어온 값을 EUC-KR에서 ISO-8859-1로 변환해주어야 하는 것이다.

레신의 경우는 톰캣과 약간 다를 수도 있으나 기본적인 원리는 같다. 레신과 오라클에 대한 내용은 다음 글에서 자세히 살펴볼 것이다.

MySQL과 한글 처리 문제

MySQL에서의 한글 처리는 JDBC URL을 알맞게 설정하는 것만으로 간단하게 해결할 수 있다. MySQL의 경우 가장 많이 사용되는 JDBC Driver는 MM MySQL일 것이다. 이 드라이버는 다음과 같이 JDBC URL을 지정하도록 되어 있다.

    jdbc:mysql:/localhost/javacan?useUnicode=true&characterEncoding=euc-kr    

여기서 한글처리의 핵심부분은 characterEncoding 속성의 값이다. 만약 읽어온 파라미터의 값이 ISO-8859-1이라면 다음과 같이 JDBC URL을 지정해주면 된다.

    jdbc:mysql:/localhost/javacan?useUnicode=true&characterEncoding=iso-8859-1    

반면에 파라미터의 값을 EUC-KR로 변환한 뒤 또는 서블릿 2.3에서 request.setCharacterEncoding("euc-kr")을 사용하여 파라미터를 EUC-KR로 읽어온 다음에 SQL 처리를 한다면, 다음과 같이 JDBC URL을 지정해주면 된다.

    jdbc:mysql:/localhost/javacan?useUnicode=true&characterEncoding=euc-kr    

MySQL과 관련해서 알아두어야 하는점은 MySQL로부터 읽어온 값의 캐릭터셋은 characterEncoding 속성값으로 지정한 캐릭터셋과 같으며, MySQL 테이블에 값을 삽입하거나 값을 변경할 때 지정해주는 값의 캐릭터셋은 characterEncoding 속성값으로 지정한 캐릭터셋과 같아야 한다는 점이다.

결론

이번 글에서는 톰캣과 한글처리 문제에 대해서 살펴보았다. 아마 이번 글을 통해서 여러분들은 그 동안 왜 그런 방법을 사용하여 한글 문제를 처리해야 했는지 알게 되었을 것이며, 앞으로 좀더 원리적인 방법으로 한글 문제를 처리할 수 있게 되었을 것이다. 다음 글에서는 계속해서 레신에서의 한글 처리 문제에 대해서 살펴볼 것이다.

관련링크:

+ Recent posts