BackEnd/Spring MVC

[Spring] 서블릿 - 1

샤아이인 2022. 2. 13.

내가 공부한것을 올리며, 중요한 단원은 저 자신도 곱씹어 볼겸 상세히 기록하고 얕은부분들은 가겹게 포스팅 하겠습니다.

 

1. Hello 서블릿

톰켓을 직접 설치하는 대신에 SpringBoot를 이용하여 내장 톰켓을 사용할 것 이다.

 

● 스프링 부트 서블릿 환경 구성하기

@ServletComponentScan 를 추가하면 스프링 부트가 서블릿을 직접 등록해서 사용할수 있도록 도와준다.

@ServletComponentScan //서블릿 자동 등록 
@SpringBootApplication
public class ServletApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServletApplication.class, args);
    }    
}
 

이제 실제로 작동하는 서블릿 코드를 구현해 보자.

우선 코드를 본후 설명해 보겠다.

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet.service");
        System.out.println("req = " + req);
        System.out.println("resp = " + resp);

        String username = req.getParameter("username");
        System.out.println("username = " + username);

        resp.setContentType("text/plain");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().write("hello" + username);
    }
}
 

@WebServlet 서블릿 애노테이션 추가해주기. 인자로 2개를 지정해 줬다.

- name: 서블릿 이름

- urlPatterns: URL 매핑

 

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

protected void service(HttpServletRequest req, HttpServletResponse resp){
    ...
}
 

이후 브라우저를 실행해서 http://localhost:8080/hello?username=zbqmgldjfh 로 접속하면 다음과 같은 결과가 출력된다.

콘솔창에 출력되는 부분인데, System.out.println() 을 통하여 출력하는 부분이다.

 

response 객체인 resp를 통해 writer 객체를 얻은후 write() 메서드를 통해 출력한 내용은 브라우저의 화면상에 나타난다.

resp.setContentType("text/plain");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().write("hello" + username); // writer객체를 얻은후 write메서드 호출
 

위의 코드는 HTTP 메시지의 헤더부분에 해당되는 contentType과 인코딩을 지정해 주었다.

또한 username을 브라우져 화면상에 출력해준다.

 

만약 콘솔창에서 HTTP 요청 메시지의 로그를 확인하고 싶다면, application.properties파일에 다음과 같이 추가해주면 된다.

logging.level.org.apache.coyote.http11=debug
 

내장된 톰켓 서버의 실행과정은 다음과 같다.

클라이언트의 요청이 오면 HttpServletRequest, HttpServletResponse 객체가 생성되고, 이후 서블릿 컨테이너의 service()메소드의 인자로 전달되면서 Service()메서드가 호출된다.

 

2. HttpServletRequest - 개요

HTTP 요청 메시지를 개발자가 직접 파싱해서 사용해도 되지만, 이걸 매번 직접하려면 매우 불편할 것이다.

서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱한다.

그리고 그 결과를 HttpServletRequest 객체에 담아서 제공한다.

 

HttpServletRequest는 추가로 여러가지 부가적인 기능또한 제공한다.

 

● 임시 저장소 기능

- 해당 HTTP 요청이 시작부터 끝날때 까지 유지되는 임시 저장소 기능

저장 : request.setAttribute(name, value)

조회 : request.getAttribute(name)

 

● 세션 관리 기능

request.getSession(create: true)

 

3. HTTP 요청 데이터 - 개요

HTTP 요청 메시지를 통해서 클라이언트에서 서버로 데이터를 전달하는 방식에 대하여 공부하였다.

 

주로 3가지 방법이 많이 사용된다.

 

● GET - 쿼리 파라미터 (노출된 데이터 전송)

- /url?username=hello&age=20 과 같이, key:value 쌍으로 전달함

- 메시지 바디가 없으며, URL의 쿼리 파라미터에 데이터를 포함하여 전달한다.

- 예를 들어 검색, 필터, 페이징 등 에서 많이 사용된다.

 

● POST - HTML Form

- content-type: application/x-www-form-urlencoded

- 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20

- 예) 회원 가입, 상품 주문, HTML Form 사용

 

● HTTP message body

- HTTP API에서 주로 사용, JSON, XML, TEXT

- 데이터 형식은 주로 JSON 사용

- POST, PUT, PATCH 메서드도 사용 가능

 

4. HTTP 요청 데이터 - GET 쿼리 파라미터

다음의 데이터를 클라이언트에서 서버로 GET 메서드를 이용하여 전송해 보자.

 

전달 데이터

- username=test

- age=20

 

메시지 바디 없이, URL 의 쿼리 파라미터 만을 이용하여 데이터를 서버로 전달할 것 이다.

 

쿼리파라미터는 URL에 다음과 같이 ?를 시작으로 보낼 수 있다. 추가파라미터는 &로 구분하면 된다.

http://localhost:8080/request-param?username=test&age=20

 

서버측 에서는 HttpServletRequest 객체가 제공하는 메서드를 통하여 손쉽게 파라미터에 접근할 수 있다.

getParameter()메서드를 사용하면 key값을 넘기면 value를 얻을수 있다.

String username = request.getParameter("username"); 
System.out.println("request.getParameter(username) = " + username);

String age = request.getParameter("age");
System.out.println("request.getParameter(age) = " + age);
 

실행하면 결과는 다음과 같다.

 

이번에는 동일 파라미터를 전송한다고 가정해보자. 다음 URL을 확인해 보자.

 

http://localhost:8080/request-param?username=test1&username=test2&age=20

 

username이 중복되어 있다.

 

중복된 파라미터에서는 request.getParameterValues("username"); 를 사용하여 배열을 반환받으면 된다.

우선 전체 코드를 살펴보자.

@WebServlet(name = "RequestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("[전체 파라미터 조회] - start");
        request.getParameterNames().asIterator().
                forEachRemaining(paramName -> System.out.println(paramName + "=" + request.getParameter(paramName)));
        System.out.println("[전체 파라미터 조회] - end");
        System.out.println();

        System.out.println("단인 파라미터 조회");
        String username = request.getParameter("username");
        String age = request.getParameter("age");

        System.out.println("username = " + username);
        System.out.println("age = " + age);
        System.out.println();

        System.out.println("이름이 같은 복수 파라미터 조회");
        String[] usernames = request.getParameterValues("username");
        for (String name : usernames) {
            System.out.println("username = " + name);
        }

        response.getWriter().write("ok");
    }
}
 

결과는 다음과 같다.

그럼 복수의 파라미터를 갖는 URL은 전달했을때, 단일 파라미터를 조회하면 뭐가 나올까?

username=test1&username=test2 과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?

 

request.getParameter() 는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다.

지금처럼 중복일 때는 request.getParameterValues() 를 사용해야 한다.

참고로 이렇게 중복일 때 request.getParameter() 를 사용하면 request.getParameterValues() 의 첫 번째 값을 반환한다.

'BackEnd > Spring MVC' 카테고리의 다른 글

[Spring] MVC 프레임워크 만들기 - 1  (0) 2022.02.19
[Spring] 서블릿, JSP, MVC 패턴  (0) 2022.02.17
[Spring] 서블릿 - 2  (0) 2022.02.14
[Spring] 웹 애플리케이션 이해  (0) 2022.02.12
[Spring] 스프링 MVC 프레임워크  (0) 2022.01.31

댓글