MVC 패턴이란? (feat 적용)

송민준·2023년 11월 5일
0

우테코 프리코스

목록 보기
4/10

MVC 탄생 배경

옛날에는 많은 개발자들이 고질적으로 겪는 문제가 있었다. 코드가 많아질 수록 복잡해져 수정이 어려운 문제가 있어 갈아엎는 경우가 많았다. (유지 보수의 어려움)
그러다 머리 좋은 개발자들이 이런 유지보수의 문제점을 해결할 수 있는 패턴을 발견했고 그것이 MVC 패턴이다.

MVC?

어플리케이션을 3가지 컴포넌트(Model, View, Controller)로 나누고 역할을 부여하는 패턴(개발 방법론)이다.
MVC를 적용했을 때 이점은 도메인(비즈니스) 영역과 UI 영역이 분리된다는 점이다. 분리가 된다면 한쪽이 변경되었을 때 다른 한쪽 영역은 영향을 받지 않으므로 적용하지 않았을 때보다 쉽게 유지보수가 가능하다는 장점이 있다.
사용자가 View를 이용해 요청을 보내면 Controller가 받아서 원하는 결과를 Model로부터 가져온 뒤 View를 통해 사용자에게 요청에 대한 결과를 전달하는 식으로 요청/응답 을 한다.

각 컴포넌트별 역할

mvc
(출처: geeksforgeeks - MVC Design Pattern)

Model

무엇을 할 지 정의한다. 즉 도메인 로직을 처리하는 역할이다.
어플리케이션이 해결해야 하는 문제에 대한 중요한 로직이 이 Model에서 처리한다. 도메인 로직을 처리한 뒤에는 컨트롤러에 결과를 전달한다.

규칙

  • View와 Controller에 대한 어떠한 정보도 가지고 있으면 안된다(의존하면 안된다).
    • 정보? :어떻게 생겼고 어떤 메서드를 가지고 있는지에 대한 정보. 코드로 치면 View, Controller의 클래스를 참조하면 안된다.
    • "어떠한 정보도 가지고 있으면 안된다." 라는 규칙이 모델이 독립성을 가지게 되어 변경에 자유로울 수 있다.

View

무언가 보여주는 역할을 한다. (단지 표현하는 역할만 한다.) 모델이 처리한 결과를 가지고 사용자에게 출력할 화면을 만드는 역할이다. (화면은 콘솔이 될 수 있고 웹 브라우저에서 HTML로 보여질 수 있다.)

규칙

  • View는 Model에만 의존하고 Controller에 의존하면 안된다.
  • View는 Model의 데이터를 접근할 수 있는 방법은 알지만 그 데이터가 무엇을 할 수 있는지, 사용자가 이 데이터를 조작하기 위해 무엇을 할 수 있는지를 모른다.
  • View가 Model의 데이터를 받을 땐 사용자마다 다르게 보여질 수 있는 데이터만 받아야한다. (예를들면 유튜브 홈 화면. 사용자마다 다른 영상이 추천된다.)

Controller

Model과 View 사이에 존재하고 Model이 데이터를 어떻게 처리할지 알려주는 역할이다. 뷰 또는 다른 외부소스로부터 이벤트를 수신하고 이벤트에 대한 적절한 반응을 한다. (보통 Model의 메서드를 실행한다.)

규칙

  • 모델이나 뷰에 대한 정보를 알고 있어야한다.
  • 사용자로부터 이벤트를 수신 받아야한다.
  • View가 Model로부터 데이터를 받을 때 Controller를 통해 받아야한다. (중간 다리 역할)

적용

MVC 패턴 적용 전

MVC가 적용되기 전 코드이다.

public class Car { 
...
	public void printPresentMovingDistance() {  
		OutputView.printMovingDistance(carName, movingDistance);  
    }
}
public class OutputView { 
...
	public static void printMovingDistance(Object carName, int movingDistance) {  
	    System.out.print(carName + " : ");  
	    for (int moved = 0; moved < movingDistance; moved++) {  
	        System.out.print("-");  
	    }  
	    System.out.println();  
	}
}

현재 이동거리를 Car에서 직접 OutputView의 메서드를 호출해서 나타내고 있는 코드이다. Car는 OuputView에 대한 정보를 알고 있으므로 규칙에 어긋난다.
만약 여기서 OuputView 클래스에서 자동차의 번호도 출력되는 것으로 변경된다면 Car 클래스도 변경이 되어야한다. 즉 Model이 View의 영향을 받는다.

MVC 패턴 적용 후

이를 해결하기 위한 MVC가 적용된 코드다.

public class Car { // Model
...
	public void getMovingDistance() {
		return movingDistance;
	}

	public void getName() {
		return name;
	}
}

public class OutputView { // View
...
	public static void printMovingDistance(Car car) {  
	    System.out.print(car.getName() + " : ");  
	    for (int moved = 0; moved < car.getMovingDistance(); moved++) {  
	        System.out.print("-");  
	    }  
	    System.out.println();  
	}
}

public class Controller { // Controller
	public void printPresentStatus(List<Car> cars) {
		for (Car car : cars) {
			OutputView.printMovingDistance(car);
		}
	}
}

Model은 View와 Controller에 대한 정보를 알지 못하고 View는 Model의 사용자마다 변경될 수 있는 데이터를 받아서 표현한다. 그리고 Controller는 View와 Model에 대한 존재를 알고 있으며 Model을 받아서 직접 View에 전달하는 모습을 볼 수 있다.

public class OutputView { // View
...
	public static void printMovingDistance(Car car) {  
	    System.out.print(car.getId() + car.getName() + " : ");  
	    for (int moved = 0; moved < car.getMovingDistance(); moved++) {  
	        System.out.print("-");  
	    }  
	    System.out.println();  
	}
}

만약 여기서 자동차의 번호도 출력하는 것으로 변경된다면 위 코드처럼 View에서 Car의 getNumber를 호출하면 된다. 즉 Model이 다른 컴포넌트의 변경으로부터 자유로워졌다.

MVC의 한계

Controller는 Model과 View에 대한 정보를 알고 있다는 점에서 프로젝트가 커져갈수록 필연적으로 Controller의 스케일이 커지는 문제가 발생한다. (Massive-View-Controller) 때문에 이를 보완하기 위한 다양한 패턴이 생겼다.

  • MVP / MVVM / Flux / Redux / RxMVVM

Reference

profile
개발자

0개의 댓글