웹 브라우저에서 보낸 한글 데이터를 서블릿에서 꺼낼 때 한글이 깨지는 경우가 있다. 그 이유와 해결책을 알아본다.
회원등록 입력폼의 이름 입력단에 한글 이름을 입력 후 추가버튼을 클릭한다(그림 1).

회원 목록 조회 결과를 확인한다(그림 2).

한글로 '가각간'이라고 입력한 이름부분이 깨진 것을 확인할 수 있다.

DB의 MEMBERS 테이블 조회문을 실행하니 한글이 깨져서 데이터가 저장된 것 또한 확인할 수 있다(그림 3).
한글이 깨진 이유를 살펴보기 위해 웹 브라우저의 기본 문자집합을 확인한다(그림 4).

현재 사용하는 크롬의 기본 문자집합이 유니코드(UTF-8)로 설정되어 있는 것을 확인할 수 있다.
(크롬은 따로 기본 문자집합을 확인할 수 있는 방법이 없어서 Set Character Encoding 이라는 크롬 확장 프로그램을 설치하여 확인하였다)
웹 브라우저가 웹 서버로 데이터를 보낼 때 웹 페이지의 기본 문자집합으로 인코딩하여 보내기 때문에 사용자가 입력한 값은 UTF-8로 인코딩되어 서버에 전달된다. 즉, 웹 브라우저에선 한글이 깨지지 않게 보내짐을 확인할 수 있다.
그럼 서블릿에서 데이터를 꺼낼 때 문자 형식을 살펴본다. MemberAddServlet 클래스의 doPost()에서 입력 매개변수에 값을 지정할 때 HttpServletRequest 클래스의 메소드 getParameter()를 호출하는 모습을 볼 수 있다.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
stmt.setString(1, request.getParameter("email"));
stmt.setString(2, request.getParameter("password"));
stmt.setString(3, request.getParameter("name"));
...
}
서블릿에서 getParameter()를 호출하면 기본적으로 매개변수의 값이 ISO-8859-1(ISO-Latin-1)로 인코딩되었다고 가정하고 각 바이트를 유니코드로 바꾸고 나서 반환한다. 즉 클라이언트가 보낸 문자를 영어로 간주하고 유니코드로 바꾼다. 바로 여기서 문제가 발생한 것이다. 서블릿이 웹 브라우저로 받은 한글 데이터는 UTF-8로 인코딩된 값이다. UTF-8은 한글 한 자를 3바이트로 표현한다. 서블릿은 이 3바이트를 하나의 문자로 인식하지 않고 각각의 바이트를 개별 문자로 취급하여 유니코드를 변환하기 때문에 각각으론 의미 없는 바이트들이 유니코드로 바뀌어져 한글이 깨진 것이다(그림 5).

한글이 깨지는 것을 해결하려면 getParameter()를 호출하기 전에 클라이언트가 보낸 매개변수의 값이 어떤 인코딩으로 되어 있는지 지정해야 한다.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//setCharacterEncoding() : 매개변수 값의 인코딩 형식 지정하는 메소드(이 메소드가 호출되기 전 getParameter()가 호출되면 아무 소용 없다.)
request.setCharacterEncoding("UTF-8");
...
stmt.setString(1, request.getParameter("email"));
stmt.setString(2, request.getParameter("password"));
stmt.setString(3, request.getParameter("name"));
...
}
HttpServletRequest 클래스의 메소드 setCharacterEncoding()는 매개변수 값의 인코딩 형식을 지정한다. 단, 이 메소드가 호출되기 전에 getParameter()를 호출하면 이 메소드의 기능이 아무 소용없어 진다.
톰캣 서버를 재시작한 뒤 회원 정보를 다시 등록하고 회원 목록 조회 결과를 확인한다.

마지막 행을 보면 한글이 깨지지 않고 제대로 출력된 것을 확인할 수 있다.

DB의 MEMBERS 테이블 조회문을 실행하니 한글이 깨지지 않고 올바르게 저장된 것을 확인할 수 있다.
톰캣(5.X 이상)의 경우 클라이언트에서 GET 요청으로 데이터를 보내면 여전히 한글이 깨진다. GET 요청에서는 매개변수의 값을 URL에 포함하여 보내는데 setCharacterEncoding()은 이런 쿼리스트링에 대해서는 적용되지 않기 때문에 톰캣 서버의 server.xml에서 다음 코드를 찾아 URIEncoding="UTF-8"을 추가하여 해결해야 한다.


<Connector connectionTimeout="20000" port="9999" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8" />
이렇게 편집한다. 이클립스는 톰캣 실행 환경을 별도의 프로젝트로 관리한다. Servers 프로젝트를 살펴보면 각 톰캣 실행 환경마다 서버 설정 파일이 있음을 확인할 수 있다. 서블릿 컨테이너마다 설정 방법이 다르니 반드시 제품 매뉴얼을 확인해야 한다.
만약 톰캣 서버를 설치 폴더에서 독립적으로 실행하는 경우 톰캣이 설치된 폴더에서 conf/server.xml파일을 편집한다.

server.xml파일 위치 : C:\javaide\server\apache-tomcat-8.5.73\conf\server.xml
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
28. 리다이렉트 (0) | 2022.01.24 |
---|---|
27. 리프래시 (0) | 2022.01.23 |
25. HttpServlet으로 POST 요청 다루기 (0) | 2022.01.20 |
24. HttpServlet으로 GET 요청 다루기 (1) | 2022.01.19 |
23. 데이터베이스에서 데이터 가져오기 (2) (0) | 2022.01.18 |
댓글