아키텍처가 대체 무엇일까. MVC, MVVM ... 많이 들어는 봤는데 그래서 그게 뭔데? 라고 물어보면 제대로 답을 하지 못했다. 아키텍처가 무엇인지, 프론트엔드에서 주로 사용했던, 그리고 사용하고 있는 아키텍처들을 나름대로 공부하고 간단히 정리해보았다.
시스템의 구조와 구성 요소간에 특정한 규칙을 가지고 데이터를 주고받는 인터페이스를 설계하는 것을 아키텍처라한다. 아키텍처 설계를 하고 개발을 한다면 유지보수하기 좋은 코드로 개발이 될 것이다.
💡 디자인 패턴?
소프트웨어 개발 시 특정 상황에서 자주 발생하는 문제를 해결하는 패턴을 재사용하기 쉽도록 추상화한 것이다.
(예: singleton, observer, abstract, prototype...)
프론트엔드에서 사용하는 아키텍처에는 다음과 같은 것들이 있다.
1. MVC
2. MVVM
3. MVI
기존에 사용되던 아키텍처의 불편한 점들을 개선하기 위해 많은 아키텍처 디자인 패턴들이 나왔다. 네이밍 보다는 왜 이런 아키텍처 패턴들이 나왔는지 흐름을 파악하는 것에 집중하자.
너무나도 유명하고 고전적인 Model-View-Controller 패턴이다.
사용자에게 보여지는 View 화면, 데이터를 다루는 영역인 Model, 사용자로부터 동작을 받아서 처리해주는 Controller로 이루어진 패턴이다.
MVC 세 부분으로 나뉘어진 이유는 다음과 같다.
1. 각자 하는 기능에 따른 분류
2. view / model 간의 의존 관계 최소화
프론트엔드라는 개념이 없던 시절에는 백엔드에서 View 화면까지 모두 만들어 보내주었다. ajax와 jQuery가 생기며 프론트에도 MVC와 비슷하게 적용하는 듯 했으나, event를 연결하는 과정에 반복적인 패턴이 나타는 등 불편한 점을 찾게 되었다.
프론트에는 view와 event가 많고, 복잡한 view-model 사이의 관계를 단순하게 만들고 싶었고, MVC보다 나은 선택지들을 찾게되었다.
Model-View-ViewModel을 줄여 쓴 말이다.
사용자에게 보여지는 View 화면, 데이터를 다루는 영역인 Model, View를 나타내기 위한 데이터 처리를 하는 ViewModel로 이루어져있다.
View를 통해 사용자의 동작이 전달되면 Model로부터 데이터가 ViewModel에 들어오게 되고 그 데이터를 View에게 전달한다. ViewModel과 View는 변경이 생기면 서로를 업데이트 해 주고, 데이터 바인딩(observer 패턴을 통해 뷰와 모델을 양방향 바인딩을 해 주어 데이터를 자동으로 변경해준다.)을 해 준다.
MVVM은 템플릿과 바인딩을 통하여 HTML에 직접 선언하는 방식을 사용한다.
방법만 다를 뿐 angular, react, vue, svelte와 같은 프레임워크들이 MVVM 패턴을 사용한다.
하나의 페이지 안에 여러 모듈이 구성이 되도록 발전함에 따라, 페이지 단위가 아닌 재사용 가능한 작은 단위로 분리하여 조립하는 방식으로 변화하였다. 이것이 Component 방식이다.
또한 비즈니스 로직을 관리하는 Container 컴포넌트와 데이터만 보여주는 Presenter 컴포넌트로 분리하여 관리하는 Container-Present 아키텍처가 만들어진다.
하지만 이것은 하위에 특정 값을 전달하기 위해 사이에 있는 모든 component들이 해당 값을 가지고 있어야 하는 'props drilling' 문제를 유발한다.
계층적 구조로 인하여 props를 통해 데이터를 전달할 때, model 관리가 분산된다는 문제가 생겨, 단방향으로 데이터 흐름을 유지하는 flux 패턴을 제안했다. Redux가 이 패턴을 활용하여 만들어졌다.
view에서 사용자의 동작이 입력되면, dispatcher를 통해 store에 데이터가 저장되고, 다시 view로 전달된다.
이 기점으로 비즈니스 로직(dispatcher-store)과 View를 완전히 분리하여 상태관리의 개념이 생겼다.
View와 Model은 분리하지만, dispatch, reducer 등 복잡한 구조를 가지는 것에 회의적인 입장에서 만들어진 방법이다.
atomic 패턴은 컴포넌트를 잘 관리하기 위한 방법론으로 Atoms - Molecules - Organisms - Templates - Pages 순으로 작은 것을 결합하여 큰 것을 만드는 방법이다. 여기서 개념을 가져온 것인데, flux 패턴보다 간단하게 데이터를 주고받을 수 있다.
Recoil, jotai, Svelte Store, Vue Composition 등이 이 패턴을 활용하였다.
필요한 부분의 공통 부모 컴포넌트에 context를 두고 데이터를 제공받는 방식이다. react에서 기본으로 제공한다.
(글쓴이의 개인적인 입장으로는 위의 flux, atomic과는 다른 느낌이라 대체가 되는 것 같진 않다.)
위의 부분을 MVI 공통으로 묶고 먼저 정리한 이유는, 모두 MVI 아키텍처로 설명이 되며, MVI보다 위의 개념들이 우선적으로 나왔기 때문이다.
MVI는 Model-View-Intent를 줄여 쓴 말이다.
계속 사용되던 Model과 View에 사용자의 의도를 파악하는 Intent가 추가되었다.
MVI는 다음과 같은 특징을 가진다.
1. 단방향 데이터이다.
2. 데이터가 전역으로 구성된다.
3. View는 Model에 의존하지만, 비즈니스 로직에 의존하지 않기에 화면 변화에 유연하다. => 테스트가 용이함.
4. View의 생명주기와 무관하게 상태가 일관성있다.
정리를 하면서 프론트엔드 생태계의 아키텍처 설계가 발전하는 방향에 대해 자세하게 알 수 있었다. 대략적으로만 알고있던 내용들에 대해 알아가는 시간이 되었고, 배운게 참 많았다.
프론트엔드에서 많이 사용하는 상태관리라는 개념이 왜 나오게 되었고, 어떤 특징이 있는지, 어떤 방향으로 개발을 해야 잘 적용을 할 수 있는지 제대로 알게 된 것 같다.
간단하게 정리하느라 내용이 많이 빠졌는데, 상세하게 알고 싶은 사람은 테오님의 게시글이 정리가 잘 되어있으니 궁금하면 가서 확인해보면 좋을 것 같다.
💡 Reference.
프론트엔드에서 MV* 아키텍쳐란 무엇인가요?
프론트엔드에서 비즈니스 로직과 뷰 로직 분리하기 (feat. MVI 아키텍쳐)
프론트엔드에서 MVC보다 더 많이 쓰이는 패턴은 ?
[디자인패턴] MVC, MVP, MVVM 비교
프론트엔드 아키텍처의 가장 최근 트렌드는?
[React] Flux 패턴 알아보기