본문 바로가기
Spring

MVC패턴에 대해 알아보자. (Spring MVC)

by 매트(Mat) 2022. 7. 17.

MVC패턴에 대해 알아보자. (Spring MVC)

서블릿 에 대해서도 조금 알게되었으니 이제 MVC 패턴에 대해 알아보도록 하자!

MVC 패턴 사용 이유

MVC 패턴을 적용 안한 JSP를 예를 들어보자.
JSP 페이지 안에는 자바 코드가 들어갈 수 있다. 따라서 비즈니스 로직을 넣을 수 있고, Connection 객체를 이용한 DB 연동도 할 수 있다. 또한 JSP는 클라이언트에게 View를 렌더링하는 역할도 수행한다. 여기까지만 봐도 JSP는 너무나 많은 역할을 가지고 있다.

이렇게 JSP가 많은 역할을 하게 되면 나중에 유지보수에도 굉장히 힘들어진다. JSP 페이지 안에 비즈니스 로직과 DB 연동 코드 모두 들어가 있으면 일단 코드 라인수도 많을 것이고, 비즈니스 로직을 수정하는데 여러가지 코드가 막 섞여있으면 보기가 힘들어지고, 간단한 UI하나만 수정해도 한 페이지 안에 비즈니스 로직까지 섞여있어서 개발자가 실수할 확률도 높아진다.

그래서 이렇게 많은 역할을 분리시키는 것이다. 기본적으로 가장 많이 사용되는 MVC 패턴에 대해 살펴보자

변경의 주기(라이프 사이클)가 다르면 분리를 고려해라.

MVC 패턴 개념

기존에 JSP 페이지 안에 모든 로직을 처리를 했다면 컨트롤러(Controller), 모델(Model), 뷰(View)로 서로의 역할을 나눈다.

  • 컨트롤러: HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행하고, 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다.
    • 컨트롤러는 이미 충분히 많은 역할을 수행하기 때문에 복잡한 비즈니스 로직 같은 경우는 따로 클래스를 분리한다.
  • 모델: 뷰에 출력할 데이터를 담는다. 뷰가 필요한 데이터를 모두 모델에 담아서 전달해주는 덕분에 뷰는 비즈니스 로직이나 데이터 접근을 몰라도 되고 화면을 렌더링하는 일에 집중할 수 있다.
  • 뷰: 모델에 담겨있는 데이터를 사용해서 화면을 그리는 일에 집중한다. 여기서는 HTML을 생성하는 부분을 말한다.

mvc1

  1. 클라이언트가 요청을 하게 되면 Controller는 요청을 받아서 검증을 한다. (HTTP 스펙에 맞게 제대로 요청했는지, 안맞으면 400대 오류를 발생시킨다.)
  2. 검증이 제대로 되면 Service 로 간다.
  3. Service에서 DB에 있는 데이터가 필요하면 Dao라는 인터페이스를 통해 데이터를 가져온다.
  4. DaoDB에서 CRUD 하는 행위들을 인터페이스로 관리한다.
  5. ControllerService에서 가져온 데이터들을 Model에 전달한다.
  6. Model에 제대로 전달이 되면 그 결과를 View에 넘긴다.
  7. 그럼 View는 받은 결과를 통해 Model에 있는 데이터를 참조한다.
  8. 마지막으로 View를 출력해서 클라이언트에 응답한다.

컨트롤러는 클라이언트의 요청을 받아서 검증도 하고, 비즈니스 로직도 호출해주고, 모델에 데이터도 전달해주고, 그 결과를 뷰에 넘겨주기도 하기 때문에 결국에 컨트롤러는 중간에서 조정자 역할로서, 매우 중요한 일을 하고 있다.

프론트 컨트롤러

mvc2

