Skip to content

Latest commit

 

History

History
167 lines (108 loc) · 7.51 KB

File metadata and controls

167 lines (108 loc) · 7.51 KB

스프링 MVC 프레임워크 동작 방식

이번 글에서는 Spring MVC 핵심 구성 요소들이 어떻게 동작하는지에 대해서 알아보겠습니다. Servlet 정리 예전에 Servlet에 대해서 정리한 적이 있습니다.

1

Servlet 글을 보면 알겠지만 요청 마다의 Servlet을 생성하고 그에 맞는 Controller에게 맵핑이 되어 요청을 보내주는 코드를 작성해야 했습니다. 하지만 최근에는 이러한 복잡한 것들을 해결하기 위해 DispatcherSevlet 이라는 것이 나왔습니다. 이것은 FrontController 라고도 하는데요.

2

즉, DispatcherServlet에서 요청을 받아서 요청에 맞는 Controller로 보내주는 역할을 하게 됩니다. 이런 FrontController의 역할을 통해서 상당히 개발하기 편해졌는데요. 내부적으로 어떤 원리로 작동하기에 이런 것들이 가능한 것일까요?



스프링 MVC 핵심 구성 요소

3

MVC가 동작하는 대표적인 그림은 위와 같습니다.

  1. 클라이언트 애플리케이션에 접근하면 접근한 URL 요청을 DispatcherSevlet이 가로챕니다.
  2. 가로채 정보를 HandlerMapping에 보내 해당 요청을 처리할 수 있는 Controller를 찾아 리턴합니다.
  3. 컨트롤러를 해당 요청을 처리한 후에 보통 컨트롤러는 요청을 응답받을 View의 이름을 리턴하게 됩니다.

하지만 위의 내용은 Controller 어노테이션이 동작하는 원리에 가깝고 RestController의 동작 방식은 살짝 다릅니다.



Controller

  • MVC 중에 하나인 Controller이 있습ㄴ디ㅏ. @Controller 어노테이션을 추가해주면 스프링에서 Controller라고 인식을 해줍니다.
  • Bean으로 등록됩니다. (Bean, IoC 컨테이너.. 무엇인지 기억나시죠??)
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HelloController {
    
    @GetMapping("/")
    public String test(Model model) {
        model.addAttribute("data", "hi");
        return "hello";
    }
}

HelloController에 간단하게 위와 같이 작성해보겠습니다. 코드를 보니 Model, Controller가 여기에 존재합니다. model는 key, value 형태의 데이터를 담는 공간이라고 생각하면 편할 거 같습니다.


HTML View

스크린샷 2021-04-30 오후 12 42 24

Spring Project에서 View를 작성하는 폴더는 resources 아래에 작성합니다. (Thymeleaf를 쓰냐 jsp를 쓰냐에 따라 조금은 다르지만..)


<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}">안녕하세요. 손님</p>
</body>
</html>
안녕하세요. hi

그래서 위의 html을 보면 결과는 Model에 담아놓았던 데이터를 key로 꺼내면 data에 해당하는 것이 출력이 됩니다. 즉, 간단히 말하면 Controller에 요청이 들어오면 요청 받은 뷰의 필요한 데이터를 Model에 담아 view로 보내주는 역할을 하게 됩니다.



Controller 내부 구조

Controller

  • 요청이 오면 DispatchServlet에 의해 요청 URL이 존재한다면 Controller에게 전달합니다. (DispacherServlet은 또 뭐지..? 이것도 다른 글에서 따로 정리할 예정입니다.)
  • Controller는 내부적으로 viewResolver가 존재하기 때문에 return 값이 view 파일 이름입니다. 즉, 위의 코드에서 hello를 return 하고 있기 때문에 hello.html 파일을 찾게 됩니다.
@Controller
public class HelloController {

    @GetMapping("/")
    public String test() {
        return "Gyunny";
    }
}

그러면 위의 코드에서 Gyunny를 return 하고 있으니 Gyunny.html 파일을 찾을 것입니다. 없다면 어떤 것이 뜨게 될까요?

스크린샷 2021-04-30 오후 12 50 46

당연히 404가 뜰 것입니다. Gyunny.html 파일이 없으니 찾을 수 없다고 뜨는 것입니다.


RestController 구조

RestController

  • RestController = Controller + ResponseBody입니다.
  • RestController는 내부적으로 HttpMessageConverter가 사용되기 때문에 return 타입에 따라 변환을 해줍니다.
  • ex) return 타입이 Object라면 JsonConverter가 실행 되고, return 타입이 String 이라면 StringConverter가 실행된다.

@RestController
public class HelloController {

    @GetMapping("/")
    public String test() {
        return "Gyunny";
    }
}

위와 같이 return 타입이 String이면 StringConverter가 실행되게 됩니다.

스크린샷 2021-04-30 오후 4 25 36


@RestController
public class HelloController {

    @GetMapping("/")
    public HelloDto test() {
        HelloDto helloDto = new HelloDto(1L, "Gyunny");
        return helloDto;
    }
}

이번에는 Object 타입을 return 타입으로 놓겠습니다. 위의 API는 어떤 것을 반환할까요? 위에서 말했듯이 Object 타입이면 JsonConverter가 실행되는데요. 반환 결과도 JSON으로 나오게 됩니다.

스크린샷 2021-04-30 오후 4 26 47



HttpMessageConverter란?

스크린샷 2021-04-30 오후 4 29 01

HttpMessageConverter는 위와 같이 다양하게 존재하는데요. 각 특징들은 읽어보면 알 수 있습니다. 그러면.. 스프링은 도대체 상황에 따라 어떤 HttpMessageConverter를 사용할 지를 어떻게 결정할 수 있을까요? 응답(Response)을 줄 때는 반환 타입에 따라서 결정이 된다고 위에서 말했습니다. 그러면 요청(Request)에서는 어떻게 알 수 있을까요? 바로 HeaderContent-Type을 보고 결정하게 됩니다.

즉, RequestBodyapplication-json 이라면 Jackson2HttpMessageConverter가 실행되고, 다른 형태면 그 형태가 Spring에서 지원한다면 그 형태에 맞는 HttpMessageConverter가 실행되게 됩니다.