웹 환경에서의 한글 인코딩
웹개발을 하다보면 글자 인코딩과 관련된 이슈를 많이 접하게 됩니다.
영어 알파벳은 ASCII 코드가 어느 Characterset(이하 캐릭터셋 또는 문자셋)에나 기본적으로 포함되어 있기 때문에 어떠한 인코딩을 사용하든지 깨질 일이 없지만 한글의 경우에는 EUC-KR, UTF 계열 인코딩 등 특정 캐릭터셋이 아니면 한글을 표현하지 못해 깨지는 현상이 발생합니다.

웹 환경에서의 데이터는 보통 브라우저(클라이언트) - 서버 - DB서버 처럼 3계층에 거쳐 주고받게 되는데 이때 세 가지 요소의 인코딩이 서로 맞아야 합니다.
데이터를 입력받거나 출력하는 통로를 스트림이라고 하는데 얼핏 보기에는 하나의 스트림을 통해 데이터를 주고 받는것처럼 보이지만 사실은 입력스트림과 출력스트림을 통해 데이터를 각각 입력 및 출력하기 때문에 각 스트림의 데이터 형식을 맞춰 주어야합니다.

예를들어 브라우저에서 보낸 한글 데이터를 웹서버에서 UTF-8로 받은 후 웹서버에서 DB서버로 ISO-8859-1같은 한글을 표현할 수 없는 캐릭터셋으로 보낸다면 이 과정에서 한글이 깨지게 됩니다.
또는 웹서버에서 DB서버로 한글을 UTF-8형식으로 잘 보냈지만 DB 서버에서 받을때 ASCII 로 받는다면 한글 인코딩 문제가 발생할 것입니다.

 

 

 

한글 입력 실험
다음 예제에서는 한글로 가입 정보를 입력하고 전송을 누른 경우 입력한 정보가 주소 : 서울특별시 같은 형식으로 다시 출력되기를 기대했습니다.
그러나 두번째 사진처럼 결과값에서는 한글이 깨지게 되었습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@WebServlet("/RequestTest")
public class RequestTest extends HttpServlet implements Servlet {
 
     protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
 
           PrintWriter out = response.getWriter();
 
           String id = request.getParameter("id");
           String passwd = request.getParameter("passwd");
           String address = request.getParameter("address");
           String gender = request.getParameter("gender");
           String checkDog = request.getParameter("checkDog");
           String checkCat = request.getParameter("checkCat");
           String checkEtc = request.getParameter("checkEtc");
           String source = request.getParameter("source");
           String etc = request.getParameter("etc");
 
           out.println("<html><head><title></title></head>");
           out.println("<body>");
           out.println("아이디 : " + id + "<br>");
           out.println("비밀번호 : " + passwd + "<br>");
           out.println("주소 : " + address + "<br>");
           out.println("성별 : " + gender + "<br>");
           ..아래생략..
 
cs

 

 

 

 

한글이 깨지는 원인
그렇다면 왜 이런 현상이 일어난 것일까요??
이유는 문자 인코딩 차이때문입니다.

WAS 종류에 따라 기본 문자 인코딩방식은 달라집니다.
톰캣의 경우에는 8버전은 기본적으로 따로 설정하지 않는 경우 UTF-8이며 8버전 미만에서는 ISO-8859-1 캐릭터셋을 입출력에 사용합니다.
하지만  ISO-8859-1 은 한글을 표현할 수 없기때문에 브라우저가 보낸 한글을 이해할 수 없습니다.

request.getParameter("address") 메서드를 호출할 경우 인코딩이 맞지 않아 깨진 문자들이 반환될 것이고 이러한 문자들을 곧바로 브라우저로 출력하게 됩니다.


해결 방법
처음에도 언급했듯이 웹 환경에서는 여러가지 요소들의 인코딩 방식이 서로 맞아야하며 인코딩 문제가 발생하면 찾기도 번거롭습니다.
때문에 개발 및 환경설정 시점에서부터 인코딩 설정들을 맞춰 주는것이 좋습니다.


1. 이클립스 혹은 사용중인 개발툴(IDE) 설정을 UTF-8로 바꿔줍니다.

 

2. html 소스파일 <meta> 태그 charset 설정
meta태그를 통해 현재 html페이지가 UTF-8을 사용한다는 것을 브라우저에게 알려줍니다.
1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
cs

 

3. jsp인 경우의 설정
JSP의 경우 page디렉티브의 contentType 속성과 pageEncoding 속성의 캐릭터셋을 지정해줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
   
</body>
</html>
cs

 

 

4.서블릿인 경우 인코딩 설정

요청이 POST 방식인 경우
다음과 같이 setCharacterEncoding 설정을 통해 request 객체와 response 객체의 캐릭터셋을 한글을 표현할 수 있는 인코딩으로 셋팅해줍니다.
이 때 주의할점은 response.getWriter() 과 request.getParameter() 메서드 사용 이전에 셋팅해주어야 한다는 점입니다.
1
2
3
4
5
6
7
8
9
10
11
@WebServlet("/hello")
public class FirstServlet extends HttpServlet {
    
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");
        
        ...req.getParameter() 와 resp.getWriter() 사용 전 셋팅....
    }
}
cs

 

 

요청이 GET방식인 경우
HttpServletRequest객체의 setCharacterEncoding() 메서드의 경우 클라이언트가 보낸 HTTP 요청 메세지의 BODY 부분을 인코딩해주는 메서드입니다.
즉 GET방식의 요청의 경우 HTTP 메세지의 바디부분이 없기 때문에 다른 설정이 필요합니다.
GET방식 요청의 경우 데이터는 URI에 쿼리스트링 형태로 담겨져 오기때문에 컨테이너는 URI를 인코딩하여 받는 설정을 해주어야 합니다.
[톰캣 설치 경로]/conf/server.xml 을 에디터로 열어줍니다.

특별한 설정을 하지 않은 경우 톰캣의 연결 포트는 8080포트입니다.
컨트롤 + F 를 통해 문자열 검색으로 8080을 검색하면 다음과 같은 코드가 나오는데 URIEncodig="utf-8" 을 추가해 줍니다.
1
2
3
4
5
6
    <Connector
     connectionTimeout="20000"
     port="8080"
     protocol="HTTP/1.1"
     redirectPort="8443"
     URIEncoding="utf-8"/>
cs

 

5. db서버 인코딩 설정
dbms가 사용하는 인코딩 또한 맞춰주어야 합니다.
dbms의 경우 서버마다 설정이 다르므로 해당 dbms에 맞게 설정합니다.

 

 

 

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,