2015년 7월 6일 월요일

인코딩(Encoding)에 대한 이해 - (3) JSP 에서의 인코딩 설정 및 한글 매개변수 가져오기에 대한 고찰.

웹 개발을 하면서 처음에는 까다롭게 다가오다가 어느 순간 의미도 모른채 그냥 그 설정 그대로 유지하는게 바로 언어에 대한 인코딩이 아닌가 합니다. 특히 정형화된 구조에서 크게 문제가 발생하지 않기 때문에 신경을 쓰지 않다가 새로운 환경으로 이전을 하게 된다거나 할 때 한글이 깨지는 등의 문제가 발생하여 고생을 할 때가 종종 있습니다.


그래서 인코딩에 대한 최소한의 내용을 알려드려 크게 당황하지 않도록 도움을 드리고자 합니다.


이 글은 초보자를 위한 글이므로, 인코딩(Encoding) 정도는 우습다는 분은 패스해주길...^^;;;


------------------------------------------------------------------------------------------------------


이번에는 HTML 이 아닌 JSP 의 인코딩 설정에 대해서 먼저 간단하게 집고 넘어가겠습니다.



JSP 는 ASP, PHP 와 같은 웹 언어들과 비슷한 것 같지만, 비교 우위에 있는 큰 장점이 하나 있습니다. 바로 훌륭한 개발툴인 이클립스(Eclipse) 등의 존재입니다.

이클립스와 같은 개발툴은 JSP 을 지원했다기 보다는 Java 와 같은 개발 언어를 지원하는데, 이를 JSP 에서도 도움을 받을 수 있어서 실제 개발을 하다 보면 ASP 나 PHP 는 ultraedit 나 editplus 와 같은 일반 텍스트 에디터로 개발을 많이 하는 반면 JSP 를 개발하는 분들은 십중팔구 이클립스를 이용합니다.


그런데, 이클립스와 같은 개발툴이 JSP 의 인코딩 방식이 무엇인지 알 수 있게 선언할 수 있는 방법이 있습니다. 바로 파일 상단에 이에 대한 선언을 하는 것입니다.


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>


이런 선언을 많이 보셨을 겁니다. 이렇게 선언을 하면 이클립스와 같은 IDE 는 해당 파일이 UTF-8 로 인코딩된 파일이라는 것을 눈치채고 파일을 열어주게 됩니다.



그럼 왜 UTF-8 이 두 번 선언이 되어 있을까요?


JSP 는 먼저 서버에서 Java 로 변환이 된 뒤에 그 결과(=HTML)를 클라이언트에 전송하고, 클라이언트는 HTML 만을 해석하여 사용자에게 제공을 합니다. 그래서 HTML 의 <meta> 는 브라우저를 위한 설정값이라면, 위의 contentType 와 pageEncoding 은 서버를 위한 설정값인데, contentType 은 서버에서 생성될 HTML 의 캐릭터셋, pageEncoding 은 JSP 내의 Java 코드에 대한 캐릭터셋에 대한 정보입니다. 그래서 아래와 같이 두 가지 다른 캐릭터셋으로 정의를 한 뒤 출력할 수도 있습니다.


<%@ page language="java" contentType="text/html; charset=UNICODE" pageEncoding="EUC-KR" %>


예전에는 이렇게 정의를 해서 개발을 했던 적도 실제 있습니다. 실제 HTML 부분에는 한글 등이 없고 DBMS 에서 불러온 값만 출력해주는데, 이 데이터들이 UTF-16 으로 인코딩되어 있을 경우 pageEncoding 까지 UTF-16 으로 선언하면 Java 코드의 크기까지 같이 커지기 때문에 이와 같이 다른 캐릭터셋으로 선언해서 개발하던 적도 있었습니다. 하지만, 요즘은 그렇게 개발을 하지는 않습니다. 바로 디스크의 용량이 비약적으로 커지고 소스 크기는 그렇게 커지지 않았기 때문에 용량에 대한 부담이 거의 없기 때문입니다. 그래서 요즘은 그냥 UTF-8 로 통일해놓고 개발하는 것을 다시 한 번 권해드리는 겁니다.




그런데, HTML 에서 UTF-8 로 인코딩되어 사용자에게 정보가 보여졌는데, 게시글 입력과 같이 사용자가 한글이나 한자 등의 데이터를 입력해서 서버에 전송하게 될 때는 어떤 일이 벌어질까요?