기존의 MVC 패턴에는 한 가지 문제점이 있는데 바로 위 그림이다.
그림을 보는 것처럼 각각의 클라이언트들이 필요한 리소스에 맞는 각각의 컨트롤러를 요청한다. 이 때 컨트롤러에서 작업하는 공통 코드들이 있는데 각각의 컨트롤러들은 이 공통 코드를 매번 만들어주아야 한다는 불편함이 있다. 그래서 이 공통 코드를 하나의 서블릿에서 모두 처리할 수 있도록 앞에 프론트 컨트롤러를 도입한다.

mvc3

위 그림처럼 프론트 컨트롤러는 공통 코드를 책임지고 클라이언트들의 모든 요청을 받는다. 그리고 요청에 맞는 컨트롤러를 찾아서 호출한다.

프론트 컨트롤러를 사용하면 프론트 컨트롤러 하나만 서블릿을 사용하고 나머지 컨트롤러는 서블릿을 사용하지 않아도 된다.

Spring MVC

MVC 패턴에 프론트 컨트롤러를 사용한 프레임워크가 바로 Spring MVC이다. Spring MVC에서는 프론트 컨트롤러를 DispatcherServlet이라고 한다. 이 DispatcherServlet은 클라이언트들의 모든 요청을 받는 클래스이다. 즉, DispatcherServlet 클래스는 프론트 컨트롤러로서 역할을 수행하고 Spring MVC 애플리케이션의 흐름을 책임지고 있기 때문에 Spring MVC에서 가장 핵심적인 역할을 맡고 있다.

mvc4

  1. DispatcherServlet은 클라이언트가 보낸 요청을 받는다.
  2. DispatcherServletHandlerMapping에게 적절한 Controller를 찾도록 요구한다. HandlerMapping은 HTTP 요청 메시지를 기반으로 요청 URL을 확인한 후 맞는 ControllerDispatcherServlet에게 반환한다.
  3. DispatcherServletHandlerAdapter에게 Controller의 비즈니스 로직을 실행하라고 명령한다.
  4. HandlerAdapterController의 비즈니스 로직을 호출한다.
  5. Controller는 비즈니스 로직을 실행해서 Model에 데이터를 담고, 반환된 view nameHandlerAdapter에게 전달한다.
  6. DispatcherServletHandlerAdapter로부터 받은 view nameViewResolver에게 전달해서 클라이언트에게 보여줄 View와 이름이 일치하는지 명령한다. ViewResolverview name과 일치한 View를 반환한다.
  7. DispatcherServletView에게 반환된 View를 전달하고 렌더링을 진행하라고 명령한다.
  8. ViewModel 데이터를 렌더링하고 최종적으로 응답 결과를 클라이언트에게 반환한다.

HandlerMapping은 HTTP 요청 메시지 정보를 이용해서 적절한 컨트롤러를 찾아주는 기능을 수행한다.

HandlerAdapter는 HandlerMapping을 통해 찾은 컨트롤러를 직접 실행하는 기능을 수행한다.
HandlerMapping을 통해 찾은 컨트롤러를 HandlerAdapter 목록에서 supports 메서드에 대입하며 지원여부를 살핀다. 부합할 경우 handler 메서드를 실행하여 ModelAndView를 리턴한다.

마무리

Spring MVC는 HandlerMapping, HandlerAdapter, ViewResolver 모두를 개발자들이 유연하고 편하게 사용할 수 있게 인터페이스로 개발되었습니다.
저도 MVC 패턴과 Spring MVC를 공부하면서 얕게 알고 있었던 부분들을 좀 더 자세하게 알게되었습니다. (더 세세하게 들어가기에는 제 머리에 한계가 올듯..)

만약 위 내용이 이해가 안된다면 인프런의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의에서 MVC 프레임워크 만들기를 참고하면 좋을 것 같네요. 저도 나중에 한번 더 따라해볼 예정이고 그 때 자바 웹 프로그래밍 Next Step이란 책도 같이 공부할 계획입니다! (언제가 될까요?😅)

References

댓글