Spring Boot를 이용한 RESTful Web Services 개발 #9 DispatcherServlet과 프로젝트 동작의 이해 (디스패쳐 서블릿, 핸들러 매핑, 핸들러 어댑터 개념 정리)

Jake Seo·2021년 9월 13일
1

Spring-boot-restful

목록 보기
9/17

SpringBoot 동작 원리 탐방

로깅 설정 변경하기

기존 application.properties였던 application.yml에서 로깅 설정을 살짝 변경해보자.

logging:
  level: 
    org.springframework: debug

위와 같이 springframework에 대한 로깅을 전부 debug 레벨로 변경해보자. 로깅에는 로그를 남기게 만든 개발자가 설정한 레벨이 있는데

ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF 순으로 에러 표출의 정도가 달라진다.

기본적으로 오른쪽으로 갈수록 심각한 것들이라고 보면 된다. 그래서 운영 상에서는 로그로 인한 메모리나 저장소 낭비를 최소한으로 하기 위해 심각한 로그들만 출력하는 반면, 개발이나 학습 단계에서는 그냥 아키텍처나 프로세스, 동작방식 등의 이해를 위해서 많은 로그를 출력해보는 편이다.

그래서 logging.level.org.springframework: debug의 의미는 org.springframework 패키지가 출력하는 로그 중 debug 이상으로 취급되는 로그는 전부 출력한다는 뜻이다.

로깅 레벨을 바꾸면 일어나는 변화

스프링 부트라는 것은 기본적으로 '사용자가 정의한 설정이 없다면, 기본 설정을 사용'한다. 그것을 AutoConfiguration이라고 부르는데, org.springframework의 로깅 레벨을 debug로 바꾸면 CONDITIONS EVALUATION REPORT라는 것이 나오면서 어떤 것이 AutoConfiguration을 이용해 설정되었는지 나온다.

주의깊게 봐야 할 AutoConfiguration 목록

  • DispatcherServletAutoConfiguration
  • ErrorMvcAutoConfiguration
  • HttpMessageConvertersAutoConfiguration -> JSON convert

위와 같은 것들이 있다. 앞으로의 동작을 이해하는데에 위의 설정에 대한 이해가 필요하다.

DispatcherServletAutoConfiguration

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - found 'session' scope (OnWebApplicationCondition)

로그에 위와 같은 메시지가 출력되며, org.springframework.web.servlet.DispatcherServlet이 발견되어 AutoConfiguration 되었다는 것을 알 수 있다.

DispatcherServlet이란 스프링에서 가장 중요한 컴포넌트 중 하나로 사용자가 입력한 요청에 따라 어떠한 로직을 실행시켜야 할지 알려주는 게이트웨이의 역할을 한다.

HttpMessageConverterAutoConfiguration

   HttpMessageConvertersAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.http.converter.HttpMessageConverter' (OnClassCondition)
      - NoneNestedConditions 0 matched 1 did not; NestedCondition on HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition.ReactiveWebApplication did not find reactive web application classes (HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition)

자바 오브젝트로 된 데이터를 JSON 포맷으로 변환시키고 클라이언트에게 반환시키는 역할을 한다.

DispatcherServlet의 동작방식

  • 모든 클라이언트의 요청은 일단 DispatcherServlet이 받아서 확인한다.
  • DispatcherServletHandlerMapping을 통해 알맞은 Handler에게 요청을 전달한다.
  • 마지막엔 Handler의 실행 결과를 HttpResponse 형태로 반환한다.

디스패쳐 서블릿(DispatcherServlet)이란?

Presentation 계층 맨 앞에 놓여 중앙 집중식 처리를 하기 위한 컴포넌트이다. 보통 스프링 MVC에서 front controller라는 이름으로 불린다. 모든 HTTP 요청을 받아서 처리한다.

간단히 설명하면, 처리과정은 HandlerMapping의 도움을 받아 요청을 관련된 컴포넌트에 전달함으로써 일어난다.

HandlerMapping은 인터페이스로 요청과 핸들러 오브젝트 사이의 연결을 정의하는 인터페이스이다.

핸들러 매핑(HandlerMapping)이란?

메소드를 특정 URL에 매핑하기 위한 도구이다.

이를테면 우리는 이전에 /hello-world라는 URL에 public String helloWorld()라는 메소드를 매핑했다.

핸들러 어댑터란?

핸들러 어댑터는 스프링 MVC에서 조금 더 유연한 방법을 이용해 HTTP 요청을 다루기 쉽게 만들기 위한 인터페이스이다.

메소드를 특정 URL에 매핑하기 위한 HandlerMapping과 함께 사용된다.

DispatcherServlet은 메소드를 호출하기 위해 HandlerAdatper를 사용한다. 서블릿은 메소드를 직접적으로 호출하지 않는다. 서블릿은 기본적으로 핸들러 오브젝트와 HandlerAdapter의 사이에서 다리 역할을 하며, 느슨하게 결합된 설계를 이룬다.

소스코드를 보면 다음과 같은 모양으로 생겼다.

public interface HandlerAdapter {
  boolean supports(Object handler);
  
  ModelAndView handle(
    HttpServletRequest request,
    HttpServletResponse response,
    Object handler
  ) throws Exception;
  
  long getLastModified(HttpServletRequest request, Object Handler);
}

supports() 메소드

supports() 메소드는 이름처럼 특정 핸들러 오브젝트가 지원할 수 있는지 살펴보기 위해 존재한다. handle() 메소드가 호출되기 전에 반드시 supports() 메소드로 지원 여부를 확인해야 한다.

보통 supports() 메소드를 구현하게 되면 형태는 아래와 같다.

    @Override
    public boolean supports(Object handler) {
        return (handler instanceof SpecificController);
    }

보통 어떤 컨트롤러가 해당 핸들러의 인스턴스인지(타입이거나 상위 타입인지) 검사한다.

그렇다면 RestController는?

  • 일반적으로 뷰를 갖지 않는 컨트롤러를 말한다.
    • View를 갖지 않고, REST Data(JSON/XML)를 반환한다.
  • Spring4부터 @RestController라는 애노테이션이 지원된다.
  • @Controller 애노테이션과 @ResponseBody 애노테이션을 합친 것이다.
    • 그냥 @Controller 애노테이션을 클래스 레벨에 달고, 메소드에 @ResponseBody를 달아도 된다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글