02. 스프링 MVC

02. 스프링 MVC

스프링 MVC #

MVC 는 아주 일반적인 UI 디자인 패턴이다.

Model, View, Controller 의 역할을 분리한다. (* UI 에서 비즈니스 로직을 분리시킬 수 있다.)

  • Model : Data 에만 집중한다.
  • View : Model(Data)를 보여주는 것에만 집중한다. (렌더링에 집중한다.)
  • Controller : 요청을 받고, 비즈니스 로직을 수행을 위해 적절히 업무를 분배한다.



Front Controller #

Front Controller(프론트 컨트롤러)는 Spring MVC 의 중심 컴포넌트이다.

Spring MVC 에서 ‘Dispatcher Servlet’ 는 Front Controller 패턴을 구현한 것이다.

Spring의 Controller 에는 @Controller, @RestController 를 사용한다.

  1. Controller 에 요청이 들어온다.
  2. Controller 내에서 핸들러 메서드(@RequestMapping 등이 붙은 메서드)를 찾아 위임한다.
  3. 핸들러 메서드에서 비즈니스 로직이 수행된다.
  4. 비즈니스 로직 수행 후, View 를 통해 렌더링할 데이터를 만든다.



Spring MVC 애플리케이션 설정 #

(현재 개발 중인 GG-PIGS Spring Boot 프로젝트 기준으로) 빌드 시 다음과 같은 Directory 구조가 만들어진다.

  • build/classes/ : class 파일들
  • build/libs/ : (빌드 된)jar 파일

자바 EE 명세에는 다음과 같은 디렉토리 구조가 명시되어 있다.

  1. WEB-INF 루트에 web.xml(웹 배포 서술자) 위치하거나
  2. 1개 이상의 ServletContainerInitializer 구현 클래스 구성하거나
  3. (웹 애플리케이션에 필요한) 각종 class, jar 파일들은 WEB-INF/classes/, WEB-INF/lib 등에 위치

web.xml(웹 배포 서술자) 는 자바 웹 애플리케이션의 필수 구성 파일이다.

  • 예를 들어 서블릿 정보, 매핑 정보를 기술한다.

(* DispactherServlet 은 필요 시 여러 개를 정의할 수 있다.)

public class CourtServletContainerInitializer implements ServletContainerInitializer {
    
    ...

    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        // AnnotationConfigApplicationContext <-> AnnotationConfigWebApplicationContext
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); <-- IoC 컨테이너

        applicationContext.register(CourtConfiguration.class);  <-- 구성 클래스 등록

        DispatcherServlet dispatcherServlet = new DispatcherServlet(applicationContext) <-- DispatcherServlet 에 IoC 컨테이너 등록(?)

        ...
    }
}



Spring MVC Controller 예시 #

@Controller
@RequestMapping("/reservationQuery")
public class ReservationQueryController {

    private final ReservationService reservationService;

    public ReservationQueryController(ReservationService reservationService) {
        this.reservationService = reservationService;
    }

    @GetMapping
    public void setupForm() {}  <-- (View 이름을 의미하는) 반환 값이 없다는 것은 url 의 이름을 따라간다는 것을 의미한다.

    @PostMapping
    public String submitForm(@RequestParam("courtName") String courtName, Model model) {
        List<Reservation> reservations = java.util.Collections.emptyList();

        if(courtName != null) {
            reservations = reservationService.query(courtName); <-- 비즈니스 로직 처리
        }

        model.addAttribute("reservations", reservations);   <-- Model 에 데이터 세팅

        return "reservationQuery";
    }
}