MVC 패턴

MVC 패턴은 소프트웨어 개발 Architecture의 대표적인 방법론 중 하나이다.

MVC의 개념에 대해서는 워낙 좋은 글들이 많으므로 간략하게 적고,

좀 더 실전적인 차원에서 MVC 패턴을 정리해보려고 한다.

MVC 패턴이란?

image

  • 모델(Model), 뷰(View), 컨트롤러(Controller)로 이루어진 디자인 패턴

모델

  • 애플리케이션의 데이터와 관련된 부분
    • 데이터베이스, 상수, 변수 등

뷰

  • 사용자 인터페이스 요소(UI)
    • 모델을 기반으로 사용자가 볼 수 있는 화면

컨트롤러

  • 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할
    • 메인 로직을 담당

MVC 흐름

image

  1. 사용자는 원하는 기능을 처리하기 위한 모든 요청을 컨트롤러에게 보낸다
  2. 컨트롤러는 모델을 사용하고, 모델은 알맞은 비즈니스 로직을 수행한다
  3. 컨트롤러는 사용자에게 보여줄 뷰를 선택한다
  4. 선택된 뷰는 사용자에게 알맞은 결과 화면을 보여준다
  5. 이 때, 사용자에게 보여줄 데이터는 컨트롤러를 통해서 전달받는다

MVC 패턴의 실전 적용

1. Model은 Controller와 View에 의존하지 않아야 한다

  • Model 내부에 Controller와 View에 관련된 코드가 있으면 안 된다
public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.nume = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

2. View는 Model에만 의존해야 하고, Controller에는 의존하면 안 된다

  • View 내부에 Model 코드만 있을 수 있고, Controller 코드가 있으면 안 된다
public class OutputView {
    // 파라미터로 Student 모델 객체를 받음
    public void printProfile(Student student) {
        System.out.println(
            "내 이름은 " + student.getName() + "입니다."
        );
        System.out.println(
            "내 나이는 " + student.getAge() + "입니다."
        );
    }
}

3. Controller는 Model과 View에 의존해도 된다

  • Controller 내부에는 Model과 View의 코드가 있을 수 있다
public class Controller {
    public static void main(String[] args) {
        Student student = new Student("기철", 25);
    }
}

4. View가 Model로부터 데이터를 받을 때, 반드시 Controller를 통해서 받아야 한다

  • View에서 일어나는 ‘과한’ 값 검증과 예외 처리에 주의
  • View에서 일어나는 비즈니스 로직에 주의

5. 올바른 컨트롤러의 예시

  • main()은 MVC에서 Controller의 역할로 가능한 가볍게 구현
  • Controller 내에서 로직은 최대한 배재
  • Model과 View 사이의 연결 역할만 하도록 구현
public static void main(String[] args) throws Exception {
    Players players = InputView.createPlayers();
    Rewards rewards = InputView.createRewards();

    Ladder ladder = LadderFactory.createLadder(players.countOfPeople(), InputView.getHeight())
    OutputView.printLadder(players, ladder, rewards)

    MatchingResult matchingResult = ladder.play();
    LadderResult result = matchingResult.map(players, rewards);

    OutputView.printResult(result);
}

나중에 공부하면 좋을 것들

image

Serive에 대한 이해

  • 비즈니스 로직을 수행하는 메서드를 가지고 있는 객체
  • 비즈니스 메서드를 별도의 Service 객체에서 구현
    • 컨트롤러는 Service 객체를 사용하도록 함

Repository에 대한 이해

  • DAO(Data Access Object)
  • 데이터 엑세스 메서드를 별도의 Repository 객체에서 구현
  • Service는 Repository 객체를 사용

유용한 블로그