Light Blue Pointer
본문 바로가기
Developing/TIL(Develop)

Spring mvc 패턴

by Greedy 2024. 5. 14.

Spring MVC 패턴이란

디자인 패턴의 일종으로 Spring MVC (Model-View-Controller) 패턴은 자바 기반의 웹 애플리케이션 프레임워크인 스프링 프레임워크에서 제공하는 웹 애플리케이션 개발을 위한 패턴이다.

이 패턴은 애플리케이션의 각 부분을 분리하여 개발하고 유지보수를 용이하게 한다.

Spring MVC는 크게 Model, View, Controller의 세가지 구성요소로 나뉜다

Model

모델은 애플리케이션의 데이터 및 비즈니스 로직을 포함합니다. 데이터베이스와 상호작용하고, 데이터를 처리하며, 그 결과를 반환한다

Model의 구성요소

  • 도메인 객체: 애플리케이션에서 사용하는 데이터의 구조를 정의한다
  • 서비스: 비즈니스 로직을 구현한다
  • DAO (Data Access Object): 데이터베이스와 상호작용하는 객체이다

View

뷰는 사용자에게 보여지는 화면을 담당한다

HTML, JSP, Thymeleaf 등 다양한 템플릿 엔진을 사용할 수 있다

뷰는 컨트롤러에서 전달된 데이터를 사용자에게 적절한 형식으로 렌더링한다

Controller

컨트롤러는 사용자 요청을 처리하고, 모델과 뷰 사이의 상호작용을 담당한다

사용자의 입력을 받고, 이를 처리한 후, 처리 결과를 모델에 저장하고, 뷰에 전달한다

컨트롤러는 다음과 같은 작업을 수행한다

Controller의 구성요소

  • 요청 매핑: URL을 특정 메서드와 매핑한다
  • 요청 처리: 요청 파라미터를 받고, 비즈니스 로직을 실행하며, 모델을 업데이트한다
  • 뷰 선택: 처리 결과를 뷰에 전달한다

Spring MVC의 주요 구성 요소

  • DispatcherServlet
    • 프론트 컨트롤러로, 모든 요청을 중앙에서 처리한다
    • 요청을 적절한 컨트롤러에 전달하고, 결과를 뷰로 전달한다
  • Controller
    • 요청을 처리하고, 비즈니스 로직을 실행하며, 모델을 업데이트한다
    • @Controller 또는 @RestController 어노테이션을 사용하여 정의한다
  • ModelAndView
    • 모델과 뷰 정보를 함께 담고 있는 객체이다
    • 컨트롤러가 처리 결과를 반환할 때 사용한다
  • ViewResolver
    • 뷰의 이름을 실제 뷰 객체로 변환하는 역할을 한다
  • HandlerMapping
    • 요청 URL을 적절한 컨트롤러 메서드와 매핑한다

Spring MVC의 동작 흐름

요청 수신

  • 클라이언트로부터의 요청이 DispatcherServlet으로 전달된다

요청 매핑

  • DispatcherServlet은 요청을 적절한 컨트롤러로 매핑하기 위해 HandlerMapping을 사용한다

요청 처리

  • 매핑된 컨트롤러 메서드가 요청을 처리하고, 비즈니스 로직을 실행하며, ModelAndView 객체를 반환한다

뷰 선택

  • DispatcherServlet은 ViewResolver를 사용하여 적절한 뷰를 선택한다

뷰 렌더링

  • 선택된 뷰가 모델 데이터를 사용하여 클라이언트에게 응답을 생성한다

Spring MVC의 요청 처리

클라이언트의 요청이 서버에서 처리되고 응답이 클라이언트에게 전달되는 일련의 단계

1. 핸들러 조회

클라이언트가 보낸 요청은 **DispatcherServlet에 의해 처음으로 받아들여진다DispatcherServlet**은 Spring MVC의 프론트 컨트롤러 역할을 한다

  • 핸들러 매핑 조회: **DispatcherServlet**은 요청 URL을 기반으로 어떤 컨트롤러가 요청을 처리할지 결정하기 위해 여러 HandlerMapping 객체 중 하나를 사용한다
  • 핸들러 결정: **HandlerMapping**은 요청 URL에 매핑된 핸들러(컨트롤러)를 찾아 반환한다

2. 핸들러 어댑터 조회

핸들러가 결정되면, 그 핸들러를 실행할 수 있는 핸들러 어댑터를 조회해야 한다

  • 핸들러 어댑터 결정: **DispatcherServlet**은 요청을 처리할 수 있는 적절한 **HandlerAdapter**를 찾는다 이는 핸들러의 타입(예: @Controller, @RestController, SimpleController 등)에 따라 다를 수 있다

3. 핸들러 어댑터 실행

적절한 핸들러 어댑터를 찾으면, 이 어댑터를 사용하여 핸들러를 실행한다

  • 핸들러 실행: 핸들러 어댑터는 핸들러(컨트롤러)를 실행하고, 필요한 경우 요청 데이터를 컨트롤러 메서드에 전달한다

4. ModelAndView 반환

핸들러(컨트롤러)가 로직을 수행하고 나면, 결과를 ModelAndView 객체로 반환한다

  • ModelAndView 생성: 컨트롤러 메서드가 반환하는 정보(모델 데이터와 뷰 이름)를 ModelAndView 객체로 포장한다
  • RESTful 웹 서비스에서는 이 과정이 생략되고 대신 데이터 객체가 직접 반환된다

5. ViewResolver 호출

