Spring/MVC

[Spring] MVC1 & MVC2, DispatcherServlet

ummchicken 2023. 1. 27. 19:22

이번 포스팅도 역시 "기본"에 관한 것이다.


'백견불여일타'라고,
아무리 읽고 또 읽어도 한번 코드 쳐보고 실행하는 것만도 못하다는 뜻이다.

난 이 말에 백번천번 동의한다.

원래 내 스타일도
이론을 쭉 훑고, 이해 갈 때까지 읽고 또 읽고 그 다음에 코딩을 하는 것이 아닌,
일단 한번 쳐보고 그 다음에 그 배경을 찬찬히 살펴본다.
(그래도 어렵고 이해 잘 안 가는 건 함정)

그러면 내가 코드 쳐보면서 이해가 안 갔던 부분들이
'아 이래서 이런 거였구나?'하면서 뭔가 더 머릿속에 잘 들어오는 느낌;;;
뭐 물론 나만 그럴수도.


암튼 각설하고.
오늘은 MVC 패턴의 변화와 @SpringbootApplication에 대해서 다뤄볼 것이다.
(글이 길어져서 @SpringbootApplication는 따로 뺌)


근본 중의 근본인 내용이지만, 이제야 정리하는...

반성하게 되는 포스팅이다.


 

✔️ MVC 패턴이란?

MVC 패턴은 소프트웨어 공학에서 사용하는 디자인 패턴 중 하나로
Model, View, Controller의 앞 글자를 따서 MVC 디자인패턴이라고 한다.
  • Model : 어플리케이션의 정보나 데이터, DB 등을 말한다. View에 출력할 데이터를 담아둔다. View가 필요한 데이터를 모두 Model에 담아서 전달해주는 덕분에, View는 비즈니스 로직이나 데이터 접근을 몰라도 되고, 화면을 렌더링 하는 일에 집중할 수 있다.
  • View : 사용자에게 보여지는 화면, UI를 말한다. Model에 담겨있는 데이터를 사용해 화면을 그린다.
  • Controller : HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행한다. 그리고 View에 전달할 결과 데이터를 조회해서 Model에 담는다.


이처럼 사용자는 얻고자 하는 정보나 기능을 Controller에게 요청하고,
Controller는 사용자의 요청을 수신받아 그에 맞는 비즈니스 로직을 수행하여 (필요에 따라 Model을 호출하여 데이터 요청),
요청을 처리 이후 View(화면)를 통해 사용자가 원하는 정보를 표출한다.

※ 참고
컨트롤러에 비즈니스 로직을 둘 수도 있지만, 이렇게 되면 컨트롤러가 너무 많은 역할을 담당한다.

따라서 일반적으로 비즈니스 로직은 서비스(Service)라는 계층을 별도로 만들어 처리한다.
그리고 컨트롤러는 비즈니스 로직이 있는 서비스를 호출하는 역할을 담당한다.

(비즈니스 로직을 변경하면, 비즈니스 로직을 호출하는 컨트롤러도 변경될 수 있음)



이러한 MVC 패턴은 크게 MVC 모델1 패턴과 Spring이 채택한 MVC 모델2 패턴으로 나누어 볼 수 있다.

✔️ MVC 패턴 이전



✔️ MVC 1 패턴

 

MVC 모델 1 패턴의 경우에는
View와 Controller를 모두 JSP가 담당하는 형태이다.
(뷰와 컨트롤러 역할이 합쳐져 있음)

요청이 JSP단에서 처음 다뤄지고, 다뤄지면서 Bean하고 상호작용을 한다.
DB와 상호작용하는 Bean으로 대량의 프로세싱 로직이 다뤄진다 하더라도,
JSP 페이지는 부분적인 프로세싱 로직을 가지고 있을 수 있다.

JSP단에서 View와 Controller의 역할을 같이 수행, Bean은 Model의 역할을 가지고 있다.

애플리케이션이 복잡해지면 개발과 유지보수가 어려워진다.



JSP 하나로 유저의 요청을 받고, 응답을 처리하기 때문에 구현 난이도는 쉬운 편이다.
단순한 프로젝트에서는 괜찮지만, 복잡해지고 커질수록 단점이 생기게 되는 패턴이다.

  • 장점 : 페이지 흐름이 단순하고, 구조가 간단하여 중소형 프로젝트에 적합하다.
  • 단점 : 유지보수가 어렵다(재사용성 및 가독성 떨어짐), 개발자와 디자이너 역할 분담이 어려워 원활한 의사소통이 필수적이다.




