Spring MVC

bp.chys·2020년 4월 28일
0

Spring Framework

목록 보기
3/15

스프링 MVC

  • 자바 웹 애플리케이션을 개발할 때 가장 많이 쓰이는 웹 프레임워크이다.
  • MVC 는 Model-View-Controller 의 약자로, 기본 시스템 모듈을 MVC 로 나누어 구현되어있다.
    • Model : 뷰를 생성하는 데 사용할 데이터
    • View : 모델을 사용해 화면을 렌더링
    • Controller : 흐름을 제어함. 브라우저 요청을 받아 모델을 만들고 뷰로 리다이렉션한다.
  • Web 서버에 특화되어 만들어진 모듈로서 다음과 같은 주요 기능을 포함한다.
    • 다양한 범위의 파라미터와 반환값을 가지는 유연한 컨트롤러 메서드 정의.
    • 도메인 POJO 객체의 폼 백엔드 객체로의 재사용.
    • 모델은 키-값 쌍과 함께 해시 맵을 사용. 또한 여러 뷰 기술과의 통합을 허용함.
    • 바인딩이 유연하다. 타입 불일치 발생시 런타임 에러 이전에 밸리데이션 에러(400)로 해결 가능.
    • 단위 테스트 컨트롤러에 MockMvc 프레임워크 포함.
  • 스프링 부트를 사용하면 자바 애플리케이션이 내장 톰캣을 만들고 그 안에 DispatcherServlet을 등록한다.

스프링 MVC 아키텍처

  • 모델 2 프론트 컨트롤러 아키텍처를 기반으로 설계되었다.
  • 프론트 컨트롤러(DispatcherServlet)은 어떤 컨트롤러가 요청을 수행할지 결정하고, 랜더링할 뷰를 결정하는 결할을 한다.
  • 스프링에 DispatcherServelt 의존성을 추가하고 스프링 컨텍스트를 시작하면, 요청 매핑, 예외 처리, 데이터 바인딩 및 벨리데이션, @RequestBody를 통한 JSON변환 등 웹 MVC에 필요한 여러 기능들이 초기화 된다.

DispatcherServlet 동작 방식

스프링 부트와 구조가 다르다.
servlet context안에 spring이 들어가는 구조인 반면에 spring boot 경우에는 spring java application안에 tomcat이 들어가는 구조이다.

  1. 브라우저는 특정 URL에 요청을 보내고, DispatcherServlet은 가장 먼저 요청을 받아들인다.
  2. DispatcherServlet은 URI를 보고, 핸들러 매핑과 통신하여 요청을 전달할 컨트롤러를 찾는다.
  3. 핸들러 어댑터는 반환된 컨트롤러에서 어떤 메서드를 호출할지 결정한다.
  4. 핸들러 어댑터는 결정된 핸들러 메서드를 호출한다.
  5. 핸들러 메서드는 모델과 뷰를 반환한다.
  6. DispatcherServlet에서 반환된 뷰 이름을 가지고 뷰리졸버를 호출해 물리적 뷰를 찾는다.
  7. 뷰리졸버는 해당하는 뷰를 찾아 뷰로 반환한다.
  8. DispatcherServlet은 응답을 브라우저로 보낸다.

핸들러 매핑 vs 핸들러 어댑터

  • 핸들러 매핑 : 요청을 처리할 핸들러를 찾는 인터페이스
    RequestMappingHandlerMapping : 컨트롤러에 작성한 url을 기반으로 핸들러를 찾음
    BeanNameUrlHandlerMapping : method 자체가 핸들러가 됨
  • 핸들러 어댑터 : 핸들러 매핑이 찾아낸 핸들러를 처리하는 인터페이스
    SimpleControllerAdapter
    RequestMappingHandlerAdapter (가장 많이 쓰임)

View Resolver (뷰리졸버)

  • 뷰리졸버의 역할은 핸들러에 명시된 논리적 뷰의 이름을 가지고 물리적 뷰를 찾는 인터페이스이다.

핸들러 매핑과 인터셉터

RequestMapping

  • URI를 특정 컨트롤러 또는 컨트롤러 메서드에 매핑하는데 사용한다.
  • 클래스 또는 메서드 레벨에서 사용할 수 있다.
  • 선택옵션의 요청 메서드로 GET, POST, PUT, DELETE 등을 사용할 수 있다. 아무것도 적지않으면 GET으로 인식한다.
  • @GetMapping , @PostMapping 도 가능하다.

