MVC 패턴에 대해

Jii·2023년 10월 27일
0

우테코

목록 보기
3/5
post-thumbnail

프리코스 1주차 미션(숫자 야구 게임)을 진행하면서 나름대로 객체지향적으로 짜려고 노력을 많이했다.
나중에 서비스가 커지거나 요구 사항이 변경될 때를 감안하여 유지보수가 쉽게끔 유연하게 구현하는 것 말이다.

그 중 메서드는 최대한 10줄 이내로 한가지 기능만 할 수 있도록 나누는게 그렇게 힘들지 않았는데, 클래스 별로 한가지 책임만 부여하는 것이 너무 어려웠다.
한 클래스에 너무 많은 책임을 부여하지 않기 위해서는 분리가 필요했지만, 무엇을 기준으로 어떻게 나누어 하는지에 대해 잘 알지 못했기 때문이다.

1주차 미션이 끝나고 다른 분들의 코드를 보니 많은 분들께서 MVC패턴을 사용하셨고, 이 패턴을 적용한 코드들을 살펴보니 하나의 클래스가 너무 비대하지도 않으며 객체에게 한 가지 책임만 부여할 수 있다는 것을 깨닫게 되었다.
이에 MVC패턴의 이점을 알게되었고, 좀 더 자세히 공부한 후 2주차 미션에 적용시켜보고자 이 글을 작성하게 되었다.

아래 예시 코드들은 1주차 과제를 다시 리팩토링을 해 본 코드이다.
각설하고, MVC패턴에 대해 파헤쳐보자!

1. MVC란?

MVC(Model - View - Controller) 는 어플리케이션을 세 가지 역할로 구분한 개발 방법론이다.

  • 사용자가 View를 통해 요청 보냄 -> Controller에서 요청 받음
  • Model -> Controller에 데이터를 가져옴
  • Controller -> View에 데이터 전달

2. MVC 패턴의 구성요소

2-1. M (Model)

Model은 내부 비지니스 로직을 처리하기 위한 객체라 볼 수 있으며, View에게 전달할 데이터에 대해 다룬다.
예를 들어 숫자 야구 게임의 비지니스 로직중 하나인 볼, 스트라이크 개수를 가진 BallResult가 Model이라 볼 수 있다.

public record BallResult(int ballCount, int strikeCount) { 
}

이번 기수부더 JDK17버전을 사용하게 되면서 활용가능해진 record를 통해 BallResult를 나타내 보았다. 아직 record에 익숙하지 않으신 분들은 아래 코드를 참고해주면 된다. (아래 코드들을 위의 한 줄로 단축시킬 수 있음!!👍🏻)

public class BallResult {
    private final String ballCount;
    private final int strikeCount;
    
    public Person(String ballCount, int strikeCount) {
        this.ballCount = ballCount;
        this.strikeCount = strikeCount;
    }
    
    public int ballCount() { //getter지만 메서드명에 get 빠짐
        return ballCount;
    }
    
    public int strikeCount() { //getter지만 메서드명에 get 빠짐
        return strikeCount;
    }
}

2-2. V (View)

View는 사용자에게 UI(화면)을 보여준다. 따라서 데이터를 보여주는 방식을 정의하는 역할을 한다고 볼 수 있다.
다시 말하자면, 모델이 처리한 데이터나 그 결과를 가지고 사용자에게 출력할 화면을 만든다.
중요한 것은 View가 Model로부터 데이터를 받을 땐, 사용자마다 다르게 보여주어야 하는 데이터에 대해서만 받아야 한다는 것이다.

예를 들어서 숫자 야구 게임에서 숫자를 입력해주세요 :라는 문구는 모든 사용자에게 공통적으로 나타내주어야 하므로 Model에 포함되어서는 안된다. 즉, Model로 부터 데이터를 받아오는 것이 아니라 View자체에서 처리되어야 한다는 것이다.

아래 OutputView 클래스는 숫자 야구 게임에서 숫자 비교 결과를 출력하는 View이다.

public class OutputView {
	private static final String BALL = "볼";
    public final static String STRIKE = "스트라이크";

    public void printGameResult(final BallResult ballResult) {
        if (ballResult.ballCount() == 0 && ballResult.strikeCount() == 0) {
            System.out.print(NOTHING);
        }
        if (ballResult.ballCount() > 0) {
            System.out.printf("%d%s ", ballResult.ballCount(), BALL);
        }
        if (ballResult.strikeCount() > 0) {
            System.out.printf("%d%s", ballResult.strikeCount(), STRIKE);
        }
        System.out.println();
    }
}

2-3. C (Controller)

Model과 View를 잇는 다리 역할로써, 모델과 뷰의 상태 변경을 시켜준다.
사용자로부터 요청을 받아 Model에게 요청에 맞는 데이터 변경을 지시하고, Model이 업무 수행을 완료하면 Controller는 Model로부터 데이터를 받아와 View에 전달한다.

아래는 숫자 야구 게임 흐름을 제어하는 Controller 중 일부 메서드로, 흐름은 다음과 같다.
먼저 inputView에서 사용자의 요청(예상 정답 숫자)를 받아 Model에 전달한다.
이후 Model은 정답 숫자와 사용자의 숫자를 비교하여 데이터(볼, 스트라이크 개수)를 전달한다. 비지니스 로직을 처리하는 것이다!!
Controller는 모델로부터 받은 데이터를 OutputView에 전달하여 View가 데이터를 화면을 생성할 수 있도록 한다.

private void play(final BaseballGame game) {
        while (true) {
            BallNumbers userBallNumbers = inputView.getUserBallNumbers();
            final BallResult result = game.referee(userBallNumbers);
            outputView.printGameResult(result);
            if (result.strikeCount() == THREE_STRIKE) {
                break;
            }
        }
    }

3. 규칙

위의 내용들을 정리 및 요약해보자면,
MVC 패턴은 각각의 구성요소마다 역할을 가지고 있기 때문에 안전하게 활용하기 위해서는 다음과 같은 규칙을 가지게 된다.

Model

  • Model은 Controller, View의 책임을 가지면 안된다
    (Model 코드 내부에 Controller과 View가 있으면 안됨)

View

  • View Model로부터 데이터를 받을 때는, 반드시 Controller를 통해 전달받아야 한다.
  • 사용자마다 다르게 변경되는 데이터만 받아야 한다.
  • View 내에는 Model의 코드가 있을 수 있지만, Controller의 코드가 있어서는 안된다.

Controller

  • Controller 내부에는 Model과 View가 있어도 된다(의존 가능).

참고자료

profile
Empower Yourself

0개의 댓글