본문 바로가기
Web/spring study

[Spring] 서블릿, HttpServletRequest, HttpServletResponse

by 장인이 2023. 1. 17.

1. 개요

 이번 게시물에서는 실제로 서블릿을 사용해 볼 것이다. 서블릿에 대한 설명은 아래 게시물을 참고해보자.

(서블릿에 대한 설명)

 

 

2. 서블릿 사용하기

 서블릿을 사용하려면 웹 애플리케이션 서버를 직접 설치하고, 서블릿 코드를 클래스 파일로 빌드한 후, 톰캣 서버를 실행해야 한다. 이는 매우 번거럽기 때문에 톰캣 서버를 내장하고 있는 스프링 부트를 사용하면 된다.

(사실 이제는 스프링 MVC 패턴을 주로 사용, 서블릿 동작 원리만 확인해 보기 위함이기 때문)

 

- 스브링 부트 서블릿 환경 구성

@ServletComponentScan //서블릿 자동 등록
@SpringBootApplication
public class ServletApplication {
    public static void main(String[] args) {
    	SpringApplication.run(ServletApplication.class, args);
    }   
}

 스프링 부트에서 서블릿을 직접 등록해서 사용할 경우, @ServletComponentScan 에노테이션을 추가하면 된다.

 

- 서블릿 등록하기

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

 서블릿을 사용하려면 HttpServlet 클래스를 상속받은 후, @WebServlet 애노테이션을 붙인다. name으로 서블릿 이름을 지정, urlPatterns로 URL 매핑을 해준다.

 

 HTTP 요청을 통해 매핑된 URL이 호출되면, 서블릿 컨테이너는 service 메서드를 실행한다. 

 

 service 메서드 내에서 HttpServletRequest request를 통해서 클라이언트의 요청 정보를 가져오고, HttpServletResponse response에 응답할 정보를 지정해준다.

 

 

3. HttpServletRequest

 Http 요청 메시지를 개발자가 직접 파싱해서 사용해도 된다. 하지만, 매우 불편할 것이다. 따라서 서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 대신 파싱한다. 그 후 결과를 HttpServletRequest 객체에 담아서 제공해준다.

 

- request header

헤더 내용을 직접 가져올 수 있으며, 함수들은 아래 링크를 참조 바란다.

https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html

 

HTTP 요청 방식은 크게 3방식으로 나눌 수 있으며, 관련 수칙은 아래 내용을 참고 바란다.

(HTTP API 설계하는 법)

 

1) GET 요청, 쿼리 파라미터로 정보 받기

ex) /url?username=hello&age=20

- 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달한다.

 

//단일 파라미터 조회
String username = request.getParameter("username");

//파라미터 이름들 모두 조회
Enumeration<String> parameterNames = request.getParameterNames();

//파라미터를 Map으로 조회
Map<String, String[]> parameterMap = request.getParameterMap();

//복수 파라미터 조회
String[] usernames = request.getParameterValues("username");

- username=hello&username=kim 와 같이 파라미터 이름은 하나인데, 값이 중복이라면?

-> 위에 있는 getParameterValues를 통해 받아야 한다.

-> getParameter()를 사용한다면 첫 번째 값을 반환한다.

(예시의 경우 hello를 반환)

 

2) POST 요청, HTML Form

 Html의 Form을 사용해서 클라이언트에서 서버로 데이터를 전송하는 경우, content-type: application/x-www-form-urlencoded으로 전송된다. 또한 메시지 바디에 쿼리 파라미터 형식으로 데이터가 전송된다.

 즉, 위치가 start-line에서 메시지 바디로 바뀐 것 뿐, 형식 자체는 동일하다.

-> 따라서 쿼리 파라미터 조회 메서드를 그대로 사용하면 된다.

 

- 정리해보면, request.getParameter() 메서드를 통해 GET URL 쿼리 파라미터 형식도 지원하고, POST HTML Form 형식도 지원한다.

 

3) POST 요청, API 메시지 바디

 HTTP message body에 데이터를 직접 담아서 요청하는 방식이다. HTTP API에서 주로 사용하고, TEXT, JSON, XML 등등 형식으로 보낼 수 있다. 주로 JSON 형식을 사용하며, POST, PUT, PATCH HTTP 메서드에서 사용한다.

 

- Text/plain

ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

 inputStream은 byte 코드를 반환하므로, 문자표 UTF_8을 통해 우리가 읽을 수 있는 문자(String)으로 변환하였다.

 

- JSON 형식 파싱

@Getter
@Setter
public class HelloData {
    private String username;
    private int age;
}

 JSON 형식으로 파싱하기 위한 객체를 하나 생성한다. 롬복의 @Getter, @Setter 애노테이션으로 getter, setter가 자동 생성된다.

 

//필드에 생성, JSON 결과를 파싱해서 자바 객체로 변환시켜줌
private ObjectMapper objectMapper = new ObjectMapper

ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

//위에서 만든 클래스로 인스턴스 생성
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);

- 우선 일반적인 Text를 받을때와 같이 메시지 바디를 messageBody에 저장한다.

- 그 후, JSON 결과를 파싱해서 자바 객체로 변환 시켜주는 objectMapper를 사용해서 HelloData 인스턴스를 만든다.

- 원하는 곳에서 사용하면 된다.

 

 

4. HttpServletResponse

 HTTP 응답 메시지를 생성하도록 도와준다.

 

- status-line(start-line)

response.setStatus(HttpServletResponse.SC_OK);
response.setStatus(200);

응답 상태코드를 직접 지정해준다.

 

- response-headers

//기본 사용
response.setHeader("Content-Type", "text/plain;charset=utf-8");

//Content 편의 메서드
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");

//쿠키 편의 메서드
Cookie cookie = new Cookie("myCokie", "good"); //myCookie=good
cookie.setMaxAge(600);
response.addCookie();

//redirect 편의 메서드
response.sendRedirect("/basic/hello-form.html");

- 기본적으로 setHeader("헤더 명", "헤더 내용")을 통해 지정 가능하다.

- 이 외에도 위 예시처럼 Content, 쿠키, redirect 관련 편의 메서드가 존재한다.

 

- message body(단순 텍스트, HTML)

PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println(" <div>안녕?</div>");
writer.println("</body>");
writer.println("</html>");

- HTML을 반환 시 content-type을 text/html로 지정해야 한다.

 

- message body(API JSON)

//필드로 선언
private ObjectMapper objectMapper = new ObjectMapper();

HelloData data = new HelloData();
data.setUsername("kim");
data.setAge(20);
String result = objectMapper.writeValueAsString(data);

response.getWriter().write(result);

HTTP 응답으로 JSON을 반환할 때는 content-type을 application/json으로 지정해야 한다. objectMappter.writeValueAsString()를 사용하면 객체를 JSON 문자로 변경할 수 있다.

 

 

5. 마무리

 이렇게 서블릿, HttpServletRequest, HttpServletResponse를 활용하면 개발자가 비즈니스 코드에만 집중할 수 있을 뿐만 아니라, 직접 HTTP 메시지를 파싱하지 않을 수 있게 되었다. 하지만 여기서 더 간편하게 만든 것이 바로 스프링 MVC 패턴이다. 이에 대해 추후에 공부해보자.

 


위 내용은 김영한 님의 인프런 강의 "스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술"의 내용과 강의자료를 토대로 작성된 게시글입니다.

강의 링크:

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

댓글