기존 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
을 이용해 설정되었는지 나온다.
DispatcherServletAutoConfiguration
ErrorMvcAutoConfiguration
HttpMessageConvertersAutoConfiguration -> JSON convert
위와 같은 것들이 있다. 앞으로의 동작을 이해하는데에 위의 설정에 대한 이해가 필요하다.
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
- found 'session' scope (OnWebApplicationCondition)
로그에 위와 같은 메시지가 출력되며, org.springframework.web.servlet.DispatcherServlet
이 발견되어 AutoConfiguration
되었다는 것을 알 수 있다.
DispatcherServlet
이란 스프링에서 가장 중요한 컴포넌트 중 하나로 사용자가 입력한 요청에 따라 어떠한 로직을 실행시켜야 할지 알려주는 게이트웨이의 역할을 한다.
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
은 HandlerMapping
을 통해 알맞은 Handler
에게 요청을 전달한다.Handler
의 실행 결과를 HttpResponse
형태로 반환한다.Presentation
계층 맨 앞에 놓여 중앙 집중식 처리를 하기 위한 컴포넌트이다. 보통 스프링 MVC에서 front controller
라는 이름으로 불린다. 모든 HTTP 요청을 받아서 처리한다.
간단히 설명하면, 처리과정은 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()
메소드는 이름처럼 특정 핸들러 오브젝트가 지원할 수 있는지 살펴보기 위해 존재한다. handle()
메소드가 호출되기 전에 반드시 supports()
메소드로 지원 여부를 확인해야 한다.
보통 supports()
메소드를 구현하게 되면 형태는 아래와 같다.
@Override
public boolean supports(Object handler) {
return (handler instanceof SpecificController);
}
보통 어떤 컨트롤러가 해당 핸들러의 인스턴스인지(타입이거나 상위 타입인지) 검사한다.
View
를 갖지 않고, REST Data(JSON/XML)를 반환한다.Spring4
부터 @RestController
라는 애노테이션이 지원된다.@Controller
애노테이션과 @ResponseBody
애노테이션을 합친 것이다.@Controller
애노테이션을 클래스 레벨에 달고, 메소드에 @ResponseBody
를 달아도 된다.