MVC (jQuery)
- View (화면)
- 웹 프론트에서 최종적으로 HTML과 CSS로 만들어지는 결과물을 의미함
- 즉 최종 사용자에게 무엇을 UI로 보여주기위한 역할
- Model (데이터)
- 데이터를 다루는 영역
- Model의 범주
- javascript의 Object
- 서버의 API로 받는 데이터
- Controller (컨트롤러)
- Model의 데이터를 받아 View가 화면에 그리고 다시 유저의 동작을 받아 Model을 변경하게 해주는 것이 Controller의 역할
- 즉 Model과 View사이의 중간 다리 역할.
MVC로 분리한 이유
- 화면을 다루는 문제와 데이터를 다루는 문제의 성격이 달라서 분리하기 위해서
- Model과 View간의 의존관계를 최소화 해서 화면의 수정이 데이터수정에 영향을 미치지 않고 데이터 수정이 화면의 수정에 영향을 미치지 않고자 하려고
jQuery시절의 MVC 아키텍쳐
- ajax로 부터 받는 데이터를 Model로 취급
- HTML과 CSS로 만들어지는 화면을 View로 취급합
- javascript가 중간에서 서버의 데이터를 받아서 화면을 바꾸고 이벤트를 처리해서 서버에 데이터를 전달하는 Controller의 역할을 수행
MVVM (Angular, React, Vue)
MVC의 니즈
- 데이터를 찾아서 데이터를 바꾸고 데이터를 수정하고 이벤트를 연결하고 이벤트를 수정하는 해야함 ⇒ 피곤하고 반복적인 패턴
- 직접 DOM을 건드리는거 보다 템플릿과 같은 선언적인 방식으로 변경하고 싶음
해결방안
- Model이 변하면 View를 수정하고 View에서 이벤트를 받아서 Model를 변경한다는 Controller의 역할은 그대로 인데 이를 구현하는 방식이 jQuery와 같은 DOM 조작에서 템플릿과 바인딩을 통한 선언적인 방법으로 변하게 됨.
- DOM을 가져오고 조작하는 로직이 사라지고 이를 프레임워크가 대신 담당하게 되었고 데이터와 비즈니스 로직을 만들어 프레임워크에 전달하면 알아서 그려줌.
- View를 그리는 Model만 다루게 되었다는 의미로 ViewModel이라고 부르며 이 방식을 MVVM이라고 함.
- 기존 MVC에서 컨트롤러의 반복적인 기능이 선언적인 방식으로 개선이 되고 Model과 View의 관점을 분리하려 하지 않고 하나의 템플릿으로 관리하려는 방식으로 발전.
MVC에서 MVVM으로 오면서 달라진 부분
- 컨트롤러의 반복적인 기능이 선언적인 방식으로 개선 됨
- Model과 View의 관점을 분리하려 하지 않고 하나의 템플릿으로 관리하려는 방식으로 발전.
- 기존에는 class나 id등으로 간접적으로 HTML에 접근하려고 했다면 이제는 직접적으로 HTML에 접근하는 방법으로 확장.
변화
- 생산성 증가 : 웹의 DOM API를 잘 다루지 못하더라도 비지니스로직에만 집중한다면 금방 금방 서비스를 만들 수 있음
- 웹 서비스가 발전하게 되면서 이제는 하나의 Page단위가 아니라 Page안에 여러가지 모듈이 있고 Modal이나 여러 화면들이 하나의 화면에서 구성이 될 수 있도록 발전
(컴포넌트 화)
- MVVM이 이제 화면단위가 아니라 조금 더 작게 재사용 할 수 있는 단위로 만들어서 조립을 하는 방식으로 발전
Component - Presenter
처음 이 패턴을 소개한 Dan Abramov는 2019년 기준으로 현재는 이 패턴을 사용하지 말라고 언급하고 있다. (출처)
2019년 업데이트 : 이 아티클을 예전에 썼었고 이제는 내 관점이 달라졌다. 특히 나는 더 이상 이런 방식으로 component를 나누는 것을 추천하지 않는다.만약 자연스럽게 이 패턴의 필요성을 찾는다면 이 패턴은 유용할 것이다. 하지만 어떤 필요성 없이, 독단적으로 이 패턴이 강제되고 있음을 여러번 보았다. 내가 이 패턴을 유용하게 보았던 주된 이유는 이 패턴이 다른 관점의 컴포넌트로부터 복잡하고 stateful한 로직을 분리하게 해주었기 때문이다. 임의의 분리없이 Hook은 똑같은 일을 할 수 있다. 이 글은 역사적인 이유로 보길 바라며 심각하게 받아들이지 마라.
필요했던 이유
- 리액트의 컴포넌트는 상태, DOM, 이벤트 등 모두 관리할 수 있음. 리액트에서 자유롭게 컴포넌트를 활용할 수 있다는 의미일수 있지만 컴포넌트간의 의존도가 높아졌을 때 코드 재사용이 불가능 해진다는 단점 존재
- 컴포넌트 내에서도 추가적으로 레이어를 나눠 의존도를 낮출 필요성을 느낌
- Hook의 등장 전이기 때문에 비즈니스 로직과 View를 분리 하기 위해 등장
개념
- **presentational 컴포넌트**
- html, css, presentational component만 사용 가능
- app에 대해 완전히 몰라야한다. => 다른 app에서도 이 component를 사용할 수 있을지 스스로에게 물어보자
- presentational과 container 모두를 내부적으로 가질 수 있다.
- 작은 레고 블럭처럼 가능한 작게 만들어야 한다.
- 상태를 가질 수 있지만 UI에 관련된 상태만 가질 수 있다.
- 필요 시 visual을 바꾸는 props를 받을 수 있어야 한다.
- **container 컴포넌트**
- 어떠한 동작을 할 것인가에 대해 책임진다.
- 절대로 DOM 마크업 구조나 스타일을 가져서는 안된다.
- presentational과 container 모두를 내부적으로 가질 수 있다.
- 주로 상태를 가지고 있다.
- side effects를 만들 수 있다. ex) db에 CRUD를 요청
- props를 자유롭게 받을 수 있다.
장점
- 재사용성 ↑
- 로직이 포함되어 있지 않은 presentational 컴포넌트는 그저 받아온 정보를 화면에 표현할 뿐이므로presentational 컴포넌트가 다른 컴포넌트를 알 필요가 없다는 점에서 의존도가 낮아 다양한 container 컴포넌트와 조합하여 재사용할 수 있음.
- 가독성 ↑
- 기능과 UI가 명확히 분리되므로 개발자 입장에서 코드 구조에 대한 이해가 쉬워짐.
- 마크업 작업 능률 ↑
- presentational 컴포넌트는 layout 컴포넌트로 활용하여 반복되는 마크업 작업을 줄여 줄 수 있음.
단점
- 컴포넌트 구조가 복잡해짐에 따라 하위에 특정 값을 전달하기 위해서는 중간 레벨에 있는 컴포넌트들은 전부 그 props를 가지고 있어야 하는 문제가 발생