프론트 아키텍처 흐름
MVC
- Model - View -Controller로 나눈 아키텍처
- Model
- 컨트롤러가 호출했을때, 요청에 맞는 역할을 수행한다.
비즈니스 로직을 구현하는 영역
으로 응용프로그램에서 데이터를 처리하는 부분 - 뷰나 컨트롤러에 대해서 어떤 정보도 알지 말아야한다.
- 컨트롤러가 호출했을때, 요청에 맞는 역할을 수행한다.
- Controller
- 클라이언트의 요청을 받았을 때, 그 요청에 대해 실제 업무를 수행하는 모델컴포넌트를 호출한다. 또한 클라이언트가 보낸 데이터가 있다면, 모델에 전달하기 쉽게 데이터를 가공한다.
- 모델이 업무를 마치면 그 결과를 뷰에게 전달한다.
- 모델이나 뷰에 대해 알고 있어야 하며, 둘의 변경을 모니터링해야한다.
View
컨트롤러로부터 받은 모델의 결과값을 가지고, 사용자에게 출력할 화면을 만드는 일을 한다.
만들어진 화면을 컨트롤러로 다시 보내고, 컨트롤러는 이를 웹 브라우저에 전송하여 웹 브라우저가 출력하게 한다.
모델과 컨트롤러에 대해 몰라야한다.
- 단점 : jquery로 작업할 떄 반복되는 부분이 나타남
MVVM
- Model - View - View Model 의 약자로, 프로그램의 비지니스 로직과 프레젠테이션 로직을 UI로 명확하게 분리하는 패턴.
- MVC에서 jquery로 작업할 떄 나타나는 반복되는 부분을 줄이기 위해 등장
구성요소
Model : 데이터를 보관하고 있는 부분으로, 데이터를 불러오거나 업데이트하는 비즈니스 로직이 있음.
- View Model : Model에 데이터를 요청하고 가공함. 비지니스 로직을 처리. View로부터 입력을 받아 적절한 처리를 함
- MVC에서 Controller는 View에서 데이터를 요청할 때마다 기능을 반복적으로 수행했다면, View Model은 View와 데이터 바인딩이 되어있다. 따라서 Model에서 데이터가 변경되면 View에서도 자동으로 변경된다.
- View : UI 담당. UI에 연관된 로직만 수행한다. 필요한 데이터는 View Model과 data binding을 통해 얻는다. 사용자의 입력을 VM으로 전달.
특징
- View와 ViewModel이 n : 1 관계이다. 하나의 View Model에 여러 View가 결합이 가능하여 View Model의 재사용성이 높다.
장점
데이터를 관리하는 로직과 UI로직을 깔끔하게 분리하여 유지보수에 용이해짐.
코드의 재사용성을 개선
UI 디자이너와 개발자가 쉽게 협업할 수 있는 디자인 패턴
단점
- View Model의 설계가 쉽지 않다.
- 상태 끌어올리기, Props drilling 문제가 있음.
Container- Presenter 패턴
- 컴포넌트를 재사용하기 위해선, 컴포넌트에 비즈니스로직에 포함되어선 안됨.
- 따라서 비즈니스 로직를 관장하는 컴포넌트를 container라고 하고, 화면만 그리는 컴포넌트를 presenter라고 나눔
- 단점 : props drilling
FLUX 패턴과 Redux
props drilling을 해결. view에서 액션을 디스패치하면 store에서 데이터를 변경하고 다시 뷰로 전달하는 단방향 흐름을 갖는 패턴.
데이터 흐름 : Stores -> view -> action -> dispatcher-> Stores
- 단방향 데이터 흐름을 가져 이해하기가 쉽다.
- Redux 패턴 : Store가 하나이고, dispatcher 대신 리듀서를 사용한다.
- 루트 리듀서 : 서브 리듀서를 관리하고, 액션을 서브 리듀서로 보냄. 서브 리듀서로부터 업데이트 된 상태 객체를 받고 store로 보냄.
- 서브 리듀서 : 이전 상태를 변경하지 않고 복사해서 변경한다. 이후 상태 객체를 업데이트하고 루트 리듀서에게 돌려줌.
redux : flux 패턴을 이용한 구현체.
- 컴포넌트 트리 외부에 store가 저장하여 이 store에서 상태를 저장함. 그리고 컴포넌트들은 이 store에 들어있는 상태를 사용하거나 업데이트함.
장점 : props drilling을 해결. 거대한 view와 상태관리인 model을 나눔
단점 : redux는 보일러플레이트가 많다.
observer-observable 패턴
- props drilling을 해결. flux 처럼 거대한 view와 상태관리인 model을 나누는 관점은 동일
- 복잡한 dispatch와 action을 배제하고, 값이 바뀌면 바뀐 값을 모두에게 전달한다는 개념.
- 주로 RxJS 사용
- MVI 패턴
- flux 패턴의 dispatch, action, update의 인터페이스를 모두 observable을 이용한 스트림의 하나의 방식으로 만들어 비동기 문제 해결, 복잡함을 해소한 하나의 인터페이스로 만들었다.
MVI 아키텍쳐
Model - View - Intent
사용자가 다른 동작을 했는데, 실제로는 같은 데이터의 변화를 의미하는 경우가 있다. 예를들어, 키보드로 위 버튼을 누른 것과, 마우스로 + 버튼을 클릭한 것은 같은 데이터의 변화를 의미할 수 있다.
이떄 우리는 비즈니스 로직을 두 가지 레이어로 나눌 수 있다.
- 사용자가 View를 통해서 전달한 UI Event를 어떠한 데이터 변화를 하게 할지 전달하는 역할
- 전달받은 요청에 따라서 적절히 데이터를 변화하는 역할
여기서 1번을 Intent라 하고, 2번을 Model이라고 정의하면 MVI 모델이 생긴다.
MVI의 특징
MVI 아키텍쳐의 특징은, MVC, MVVM과 다르게 하나의 컴포넌트가 아니라 앱 전체에 적용된다는 점이다. 그래서 전체적으로 데이터의 방향성이 단방향으로 연결되며, 데이터가 전역적으로 구성되는 것이 특징이다. View는 모델에 의존적이지만, 비즈니스 로직은 View와의 의존성이 없기 때문에 화면변화에 유연하며, 별도로 테스트하기 쉽다. 또한 컴포넌트 간 데이터 통신에 의존하지 않기에 일관성있는 상태를 유지하기도 용이하다.
- 데이터가 단방향으로 순환한다 -> 데이터의 흐름을 이해하고 디버깅하기 쉬워진다.
- 비즈니스 로직이 View에 의존하지 않다 -> UI 변화 요구사항에 유연하게 대응할 수 있다.
- View의 생명주기와 무관하게 일관성 있는 상태를 갖는다. -> 컴포넌트 생명주기에 따른 상태 동기화 문제를 해결한다.
이를 통해 View에서는 Model로부터 데이터를 조회하는 Query와 데이터를 변화시키는 Command를 언제든 조립해서 사용(CQRS 패턴)할 수 있다. 또한 View는 비즈니스 로직에 의존적이지만, View끼리는 느슨하게 결합하여 UI 요구사항 변화에 긴밀하게 대응할 수 있다.
현재 프론트 아키텍처의 방향성
context와 hook, props 상속
- props drilling만 문제라면 props만 새로 뚫지 않도록 하여 해결하는 방법.
- React의 기본 기능인 Context API를 사용
atomic 패턴 (recoil)
- view-model은 분리하되 action-dispatch-reducer 와 같은 복잡한 구조 말고, 간단한 문법으로 동작하도록하자.
컴포넌트 관리를 위한 방법론. View를 원자로 나누고 분자, 유기체, 템플릿, 페이지 순으로 결합하여 큰 단위의 View를 그리는 방법.
- Recoil : Redux보다 간단한 문법으로 컴포넌트 외부에서 공통의 set, get을 할 수 있게 하면서 동시에 동기화할 수 있게 함.
- Atoms : 작은 store 개념
- Selector : 다른 atom이나 selector를 입력으로 받고, 상위의 atoms, selector가 업데이트되면 하위의 selector 함수도 다시 실행되며 컴포넌트들도 리렌더링 된다.
react-query
- 서버를 하나의 model로 보고, react를 view로 보는 관점.
출처
https://yozm.wishket.com/magazine/detail/1663/
https://velog.io/@teo/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%97%90%EC%84%9C-MV-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94#mvvm-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90—angular-react-vue