2.2 스프링 부트의 동작 방식

김찬미·2024년 6월 3일
0

스프링 부트의 기본 의존성 중 하나인 spring-boot-starter-web 모듈을 사용하면 기본적으로 내장 톰캣(Tomcat)을 사용하는 스프링 MVC 구조를 기반으로 동작한다. 아래 그림은 일반적인 웹 요청이 들어왔을 때의 스프링 부트 동작 구조이다.

클라이언트의 요청이 들어오면 *서블릿이 이를 처리해야 하는데, 서블릿은 서블릿 컨테이너에서 관리하며 톰캣서블릿 컨테이너의 역할과 WAS(Web Application Server)의 역할을 담당하는 대표적인 컨테이너이다.

서블릿(Servlet)은 클라이언트의 요청을 처리하고, 결과를 반환하는 자바의 웹 프로그래밍 기술이다.

서블릿 컨테이너의 특징

  • 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리한다.
  • 서블릿 객체는 싱글톤 패턴으로 관리된다.
  • 멀티 스레딩을 지원한다.

스프링에서는 DispatcherServlet서블릿의 역할을 수행한다. 일반적으로 스프링은 톰캣을 embed해 사용한다. 그렇기에 서블릿 컨테이너와 DispatcherServlet은 자동 설정된 web.xml의 설정값을 공유한다.

DispatcherServlet의 동작 방식

(1) DispatcherServlet으로 요청(HttpServletRequest)이 들어오면 DispatcherServlet은 핸들러 매핑(Handler Mapping)을 통해 요청 URI에 매핑된 핸들러를 탐색한다. 여기서 핸들러는 컨트롤러(Controller)를 의미한다.

(2) 그리고 핸들러 어댑터(HandlerAdapter)로 컨트롤러를 호출한다.

(3) 핸들러 어댑터에 컨트롤러의 응답이 돌아오면 ModelAndView로 응답을 가공해 반환한다.

(4-1) @Controller 사용 시

  1. *View Resolver를 찾고 실행한다.
  2. View Resolver는 View의 논리 이름을 물리 이름으로 바꾸고, 랜더링 역할을 담당하는 View 객체를 반환한다.
  3. View를 랜더링하여 클라이언트에 반환한다.

뷰 리졸버는 뷰의 렌더링 역할을 담당하는 뷰 객체를 반환한다.

(4-2) @RestController 사용 시

  1. View와 ViewResolver를 거치지 않는다.
  2. Controller로부터 반환받은 데이터를 *MessageConverter를 거쳐서 Json 형식으로 변환한다.
  3. Json을 ResponseBody로 응답한다.

MessageConverter는 요청과 응답에 대해 Body 값을 변환하는 역할을 수행한다.
스프링 부트의 자동 설정은 HttpMessageConverter 인터페이스를 사용한다.

주요 인터페이스 목록

스프링 MVC의 큰 강점은 DispatcherServlet 코드의 변경 없이, 원하는 기능을 변경하거나 확장할 수 있다는 점이다. 주요 인터페이스 목록은 다음과 같다.

  • 핸들러 매핑 : org.springframework.web.servlet.HandlerMapping
  • 핸들러 어댑터 : org.springframework.web.servlet.HanlerAdapter
  • 뷰 리졸버 : org.springframework.web.servlet.ViewResolver
  • 뷰 : org.springframework.web.servlet.View

Handler Mapping과 구현체

핸들러 매핑은 요청 정보를 기준으로 어떤 컨트롤러를 사용할지 선정하는 인터페이스이다. 핸들러 매핑 인터페이스는 여러 구현체를 가지며, 대표적인 구현체는 다음과 같다.

  • BaseNameUrlHandlerMapping

    • 빈 이름을 URL로 사용하는 매핑 전략이다.
    • 빈을 정의할 때 _슬래시('/')가 들어가면 매핑 대상이 된다.
      // "/hello"라는 URL로 들어오는 요청이 helloController() 빈으로 매핑된다.
      // MyController 클래스는 @Controller 어노테이션이 붙어있어야 한다.
    
      @Configuration
      public class AppConfig {
    
          @Bean("/hello")
          public MyController helloController() {
              return new MyController();
          }
      }
  • ControllerClassNameHanderMapping

    • URL과 일치하는 클래스 이름을 갖는 빈을 컨트롤러로 사용하는 전략이다.
    • 이름 중 Controller를 제외하고 앞부분에 작성된 suffix를 소문자로 매핑한다.
    // 'HelloWorldController' 클래스가 'helloworld' URL로 매핑된다.
    // 즉, '/helloworld' 요청이 들어오면 'HelloWorldController' 클래스가 처리한다.
    
    @Controller
    public class HelloWorldController {
        // 메서드들 정의
    }
  • SimpleUrlHanderMapping

    • URL 패턴에 매핑된 컨트롤러를 사용하는 전략이다.
    • XML 설정 파일이나 자바 설정 클래스를 통해 URL 패턴을 명시적으로 설정할 수 있다.

    예시 (XML 설정)

    // '/welcome' 요청이 welcomeController 빈으로, '/hello' 요청이 helloController 빈으로 매핑된다.
    <beans>
        <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <prop key="/welcome">welcomeController</prop>
                    <prop key="/hello">helloController</prop>
                </props>
            </property>
        </bean>
    
        <bean id="welcomeController" class="com.example.WelcomeController"/>
        <bean id="helloController" class="com.example.HelloController"/>
    </beans>
  • DefaultAnnotationHanderMapping

    • 어노테이션으로 URL과 컨트롤러를 매핑하는 방법이다.
    • 보통 @RequestMapping 어노테이션을 사용하여 URL과 컨트롤러 메서드를 매핑한다.
    @Controller
    public class MyController {
    
        @RequestMapping("/hello")
        public String hello() {
            return "helloView";
        }
    
        @RequestMapping("/welcome")
        public String welcome() {
            return "welcomeView";
        }
    }
profile
백엔드 개발자

0개의 댓글

관련 채용 정보