✔️ MVC 2 패턴

 

MVC 모델 2 패턴은 기존에 View와 Controller의 역할을 모두 수행하던 JSP는
View의 역할만 하게 되고, 대신 Controller의 역할을 Servlet(서블릿)이 수행한다.

모델2는 사용자의 요청을 하나의 컨트롤러(Servlet)가 먼저 받는다.
서블릿은 웹 브라우저의 요청을 알맞게 처리한 후,
그 결과를 JSP 페이지로 포워딩한다.

유지보수 큰 이점.




 

✔️ Spring Framework의 MVC 모델2

Spring의 MVC2

 

 

구성요소 설명
DispatcherServlet 클라이언트의 요청을 전달받아
요청에 맞는 컨트롤러가 리턴한 결과값을 View에 전달
HandlerMapping 클라이언트의 요청(URL)을 어떤 컨트롤러가 처리할지 결정
Controller 클라이언트의 요청을 처리한 뒤, 결과를 DispatcherServlet에 전달
ModelAndView 컨트롤러가 처리한 결과 및 뷰 선택에 필요한 정보를 담음
ViewResolver 컨트롤러의 처리 결과를 생성할 뷰 결정
Veiw 컨트롤러의 처리 결과 화면을 생성




✔️ DispatcherServlet이란?

DispatcherServlet은 표현 계층(Presentation layer) 전면에서
HTTP 프로토콜을 통해 들어오는 모든 요청을 중앙집중식으로 처리하는
프론트 컨트롤러(Front Controller)이다.
DispatcherServlet은 Spring MVC의 핵심 요소이다.

클라이언트로부터 어떤 요청이 들어오면, 서블릿 컨테이너(ex. 톰캣)이 요청을 받는다.
❗ 이때 공통 작업은 DispatcherServlet에서 처리하고,
이외 작업은 적절한 세부 컨트롤러로 위임한다.
※ DispatcherServlet 장점 : Spring MVC는 DispatcherServlet이 등장함에 따라 web.xml의 역할을 축소시켜줬음.
과거에는 모든 서블릿을 URL 매핑을 위해 web.xml에 모두 등록해주어야 했지만, 
DispatcherServlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링해주고, 공통 작업을 처리하면서
상당히 편리하게 이용할 수 있게 되었음.
우리는 컨트롤러를 구현해두기만 하면 디스패처 서블릿가 알아서 적합한 컨트롤러로 위임을 해주는 구조가 되었다.

 

 

 

✔️ Spring MVC 동작 흐름

Front Controller 부분이 바로 DispatcherServlet을 나타낸다.

 

① DispatcherServlet으로 클라이언트의 웹 요청(HttpServletRequest)가 들어온다.
- 웹 요청을 LocaleResolver, ThemeResolver, MultipartResolver 인터페이스 구현체에서 분석한다.

② 웹 요청을 HandlerMapping에 위임하여 해당 요청을 처리할 Handler(Controller)를 탐색한다.

③ 찾은 Handler를 실행할 수 있는 HandlerAdapter를 탐색한다.

④, ⑤ 찾은 HandlerAdapter를 사용해서 Handler의 메소드를 실항한다.
이때, Handler의 반환값은 ModelView이다.

⑥ View 이름을 ViewResolver에게 전달하고, ViewResolver는 해당하는 View 객체를 반환한다.

⑦ DispatcherServlet은 View에게 Model을 전달하고 화면 표시를 요청한다.
이때, Model이 null이면 View를 그대로 사용한다.
반면, 값이 있으면 View에 데이터를 렌더링한다.

⑧ 최종적으로 DispatcherServlet은 View 결과(HttpServletResponse)를 클라이언트에게 반환한다.

→ 해당 흐름은 @Contoller를 기준으로 설명한 것이다.
@RestController의 경우 ⑥, ⑦과정이 생략된다.
즉, ViewResolver를 타지 않고 반환값에 알맞는 MessageConverter를 찾아 응답 본문을 작성한다.





출처