본문 바로가기
BackEnd/java spring

[Spring MVC] MVC 패턴에 대해서

by kkkdh 2023. 3. 20.
728x90

MVC 패턴 - 개요

기존 방식의 문제점

(출처: 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의)

기존의 서블릿이나 JSP만을 사용하는 개발 방식에서는 비즈니스 로직과 뷰 랜더링을 구현하는 로직 간의 구분이 모호하고, 유지 보수가 어렵다는 문제들이 있었다.

 

사실 진짜 문제는 둘 사이(비즈니스 로직과 뷰 파트)의 변경의 라이프사이클이 다르다는 점이라고 한다. 예를 들어 UI를 수정하는 작업과 비즈니스 로직을 수정하는 작업은 각각 다르게 발생할 가능성이 매우 높다.

 

또한 둘 사이의 연관성이 크게 없을 가능성 또한 매우 높고, 서로에게 영향을 주지 않는 작업이 대부분을 차지한다. 따라서 두 부분을 하나의 코드로 관리하는 것에서 유지 보수에 좋지 않은 영향을 미치는 것이다.

 

특히 JSP와 같은 템플릿 엔진들은 화면(view)을 렌더링 하는데 최적화되어 있기 때문에, 이 부분의 업무만을 담당하는 것이 가장 효율적이다.

 

Model - View - Controller

이러한 문제를 해결하기 위해 MVC 패턴이 등장했다.

 

MVC 패턴은 앞서 설명한 바와 같이 하나의 서블릿이나, JSP가 단독으로 처리하던 작업을 컨트롤러(Controller)와 뷰(View)라는 영역으로 역할을 나눠 구현하는 개발 방식을 의미한다.

 

대부분의 웹 애플리케이션들은 보통 MVC 패턴을 사용한다고 함.

  • Model
    • View에 출력할 데이터를 담아둔다.
    • Model이 데이터를 저장하고 관리하는 역할 + Controller가 전달하는 역할을 담당하기 때문에, View 파트에서는 비즈니스 로직이나 데이터에 접근하는 방법에 대해서는 몰라도 지장이 없다.
  • View
    • 전달 받은 데이터를 이용해 화면을 렌더링 하는 작업에 집중한다. (HTML 생성)
  • Controller
    • HTTP request를 받아 parameter를 검증하고, 비즈니스 로직의 실행을 담당한다. 
    • Model에서 받아온 데이터를 View 컴포넌트에게 전달한다.

(출처: 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의)

보통 위와 같이 MVC 패턴에서의 역할 담당이 나뉜다고 볼 수 있다.

 

하지만, 다음과 같이 Controller에서 비즈니스 로직에 대한 부분과 데이터에 접근하는 부분을 서비스(Service)와 리포지토리(Repository) 클래스를 추가적으로 설계해서 담당하는 역할을 분리하기도 한다.

(출처: 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의)

그래서 컨트롤러는 요청에 대한 입력 확인과 서비스나 리포지토리를 호출하는 중간 다리의 역할을 수정하는 방식이다.

 

또 요즘 개발 추세에서는 프론트엔드가 뷰 로직을 구현하는 역할을 담당한다고 정리할 수 있을 것 같다.

지금 진행하고 있는 프로젝트에서 MVC 패턴 2와 같이 개발하고 있다고 정리할 수 있을 것 같다.

MVC 패턴 적용

View를 JSP로 Controller를 Servlet로 하여 MVC 패턴을 적용해 보자.

 

Dispatcher를 이용한 forward

기존 request 객체(HttpServletRequest)에서 getRequestDispatcher method를 사용하면 RequestDispatcher를 반환받을 수 있다.

 

반환받은 dispatcher 객체의 forward() method를 이용하면, 다른 서블릿이나 JSP로 이동할 수 있다. (서버 내에서 다시 호출하는 구조)

 

WEB-INF

  • 이 경로 안에 위치한 JSP 파일들에 대해서는 직접 호출 불가능
  • MVC 패턴에 따라 구현하기 위해서는 항상 controller를 통해 JSP가 호출되도록 구현해야 한다.
  • 즉, url에 맞는 요청을 처리하는 servlet을 JSP와 별개로 생성해야 한다.

 

redirect vs forward

  • redirect는 실제 클라이언트에 응답이 갔다가, 클라이언트가 redirect 경로로 다시 요청하는 방식으로 동작한다.
  • 따라서 사용자가 인지할 수 있고, URL도 실제로 변경되는 것을 확인할 수 있다.
  • 반면, forward내부 서버에서 일어나는 호출이기 때문에, 클라이언트가 인지할 수 없다.

View 역할만을 하는 JSP로 변경

<% 
	request.getAttribute("member").getId() 
%>
->
${member.id};

이런 식으로 JSP에서 제공하는 표현식(${})을 통해 Java 코드를 넣을 때, 간단하게 처리할 수 있다.

 

<%, %>로 감싸는 부분은 JSP 파일에서 Java 코드가 들어가는 부분을 지칭한다.

 

JSP에는 이렇게 Java 코드를 삽입할 수 있으며, 삽입된 코드는 servlet으로 만들어져 servlet 객체의 service method (request에 따라 동작하는 코드)로 만들어져 실행된다.

JSP에 자바 코드가 포함되어 servlet까지 자동으로 생성하는 코드

이렇듯 JSP는 요청이 들어옴에 따라 알아서 servlet을 생성해 비즈니스 로직을 처리할 수 있다는 점이 장점이었으나, 시간이 지남에 따라서 MVC 패턴에 따른 개발 방식이 대세로 떠올랐고, 오히려 이러한 부분이 단점으로 변모된 것 같다.

 

최근 들어 Spring과 함께 많이 사용하는 template engine인 Thymeleaf는 템플릿 내에 자바 코드를 포함하지 않는데, 이는 JSP와 다르게 MVC 중 View component의 역할만을 템플릿 엔진이 집중하는 흐름과 굉장히 어울린다는 생각이 들었다.

 

아마 그래서 JSP가 아닌 Thymeleaf를 권장하고, 많이들 사용하는 흐름으로 변한 것이 아닐까 싶었다.

표현식을 이용해 servlet에서 저장된 결과를 보여주는 JSP

일단 위와 같이 JSP를 View 파트의 역할만 담당하도록 변경했다.

비즈니스 로직은 servlet에서 처리한다. (Controller의 역할)

위 코드에서 볼 수 있듯이 servlet에서 Controller의 역할 담당에 집중하게 되며, dispatcher를 이용해 forward 하여 Model(request의 attribute)에 데이터를 담아 View로 전송하게 된다.

 

하지만, 이렇게 MVC pattern으로 코드를 개선해도 중복되는 코드(dispatcher를 이용해 request, response 객체 전달하는 부분 포함)가 많고, 이를 개선하기 위해 만들어진 것이 Spring MVC 프레임워크라고 한다.

 

하나씩 개선하면 지금의 Spring MVC 프레임워크가 만들어진다고 한다.

728x90

댓글