본문 바로가기
웹 프로그래밍/Servlet & JSP

Servlet 응답 정보 처리 (HttpServletResponse, 한글 응답)

by kgvovc 2021. 3. 11.
반응형

응답정보

 

객체 생성 및 삭제

HttpServletRequest는 클라이언트가 서버에 보내는 요청정보를 처리하는 객체이고, HttpServletResponse는 서버가 클라이언트로 보내는 응답정보를 처리하는 객체입니다.

 

클라이언트의 요청으로부터 시작되는 웹서버의 처리 순서를 알아보면 다음과 같습니다.

1) 클라이언트가 웹 브라우저에서 서비스를 요청합니다. 이때 HTTP 프로토콜 기반으로 요청정보가 만들어져 웹서버에 전달됩니다.

2) 웹서버는 클라이언트로부터 전달받은 요청정보의 URI를 살펴보고, 서블릿이라면 서블릿 컨테이너에 처리를 넘깁니다.

3) 서블릿 컨테이너는 요청받은 서블릿 클래스 파일을 찾아서 실행합니다.

4) 실행할 때 첫 순서는 최초의 요청인지를 파악합니다. 최초의 요청이라면 메모리에 로딩 후 객체를 생성하고 init() 메소드를 호출합니다.

5) init() 메소드 실행이 끝난 다음에는 최초의 요청이든지 그렇지 않든지 서블릿 실행 요청이 들어올 때마다 실행되는 작업으로, 서블릿 컨테이너는 HttpServletRequest와 HttpServletResponse 객체를 생성합니다. HttpServletRequest 객체는 클라이언트로부터 요청받은 정보를 처리할 목적으로 생성하고, HttpServletResponse 객체는 클라이언트에게 보내는 응답정보를 처리할 목적으로 생성합니다.

6) service() 메소드를 호출합니다. 이때, 앞에서 생성한 HttpServletRequest와 HttpServletResponse 객체의 주소를 인자로 넘깁니다. service() 메소드에서는 인자로 받은 두 객체를 사용하여 프로그램을 구현합니다.

7) service() 메소드가 완료되면 클라이언트에게 응답을 보내고 서버에서 실행되는 프로그램은 완료됩니다. 이때, HttpServletRequest와 HttpServletResponse 객체는 소멸합니다.

 

이러한 처리 과정에서 꼭 기억해야 할 점은 HttpServletRequest와 HttpServletResponse 객체의 생존 기간입니다. 한번 더 강조하자면, HttpServletRequest와 HttpServletResponse 객체는 service() 메소드가 실행되기 전에 생성되었다가 끝나면 소멸합니다. 따라서 service() 메소드가 실행되는 동안에만 메모리에 상주하고 있어서 그동안에만 사용할 수 있습니다.

 

 

응답정보 처리 - HttpServletResponse

서비스를 요청한 클라이언트에게 응답하기 위한 기능을 처리할 때 javax.servlet 패키지의 ServletResponse 인터페이스를 사용합니다. 이 인터페이스를 이용하여 클라이언트의 요청에 응답하기 위한 출력스트림을 추출하거나 버퍼의 크기를 설정하고, 응답할 내용의 타입과 문자셋을 설정하는 등의 작업을 수행할 수 있습니다.

 

또한, HttpServletResponse 인터페이스는 우리가 웹 애플리케이션을 개발하면서 응답 관련 작업을 수행할 때 사용하는 ServletResponse 인터페이스를 상속합니다. 따라서 일반적인 네트워크 통신에서 응답과 관련된 메소드들을 포함하고 있으며, 여기에 HTTP 프로토콜 통신 기반의 응답 관련 메소드들도 확장하여 포함하고 있습니다.

 

  • ServletResponse: 일반적인 네트워크 통신에서의 응답 관련 메소드 제공
  • HttpServletResponse: HTTP 통신 기반의 응답 관련 메소드 확장 제공

 

 

ServletResponse 인터페이스의 주요 메소드

함수 기능
PrintWriter getWriter() 서비스를 요청한 클라이언트와 서버 간에 연결된 PrintWriter 객체를 생성하여 반환한다.
void setBufferSize(int size) 출력스트림의 버퍼 크기를 설정한다.
void setCharacterEncoding(String charset) 응답정보 인코딩에 사용할 문자를 설정한다.
void setContentLength(int len) 응답정보의 데이터 길이를 설정한다.
void setContentType(String type) 응답정보의 데이터 형식(MIME 타입)을 설정한다.
void setLocale(Locale loc) 클라이언트가 사용하는 언어, 국가코드 등 클라이언트의 환경을 설정한다.

 

ServletResponse 인터페이스에는 네트워크 환경에서 필요한 응답 관련 메소드들을 정의하고 있지만, HTTP 프로토콜 기반의 응답과 관련된 메소드들은 ServletResponse를 확장한 HttpServletResponse 인터페이스에서 정의하고 있습니다. HttpServletResponse는 쿠키 설정, HTTP 응답 헤더 설정 등 HTTP 프로토콜과 직접적인 관계가 있는 메소드들을 포함하고 있습니다.

 

 

 

 

HttpServletResponse 인터페이스 주요 메소드

