MVC는 디자인 패턴일까? 아키텍처 패턴일까?
위의 질문은 내가 요즘 만나는 개발자마다 묻는 공통 질문이다.
"디자인 패턴이다," "아키텍처 패턴이다"라는 의견이 주로 반반 나오는 것 같다.
1. MVC 패턴이란?
MVC패턴은 Model View Controller로 이루어진 소프트웨어 디자인 패턴이다.
- 공식문서에서 디자인 패턴으로 정의를 하였습니다. (https://developer.mozilla.org/ko/docs/Glossary/MVC)
1. Model (Service)
Model은 데이터와 비즈니스 로직을 담당하는 부분입니다.
1. 데이터 관리
모델은 애플리케이션의 상태나 데이터를 관리합니다. 데이터베이스와 상호작용, API 호출 등이 Model에 위치합니다.
2. 비즈니스 로직
Model은 Controller에서 받은 데이터를 가공하거나, 처리합니다. 데이터의 유효성 검사, 계산, 다양한 알고리즘등이 Model에 위치합니다.
3. 독립성
Model은 Controller나 View의 상태를 몰라야 합니다.
상태를 모른다...? 이게 무슨 소리야?
코드와 함께 설명하겠습니다.
Model이 Controller, View의 상태를 모르는 경우
public class UserModel {
private String username;
private String email;
public void updateUserDetails(String username, String email) {
this.username = username;
this.email = email;
}
public String getUsername() {
return username;
}
public String getEmail() {
return email;
}
}
Model이 Controller, View의 상태를 아는 경우
public class UserModel {
private String username;
private String email;
// Model은 Controller와 View를 알고 있음
private UserController controller;
private UserView view;
public UserModel(UserController controller, UserView view) {
this.controller = controller;
this.view = view;
}
public void updateUserDetails(String username, String email) {
this.username = username;
this.email = email;
controller.modelUpdated();
view.displayUserDetails(username, email);
}
// Model은 Controller와 View의 상태를 알고 있으므로 직접 업데이트 가능
public void updateControllerAndView(String username, String email) {
controller.updateModelAndDisplayView(username, email);
}
}
model이 Controller, View의 상태를 모르는 코드와 아는 코드입니다.
만약 Model이 Controller, View에게 상태를 알리고 싶으면 옵저버 패턴을 사용할 수 있습니다.
어느 상황에서도 절대 Controller, View를 직접 참조 하면 안 됩니다.
https://solution-is-here.tistory.com/195
2. Controller
Controller는 Model과 View 사이를 적절히 중재하는 중재자입니다.
1. 사용자의 입력을 처리한다.
Controller는 사용자의 입력을 처리합니다. 버튼 클릭, 키보드 입력, 마우스 동작 등 다양한 입력을 처리합니다.
2. Model과 View 조정
Controller는 사용자의 입력에 따라 Model의 상태를 조정하거나, View를 업데이트합니다.
public void gameStart() {
String randomNumber = computerService.createRandomNumber();
Boolean isDifferent = true;
while (isDifferent) {
String input = inputView.getInput();
validationService.isValidNumber(input);
isDifferent = baseballService.startGame(randomNumber, input);
}
outputView.endGame();
promptForRestart();
}
우아한 테크코스 1차 미션 때 작성했던 코드입니다.
isDifferent = baseballService.startGame(randomNumber, input);
이 줄을 보시면 controller에서 service(Model)의 함수를 호출해 데이터를 가공하는 모습을 볼 수 있습니다.
가공된 데이터는 View를 통해 사용자에게 보여집니다.
3. 애플리케이션 흐름 제어
Controller는 Model과 View의 정보를 가지고 있어 어떤 순서로 진행될지 결정할 수 있습니다.
3. View
시스템에서 입출력만큼 중요한 요소가 없죠! 바로 View 담당입니다.
1. 사용자 입력 전달
절대 헷갈리시면 안 됩니다. Controller -> 사용자 입력 처리, View -> 사용자 입력 전달입니다.
view는 사용자에게 입력을 받은 뒤, Controller에게 보냅니다.
2. Controller에게 데이터를 받아서 출력한다.
View는 Controller에게 Model을 통해 가공받은 데이터를 받아서 출력하는 역할을 합니다.
3. Model에게 데이터를 받아서 출력한다.
방금 위에서 Controller에게 데이터를 받아서 출력한다고 했는데 Model에게서도 받아서 출력을 해?라는 생각 저도 했습니다....
각 사용자에게 다르게 보여지는 코드는 Model에게 데이터를 받아서 출력합니다.
이해하기 쉽게 예시를 들어서 설명하겠습니다.
각 사용자에게 다르게 보여지는 것이란?
위 화면은 배달 기사님께서 배달 오시는 위치를 나타낸 그림입니다.
만약 내가 사는 곳이 송파구가 아닌 서초구면 화면은 다르게 보입니다.
사용자들이 사는 곳에 따라 다르게 보이므로 이 화면은 "사용자들에게 각각 다르게 보이는 화면입니다."
이처럼 View가 Model에게 받는 것은 사용자 각각 다르게 받는 값입니다.
그 외의 값은 전부 Controller에게서 받습니다.
2. 왜 MVC 패턴을 선택했나요?
저는 우아한 테크코스 숫자야구 미션을 진행하면서 MVC 패턴을 채택했습니다.
제가 왜 MVC 패턴을 선택했는지 설명하겠습니다.
"높은 응집도 낮은 결합도"
"높은 응집도와 낮은 결합도"는 제가 코드를 작성할 때 가장 중요하게 고려하는 설계 원칙입니다.
이 원칙을 지키면 유지보수가 용이하고 확장성이 뛰어난 소프트웨어를 개발할 수 있습니다.
객체지향 5원칙(SOLID)은 이러한 설계 원칙을 자연스럽게 준수하도록 도와줍니다.
- 높은 응집도를 유지하게 되면 SRP, ISP 원칙을 준수하여 클래스가 단일 책임을 가지고, 인터페이스가 클라이언트에 필요한 기능만을 제공하도록 설계합니다.
- 낮은 결합도를 유지하면 OCP, LSP, DIP 원칙을 준수하여 확장에는 열려있고, 변경에는 닫혀 있는 설계를 구현하며, 추상화와 인터페이스를 활용해 의존성을 역전시킵니다.
MVC는 역할을 명확하게 분리하여 독립적인 개발과 수정이 가능해짐으로써 "높은 응집도 낮은 결합도"를 실현하는데 큰 도움이 됩니다.