Eddy의 스프링 디자인 패턴 - Spring MVC Pattern
이 글은 스프링 MVC 의 기본적인 개념에 대해서 정리한 글이다. @Controller, @RequestMapping 와 같이 실제 구현에 대한 내용은 생략하였다.
잘못된 내용이 있을 수 있습니다. 피드백 부탁드립니다.
MVC(모델-뷰-컨트롤러, Model-View-Controller) 패턴은 소프트웨어 디자인 패턴이다. 이 패턴은 사용자 인터페이스로부터 비즈니스 로직을 분리하여 애플리케이션의 시각적 요소나 그 이면에서 실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있는 애플리케이션을 만들 수 있다.[1] MVC 패턴에서 Model(모델)은 모든 뷰 템플릿에 렌더링할 수 있도록 데이터를 유지 관리하는 역할을 한다. View(뷰)는 사용자에게 화면을 보여주기 위해서 모델의 데이터를 전달받아서 사용자가 읽을 수 있도록 표시하는 역할을 한다. Controller(컨트롤러)는 Model(모델), View(뷰) 사이의 상호작용을 제어하는 역할을 한다. Model(모델) 을 만들고 모델을 View(뷰)에 전달하는 역할을 한다. 복잡한 웹 사이트에서는 요청을 처리할 때 유사한 작업이 많이 있다. 보안 등 유사한 공통 작업을 여러 컨트롤러에 분산시키면 많은 중복코드가 발생하게 된다. 중복 코드를 제거하는 것은 소프트웨어의 전반적인 유지 보수 관리를 향상시키기 때문에 매우 중요한데, Front-Controller 패턴(프론트 컨트롤러 패턴)은 하나의 컨트롤러를 통해서 모든 요청을 제어하고, 모든 요청 처리 기능을 통합한다.[2] 즉, 모든 리소스 요청을 처리해주는 하나의 Controller를 앞에 두는 패턴이다. 일반적으로 Front-Controller 패턴은 MVC 패턴과 함께 사용되는데, 스프링(Spring)도 역시, Front-Controller 패턴에 기반으로 설계된 프레임워크이다.
J2EE가 널리 사용되던 14년 전으로 거슬러 올라가보자. 스프링 프레임워크가 실무에서 사용되기 전으로, 코어 J2EE 패턴(2판) 개정판이 출간 되었던 시절이다. 현재는 절판되어서 구매할 수 없다.
스프링이 널리 사용되기 전에, J2EE 에서도 역시 Front Controller 개념이 사용되고 있었다. 참고로, 스프링 프레임워크는 Rod Johnson 이 출판한 책(Expert One-one-One J2EE Design and Development)에 샘플 프레임워크를 만들어 실었는데, 이것이 나중에 스프링이라는 자바 표준 프레임워크로 발전하게 되었다고 한다.
http://www.corej2eepatterns.com/FrontController.htm
MVC 패턴의 모델1 방식에서는 사용자의 요청은 JSP 로 전달된다. JSP 는 요청을 처리하고, 비즈니스 로직 및 데이터 검증 및 응답을 생성한다. 구현하기는 매우 쉽지만, 대규모 애플리케이션에는 적합하지 않고, 많은 중복 코드가 발생하게 된다. 또한, 애플리케이션에서는 너무 많은 요청을 처리하기 위해 재사용하기 어려운 수많은 컨트롤러가 필요하다.
Model 2 구조는 Model 1 과는 다르게 사용자의 요청을 중앙 집중식 제어 로직을 추가하여, 전체 로직의 일부를 컨트롤러에 위임하고, 모든 흐름의 제어는 앞쪽의 FrontController 가 담당한다. Model 1 에서의 문제에 대한 해결책을 제시한다.
수많은 요청은 Front Controller 에서 먼저 처리되는데, 재사용 가능하고 관리가 용이한 구조로 애플리케이션을 구성할 수 있다. 스프링 프레임워크는 MVC 패턴 중 Model 2 아키텍처에 기반한 모듈을 제공한다.
스프링 MVC 처리 흐름을 아래의 Component&Connector View 로 그려봤다. 일단, Dispatcher Servlet 는 MVC 패턴의 Front Controller 역할을 한다.
1. 사용자는 인터넷 브라우저를 통해서 웹사이트에 접속한다.
2. 웹서버(Nginx 또는 Apache Httpd)는 WAS(Tomcat 등)에 Reverse Proxy 처리를 수행하고, DispatcherServlet 에서는 요청을 받는다. Front Controller 는 모든 요청을 단일 지점으로 이동시키며, 요청 흐름제어를 중앙으로 집중화한다.
3. 특정 컨트롤러에 위임을 해야 하는데, 어떤 컨트롤러로 위임할지 HandlerMapping 의 도움을 받는다. HandlerMapping 은 요청 URL에 매핑 된 Controler(컨트롤러)를 선택해서 DispatcherServlet에 반환한다.
4. DispatcherServlet는 HandlerMapping의 도움으로 선택 된 Controller에 요청을 보낸다. Controller는 비즈니스 로직을 실행하고, 처리 결과를 모델로 설정하여 반환한다.
5. DispatcherServlet 는 ViewResolver 의 도움을 받아서, View이름에 매핑 된 View 를 반환한다.
6. View는 화면을 템플릿 작업을 수행하여 반환하고, DispatcherServlet 에 의해서 사용자의 브라우저로 반환한다.
DispatcherServlet 를 설정하기 위한 방법은 아래와 같다.
web.xml 설정
Java Class 설정
자동 설정
필자가 아래와 같이 모듈뷰 문서를 작성해봤다. 하지만, 이해하기 쉽지 않다.
현재 스프링 3.1 이후 버전에서는 Java 를 사용하여 DispatcherServlet 를 사용한다. 물론, 기존 web.xml 방식도 사용할 수 있지만 이 글에서는 생략한다. 3.2 부터는 AbstractAnnotationConfigDispatcherServletInitializer 추상 클래스를 상속받아서 구현하면 되는데, 해당 클래스의 부모클래스인 AbstractDispatcherServletInitializer 보면, registerDispatcherServlet 메서드에서 DispatcherServlet를 생성하는 소스를 확인할 수 있다. 어쨋든 DispatcherServlet 설정을 하기 위해서는 아래와 같이 설정할 수 있다.
getServletMappings() 는 DispatcerServlet이 매핑되기 위한 하나 혹은 여러 개의 Path를 지정한다.
Java 기반의 스프링 구성을 설정하는 경우에는 이렇게 하면 되고, XML 기반이라면 AbstractDispatcherServletInitializer 를 상속 받아서 직접 구현하면 되는데, 해당 방법에 대해서는 생략하겠고, 스프링 레퍼런스[3] 또는 스프링 인 액션[4] 의 Chapter7에서 참고하면 된다. 참고로, 스프링 부트에서는 자동으로 DispatcherServlet 설정이 된다. DispatcherServletAutoConfiguration 에서 DispatcherServlet 를 생성한다.
Spring MVC 설정 방법은, 마찬가지로 XML, Java 두가지 방법이 있는데, 필자는 Java기반의 설정 방법에 대해서 정리를 하겠다.
@EnableWebMvc 어노테이션을 붙여주면 기본 설정이 적용된다. 대부분 프로젝트에서는 기본 설정 외에 추가 설정이 필요하기 때문에 WebMvcConfigurerAdapter 클래스를 상속하여 구현을 한다. 스프링 공식 레퍼런스를 참고하길 바란다.
Spring Boot 에서는 MVC 설정을 위한, @EnableWebMvc 어노테이션을 적용 안해도 된다. WebMvcAutoConfiguration 에서 자동으로 설정해준다. 만약, 커스텀한 설정이 필요하다면 WebMvcConfigurerAdapter 을 상속받아서 구현해주면 된다. 명시적으로 @EnableWebMvc 어노테이션을 써주면, WebMvcAutoConfiguration 는 동작하지 않게 되고 Spring Boot 의 기본 설정은 적용되지 않는다. 아무튼, SpringBoot 의 기본 설정과 WebMvcConfigurerAdapter 를 적용하여 웹프로젝트를 구성하면 된다. [그림2]Spring MVC Module View 를 참고해보면 하늘색 영역이 바로 Spring Boot 로 실행되는 영역이다.
생략한다. 시중에 나와있는 스프링 프레임워크 관련 책에서 대부분 잘 설명이 되어있다.
[1]모델-뷰-컨트롤러, 위키백과, https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC
[2]Front Controller 패턴, 마틴 파울러, https://www.martinfowler.com/eaaCatalog/frontController.html
[3]Web MVC framework, docs.spring.io, https://docs.spring.io/spring/docs/4.2.7.RELEASE/spring-framework-reference/html/mvc.html#mvc-features
[4]스프링 인 액션 제4판, 크레이그 월즈-제이펍출판사