Search
🌍

bc1_2. title: 컴포넌트 구조에서 모델-뷰-컨트롤(‣) 패턴을 어기고 양방향 바인딩을 이용하다 보니, 프로퍼티 내려꽂기(Props drilling) 문제와 이벤트 버스(Event bus)로 주고받는 데이터의 추적이 어려워져 복잡성이 배가 되었다. 이러한 복잡성을 덜기 위해 중앙집중식으로 상태를 관리하는 디자인 패턴이 등장했고 그것이 플럭스(‣)패턴이다.

생성
🚀 prev note
🚀 next note
♻️ next note
14 more properties
컴포넌트 단위로 웹 페이지를 만들어나가는 뷰(Vue)(from2)나 리액트(React)(from3)같은 프레임워크들에서는 상위 프로퍼티와 하위 프로퍼티가 트리식으로 정리된다. 이렇게 트리식으로 정리된다는 이야기는 프로퍼티 내려꽂기(Props drilling) 문제(참고1)가 발생하기 쉽다는 것을 의미한다.
그림(참고5), 벌써부터 어지럽다.
이를 해결하기 위해 이벤트 버스(Event bus)같은 방법을 도입하곤 하지만(참고2) 이 방법에도 문제가 있다. 이벤트버스에 무슨 문제가 있는지를 이해하기 위해 이벤트버스를 이용해 컴포넌트들 사이의 정보를 어떻게 주고받을 수 있는지 간단히 알아보자. 아래 스크립트는 어떤 컴포넌트에서 이벤트가 종료된 다음 발생하는 트리거이다.
위와 같은 트리거를 감지하려면 아래와 같은 구독자를 생성해야 한다.
// 컴포넌트 B mounted() { EventBus.$on('isButtonClicked', (state) => { this.isButtonEnabled = !state }) }
JavaScript
복사
이러한 이벤트가 많아지면 많아질수록 발행자와 구독자가 수많은 컴포넌트들 사이를 가로지를 것이다. 그렇게 되면 이벤트의 선후관계는 모두 사라져 버리고 의존관계 추적이 어려운 정신없는 소스코드가 되고 말 것이다. 이렇게 정신없이 꼬여버린 상황에서 어디서는 전달받은 값을 함부로 바꾸고 있고, 어디서는 값이 바뀌는지도 모르는 채 읽고 있다면 위험하다.
그림(참고6), 추적되지 않는 컴포넌트 간 의존관계. 하나의 데이터를 다양한 컴포넌트가 읽고 쓰는 일이 많다면 어떤 이벤트가 먼저 발생했는지 추적되지 않는 문제가 발생할 수 있다.
페이스북은 이러한 문제를 해결하기 위해 컴포넌트 사이 통신을 할 때 반드시 중앙 저장소를 통해 거쳐가는 데이터 흐름을 만들어 데이터 흐름의 형태를 강제하고 추적할 필요가 있다고 보았다. 이러한 아이디어를 실천할 방법을 플럭스(Flux) 패턴이라고 부르며 이 패턴 구현을 도와주는 라이브러리 리덕스(redux)를 출시했다(참고3).
플럭스(Flux) 패턴
플럭스 패턴에서는 컴포넌트에서 다른 컴포넌트로 데이터를 갱신해 보내고 싶을 때에는 반드시 액션(Action)을 사용해서 중앙 저장소에 있는 값을 변경하도록 강제하도록 했다. 액션을 사용하면 변경사항이 커밋된다고 표현한다. 이는 라이브러리단에서 변경이 추적되고 있음을 내포한다(참고9:정확히는 action이 아니라 mutation 이라는 단계가 포함되어 있지만, pinia 같은 경우에는 mutation 없이 action만으로도 추적한다. 본질은 action이라는 통일된 API 를 사용함으로써 추적 가능성을 확보한 것이다). 다른 컴포넌트에서는 미리 정의되어 있는 getter 메서드를 사용하도록 했다.
프레임워크 뷰(Vue)에는 리덕스 라이브러리로부터 영향을 받은 상태 관리자 Vuex가 있다. Vuex 저장소를 사용하면 반드시 지정된 방법으로만 저장소의 값을 편집하도록 강제당한다(참고8). 대신, Vuex 저장소는 어떻게 값이 편집되었는지 깃헙 소스코드를 커밋하듯 관리하고 추적해 준다.
많은 사람들이 MVC 구조나 컴포넌트 구조의 대안으로 Flux 구조가 태동했다고 설명하곤 하지만, 모델-뷰-컨트롤러(‣ Model-View-Controller (MVC)) 구조, Flux, 컴포넌트 구조는 배타적인 개념이 아니라는 것을 유념해야 한다. 우리는 앞서(from4) 우선 컴포넌트 구조에서 MVC가 나타날 수 있음을 살폈다. MVC 구조를 엄밀하게 지켰다면, 뷰(View)가 모델(Model)을 직접적으로 갱신하는 일은 일어나지 않는다. 뷰(View)가 모델(Model)을 직접적으로 갱신하는 상황은 프론트엔드 프레임워크의 기능, 특히 양방향 바인딩에 의해 일어난다(from5). 무작정 플럭스(Flux)패턴 구현을 돕는 복잡한 저장소를 들이밀기 전에 양방향 데이터 바인딩이 걸려 있는 요소들을 살펴보며 양방향 바인딩이 정말 꼭 필요한 상황이 맞는지, 컴포넌트 내부의 데이터 흐름은 정말 지금이 최선인지부터 고민해 볼 필요가 있다. MVC를 잘 준수했더라면 Flux는 복잡한 컴포넌트 구조에서 데이터를 중앙집중화된 방식으로 저장하는 방법에 대한 솔루션일 뿐이다.
컴포넌트 구조에서 모델-뷰-컨트롤 패턴을 어기고 양방향 바인딩을 이용하다 보니, 프로퍼티 내려꽂기(Props drilling) 문제와 이벤트 버스(Event bus)로 주고받는 데이터의 추적이 어려워져 복잡성이 배가 되었다. 이런 복잡성을 경감시키기 위해 중앙집중식으로 상태를 관리하는 디자인 패턴이 등장했고 그것이 플럭스(Flux)패턴이라고 요약할 수 있다.
parse me : 언젠가 이 글에 쓰이면 좋을 것 같은 재료들.
from : 과거의 어떤 생각이 이 생각을 만들었는가?
2.
3.
supplementary : 어떤 새로운 생각이 이 문서에 작성된 생각을 뒷받침하는가?
1.
None
opposite : 어떤 새로운 생각이 이 문서에 작성된 생각과 대조되는가?
1.
None
to : 이 문서에 작성된 생각이 어떤 생각으로 발전되고 이어지는가?
2.
참고 : 레퍼런스