ModelAndView 객체를 기반으로, **DispatcherServlet**은 적절한 **ViewResolver**를 사용하여 논리적 뷰 이름을 물리적 뷰로 변환한다

  • View Resolver 결정: **DispatcherServlet**은 여러 ViewResolver 중 하나를 선택하여 논리적 뷰 이름을 물리적 뷰 이름(예: JSP 파일 경로)으로 변환한다
  • REST 컨트롤러의 경우: **@RestController**를 사용한 경우, 이 과정과 이후의 뷰 렌더링 과정은 생략되며, 대신 데이터가 HTTP 응답으로 바로 전송된다

6. View 반환

**ViewResolver**가 뷰 이름을 변환한 후, 렌더링을 담당하는 뷰 객체를 반환한다

  • 뷰 객체 반환: **ViewResolver**는 논리적 뷰 이름을 물리적 뷰 이름으로 변환하고, 그에 해당하는 View 객체를 반환한다 이 View 객체는 주로 JSP, Thymeleaf, FreeMarker 등의 템플릿을 렌더링한다

7. 뷰 렌더링

마지막으로, View 객체를 통해 클라이언트에게 응답을 생성한다

  • 뷰 렌더링: View 객체는 모델 데이터를 이용하여 HTML 등의 형식으로 응답을 생성하고, 이를 클라이언트에게 반환한다
  • 응답 전송: 생성된 응답이 클라이언트에게 전송되고, 클라이언트는 결과를 확인하게 된다

📖예시로 흐름 이해하기📖

  1. 클라이언트 요청: 클라이언트가 /home URL로 요청을 보낸다
  2. 핸들러 조회: **DispatcherServlet**이 요청을 받고, **HandlerMapping**을 사용하여 **HomeController**의 home 메서드를 핸들러로 결정한다
  3. 핸들러 어댑터 조회: **DispatcherServlet**이 **HandlerAdapter**를 사용하여 home 메서드를 실행한다
  4. ModelAndView 반환: home 메서드는 "home"이라는 뷰 이름과 모델 데이터를 포함한 ModelAndView 객체를 반환한다
  5. ViewResolver 호출: **DispatcherServlet**이 **ViewResolver**를 사용하여 논리 뷰 이름 "home"을 실제 물리적 뷰 이름으로 변환한다
  6. View 반환: **ViewResolver**는 "home.jsp"라는 JSP 파일을 가리키는 View 객체를 반환한다
  7. View Rendering: View 객체는 모델 데이터를 사용하여 "home.jsp"를 렌더링하고, HTML 응답을 생성하여 클라이언트에게 전송한다

이렇게 Spring MVC는 요청을 체계적으로 처리하고, 응답을 생성하여 클라이언트에게 전달하는 과정을 효율적으로 수행한다

MVC 패턴 장점

  • 유지보수성: 코드가 역할별로 분리되어 있어 변경 사항이 발생해도 다른 부분에 미치는 영향을 최소화할 수 있다
  • 재사용성: 동일한 모델을 여러 뷰에서 재사용할 수 있으며, 새로운 뷰를 쉽게 추가할 수 있다
  • 테스트 용이성: 비즈니스 로직과 사용자 인터페이스가 분리되어 있어 개별적으로 테스트하기 쉽다

MVC 패턴 장단점

  • 정의
    • Model, View, Controller로 분리하는 아키텍처
  • 장점
    • 과거에는 Controller에 다 담아두고 처리했다.
    • 기능 별로 코드를 분리하여, 가독성을 높이고 재사용성을 증가시킨다.
  • 단점
    • view와 model 사이에 의존성이 높아서 애플리케이션이 커질수록 복잡해지고 유지보수가 어렵다.
    • 대규모의 프로그램에서 Controller에 다수의 Model과 View가 복잡하게 연결되어 코드 분석과 테스트가 어려워 질 수 있다.

MVC 패턴 단점

복잡성 증가

  • 작은 규모의 애플리케이션에는 MVC 패턴이 오히려 복잡성을 증가시킬 수 있다.
  • 각 기능을 구현할 때 모델, 뷰, 컨트롤러 세 가지 구성 요소를 모두 작성해야 하기 때문에 초기 개발 단계에서 시간이 더 걸릴 수 있다.
  • 단순한 기능을 구현하기 위해서도 MVC 패턴을 따르다 보면 불필요하게 복잡한 설계가 될 수 있다
  • 모든 프로젝트에 MVC 패턴이 적합하지 않을 수 있으며, 프로젝트의 규모와 복잡성을 고려하여 패턴을 선택해야 한다
  • view와 model 사이에 의존성이 높아서 애플리케이션이 커질수록 복잡해지고 유지보수가 어렵다.
  • 대규모의 프로그램에서 Controller에 다수의 Model과 View가 복잡하게 연결되어 코드 분석과 테스트가 어려워 질 수 있다.
    • → 이런 의존성 문제를 해결하기 위해 MVVM, MVP 구조가 등장

퍼포먼스 오버헤드

  • MVC 패턴의 구조적 특성 때문에, 특히 대규모 애플리케이션에서는 퍼포먼스 오버헤드가 발생할 수 있다
  • 각 요청에 대해 컨트롤러가 모델과 뷰를 연결하고 데이터를 처리하는 과정에서 시간이 더 소요될 수 있다

'Developing > TIL(Develop)' 카테고리의 다른 글

Java에서 동일성과 동등성의 차이  (1) 2024.05.15
JPA 사용할때 쿼리가 복잡해지는 경우의 해결방안  (0) 2024.05.15
Spring JPA 상속 관계  (0) 2024.05.10
Spring Transactional  (0) 2024.05.09
Spring AOP  (0) 2024.05.08