함수 기능
void addCookie(Cookie cookie) 인자값으로 주어진 쿠키를 응답정보의 헤더에 추가한다. 쿠키는 응답정보의 Set-Cookie 헤더의 값으로 추가되어 클라이언트로 전송된다.
String encodeRedirectURL(String url) 클라이언트와 서버 간 세션이 유지되는 상태에서 브라우저 쿠키를 지원하지 않을 때 주어진 URL 뒤에 세션 아이디를 추가하고 인코딩하여 요청을 재전송한다.
String encodeURL(String url) 주어진 URL에 세션 아이디를 추가하여 인코딩해서 반환한다.
void sendRedirect(String location) 응답을 클라이언트가 요청한 URL이 아니라 sendRedirect()에 주어진 URL로 재전송한다. 매개변수 location은 절대 URL이나 상대 URL로 지정한다. 이 메소드는 서버의 특정 자원이 다른 URL로 이동할 때 사용할 수 있는 메소드이다.
public void setDateHeader(String name, long date) 날짜를 밀리 초로 변환하여 주어진 이름과 날짜를 응답정보 헤더에 설정한다.
public void setHeader(String name, String value) 응답정보의 헤더에 주어진 이름과 값을 설정한다.
public void setIntHeader(String name, int value) 주어진 이름과 정수값을 갖도록 응답정보 헤더에 추가한다.
public void setStatus(int sc) 응답으로 전송될 HTTP 응답에 대한 상태코드를 설정한다.

 

 

출력 응답

HttpServletResponse 객체를 활용하여 클라이언트 쪽으로 문자열을 전송한 다음, 웹 브라우저에 문자열을 출력하는 예제를 작성해보겠습니다.

 

<이클립스 디렉토리 구조>

 

package com.edu.test;

import java.io.*;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;


@WebServlet("/second")
public class SecondServlet extends HttpServlet {

	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		System.out.println("SecondServlet!!");
		PrintWriter out = res.getWriter();
		out.print("<html><head><title>Test</title></head>");
		out.print("<body><h1>have a nice day!!</h1></body></html>");
		out.close();
	}
}

 

위의 서블릿을 실행하면,

 

위와 같이 잘 접속되는 것을 확인할 수 있습니다.

 

 

한글 응답

웹 프로그램을 개발할 때 자주 발생하는 문제 중 하나가 한글이 올바르게 표시되지 않고 깨져서 나오는 것입니다. 이렇게 깨진 한글을 그냥 놔둘 수는 없으므로 복원해야 하는데요. 이번 절에서는 서버에서 웹 브라우저로 보낸 한글을 웹 브라우저로 출력했을 때 응답정보 헤더에 한글을 처리하기 위해 설정하는 내용에 대해 알아보겠습니다.

 

package com.edu.test;

import java.io.*;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;


@WebServlet("/third")
public class ThirdServlet extends HttpServlet {

	protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException {
		PrintWriter out = rsp.getWriter();
		out.print("<h1>좋은 하루!</h1>");
		out.close();
	}
}

 

위의 소스는 클라이언트와 서버 간의 out 출력스트림을 만들어 이를 이용해 out.print("<h1>좋은 하루!</h1>"); 문자열을 전송하는 소스입니다.

 

그런데 서버 프로그램에서 클라이언트로 데이터를 전송하면서 명시하지 않은 정보가 있습니다. 그것은 보내는 데이터의 타입과 문자셋 정보입니다. 응답정보의 헤더에 데이터 타입과 문자셋을 설정해서 보내야지만 클라이언트는 받은 데이터를 타입에 맞게 처리할 수 있고, 인코딩 작업도 할 수 있습니다.

 

그런데 서버가 이 정보를 명시하지 않으면 기본값으로 처리합니다. 즉, 문서타입은 text/html, 문자셋은 8859_1로 처리합니다. 그래서 "<h1>좋은 하루!</h1>"란 문자열을 보내면 HTML의 <H1> 태그로 처리하고, 인코딩 문자셋은 8859_1로 처리하는데요. 아쉽게도 8859_1 문자셋은 한글을 지원하지 않습니다. 따라서 다음처럼 한글이 깨져서 나옵니다.

 

 

이처럼 한글이 깨지는 문제를 방지하려면 서버가 클라이언트로 보내는 데이터의 문서타입과 한글을 지원하는 문자셋을 응답정보 헤더에 설정해서 보내야 합니다. 문서타입과 문자셋을 설정하려면 HttpServletResponse의 setContentType() 메소드를 사용합니다. 소스를 다음처럼 수정합니다.

 

package com.edu.test;

import java.io.*;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;


@WebServlet("/third")
public class ThirdServlet extends HttpServlet {

	protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException {
		rsp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = rsp.getWriter();
		out.print("<h1>좋은 하루!</h1>");
		out.close();
	}
}

 

위처럼 "text/html;charset=UTF-8"을 매개변수로 setContentType() 메소드를 호출하면, 응답 정보 헤더에 문서의 타입과 문자셋을 지정할 수 있습니다.

응답정보의 Content-Type 헤더에는 두 가지 정보를 설정해야 하는데요. 세미콜론(;)을 기준으로 앞에는 문서의 타입을 지정하고, 뒤에는 charset= 다음에 문자셋을 지정합니다.

 

 

다시 실행해보면, 위와 같이 한글이 잘 나오는 것을 확인할 수 있습니다.

반응형

댓글