Spring Web MVC의 내부 구조와 동작 방식

kyle·2024년 6월 30일
0

Spring Framework

목록 보기
10/16

Spring Web MVC 란?

Spring Web MVC란 Spring Framework와 Servlet API를 기반으로 하는 웹 애플리케이션 프레임워크로, 주로 Spring MVC라고 줄여서 부른다.

이 Spring MVC는 이름에서 유추할 수 있듯이, 웹 요청을 Model-View-Controller로 역할을 분리해 처리하는 MVC 패턴을 사용한다는 특징이 있고 (그 중에서도 Controller 역할을 Servlet이 수행하고 결과를 JSP를 통해 리턴하는 MVC2 패턴을 사용)

데이터 바인딩 및 검증 기능을 제공하며, Interceptor를 제공해 요청을 처리하기 전 후로 보안 / 로깅과 같은 작업을 수행할 수 있다는 특징이 있다.

Spring MVC의 장단점

장점

  • Model-View-Controller로 계층을 나누어 애플리케이션의 아키텍쳐가 유연하고 확장성이 높다.
  • DI를 통해 각 계층 간 결합도를 낮춰준다.
  • 각 계층별로 나뉘어 있기 때문에 테스트와 디버깅이 용이하다

단점

  • 깊게 학습하기 위해서는 러닝 커브가 높다.

  • 초기 환경 세팅과 설정이 복잡하다.
    -> XML을 통해 Spring Bean 등록과 의존관계를 설정이 필요하다.
    -> 단, Spring Boot를 사용하는 경우 간소화 및 자동화 해주기 때문에 해당사항 X

  • 의존성 관리가 어렵다.
    -> 스프링 프레임워크의 많은 라이브러리와 의존성을 사용하기 때문에, 라이브러리 버전 간 충돌이 발생할 수 있다.
    -> 단, Spring Boot를 사용하는 경우 간소화 및 자동화 해주기 때문에 해당사항 X


Spring Web MVC 내부 구조

위의 이미지는 스프링 MVC의 내부 구조로 실제로는 더욱 복잡하다.

1. DispatcherServlet

Spring 웹 애플리케이션의 핵심 구성 요소 중에 하나로 FrontController 패턴으로 구현되어 있는 Servlet 객체다.

이 DispatcherServlet은 사용자의 요청을 처리하기 위해 매우 많은 역할을 한다.

- 클라이언트의 HTTP 요청 수신
- Handler Mapping 조회
- Handler Adapter 조회 및 Handler 실행
- Handler 메서드 실행 결과 클라이언트로 응답

2. HandlerMapping

HandlerMapping은 Spring MVC에서 클라이언트의 요청을 어떤 Handler가 처리할 지 결정하는 역할을 하는 인터페이스이다.

Handler 등록 방식에 따라 다양한 HandlerMapping 구현체가 존재하고, 각 구현체마다 특정 전략을 통해 매핑된 Handler를 조회한다.

예를 들어, RequestMapingHandlerMaping 클래스는 스프링 빈으로 등록된 컨트롤러를 조회해서 @RequestMapping의 URL과 요청 URL이 매칭되는지 확인한다.

HandlerMapping 인터페이스가 Handler를 조회하는 순서는 다음과 같다.

1. HandlerMapping 구현체 조회
	- DispatcherServlet는 HandlerMapping 우선순위 순으로 순회하며 구현체를 가져온다.

2. Handler 조회
	- 구현체의 getHandler 메서드를 통해 클라이언트의 요청을 처리할 Handler를 조회한다. 

3. Handler 정보 리턴
	- 만약 매핑되는 Handler가 존재한다면, Handler 인스턴스와 그 외의 추가 정보가 담긴 HandlerExecutionChain 객체를 반환한다.

3. HandlerAdapter

HandlerAdapter는 Handler 메소드 호출을 위한 준비과정부터 실제 메소드 호출 및 메소드 응답값 처리를 수행하는 인터페이스이다.

HandlerMapping 인터페이스와 동일하게 Handler 등록 방법에 따른 다양한 HandlerAdapter 구현 클래스가 존재한다.

DispatcherServlet은 우선순위 순으로 HandlerAdapter 구현체를 순회하며 support 메소드를 호출해서 Handler를 지원하는 HandlerAdapter 구현체를 찾고, 찾은 HandlerAdapter 구현체의 handle 메소드를 호출해서 Handler 메서드를 실행한다.

HandlerAdapter의 handle 메소드의 내부 동작은 다음과 같다.

(1) HandlerMethod 추출
  - HandlerAdapter는 Handler에 대한 객체로 HandlerMethod를 사용한다. 
  - HandlerExecutionChain 객체에서 Handler 인스턴스와 Handler 메소드의 어노테이션 / 매개변수 등의 정보를 추출해서HandlerMethod 객체에 담는다.

(2) Argument Resolver 호출
- HandlerMethod 객체로 부터 매개변수들을 해석하고 필요한 값을 추출하는 역할을 하는 인터페이스이다.
예시로, @RequestParam, @PathVariable 등의 어노테이션에 따라서 Handler메서드 호출에 필요한 값을 추출해낸다

