모르지 않다는 것은 아는것과 다르다.

Spring

서블릿 구조

채마스 2022. 2. 26. 02:38

서블릿이란?

  • 서블릿이란 동적 페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그램밍 기술이다.
  • 다시말해서 서블릿은 웹 프로그래밍에서 클라이언트 요청을 처리하고 처리 결과를 클라이언트에게 전송하는 기술이다.
  • 자바로 구현된 CGI이다.
  • html을 사용해서 요청에 응답한다.
  • java thread를 통해서 동작한다.
  • MVC 패턴중 Controller로 이용된다.
  • HTTP 변경시 Servlet을 재 컴파일한다.
  • HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다.
    • UDP보다 속도가 느리다.

 

SpringMVC 구조

  • Spring MVC의 구조는 위와 같다.
  • 동작순서는 아래와 같다.
1. 핸들러 조회: 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러를 조회한다.
2. 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
3. 핸들러 어댑터 실행: 핸들러 어댑터를 실행한다.
4. 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행한다.
5. ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.
6. viewResolver 호출: 뷰 리졸버를 찾고 실행한다.
7. View 반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환한다.
8. 뷰 렌더링: 뷰를 통해서 뷰를 렌더링 한다.
  • 핸들러 매핑 인터페이스: org.springframework.web.servlet.HandlerMapping
  • 핸들러 어댑터 인터페이스: org.springframework.web.servlet.HandlerAdapter
  • 뷰 리졸버 인터페이스: org.springframework.web.servlet.ViewResolver

 

 

HandlerMapping (핸들러 매핑)

  • 핸들러 매핑: 해당 요청을 처리할 수 있는 핸들러를 찾는다,
  • 먼저 1순위로 RequestMappingHandlerMapping 을 조회한다. -> @RequestMapping이라는 어노테이션이 붙었을때 사용가능하다.실무에서는 거의 99프로 이 매핑을 사용하게 된다.
  • 만약 @RequestMapping 어노테이션이 붙지 않은 요청일 경우 2순위로 BeanNameUrlHandlerMapping을 조회한다. -> 스프링 빈의 이름으로 핸들러를 찾는다.

 

HandlerAdaper (핸들러 어댑터)

  • 핸들러 어댑터: 핸들러 매핑을 통해서 찾은 핸들러를 실행할 수 있는 해들러 어댑터가 필요하다.
  • 먼저 1순위로 RequestMappingHandlerAdapter 를 조회한다. -> @RequestMapping이라는 어노테이션이 붙었을때 사용가능하다.실무에서는 거의 99프로 이 매핑을 사용하게 된다.
  • 2순위로 HttpRequestHandlerAdapter 를 조회한다. -> HttpRequestHandler 처리
  • 3순뤼로 SimpleControllerHandlerAdapter 를 조회한다. -> Controller 인터페이스를 처리한다.
실무에서는 거의 @RequestMapping 형식으로 요청을 받기 때문에 RequestMappingHandlerMapping 와 RequestMappingHandlerAdapter 를 사용한다.

 

핸들러 매핑과 어댑터의 동작 과정

  • MyHttpRequestHandler -> HttpRequestHandler를 상속받아서 핸들러를 임의로 구현한다.
package hello.servlet.web.springmvc.old;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

    @Component("/springmvc/request-handler")
    public class MyHttpRequestHandler implements HttpRequestHandler {

        @Override
        public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("MyHttpRequestHandler.handleRequest");
    }
}
  • 위와 같이 핸들러가 구성 되어있으면 Spring은 어떻게 동작하는지 알아보자.
  • 먼저 @RequestMapping 형식이 아니기 때문에 1순위인 RequestMappingHandlerMapping이 아닌 2순위인 BeanNameUrlHandlerMapping가 실행 되어 MyHttpRequestHandler를 반환한다.
  • 그 다음으로 HandlerAdapter의 supports()를 순서 대로 호출한다.
  • 먼저 @RequestMapping 형식이 아니기 때문에 1순위인 RequestMappingHandlerAdapter가 아닌 HttpRequestHandlerAdapter를 호출한다.
  • HttpRequestHandlerAdapter 가 HttpRequestHandler 인터페이스를 지원하므로 대상이 된다.
  • 디스패처 서블릿이 조회한 HttpRequestHandlerAdapter 를 실행하면서 핸들러 정보도 함께 넘겨준다.
  • HttpRequestHandlerAdapter 는 핸들러인 MyHttpRequestHandler 를 내부에서 실행하고, 그 결과를 반환한다.

 

뷰 리졸버

  • 뷰 리졸버: 컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경한다.
  • 1순위로: BeanNameViewResolver를 호출한다. -> 빈 이름으로 뷰를 찾아서 반환한다.
  • 2순위로: InternalResourceViewResolver -> JSP를 처리할 수 있는 뷰를 반환한다.
  • 동작과정을 보자
    import org.springframework.web.servlet.mvc.Controller;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    @Component("/springmvc/old-controller")
    public class OldController implements Controller {

        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
          System.out.println("OldController.handleRequest");
          return new ModelAndView("new-form");
      }
}
  • 먼저 1순위인 BeanNameViewResolver를 호출한다. -> 하지만 new-form 이라는 이름의 스프링 빈으로 등록된 뷰를 찾아야 하는데 없다.
  • 그렇기 때문에 InternalResourceViewResolver 가 호출된다.
  • InternalResourceViewResolver는 InternalResourceView 를 반환한다.
  • InternalResourceView 는 JSP처럼 포워드 forward() 를 호출해서 처리할 수 있는 경우에 사용한다.
  • view.render() 가 호출되고 InternalResourceView 는 forward() 를 사용해서 JSP를 실행한다.

 

 

REFERENCES

  • 김영한님의 스프링 MVC 1편
  • kohen.tistory.com/29

'Spring' 카테고리의 다른 글

싱글톤 컨테이너  (0) 2022.02.26
스프링 타입 컨버터  (0) 2022.02.26
서블릿 예외처리  (0) 2022.02.26
빈 스코프  (0) 2022.02.26
빈 생명주기와 콜백  (0) 2022.02.26