HandlerInterceptor

  • 인터셉터는 말 그대로 핸들러에 대한 요청을 가로채는 용도로 사용된다.
  • 정확한 URI를 인터셉트할 수 있도록 따로 지정할 수 있다.
  • preHandle(HttpServletRequest request, HttpServletResponse response), postHandle(HttpServletRequest request, HttpServletResponse response), afterCompletion(HttpServletRequest request, HttpServletResponse response 메서드를 구현함으로써 요청 전후에 일부 처리를 지정할 수 있다.
  • 여러 개의 인터셉터를 체이닝할 수 있다.
  • 필터와 인터셉터에 대한 자세한 특징과 차이는 이 글을 참고하자.

핸들러 메소드

Http 메시지 컨버터

  • 요청 본문에서 메시지를 읽어들이거나(@RequestBody), 응답 본문에 메시지를 작성할 때(@ResponseBody) 사용한다.

지원메소드 아규먼트와 리턴 타입

  • WebRequest, NativeWebRequest, ServletRequest, HttpServletRequest : 요청 또는 응답 자체에 접근 가능한 API, 거의 사용할 일 x
  • InputStream, Reader, OutputStream, Writer : 요청 본문을 읽어오거나, 응답 본문을 쓸 때 사용할 수 있는 API
  • PushBuilder : 스프링5, Http/2 리소스 푸쉬에 사용
  • HttpMethod : GET, POST 등에 대한 정보
  • Locale, TimeZone, ZoneId : LocaleResolver가 분석한 요청의 Locale정보
  • @PathVariable : URI 템플릿 변수를 읽을 때 사용
  • @MatrixVariable : URI 경로 중에 키/값 쌍을 읽어 올 때 사용
  • @RequestParam : 서블릿 요청 매개변수 값을 선언한 메소드 아규먼트 타입으로 변환해준다.
    단순한 타입의 경우 이 애노테이션을 생략가능하다.
  • @RequestHeader : 요청 헤더 값을 선언한 메소드 아규먼트 타입으로 변환해준다.
  • @RequestBody : 리턴 값을 HttpMessageConverter를 사용해 응답 본문으로 사용한다.
    (@Valid를 사용해서 값을 검증할 수 있다.)
  • HttpEntity, ResponseEntity : 응답 본문 뿐 아니라헤더 정보까지, 전체 응답을 만들 때 사용한다.
  • String : ViewResolver를 사용해서 뷰를 찾을 때 사용할 뷰 이름
  • View : 암묵적인 모델 정보를 렌더링할 뷰 인스턴스
  • Map, Model : 암묵적으로 판단한 뷰 렌더링 시 사용할 모델 정보
  • @ModelAttribute : 암묵적으로 판단한 뷰 렌더링할 때 사용할 모델 정보 추가, 보통 생략 가능.

예외처리

  • 컨트롤러 레벨에서의 예외처리는 @ControllerAdvice를 활용하면 일관된 예외처리가 가능하다.
  • 컨트롤러 어드바이스는 기본적으로 모든 요청 매핑에서 공통된 기능을 제공한다. (예외처리 뿐만 아니라 바인딩 설정 모델 객체 등 활용 가능)
@ControllerAdvice
public class ExcetpionController {
    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity<ExceptionResponse> handleRuntimeException(
        HttpServletRequest request, 
        Exception ex
) {
        return ResponseEntity.badrequest(ExceptionResponse.from(ex)).build();
    }
}

결론

Spring MVC는 웹 애플리케이션을 개발할 때, HTTP 요청과 응답을 쉽게 제어할 수 있고, 요청에 알맞는 로직을 수행하도록 분리하기 위한 핸들러 매핑, 뷰리졸버의 기능을 제공한다.

요청 값의 벨리데이션과 인증, 인가에 대한 검사는 컨트롤러 어드바이스나 인터셉터를 통해서 그 오류를 일찍 발견할 수 있으므로 Spring MVC 에서 제공하는 API나 기능들을 잘 알아놓으면 효율적인(또는 REST 한) 웹 애플리케이션을 작성할 수 있을 것 같다.

profile
하루에 한걸음씩, 꾸준히

0개의 댓글