Trouble Shooting

WEB 개발시 한글 인코딩 문제

후뤼한잉여 2015. 12. 14. 23:28

한글 인코딩 문제

개인적으로 겪은 인코딩에 대한 문제와 해결 방법에 대해서 간단히 정리해보고자 문서를 남깁니다.

1. POST 방식

  1. JSP 페이지에서의 한글 처리
    다른 페이지 또는 서버로 부터 오는 정보가 아닌, 페이지 자체의 페이지 인코딩이 필요할 때 합니다.
    예를 들어 서버로 부터 넘겨받은 파라미터값은 잘 불러와지는데, 페이지 자체의 한글이나, 한글로된 리소스를 불러올 때 필요합니다.
     한글 한글
     <img src="/resources/한글파일.png" />
    
    위와 같은 소스가 깨질 때 pageEncoding 설정을 변경합니다.
     <%@ page pageEncoding="UTF-8"%>
    
  2. 다른 페이지에 넘기는 파라미터에 대한 한글 처리

    1. HttpServletResponse 객체를 이용한 설정 방법
      • 서블릿에서 처리하는 방법
        httpServletResponse.setCharacterEncoding("UTF-8");
        
      • JSP에서 처리하는 방법
        <% response.setCharacterEncoding("UTF-8"); %>
        
    2. 웹 서버의 배치 기술서(Deployment Descriptor, DD) 파일에 필터 설정

      • Tomcat Container

        [web.xml][Spring 사용 시]
        <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>
        
          <init-param>
              <param-name>forceEncoding</param-name>
              <param-value>true</param-value>
          </init-param>
        </filter>
        
        <filter-mapping>
          <filter-name>encodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
        </filter-mapping>
        

        스프링이 아닌 자체 프레임워크등을 사용시에는 직접 필터를 구현하여 설정 할 수도 있습니다.
        아래의 소스는 직접 필터를 구현하여 처리하는 간단한 예 입니다.
        UTF-8 부분을 원래 서버에 설정에서 받아오도록 해야하지만 간단한 예이므로 넘어갑니다.

        [필터 클래스]
        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 CharacterEncodingFilter implements Filter{
          FilterConfig config;
        
          @Override
          public void init(FilterConfig config) throws ServletException {
              this.config = config;
          }
        
          @Override
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain nextFilter)
                  throws IOException, ServletException {
              request.setCharacterEncoding("UTF-8");
              nextFilter.doFilter(request, response);
          }
        
          @Override
          public void destroy() { }
        }
        
        [배치 기술서 파일]
        <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>test.filters.CharacterEncodingFilter</filter-class>
        
          <init-param>
              <param-name>encoding</param-name>
              <param-value>UTF-8</param-value>
          </init-param>
        </filter>
        
        <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
        </filter-mapping>
        

2. GET 방식

  1. 서버에서의 처리
    요청에 의해 넘어온 스트링 값을 기본 형식인 ISO-8859-1의 바이트형식으로 읽어들여 한글을 처리하기 위한 형식으로 새로운 스트링을 생성한다.
     new String(request.getParameter("파라미터명").getBytes("8859_1"), "UTF-8");
     new String(request.getParameter("파라미터명").getBytes("ISO-8859-1"), "UTF-8");
    
  2. 웹 서버의 서버 설정파일 수정
    • Tomcat Container
      [server.xml]
      <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8" />
      ...
      <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8" />
      

      Conntector 설정 부분에 URIEncoding 설정을 하는 방법이다.
      서버로 들어오는 요청에 대해 인코딩 설정을 하는 부분으로 알고 있는데, 톰캣의 경우 8080은 기본 포트이고, 8009는 아파치와의 AJP 프로토콜을 통한 연동시 주로 사용하는 포트로 알고 있다.
      즉, 8080은 톰캣에 직접 요청시에 대한 인코딩 설정이며, 8009부분은 아파치를 통해 넘어오는 값에 대한 설정으로 이해하고 있다.

자바스크립트에서의 인코딩/디코딩

내장함수 명 설명
escape() 영문 알파벳, 숫자, 일부 특수 문자(@, *, -, _, +, ., /)를 제외한 모든 문자를 인코딩
1바이트 문자는 %XX의 형태로, 2바이트 문자는 %uXXXX의 형태로 변환하여 표현
unescape() escape()로 인코딩 된 내용을 디코딩
encodeURI() URL 주소표시를 나타내는 특수문자(:, ;, /, =, ?, &)를 제외한 모든 문자 인코딩
decodeURI() encodeURI()로 인코딩 된 내용을 디코딩
encodeURIComponent() 영문 알파벳, 숫자, 일부 특수문자(-, _, !, ~, *, ‘, (, ))를 제외한 모든 문자를 인코딩
/도 인코딩하기 때문에 URL 경로를 포함해서 사용시 주의가 필요하다.
decodeURIComponent() decodeURIComponent()로 인코딩 된 내용을 디코딩

자세한 내용은 모질라 재단MS사의 TechNet등 문서를 보는것이 좋을것 같습니다.

  • 이클립스에서 테스트나 익스플로러에서 테스트시 직접 URL에 한글을 입력하면 위 설정들에도 불구하고 한글이 깨져나오는 증상이 있었습니다.
    나름의 테스트 결과 갓 구글을 제외한 대형 포털인 네이버, 다음에서도 GET 방식으로 직접 한글을 입력하면 제대로 처리가 되지 않는걸로 확인되었습니다.
  • 자바스크립트를 통해 URL Encoding을 해서 값을 넘겨줘야 잘 처리되는것을 확인 할 수 있었습니다.
  • 처리할 때의 인코딩 방식은 encodeURI()나 encodeURIComponent() 사용하면 되는데, URL 전체 인코딩시에는 encodeURI()를 사용해야 합니다.
    대형 포털에서도 처리 안해주는거에 괜히 힘 빼지 않기로 생각했습니다.
    직접 테스트시에는 직접 프로그램을 만들어서 하거나, URL 인코딩/디코딩 사이트을 이용하여 한글 부분만 처리해서 입력하는 것이 머리가 덜 빠지는 길이라고 생각하고, 나중에 다국어 처리를 해볼 일이 있다면 그 때 내용을 추가하던 할 것 같습니다.
    아니면 브라우저의 콘솔모드를 이용하여 인코딩하는 방법도 하나의 방법입니다.
    마지막으로 자라나라 머리머리~!