08장-자바스크립트-MV*-패턴
8.1 MVC 패턴
애플리케이션의 구조를 개선하기 위해 관심사의 분리를 활용하는 아키텍처 디자인 패턴입니다.
비즈니스 데이터(모델), UI(뷰)를 분리하고 컨트롤러가 사용자 입력을 관리하는 구조입니다.
8.1.1 Smalltalk-80의 MVC 패턴
MVC 패턴이 나온 시절, GUI라는 것이 존재하지 않았습니다. 때문에 사용자의 화면에 렌더링되는 프레젠테이션 객체 사이를 구분하기 위해 '분리된 프레젠테이션'이라는 개념이 유명해졌습니다.
Smalltalk-80에서 구현된 MVC는 '분리된 프레젠테이션' 개념을 발전시켜 애플리케이션의 로직과 UI를 분리하는 것을 목표로 했습니다.
Smalltalk-80의 아키텍처에는 다음과 같은 특징이 있습니다.
모델: 도메인 관련 데이터를 표현했으며, UI에 대해서는 관여하지 않았습니다.
뷰: 모델의 현재 상태를 표현했습니다. 관찰자 패턴을 사용해 모델이 변경되거나 수정될 때마다 뷰가 알아차릴 수 있도록 구현했습니다.
컨트롤러: 키보드 입력이나 클릭 같은 사용자의 상호작용을 처리하며, 뷰에 무엇을 보여줄지와 입력을 어떻게 처리할지를 결정하는 역할을 하였습니다.
8.2 자바스크립트의 MVC
현재 자바스크립트는 MVC를 지원하는 여러 프레임워크를 갖추고 있어, 쉽게 MVC 패턴을 사용해 볼 수 있습니다.
8.2.1 모델
모델은 애플리케이션의 데이터를 관리하는 역할을 합니다.
UI나 프레젠테이션 계층은 담당하지 않고, 애플리케이션에 필요한 고유 데이터 형식을 나타냅니다.
예를 들어 쇼핑몰 애플리케이션을 생각해 봅시다. 쇼핑몰에서는 고유한 도메인 관련 데이터를 보여주므로 '쇼핑 아이템'이 독자적인 모델이 될 수 있습니다. 이러한 모델에는 가격, 이미지, 소스 등과 같은 관련 속성이 포함될 수 있습니다.
이러한 모델들은 인스턴스로 저장되어 재사용도 용이합니다.
MVC/MV* 프레임워크에서는 모델을 컬렉션으로 그룹화하는 기능을 제공하는 경우가 많습니다. 모델을 그룹으로 관리하면 그룹 내의 특정 모델이 변경될 때 그룹의 알림을 기반으로 애플리케이션 로직을 작성할 수 있습니다.
과거 MVC 자료에서는 모델이 상태를 관리한다고 언급된 부분이 있습니다. 자바스크립트 애플리케이션에서는 '상태'라는 용어가 다르게 해석되는데, 사용자의 화면에 특정 시점에 나타나는 '상태'(뷰)를 나타냅니다.
8.2.2 뷰
뷰는 모델에 대한 시각적인 표현으로, 현재 상태의 특정 부분만 보여줍니다.
8.2.3 템플릿
문자열의 연결을 통해 큰 HTML 마크업 블록을 수동으로 생성하는 것은 성능적으로 나쁜 작업으로 오랫동안 입증되어 왔습니다. (ex: document.write)
최신 자바스크립트 템플릿 솔루션은 ES6의 강력한 기능인 태그 템플릿 리터럴의 사용으로 방향을 전환하였습니다.
태그 템플릿 리터럴과 같은 최신 템플릿 기법은 자바스크립트 애플리케이션에서 동적인 HTML 콘텐츠를 깔끔하고, 효율적이며, 유지보수가 용이한 방식으로 만들 수 있도록 해줍니다. (ex: 리액트)
8.2.4 컨트롤러
모델과 뷰 사이의 중재자 역할을 하며, 일반적으로 사용자가 뷰를 조작할 때 모델을 업데이트하는 역할을 합니다.
8.3 MVC를 사용하는 이유는?
MVC에서의 관심사 분리는 애플리케이션의 기능을 더 간단한 모듈로 나눌 수 있도록 해주며, 다음과 같은 이점을 제공합니다.
유지보수의 단순화
모델과 뷰의 분리: 비즈니스 로직에 대한 단위 테스트의 작성이 간단해 집니다.
애플리케이션 전반에서 코드 중복이 제거됩니다.
애플리케이션의 규모와 역할의 분리 정도에 따라 코어 로직을 담당하는 개발자와 UI 작업을 담당하는 개발자가 동시에 작업할 수 있습니다.
8.6 MVP 패턴
MVC 디자인 패턴의 파생으로 처음 등장하였습니다.
8.6.1 모델, 뷰, 프리젠터
MVP에서 P는 프리젠터(Presenter)를 의미합니다. 뷰에 대한 UI 비즈니스 로직을 담당하는 구성 요소입니다. MVC와 달리 뷰에서의 이벤트 호출은 프리젠터로 위임됩니다.
MVP는 주로 '둔한' 수동형 뷰를 활용하는 구현 방식이 널리 사용됩니다. 수동형 뷰는 로직을 거의 가지고 있지 않습니다. MVC와 MVP는 역할이 다르기 때문에 구분됩니다.
P는 모델을 관찰하고 변경될 때 뷰를 업데이트 하는데 이는 MVC에서 컨트롤러가 담당하던 역할입니다.
8.6.2 MVC vs MVP
MVP는 일반적으로 프레젠테이션 로직을 최대한 재사용해야하는 엔터프라이즈 수준의 애플리케이션에서 사용됩니다.뷰가 복잡하고 상호작용이 많은 애플리케이션에서는 MVC가 적합하지 않을 수 있습니다. 이런 경우 MVP를 사용하면 로직을 프리젠터 안에 캡슐화하여 유지보수를 간단하게 만들 수 있습니다.
MVC와 MVP 간의 차이점은 대부분 의미론적인 수준이므로, MVC에 존재하는 근본적인 문제점들은 MVP에도 동일하게 존재할 가능성이 큽니다.
8.7 MVVM 패턴
이 패턴은 MVC와 MVP를 기반으로 하며, 애플리케이션의 UI 개발과 비즈니스 로직, 동작 부분을 명확히 분리합니다. 따라서 동일한 코드베이스에서 UI 작업과 개발 작업을 동시에 진행할 수 있습니다.
8.7.4 뷰모델
뷰모델은 데이터 변환기의 역할을 하는 특수한 컨트롤러로 볼 수 있습니다. 모델의 정보를 뷰가 사용할 수 있는 형태로 변환하고, 뷰에서 발생한 명령을 모델로 전달합니다.
이러한 관점에서 뷰모델은 뷰라기보다는 모델에 더 가깝다고 볼 수 있습니다.
8.10 최신 MV* 모델
Backbone, KnockoutJS와 같이 초기 MVC와 MVVM을 구현하는 데 사용되었던 프레임워크는 더 이상 인기가 없거나 업데이트가 되지 않습니다.
Vue.js의 경우 공식적으로 MVVM 패턴이라고 주장합니다.
8.10.1 MV*패턴과 리액트
리액트는 MVC 프레임워크가 아닙니다 UI 구축을 위한 자바스크립트 라이브러리이며, SPA 개발에 주로 사용됩니다.
리액트는 선언형 프로그래밍 방식을 따릅니다. 개발자가 원하는 상태를 기술하고, 리액트는 상태를 기반으로 적절한 뷰를 렌더링 합니다.
리액트가 MVC 디자인 패턴으로 사용되지 않는 이유는 서버가 브라우저에 직접적인 '뷰'가 아니라 '데이터'를 제공하기 때문입니다.
Next.js는 리액트를 기반으로 만들어진 프레임워크로 서버 사이드 렌더링을 쉽게 구현할 수 있도록 도와줍니다.
SSR 또는 SSG를 사용하는 경우 MVC와 유사한 패턴으로 동작할 수 있습니다. Next.js가 백엔드의 역할을 하며, 뷰를 사전 렌더링하면, 이후부터는 리액트의 반응형 기능을 통해 뷰를 동적으로 업데이트 함으로써 전통적인 MVC 형태로 동작합니다.