아주 예전에 웹을 설계하던 사람들은 우리의 기대를 저버리지 않고 다국어에 대한 고려를 전혀 하지 않았습니다. 그래서 웹에서 전송되는 문자는 모두 ASCII 을 기준으로 데이터가 전송되는 것으로 설계가 되었습니다. 그래서 HTML 에서 영어가 아닌 다른 캐릭터셋으로 문서를 작성해서 전송하려면 문제가 발생했습니다. 그래서 강제로 문자열을 웹에 맞는 ASCII 로 변환한 뒤 이를 다시 원하는 문자열로 변환시켜주는 작업이 필요했습니다. 이런 작업이 URL Encoding/Decoding 입니다. ASP 에서는 Server.URLEncode 로 변환을 제공하고, Java 에서는 java.net.URLEncoder 의 encode 매서드를 이용해서 변환을 한 뒤 서버로 전송하게 해줬습니다. 혹은 Javascript 에서 변환시켜주기도 했고, 넘어온 문자열을 깨지지 않고 받기 위해서 URLDecoder.decode() 을 이용해서 받거나 request.setCharacterEncoding() 을 이용해서 직접적인 선언을 해서 받아줬습니다. 또한 받은 매개변수를 정확한 내용으로 변경하기 위해 new String(request.getParameter("매개변수명").getBytes("ISO-8859-1"), "UTF-8) 와 같이 길게 변환을 해주는 작업까지 직접 해줘야 했습니다.



하지만, 이런 불편함을 해결하기 위해서 Java 진영에서는 WAS 에서 문자열을 정해진 인코딩으로 직접 받아오는 방법을 제공하기 시작했습니다.



Java 에서 가장 많이 사용되는 Apache Tomcat 에서 주로 사용하는 <Connector> 의 URIEncoding 은 이렇게해서 만들어진 것입니다. 지금은 그냥 공식처럼 <Connector URIEncoding="UTF-8" /> 와 같이 선언하면 매개변수값을 UTF-8 로 그냥 받을 수 있지만, 예전에는 그렇지 않았습니다. 물론 이 또한 GET 에서만 제공되는 방법이고, WAS 마다 GET 을 위한 URL Encoding 명시 방법은 다르기 때문에 사용하는 WAS 에서 어떤 방식을 제공하는지 확인 후 사용해야 할 것입니다. 많이 사용하는 웹로직만 간단히 예를 들면, 웹로직의 가장 기본이 되는 weblogic.xml 파일을 생성한 뒤 다음과 같은 내용을 입력하면 Tomcat 의 URIEncoding 와 같은 효과를 가지게 됩니다.

<wls:charset-params>
    <wls:input-charset>
        <wls:resource-path>/</wls:resource-path>
        <wls:java-charset-name>EUC-KR</wls:java-charset-name>
    </wls:input-charset>
</wls:charset-params>

하지만, 이것들은 WAS 에 종속적이므로 소스 상에서 직접 제어를 하고자 할 때에는 request.setCharacterEncoding() 으로 선언하는 방법을 쓸 수 있습니다. 하지만, 개인적으로는 비효율적이라 생각합니다.



그럼 POST 방식은 어떻게 구현할까요? Spring 을 쓰시는 분들은 web.xml 에 아래와 같이 선언한 것을 많이들 보셨을 겁니다.

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <async-supported>false</async-supported>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>

필터를 이용한 자동 변환 방법인데, 사실 예전에 Spring 에서 이와 같이 필터를 제공해주기 전에는 CharacterEncodingFilter 와 같은 역활을 해주는 필터를 직접 사용자가 구현해서 필터로 등록해서 사용했습니다. Spring 이 많은 편리함을 제공해준다는게 이런 곳에서도 잘 나타나는 것이죠.



개인적으로 바빠지다 보니 점점 글의 내용이 빈약해진다는게 저 스스로도 느껴지네요. 다음 번에는 인코딩에 대한 마지막 글인 MySQL 에서 정보를 가져올 때 인코딩 설정을 어떻게 하는지 간략하게 알아보고 당분간 팁을 작성하는 것은 쉬어야겠네요.

댓글 없음:

댓글 쓰기