(3) HandlerMethod 실행
- Argument Resolver를 통해 받은 매개변수 값과 함께 실제 Handler 메소드를 실행한다.

(4) ReturnValue Handler 실행
- Handler 메서드 실행 결과를 처리하는 인터페이스로, Handler 메서드의 유형에 따라 반환하는 값의 적절한 처리를 진행한다.
- 예시로, @ResponseBody 어노테이션이 붙은 메서드의 경우 ReturnValue Handler는 반환된 값을 JSON / XML 형태로 변환하는 처리가 이루어진다.

(5) 결과 반환 
- 결과를 DispatcherServlet에 반환한다.

4. Handler

클라이언트의 요청을 실질적으로 처리하는 메서드로, 흔히 컨트롤러가 이 Handler에 해당된다.

Spring MVC 에서는 아래와 같이 Handler를 여러가지 방법을 통해 등록할 수가 있는데, 그 중 어노테이션 기반으로 Handler를 등록하는 것을 주로 사용한다.

4.1 어노테이션 기반 Handler 등록

@Controller 또는 @RestController 어노테이션으로 스프링 컨테이너에 등록하고, @RequestMapping 과 같은 어노테이션으로 URL을 매핑한다.

@Controller
public class MyController {
    @RequestMapping("/hello")
    public String hello() {
        return "helloPage"; // 뷰의 논리적인 이름
    }
}

4.2 Handler 인터페이스 구현

Handler 인터페이스를 직접 구현하는 방식으로, 클래스명이 요청 URL로 매핑된다. (/myHandler)

public class MyHandler implements Handler {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 요청 처리 로직
        return new ModelAndView("helloPage"); // 뷰의 논리적인 이름
    }
}

4.3 Controller 인터페이스 구현

Controller 인터페이스를 직접 구현하는 방식으로, 클래스명이 요청 URL로 매핑된다 (/myController)

public class MyController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 요청 처리 로직
        return new ModelAndView("helloPage"); // 뷰의 논리적인 이름
    }
}

5. ViewResolver

Handler 메서드 결과 값인 View 이름을 설정된 prefix와 suffix를 기반으로 실제 뷰 객체를 찾아 반환하는 역할을 하는 인터페이스이다.

이 ViewResolver는 항상 호출되는 것은 아니고, @RestController와 같이 View를 사용하지 않는 메서드의 경우 생략된다.


Spring Web MVC 동작 방식

1. 클라이언트의 HTTP 요청

  • 클라이언트(웹 브라우저, 모바일 앱 등)에서 HTTP 요청이 생성된다.

  • 요청은 URI(Uniform Resource Identifier)와 함께 HTTP 메서드(GET, POST, PUT, DELETE 등)와 헤더, 본문 등의 정보를 포함한다.

2. DispatcherServlet의 호출

  • 클라이언트의 요청은 앞단에서 Servlet 컨테이너에 의해 받아들여진다.
  • 이때 등록된 DispatcherServlet이 요청을 가로채고 처리를 시작한다.

3. Handler Mapping을 통한 Handler 조회

  • DispatcherServlet은 클라이언트의 요청을 처리할 핸들러(Controller)를 찾기 위해 등록된 HandlerMapping 구현체들을 순회한다.
  • HandlerMapping은 요청된 URI와 매핑된 핸들러를 찾아 HandlerExecutionChain 객체를 반환한다.

4. Handler Adapter 조회

  • DispatcherServlet은 찾아진 핸들러에 대해 적절한 HandlerAdapter를 선택한다.
  • Handler Adapter 구현체의 support() 메소드를 통해 지원 여부 판단하고
    실행이 가능하다면 handle() 메소드를 통해 Handler Adapter에게 실행을 위임한다.

5. Handler 실행

  • HandlerAdapter는 HandlerExecutionChain 객체를 전달받아서 Handler를 호출하기 위한 준비를 한다.
  • 매개변수 등 필요한 정보가 모두 세팅 되면 handlerMethod를 실제 실행한다.
  • Handler 메소드가 모두 수행 된 후 결과값을 적절하게 가공 처리 한 뒤 DispatcherServlet에 반환한다.

6. View Resolver 및 View 선택 (Optional)

  • 실행된 핸들러의 반환 결과에 대해 ViewResolver가 뷰 이름을 실제 뷰 객체로 변환한다.
  • 만약, RESTful API의 경우 이 과정을 생략한다.

7. View Rendering (Optional)

  • 선택된 뷰는 렌더링을 통해 클라이언트에게 전달할 화면(HTML 등)을 생성한다
  • 만약, RESTful API의 경우 이 과정을 생략한다.

8. HTTP 응답

  • 생성된 화면 또는 응답 데이터는 HTTP 응답으로 변환되어 클라이언트에게 전송한다.
  • 응답에는 상태 코드, 헤더, 본문 등이 포함되어 있다.

9. 클라이언트로 응답 전송:

  • 생성된 HTTP 응답은 클라이언트로 전송되어 브라우저나 애플리케이션에서 처리된다.
  • 브라우저는 받은 응답을 렌더링하여 사용자에게 보여준다.
profile
서버 개발자의 소소한 개발 일기

0개의 댓글

관련 채용 정보