본문 바로가기

(노력이 많이 들어간)정리

Spring MVC RestController 실행전 정리

(1)Client에서 Server에 Http req를 전송하고, 

(3) Server에서 Client에 Http res를 전송한다.

 

그사이에 서버는 (2)무엇인가를 처리한다.

 

MVC패턴 및 Spring MVC에서 (2)에 해당하는 것을 Controller라고 할 수 있다.

 

고전적인 MVC 패턴에서는 model이 view를 observing하고 있어서, model이 변하면 view가 변경되지만, client에 front web server를 두고 있는 경우, view는 model과 바로 통하지않고, 모든 정보를 controller를 통해 받아온다.

 

 

이번 칼럼의 주제는 핵심적인 데이터의 흐름과 Dispatcher Servlet이다.

 

1. 

WAS라는 말을 찾아본 결과, 외국에서는 잘 쓰이지않고, 한국에서만 잘 사용되는 용어로 추정된다. web application과 application server의 사이에 있는 것.

 

Java의 WAS -> Servlet Container를 포함한다. 

Servlet Container -> 멀티스레드 프로그래밍을 싱글스레드 프로그래밍 처럼 편하게 개발할 수 있게 도와주는 기술 

-> 그렇기 때문에 비즈니스 로직을 처리하는 함수들을 포함하기에 적합

 

 일반적으로 요청을 처리하는 프로그램을 작성하려면 멀티스레드로 요청을 처리할 수 있게 처리하게 되고, 스레드 풀을 만들고, 요청을 받으면 해당 스레드에게 맡기고.. 이런 작업을 처리해줘야 한다. 하지만 Servlet Container는 그런 작업이 이미 다되어있고, servlet만 작성하면 된다. 프레임워크에서 이미 관련작업이 처리되어 있기 때문이다. 

 

Servlet이란 HttpServletRequest, HttpServletResponse를 parameter로 받는 함수를 구현하면 되는 템플릿 메서드 패턴의 객체이다. servlet 프로그래밍도 개발자를 멀티스레드에서 편하게 만들어주려는 시도로 개발되었다.  

 

 Servlet Container에서 서블릿 객체를 실행시킬 스레드 풀을 가지고 있으며, 요청이 들어오면 그것에 맞는 서블릿 객체를 스레드에 할당한다.

 Tomcat에서 제공하는 스레드 풀의 기본 스레드 개수는 200개. 설정을 변경하여 조작할 수 있다. 스레드 풀의 개수를 변경하거나 WAS를 증설하여 더 많은 요청을 처리할 수 있다.

 

 Spring MVC에서는 모든 http 요청에 대하여 Dispatcher Servlet를 타도록 등록해 놓는다.

 

 

Spring boot에서 tomcat을 Spring MVC의 WAS로 등록하는데,  

 

2.

할당 받은 스레드에서 socket으로부터 메시지를 가져와서, HttpRequest, HttpResponse 객체를 만든다. 객체에 값들을 입력한다.

결국 HttpServletRequest, Reponse로 변경하여 servlet객체에 param으로 넘겨준다.

 

3.

서블릿이 실행되기 전/후로 처리되는 작업이다. 모든 서블릿 전/후로 처리해야할 공통 관심사를 처리할 때 사용된다. 

 

4.

Dispatcher Servlet은 Front Controller 패턴으로 되어 있어서, 개발자가 공통 코드를 작성하지 않아도 되도록 도움을 준다. 

Dispatcher Servlet은 요청 url을 해석하여 어떤 컨트롤러를 실행할지 결정한다.

 

알고 있는 정보:

- HandlerMapping (Controller mapping 정보)

- HandlerAdpater ( controller adapter list)

그 외에 theme, locale 등 다양한 정보를 가지고 있음

 

효과

1) 기존 서블릿은 HttpServlet을 상속해야 했으나(템플릿 메서드), 이제는 다른 객체와 의존관계가 없어도 Controller를 사용할 수 있게 되었음.(과거에는 하나의 Controller당 하나의 Servlet class를 작성해야 했고, RequestMapping은 method 레벨로 작동한다)

2) 기존에는 서블릿을 작성하면 web.xml을 작성해야 했지만, 이제는 DispatcherServlet에서 SingletonRegistry에 있는 Controller 목록을 가져와서 작동(목록을 손으로 따로 관리해줄 필요가 없음)

3) 인코딩, validation, locale, convert, format과 같은 공통 작업을 처리해줌

 

5.

Component Scan으로 Spring Container에 등록된 HandlerMapping을 가져온다. HandlerMapping은 Reflection으로 가져온 메소드 레벨의 컨트롤러와 url 정보를 가지고 있는 객체이다. 

 

Dispatcher Servlet에서 Handler를 찾는 과정이 이루어진다. 

 

모든 Handler list에서 하나하나 꺼내어 요청이 들어온 url과 일치하는지 확인하는 것이다. 

 

비효율적으로 보일 수 있지만, 이런 방법으로 의존성이 하나도 없다.

 

6.

handlerAdapter를 찾는 방법도, handler(controller)를 찾는 방법과 비슷하게 작동한다. Adapter list에서 하나하나 꺼내어 해당 handler를 실행시킬 수 있는지 확인해 보는 것이다.

 

 일반적으로 handler를 어떤 handlerAdapter로 실행시킬지는 Annoation에 달렸다. ServeltAdapterHandler로 실행시키려면 @WebServlet 이 필요하다. RequestMappingHandlerAdapter로 실행시키려면 RequestMapping이 필요하다. 

 

 

7. 

핸들러 인터셉터는 서블릿 필터와 비슷하게 작동한다. 단지 서블릿 필터는 WAS에서 제공하는 기술이고, 핸들러 인터셉터는 스프링에서 제공하는 기술이다. 핸들러 인터셉터가 상대적 최신기술로 사용하기 편하고, DispatcherServlet 이후에 실행되므로 더 많은 정보를 가지고 있다.

 

8. 

그 후 handler Adapter가 실행된다. 

 

9. 

 

RequestMapping handler Adapter의 내부에는

 WebDataBinder와 같은 객체가 작업을 처리한다. WebDataBinder는 WebData와 관련하여 많은 일을 처리해주지만 3가지만 말하자면

 

1) Converter, formatter를 실행

-> HttpRequest에서 값을 받아오면 그것은 Object 타입으로 사용하려면 타입 캐스팅을 해줘야 한다.

Controller의 Parameter의 Type을 읽어와서 해당 타입으로 변환한채 넘겨준다.

2) validator 검사

-> 컨트롤러의 param을 객체로 하고, @NotNull이나 @Min(2), @Max(50)같은 조건을 입력해두면, 해당 컨트롤러의 첫줄이 실행되기전에 검사를 하고 컨트롤러를 실행한다. 

3) 매개 변수를 객체에 바인딩

들어오는 값들을 객체로 묶어서 가져올 수 있으면, 묶어서 가져온다.

 

하는 작업이 이루어진다.

 

 

 

10.

 

우리가 작성한 컨트롤러가 실행된다.

 

11. (그림에는 없지만)

그후 리턴 값이 있다면 

Jackson과 같은 ObjectMapper를 사용하여 객체를 json 으로 변경하여 전송한다. 

 

RestController가 아닌, 서버 사이드 렌더링이면 ViewResolver를 사용하여 적절한 View를 리턴해준다.

 

 

 

 

참조

1) 토비의 스프링

2) 김영한 인프런 강의

3) 인터넷 정보들

'(노력이 많이 들어간)정리' 카테고리의 다른 글

카프카 파티션 정책에 관하여  (0) 2021.12.02