FE 디자인 패턴
MVC (Model-View-Controller)
사용자는 View를 통해 명령을 입력합니다. Controller가 Input을 처리해 Model에 전달합니다. Model은 명령에 따라 View를 업데이트합니다.
Model: 데이터와 로직 관리- View: 레이아웃과 화면 처리
- Controller: Model과 View에 명령 라우팅 (Model과 View 중개)
장점
- 동시다발적 개발 가능
- 높은 응집도
- 개발용이성 (책임 구분으로 )
단점
- Controller가 다수의 View를 선택할 수 있어, 하는 일이 너무 많아질 수 있음
- 코드 일관성 유지에 노력이 필요
- View와 Model 사이 의존성 높음 (규모 커질수록 유지보수 어려워짐)
MVP (Model-View-Presenter)
화면과 로직을 분리한 디자인 패턴입니다. 사용자는 뷰를 통해 명령을 입력합니다. Presenter가 input을 받아 Model에 전달합니다. 모델에서 명령 처리 후 Presenter가 View를 업데이트합니다.
- Model: 데이터와 로직 관리
- View: 레이아웃과 화면 처리
- Presenter: Model과 View 중개, View와 직접 연결되며 1:1 관계
장점
- 좋은 확장성 (Model과 View 간 의존성 해결)
- 유닛테스트시 테스트코드 작성이 비교적 용이함
- UI, Data 각 파트가 나눠져 있어, 동시 코딩이 용이함
단점
- 애플리케이션이 복잡할수록 View와 Presenter 간 의존성 강해짐
- Presenter에 로직 집중되는 경향이 있음
- View와 Presenter가 1:1로 매칭돼, View가 많아질수록 Presenter도 많아
MVVM (Model-View-ViewModel)
VIew와 ViewModel을 양방향 데이터 바인딩하는 디자인 패턴입니다. 양방향 데이터 바인딩이란 View의 데이터와 ViewModel의 데이터를 엮어, 한 쪽이 갱신되면 다른 한쪽도 갱신하는 구조를 말합니다.
- Model: 도메인 특화 데이터 처리
- View: 레이아웃과 화면 처리
- ViewModel: 상태와 연산 View의 실제 논리 및 데이터 흐름 담당
장점
- View와 Model 간 의존성 없음
- View와 ViewModel 간 의존성 없음 (Command 패턴과 Data Binding 사용)
단점
- ViewModel 설계가 어려
Container-Presenter
컴포넌트의 레이아웃과 로직을 분리하는 디자인 패턴입니다.
장점
- 관심사 분리 (기능과 UI 분리로 인해 코드 구조 이해가 쉽고 유지보수가 용이함)
- 높은 재사용성 (Presentor 컴포넌트는 의존성 갖지 않아 재사용이 용이함)
단점
- 필요 이상으로 패턴 강제하는 현상 있음
- Hooks 통해 로직 분리 가능 (Hooks 사용시 로직 재사용도 가능)
Flux
MVC 모델의 양방향 데이터 흐름 단점을 보완하기 위해 고안된 단방향 디자인 패턴입니다. 데이터 흐름이 항상 Dispatcher → Store → View → Action → Dispatcher → … 순으로 이뤄집니다.
- Dispatcher :
- Flux의 데이터 흐름을 관리
- Action 발생시, 전달된 Action을 확인 후 콜백함수 실행해 Store로 전달
- Store:
- 어플리케이션의 상태변경 결정
- 콜백 함수 통해 Dispatcher로부터 데이터 수신
- Store 변경되면 View에 변경된 사실 전달
- View:
- 레이아웃과 화면 처리
- 자식 View로 데이터 보내는 View 컨트롤러 역할도 수행
- Action:
- Dispatcher에서 콜백 함수 실행 시 전달되는 인수 객체
- 대체로 Action creator에서 만들어
장점
- 오류 발생 지점 착기가 용이함
- 구조 흐름 파악이 용이함
Atomic
컴포넌트를 기능의 단위로 나눈 디자인 패턴입니다. Atoms, Molecules, Organisms, Templates, Pages의 다섯 단계로 디자인을 나눠 구성합니다. 간단한 문법으로 컴포넌트 외부에서 공통의 데이터를 Set, Get할 수 있도록 합니다.
장점
- 높은 UI 재사용성
단점
- 초기 디자인 시스템 구축 비용이 많이 필요함
- props drilling issue
참고
RIDI (Atomic + Container-Presenter)
컴포넌트를 세 단계로 나눠 props drilling issue 예방
- atom: 한 가지 기능을 담당하는 최소 단위 컴포넌트 (버튼, 체크박스 등)
- block: atom의 조합으로 이뤄진 pages의 하위 컴포넌트
- pages: 각 화면 컴퍼넌트
각 pages는 Container와 Presenter를 분리
디렉토리 구조
src/
components/
atoms/
blocks/
pages/
Home/
index.tsx
Home.tsx
styles.ts
hocs/
hooks/ 개인적으로 UI 작업시 주로 styled-components를 사용한다. styled-components는 작은 단위의 UI부터 블럭을 쌓아올리는 것처럼 구축해간다는 설계 철학을 갖고 있기 때문에 atomic 디자인과 잘 어울릴 것 같다. 리디북스는 style 파일도 분리했지만 styled-components를 사용한다면 같은 파일에 통합해서 작성하게 좀 더 어울릴 듯 하다.