본문 바로가기

Servlet, JSP

Servlet에서 인코딩 방식과 컨텐츠 타입을 지정해야 하는 이유

Servlet에서 인코딩 방식과 출력 형식을 지정 안 하는 경우 다음과 같은 현상이 발생합니다.

인코딩 방식을 지정 안 하는 경우 : 한글이 깨짐

콘텐츠 타입을 지정 안 하는 경우 : 브라우저가 문서의 형식을 자의적으로 해석하기 때문

한글이 깨지고 <br> 태그를 인식 못하는 크롬 브라우저

이 문제는 다음 서블릿 실행을 통해서 발생했습니다.

해결책과 이유를 알아보도록 하겠습니다.

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
	@Override
	public void service (HttpServletRequest request
			, HttpServletResponse response) throws IOException, ServletException{
		
		PrintWriter out = response.getWriter();
		
		for (int i =0; i <100; i++)
			out.println("야호 Hello Servlet <br>");
	}

}

 

해결책

다음과 같은 서블릿을 작성하고 실행하면 

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
	@Override
	public void service (HttpServletRequest request
			, HttpServletResponse response) throws IOException, ServletException{
		response.setCharacterEncoding("UTF-8"); 
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		
		for (int i =0; i <100; i++)
			out.println("야호 Hello Servlet <br>");
	}

}

한글도 깨지지 않고 <br> 태그를 인식하면서 출력됩니다.

 


 

 

HTML 태그를 인식하지 못하는 이유 : 브라우저의 자의적인 해석

브라우저는 서버가 보내는 문서의 형식이 명시되어 있지 않으면 자의적으로 문서의 형식을 해석합니다.

 

Edge, Chrome은 text로,
Explore는 html로 해석합니다.

 

다음과 같이 서블릿을 작성하면

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
	@Override
	public void service (HttpServletRequest request
			, HttpServletResponse response) throws IOException, ServletException{
		
		PrintWriter out = response.getWriter();
		
		for (int i =0; i <100; i++)
			out.println("Hello Servlet ");
	}
}

 

크롬, 에지 브라우저는 줄 넘김이 된 상태로 출력합니다.

왼쪽 크롬, 오른쪽 엣지 브라우저 - 줄넘김이 됐습니다!

Internet Explore 브라우저는 다음과 같이 줄 넘김이 되지 않았습니다.

그 이유는 응답 받은 문서의 Contents type(콘텐츠 타입) 값이 없어서 HTML로 해석했기 때문입니다.

 

다음과 같이 출력할 때 <br> 태그를 넣어보겠습니다.

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
	@Override
	public void service (HttpServletRequest request
			, HttpServletResponse response) throws IOException, ServletException{
		
		PrintWriter out = response.getWriter();
		
		for (int i =0; i <100; i++)
			out.println("Hello Servlet <br>");
	}

}

인터넷 익스플로어 같은 경우에 <br> 태그로 인해 줄 넘김이 된 것을 확인할 수 있습니다.

 

 

하지만 크롬의 경우에 <br> 텍스트를 그대로 출력한 것을 확인할 수 있습니다.

크롬이 응답 받은 문서의 Contents type(콘텐츠 타입) 값이 없어서 text로 해석했기 때문입니다.

 

 

 


 

한글이 깨지는 현상

원인 1 : 웹 서버에서 한글을 지원하지 않는 ISO-8859-1 방식으로 인코딩했기 때문입니다.

ISO-8859-1 방식은 한 글자를 1바이트씩 해석하는 방식입니다. 

한글은 한 글자가 2바이트이고, 1 바이트씩 해석하면 깨지는 현상이 발생합니다.

사용자에게는 "??"로 보입니다.

한글이 ??로 출력됨

=>  서버에서는 문서를 UTF-8 인코딩 방식으로 보낸다고 설정해줍니다.

response.setCharacterEncoding("UTF-8"); 

하지만 이것만으로는 부족합니다. 아래 사진처럼?? 는 아니지만 한글이 깨져서 나옵니다.

 

원인 2 : 서버에서는 UTF-8로 인코딩해서 보냈지만 브라우저가 다른 인코딩 방식(예- EUC-KR)으로 해석했기 때문입니다.

이상한 문자로 출력

해결책 : 브라우저는 응답 문서를 UTF-8로 읽으라고 명시합니다.

"text/html"은 브라우저가 응답 문서를 html 문서로 읽으라고 명시하는 것입니다.

response.setContentType("text/html; charset=UTF-8");