간단하게 정리한 MVC 패턴

MVC 패턴에 대해서 정리해봅니다.

Model, View, Contoller


Goal

  • MVC 패턴이 무엇인지 알아봅니다.
  • MVC 패턴의 장단점에 대해서 알아봅니다.

MVC 패턴이란

비즈니스 로직과 화면을 구성하는 인터페이스 로직을 분리해, 개발하는 디자인 패턴을 이야기합니다.

image

  1. 컨트롤러가 사용자로부터 요청을 받습니다.
  2. 컨트롤러에서 요청을 처리할 수 있는 적절한 모델을 찾아서, 모델이 요청을 처리하게 합니다.
  3. 요청을 처리한 결과를 화면에 그릴수 있도록 View에게 보냅니다.
  4. 사용자는 View를 통해 요청에 따른 결과를 받아냅니다.

Model

무엇을 할지에 대해서 정의해 둡니다.

  • 데이터를 보관하거나, 비즈니스 로직을 구현하는 부분입니다.
  • View와 Controller에 대해서 아무것도 모르고 있어야 합니다.
  • Domain이라고도 불립니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Car {
    private int speed = 0;
    private String name;

    public Car(final String name){
        this.name = name;
    }

    public void speedUp(){
        speed++;
    }

    public void changeName(final String name){
        this.name = name;
    }

    public int getSpeed(){
        return speed;
    }

    public String getName(){
        return name;
    }
}
  • 도메인인 Car에 대한 정보(이름, 속도)를 가지고 있습니다.
  • Car의 속도를 증가시키거나, 이름을 바꾸는 비즈니스 로직을 가지고 있습니다.

View

화면에 보여주는 역할을 수행합니다.

  • Model 부터 만들어진 데이터를 화면에 그려주는 역할을 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

// 출력 담당
public class OutputView {
    public static void printCarSpeed(final int carSpeed){
        System.out.println(carSpeed);
    }

    public static void printCarName(final String carName){
        System.out.println(carName);
    }
}

// 입력 담당
public class InputView {
    private static final Scanner SCANNER = new Scanner(System.in);

    public static void inputCarName(){
        return SCANNER.nextLine();
    }

    public static void printCarName(final String carName){
        System.out.println(carName);
    }
}
  • Car의 정보를 출력하는 부분을 담당하고 있습니다.

Controller

Model과 View에 사이의 중개자 역할을 합니다.

  • 사용자의 정보입력에 따른 Model의 기능 호출, 처리 결과에 따른 뷰의 호출을 처리합니다.
  • 컨트롤러를 통해서 Model에 데이터를 넣으라고 요청하거나, Model에 있는 정보를 화면에 뿌려주는것을 요청합니다.(Controller에서 비즈니스 로직을 처리하는것이 아닙니다.)
  • 당연히 Model과 View 에대해서 알고 있어야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class CarController {
    private Car car;

    public CarController(Car car) {
        this.car = car;
    }

    public void speedUp(){
        car.speedUp();
    }

    public void changeName(){
        car.changeName(InputView.inputCarName());
    }

    public void printSpeed(){
        OutputView.printCarSpeed(car.getSpeed());
    }

    public void printName(){
        OutputView.printCarName(car.getName());
    }
}
  • 요청에 따른 메소드를 적절히 찾아서 호출하고 있습니다.

어플리케이션

1
2
3
4
5
6
7
8
9
10
public class CarApp {
    public static void main(String[] args) {
        CarController carController = new CarController(new Car("JYS"));

        carController.printSpeed();
        carController.printName();
        carController.changeName();
        carController.printName();
    }
}
  • Controller를 이용해서 Car의 정보를 변경하거나, 가져올 수 있게 됩니다.
  • 여기서 AppController의 메소드만 알고 있으면되지, ModelView에 대한 정보는 전혀 모르는 구조가 나오게 됩니다.

장점

역할별로 분리된 코드를 통해서 유지보수가 편해집니다.

  • 새로운 도메인이 더 필요한 경우, Model을 추가적으로 만들어서 domain쪽 패키지에 추가해주면 됩니다.
  • A프레임워크의 컨번센에 맞춘 ControllerView를 구현한 상황인 상황에서, B프레임워크로 변경해야 된다면, Domain로직은 손을 대지 않고 ControllerViewB프레임워크에 맞춰서 변경하면 됩니다.

단점

Controller가 비대해질 수 있는 문제점이 존재합니다.

  • 분리를 했다고 하지만, 결국 ModelView는 관계가 얽혀 있다는것은 부정 할 수 없습니다.
  • 소프트웨어가 점점 복잡해져, 모델(도메인)이 많아지게 된다면, 중계자 역할을 하는 컨트롤러 역시 할일이 늘어나게 됩니다.
  • 종종 Model 에도 들어가기가 애매하고, View 에도 들어가기가 애매한 부분을 Controller 에서 처리하게 구현 하는 경우도 있습니다.
  • 결국 Massive View Controller 라는 말이 나올 정도로 컨트롤러가 비대해지는 경우가 발생할 수 있습니다.
  • 이런 단점을 보완한 여러가지 디자인 패턴들도 존재합니다. (MVVM, MVP)

참고링크

  • 위키피디아
  • https://log.hodol.dev/techcourse/mvc-pattern
  • https://www.crocus.co.kr/1539
  • https://medium.com/@jang.wangsu/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-mvc-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80-1d74fac6e256