diff --git "a/\354\261\225\355\204\260_8/\353\260\261\354\247\200\354\227\260.md" "b/\354\261\225\355\204\260_8/\353\260\261\354\247\200\354\227\260.md" new file mode 100644 index 0000000..9665ad9 --- /dev/null +++ "b/\354\261\225\355\204\260_8/\353\260\261\354\247\200\354\227\260.md" @@ -0,0 +1,198 @@ +# CHAPTER 08 자바스크립트 MV\* 패턴 + +애플리케이션 설계의 두 가지 중요한 측면 + +- 객체의 설계 (앞에서 살펴본 패턴) +- 애플리케이션 아키텍처 ([MVC](#1-mvc-패턴), [MVP](#2-mvp-패턴), [MVVM](#3-mvvm-패턴)) + +## 1. MVC 패턴 + +Model-View-Controller + +**관심사의 분리**를 활용하는 아키텍처 디자인 패턴 + +- Model = 비즈니스 데이터 +- View = UI +- Controller = 로직과 사용자 입력 + +### Smalltalk-80의 MVC 패턴 + +#### 목표 + +'분리된 프레젠테이션' 개념을 발전시켜 애플리케이션 로직과 UI 분리 + +#### 설계의 기본 개념 + +애플리케이션의 일부를 분리함으로써 모델을 애플리케이션의 다른 인터페이스에도 재사용 + +#### 특징 + +관찰자 패턴이 포함되어 있음 +Smalltalk-80의 MVC에서 뷰는 모델을 관찰해 모델(= 도메인 데이터)이 바뀔 때마다 뷰가 반응함 +ex. 주식 시장 데이터 기반 애플리케이션 + +### 자바스크립트의 MVC + +3가지 핵심 요소로 구성 + +#### 모델 + +- 애플리케이션 **데이터**를 관리하는 역할 +- 모델이 변경될 때 관찰자에게 변경사항을 알림 +- 갤러리 애플리케이션에서는 '사진'이 모델이며, 모델에는 '설명, 이미지 소스, 추가 메타데이터' 같은 속성이 포함될 수 있음 +- 모델을 컬렉션으로 그룹화하는 기능을 제공하는 경우가 많음 (개별 모델 인스턴스를 직접 관찰할 필요가 없어짐) + +#### 뷰 + +- 모델에 대한 **시각적인 표현**으로, **현재 상태**의 특정 부분만 보여줌 + + - Smalltalk의 뷰는 비트맵을 생성하고 관리하는 역할 + - JavaScript의 뷰는 여러 DOM 요소의 집합을 생성하고 정리하는 역할 + +- **모델을 관찰**하고, 모델에 변화가 생기면 알림을 받아 스스로 업데이트 + + - 모델/컨트롤러에 대한 정보를 제한적으로 갖기 때문에 뷰를 둔하다(dumb)고도 함 + +- 사용자는 뷰와 상호작용 + - 갤러리 애플리케이션의 경우 사진의 메타데이터를 편집할 수 있는 '편집 뷰'를 제공해 모델 편집을 용이하게 함 + - 실제 업데이트는 컨트롤러가 담당 + +#### 템플릿 + +- 뷰와 연관 +- 뷰 객체의 일부 또는 전체를 선언적으로 지정하는 방법이 될 수 있음 +- 뷰를 생성하기 위해 템플릿이 사용될 수 있음 +- **tagged template literals** 같은 최신 템플릿 기법을 통해 동적인 HTML 콘텐츠를 만들 수 있음 + + > styled-components, emotion에서 잘 쓰고 있던 개념이네요😮 + > https://styled-components.com/docs/advanced#tagged-template-literals + > https://emotion.sh/docs/css-prop#string-styles + > https://youtube.com/shorts/zaIWtaQle3o?si=D9_GzgolXgicxb7w + + > 또 다른 활용 사례 (이스케이프 문자) + > https://youtube.com/shorts/w-aeIlS1Qc8?si=D2YxgKARa4cTozfP + > https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/raw + > `String.raw()` 메서드는 템플릿 리터럴의 태그 함수 + > 템플릿 리터럴의 윈시 문자열을 가져오는 예시 + + ```javascript + const filePath = 'C:\Development\profile\aboutme.html'; + console.log(`The file was uploaded from: ${filePath}`); + // output: "The file was uploaded from: C:Developmentprofileaboutme.html" + ``` + + ```javascript + const filePath = String.raw`C:\Development\profile\aboutme.html`; + console.log(`The file was uploaded from: ${filePath}`); + // output: "The file was uploaded from: C:\Development\profile\aboutme.html" + ``` + +#### 컨트롤러 + +- 모델과 뷰 사이의 **중재자** 역할 +- 사용자가 뷰를 조작할 때 모델을 업데이트 +- 사용자 입력에 뷰가 응답할 수 있도록 컨트롤러가 지원하는 것은 **전략 패턴**의 예시이기도 함 + +### MVC를 사용하는 이유는? + +관심사 분리는 기능을 더 간단한 모듈로 나눌 수 있도록 해주며, 다음과 같은 이점 제공 + +- 유지보수의 단순화 : 변경사항이 데이터 중심인지, 단순히 시각적 변경인지 명확하게 구분 가능 +- 모델과 뷰의 분리 : 비즈니스 로직에 대한 단위 테스트를 작성하기 좋음 +- 코드 중복 제거 +- 모듈화를 통해 코어 로직을 담당하는 개발자와 UI를 담당하는 개발자가 동시에 작업 가능 + +### MVC의 또 다른 관점 + +GoF는 MVC를 디자인 패턴으로 언급하지 않고 **UI를 구축하기 위한 클래스의 집합**으로 간주 +GoF의 관점에서 MVC는 **관찰자, 전략, 컴포지트 패턴**의 변형 +프레임워크에서 구현된 방식에 따라 **팩토리, 템플릿 패턴**도 사용될 수 있음 + +## 2. MVP 패턴 + +Model-View-Presenter + +### 모델, 뷰, 프리젠터 + +뷰에 대한 UI 비즈니스 로직을 담당하는 구성 요소가 프리젠터 +MVC와 달리 뷰에서의 이벤트 호출은 프리젠터로 위임 +복잡한 로직을 프리젠터 안에 캡슐화할 수 있어 유지보수에 좋음 + +#### 장점 + +높은 테스트 용이성, 뷰와 모델 간의 명확한 분리 + +#### 단점 + +데이터 바인딩이 지원되지 않기 때문에 작업을 별도로 처리해야 하는 비용 발생 + +### MVP vs MVC + +MVP 패턴이 적합한 경우 + +- 프레젠테이션 로직을 최대한 재사용해야 하는 엔터프라이즈 수준의 애플리케이션 +- 뷰가 매우 복잡하고 사용자와의 상호작용이 많은 애플리케이션 + +## 3. MVVM 패턴 + +Model-View-ViewModel + +MVC와 MVP를 기반으로 하는 패턴 +UI 개발 부분과 비즈니스 로직, 동작 부분을 명확하게 분리 +선언적 데이터 바인딩을 활용해 뷰에 대한 작업을 다른 계층과 분리 +→ 동일한 코드베이스에서 UI 작업과 개발 작업 거의 동시에 진행 가능 + +### 모델 + +다른 패턴들과 마찬가지로 도메인 관련 데이터나 정보 제공 +동작을 다루지 않으며, 정보 형식을 지정하지 않고, 데이터가 브라우저에 어떻게 표현될지에 영향을 미치지 않음 +데이터 형식 지정은 뷰가 담당하고, 동작은 뷰모델에서 캡슐화하여 처리해야 하는 비즈니스 로직으로 간주 + +모델의 역할 중 유일한 예외는 **데이터 유효성 검사** +ex. 입력된 이메일 주소가 정규식을 충족하는지 모델에서 유효성 검사 수행하는 것 허용 + +### 뷰 + +- 수동적 뷰 : 단순히 화면을 출력할 뿐 사용자의 입력을 받아들이지 않음 +- 능동적 뷰 : 데이터 바인딩, 이벤트, 동작들을 포함하고 있어 뷰모델에 대한 이해를 필요로 함 + +### 뷰모델 + +데이터 변환기의 역할을 하는 특수한 컨트롤러 + +- 모델의 정보를 뷰가 사용할 수 있는 형태로 변환 +- 뷰에서 발생한 명령(사용자 조작이나 이벤트)을 모델로 전달 + +UI 계층의 뒤에 뷰모델이 위치함 +뷰모델은 뷰보다 **모델에 더 가깝지만 뷰의 디스플레이 로직 대부분을 처리** +뷰와 뷰모델은 데이터 바인딩과 이벤트를 통해 소통 + +뷰모델은 모델에 대해 전적인 책임을 지고 있음 +데이터 바인딩을 위해 모델 또는 모델의 속성을 가져올 수 있음 +뷰에 제공되는 속성을 가져오거나 조작하기 위한 인터페이스를 포함할 수 있음 + +### 장점 + +- UI와 이를 구동하는 요소를 동시에 개발 가능 +- 뷰를 추상화함으로써 뷰의 뒤에 작성되는 비즈니스 로직의 양을 줄여줌 +- 뷰모델은 이벤트 중심 코드에 비해 단위 테스트가 쉬움 +- 뷰모델은 뷰보다 모델에 가깝기 때문에 UI 자동화나 상호작용에 대한 고려 없이도 테스트 가능 + +### 단점 + +- 단순한 UI의 경우 MVVM은 과도한 구현 +- 데이터 바인딩은 선언적이고 사용하기 편리하지만, 단순히 breakpoint를 설정하는 명령형 코드에 비해 디버깅이 어려움 +- 복잡한 애플리케이션에서는 데이터 바인딩 관리 부담이 커지고, 바인딩 대상 객체보다 바인딩 코드가 무거운 상황이 생길 수 있음 +- 대규모 애플리케이션에서는 미리 뷰모델을 설계하기 어려움 + +## MVC vs MVP vs MVVM + +모두 MVC에서 파생된 패턴 +각 계층이 다른 계층에 대해 갖는 의존성, 계층이 서로 연결된 정도가 다름 + +## MV\* 패턴과 리액트 + +리액트는 MVC 프레임워크가 아님 +기존 MVC처럼 중앙 제어 역할을 하는 컨트롤러 혹은 라우터 기능이 포함되어 있지 않음 +리액트에서는 서버가 브라우저에 '뷰'를 직접 제공하지 않고, '데이터'를 제공함 +리액트와 마찬가지로 Next.js도 MVC 프레임워크는 아니지만, SSR 또는 SSG를 사용하는 경우 MVC와 유사하게 동작