- Published on
MVC Architecture
MVC 아키텍처는 환경과 언어에 따라 각기 다른 형태로 발전하고 사용되어 왔기 때문에 개발자마다 이해하고 있는 MVC의 정의가 다를 수 있다.
과거에는 프리젠테이션 로직과 도메인 로직을 혼재하여 GUI를 구현하면서 유지보수성과 가독성 등이 낮고 복잡도는 높았다.
프리젠테이션 로직
프리젠테이션 로직이란 UI를 실제로 변경하는 로직을 말한다. 타이틀 바를 그리거나 텍스트의 색상을 검은색에서 회색으로 바꾸는 등의 경우를 예로 들 수 있다.
도메인 로직
모델 고유의 데이터 그리고 그 데이터를 조작 및 관리하는 로직을 말한다. 보통 현실 세계의 비즈니스 프로세스, 서비스, 정책 등을 도메인 로직으로 작성한다.
Smalltalk-80 MVC
이런 비효율적인 문제해결을 위해 Smalltalk-80의 MVC는 "프리젠테이션의 분리"를 원칙으로 애플리케이션 로직과 사용자 인터페이스를 분리했다.
프리젠테이션의 분리
현실 세계의 개념을 모델링한 도메인과 사용자 인터페이스를 출력하는 프리젠테이션을 명확하게 구별한다는 개념
이런 방식으로 구현한 가장 큰 이유는 도메인과 프리젠테이션을 분리하면 사용자 인터페이스가 변경되도 모델은 재사용 가능하다고 생각했기 때문이다.
Model
모델은 도메인 로직을 구현하며 사용자 인터페이스(컨트롤러, 뷰)와는 관계를 맺지 않는다.
데이터가 변경되면 자신의 상태가 변경됐음을 옵저버로 통지하고 뷰는 모델의 상태를 통지 받아 항상 최신의 상태를 출력한다.
(옵저버(또는 Pub/Sub) 패턴은 Smalltalk-80의 MVC에서 동기화 문제를 해결하기 위해 사용되었다.)
View
뷰는 프리젠테이션 로직을 구현한다.
UI 요소마다 뷰와 컨트롤러가 1개씩 쌍으로 존재한다.
그 이유는 UI 요소마다 입력 분석 로직이 판이하게 달랐기 때문에 새로운 뷰가 생기면 그 뷰를 대응하는 컨트롤러를 만들어야 했다.
Controller
컨트롤러는 입력 분석 로직과 요청 처리 로직을 구현한다.
입력 분석 로직
행위, 좌표, 상황 등을 고려하여 어떤 요청인지 판단하는 로직. 자바스크립트는 이러한 입력 분석 로직을 구현하는 경우가 없으나, 캔버스를 사용한 사용자 인터페이스를 구현해야한다면 입력 분석 로직을 구현해야한다.
요청 처리 로직
요청에 필요한 행위를 구현하는 로직을 말한다. 입력 분석 로직을 통하여 사용자가 승인 버튼을 클릭했음이 분석되면 그것은 요청이 되고 모델과 뷰를 사용하여 승인 처리를 하는 로직을 요청 처리 로직이라고 한다.
Smalltalk-80 MVC의 문제점은 컨트롤러와 뷰가 강하게 결합하고 뷰가 모델의 변화를 직접 대응하다 보니 각각의 의존성 때문에 테스트 하기가 어려웠다.
또한 어디에서 UI 논리 로직을 구현할 것인지 명확히 정의되어있지 않아 컨트롤러와 뷰에 동일한 관심사가 산재되어 혼란스러운 문제가 있었다.
UI 논리 로직
UI 요소에 스타일을 변경하는 코드가 아닌 UI 요소에 어떤 행위를 시킬 것인지 결정하는 논리 로직을 의미. 예를 들면 UI 요소의 스타일을 변경하는 로직은 프리젠테이션 로직이지만 UI의 상태나 모델의 상태를 기준으로 스타일을 변경할지 안 할지 혹은 토글할지 등을 판단하는 로직을 UI논리 로직이라고 한다.
MVP
MVP는 MVC에서 파생되었다.
MVP에서 P는 프리젠터(Presenter)를 나타낸다.
프리젠터는 발표자라는 사전적 의미를 가지고 있지만, MVP의 특성상 진행자라고 하는 것이 조금 더 명확하게 의미를 전달 할 수 있다.
MVC에서는 입력 분석 로직을 컨트롤러가 담당했지만, MVP에서는 이를 뷰에서 담당한다.
입력 분석 로직 담당 변화
smalltalk-80때는 입력 분석 로직이 많이 복잡했으므로 컨트롤러에서 따로 담당했지만, 날이 갈수록 복잡한 입력 분석이 필요없어지면서 사용자 입력은 뷰를 통해서 유입하게 된다. 그러다보니 컨트롤러의 핵심 관심사가 없어졌고 따라서 모델을 감시하고 뷰를 감독하는 프리젠터로 변경되었다.
뷰에서 사용자 입력이 분석되면 프리젠터에게 요청을 전달하고, 프리젠터는 요청에 필요한 데이터를 반환하거나, 모델을 변경하는 등 요청 처리 로직과 UI 논리 로직을 구현한다.
또한 MVC에서 뷰와 컨트롤러는 쌍으로 존재하고 상호 의존했지만, MVP의 뷰는 컨트롤러를 의존 하지 않으며 프리젠터 역시 뷰를 직접 의존하지 않고 뷰의 인터페이스를 의존한다.
이러한 구현 방식은 뷰를 목(Mock)으로 대체할 수 있고, 재사용성도 극대화할 수 있다는 장점이 있다.
MVP의 패시브 뷰
뷰는 패시브 뷰(수동적인 뷰)라는 단어에서도 알 수 있듯이 입력 분석 로직과 프리젠테이션 로직만을 구현하고 모델과 관계를 맺지 않는다.
UI 논리 로직은 프리젠터에서 구현한다. 혼자서는 어떠한 의사 결정도 할 수 없는 매우 수동적인 자세를 취한다.
프리젠터
프리젠터는 뷰를 통해 요청을 받고 뷰와 모델을 사용하여 사용자 요청을 처리 한다.
모델이 옵저버를 통하여 자신의 상태 변화를 통지하면 프리젠터가 모델의 상태 변화를 통지 받아 뷰를 갱신한다.
이는 뷰가 모델의 상태 변화를 통지 받아 적극적으로 UI를 처리하던 MVC와 다른점이다.
MVC에서는 UI 논리 로직이 뷰와 컨트롤러에 산재되어 혼란스러웠다면 패시브 뷰에서는 UI 논리 로직이 프리젠터에 집중되고, 뷰는 프리젠테이션 로직만 구현함으로써 상대적으로 코드가 혼란스럽고 복잡해질 문제가 최소화된다는 장점도 있다.
또한 MVC에서 가지고 있던 뷰와 모델간의 의존성도 제거하였다.
하지만 뷰와 프리젠터간의 결합도가 높아서 프리젠터를 재사용하기 어려운 문제는 가지고 있다.
Presentation Model
Presentation Model은 UI 요소의 상태와 행동을 나타내는 방법을 정의한 아키텍처이다.
이전의 MVC에서는 프리젠테이션의 상태를 관리할 필요가 없었다.
하지만 UI의 인터렉션이 복잡해지면서 색상, 높이, 체크 여부 등 도메인이 아닌 UI 요소의 상태를 관리해야할 필요성이 생기게 되었다.
따라서 도메인 모델을 조합하고 UI 요소의 상태와 행동을 관리하는 로직을 포함한 PM을 만들어 뷰에게 제공함으로써 문제를 해결하였다
PM은 쉽게 말해 컨트롤러를 응용 프로그램 수준에서 추상화 한 것으로, 도메인 데이터를 기반으로 사용자 인터페이스의 전반적인 상태를 제어한다.
뷰는 PM과 관계를 맺고 PM의 메서드들을 호출하여 사용자 요청을 처리한다.
우리가 알고있는 MVVM은 PM에서 파생된 것으로 PM의 아키텍처에 양방향 데이터 바인딩 기술을 접목한 것이 MVVM이라고 할 수 있다.
Web MVC
웹-MVC는 UI 프로그래밍할 때의 MVC와 다르다.
가장 큰 차이점은 상태에 있다. 즉, UI 프로그래밍은 Stateful 하지만, 웹은 Stateless 하다.
웹의 Stateless
현재 웹에서 가장 많이 사용되고 있는 프로토콜인 HTTP는 Stateless 하게 설계되어 있다. 만약 Stateful 하다면 요청자 수 만큼 상태를 관리해야하므로 구현이 복잡하고 서버 확장시에도 걸림돌이 될 것이다. 물론 웹 개발 시 쿠키 또는 세션을 사용하여 상태를 관리하는 경우도 있으나 UI 프로그래밍에 비하면 대체로 간단하게 다룰 수 있다.
애플리케이션 상태를 관리할 필요가 없다보니 상태를 어떻게 관리할 것인지 그리고 UI 요소간 데이터 동기화는 어떻게 할 것인지에 대한 고민이 필요 없다.
때문에 매우 단순하고 이해하기 쉬우며, 이 단순함이 웹을 성공적으로 이끈 원인이기도 하다.
컨트롤러를 통하여 요청이 들어오면 모델을 통해 데이터를 검색해오고 그 데이터를 뷰에 전송해 데이터와 HTML 코드가 조합된 페이지를 반환받는다.
그리고 그 페이지를 요청자에게 다시 돌려주면 클라이언트는 HTML 문서를 응답받게 된다.
UI 프로그래밍의 MVC와 웹-MVC는 해결하고자 하는 문제와 서로 놓여있는 환경이 다르다.
마무리
MVC를 어떤 하나의 형태로 고착화 시키기보단, 사고를 유연하게 하여 현재 각자가 마주하고 있는 문제를 해결할 수 있도록 구현하는 것이 가장 좋은 방법이다.
구현은 정책 또는 프로세스에 따라 그리고 팀 문화에 따라서도 달라질 수 있다.