Redux와 Redux Toolkit에 대해서 #1 (MVC와 Flux 비교, Redux 개념)

eeeyooon·2023년 12월 19일
0

[React 심화]

목록 보기
2/2

1. 개요

과제를 하게 되었는데, 필수 스택 중에 ReduxRedux toolkit이 있었다. 지금까지 상태관리 툴은 recoil만 써봤던 내겐 발등에 불 떨어진 격이었다. 급하게 아주 여유롭게 듣고 있던 Redux 강의를 다시 들었는데 2021년 강의라서 그런지 현재 사용법과는 차이가 있었고, 이전 버전으로 공부하는 건 지금 급한 상황에선 어려울 거란 생각에 공식 문서를 보면서 무작정 과제에 사용하였다. 그러다보니 내가 제대로 사용한건 맞는지, 올바르게 이해한건지 걱정이 들었다. ReduxRTK에 대한 전체적인 내용을 다루고 과제를 하면서 이 둘을 어떻게 사용했는가를 작성할 것이다. 물론 야매식으로 공부한거라 보면서 의문이 들 수도 있다.


이 사람.. Redux 쓸 줄.. 모르는 것 같은데?


그럼에도 포스팅을 하는 이유는 Redux와 RTK가 등장하게 된 이유와 사용 방법에 대한 전반적인 흐름을 이해하고 싶었기 때문이다. 또한 과제에 사용했던 코드들을 다시 한번 정리하고 (개선할 부분이 보인다면 개선하고!) 좀 더 차분하게 Redux와 RTK에 대해 공부하고자 한다. 천천히 글로 정리하면서 더 나은 방법은 없는지, 더 활용도 높은 코드로 수정할 수는 없는지 고민해 볼 예정이다. 먼저 Flux와 MVC 패턴을 비교하고, 그런 Flux에 영향을 받은 Redux에 대한 개념(Redux의 등장배경)과 Redux Toolkit을 사용하게 된 이유, Redux Toolkit 개념에 대해 작성할 것이다. 1편의 내용은 MVC와 Flux의 비교, Redux 개념에 관한 것이다.


2. Flux와 MVC 패턴 비교


2-1. MVC 패턴이란

Model, View, Controller의 약자이다. 하나의 애플리케이션을 구성할 때 그 구성요소를 세가지의 역할로 구분한 패턴이다.

Model

  • 애플리케이션의 정보, 데이터를 나타내며 "DB, 초기화값, 변수 등"을 뜻한다. 또한 이러한 데이터들의 가공을 책임지는 컴포넌트를 말한다.
  • 사용자가 편집하길 원하는 모든 데이터를 가지고 있어야 하지만, 뷰나 컨트롤러를 조정할 수 있는 내부 속성값을 가져서는 안된다.

View

  • 사용자 인터페이스 요소를 나타낸다. 다시 말해 데이터 및 객체의 입력과 출력을 담당한다.
  • 화면에 표시만하고 그 화면을 그릴 때 필요한 정보들은 저장하지 않는다.
  • 사용자가 화면에 표시된 내용을 변경하게 되면 이를 Model에게 전달해서 Model을 변경해야한다.

Controller

  • Model의 데이터를 조회하거나 업데이트 하는 역할. Model과 View 간의 상호작용을 관리한다.
  • 사용자의 입력에 대한 처리(이벤트)나 Model의 데이터 업데이트 등을 수행한다.
  • 모델과 뷰에서 변경이 발생하면 이를 해석하여 각각의 구성 요소에게 전달해야 한다.

Controller는 Model의 데이터를 조회, 업데이트하고 Model의 변화는 View에 반영된다. 그리고 사용자가 View를 통해 데이터를 입력하여 Model을 업데이트 할 수 있다. 업데이트 된 View가 다른 Model을 업데이트 한다면 또 다른 View가 업데이트 될 수 있다.



2-2. MVC 패턴의 한계

MVC에서는 어플리케이션이 복잡해질수록 양방향 데이터 흐름이 복잡해지고, 버그가 많이 발생하게 된다. 페이스북과 같은 대규모 어플리케이션이 등장하게 되면서 MVC 패턴의 특성은 어플리케이션의 내부 구조를 복잡하게 만들었고 이는 페이스북 개발팀의 큰 골칫거리가 되어 이를 해결하고자 페이스북 개발팀은 Flux 아키텍처를 개발하여 적용하기로 하였다.



2-3. Flux 패턴

하나의 상태 저장소와 이를 변경하는 Dispatcher를 통해 단방향 순환 구조를 갖는 패턴. Flux는 단방향으로 데이터가 흐르게 된다. Flux는 크게 Dispatcher, Store(Model), View 세 부분으로 구성된다.

Dispatcher

Flux의 모든 데이터 흐름을 관리하는 허브 역할로, Action이 발생하면 Dispatcher로 메세지(액션 또는 객체)가 전달되고 Dispatcher는 Action을 보고 등록된 콜백 함수를 실행하여 Store에 데이터를 전달한다.

  • Dispatcher는 전체 어플리케이션에서 한 개의 인스턴스만 사용된다. (단 하나만 존재)
  • Action을 Store에 전달하는 역할을 한다.

Store (Model)

어플리케이션의 모든 상태 변경은 Store에 의해 결정된다. Dispatcher로부터 메세지를 전달받기 위해서는 Dispatcher에 콜백함수를 등록해야 한다. Store가 변경되면 View에 변경되었다는 사실을 알려줘야 한다.

  • Store는 싱글톤으로 관리된다.
  • 무조건 Dispatcher를 통해 Action을 보내야만 데이터 변경이 가능하다. Action을 Dispatcher에게 전달 받으면 상태를 변화시킨다. Store는 동시에 변화시킨 상태를 저장하는 저장소이기도 하다.

💡 싱글톤이란 객체의 인스턴스가 오직 1개만 생성되는 패턴을 말한다. 즉, 인스턴스가 필요할 때 똑같은 인스턴스를 만들어내는 것이 아니라 동일 인스턴스를 사용하게 하는 것이다. 싱글톤으로 관리하면 데이터 공유가 쉽다.


View

Flux의 View는 화면에 나타내는 것뿐만 아니라, 자식 View로 데이터를 흘려보내는 View Controller의 역할도 함께 한다. 특히 중첩된 뷰 레이어의 최상위 뷰는 스토어에서 데이터를 가져와 자식 뷰로 배분하는 역할을 하고 있기 때문에 "Controller View"라고도 부른다. 즉, 자식 뷰에서는 직접 데이터를 가져오는 대신 props 형태로 상위 뷰에서 전달 받는 방식을 주로 사용한다.

  • View는 Store의 변경 사항을 감지할 수 있는 이벤트 리스너를 Store에 등록하고, Store에 변경 사항이 발생하면 이를 View에 반영한다.
  • Store에게 상태를 전달 받아 렌더링하는 역할을 담당한다. Store의 데이터를 바탕으로 UI를 업데이트하고, 사용자의 이벤트를 Actions로 전달한다.

Action

Dispatcher에서 콜백함수가 실행되면 Store가 업데이트 되는데, 이 콜백함수를 실행할 때 데이터가 담겨있는 객체가 인수로 전달되어야 한다. 이 전달되는 객체를 Action이라고 하는데, Action은 대체로 Action Creator(액션 생성자)에서 만들어진다.

  • 어플리케이션에서 일어나는 모든 이벤트를 나타낸다.
  • View에서 발생하며 Dispatcher에게 전달된다.

💡 Action Creator는 typepayload를 포함한 Action을 생성한다. Action은 객체 형태로 정의되며, type속성으로 어떤 이벤트인지 식별한다.



  1. Dispatcher - Model - View 구조를 갖는 패턴이다.
  2. Model(Store)라는 하나의 상태를 가지며, 계층 구조가 없이 흐름이 단방향이다.
  3. View(Controller View)는 Action을 호출할 수 있으며, Action-Dispatcher-Model-View-Action..의 순환 구조가 된다.



2-4. Flux 패턴의 아쉬운 점

Flux에서 Store는 2가지 역할을 담당한다.

  • state 저장소
  • state 변화 로직 수행

따라서 state 변화 로직을 수정하면 기존에 저장되어 있던 state가 전부 새로고침이 되어 사라진다. 이러한 한계를 극복하기 위해 Redux가 등장했다.



3. Redux에 대해서


3-1. Redux란

Redux는 Flux 아키텍처의 기본 철학을 계승하지만, Flux를 실용적으로 사용가능할 수 있도록 설계되었다. Redux는 Flux의 기존 한계점을 극복하기 위해 기존 Flux의 Store가 수행하던 2가지 역할을 Reducer와 store로 분리하였다. Redux의 데이터 흐름은 단방향으로 View(컴포넌트)에서 Dispatch(store에서 주는 state를 바꾸는 함수)를 통해 Action(dipatch되는 함수 이름)이 발동되고 Reducer에 정의된 로직에 따라 Store의 state가 변화하고 그 state를 쓰는 View(컴포넌트)가 변하는 흐름을 따른다. 또한 Redux는 Flux의 개념을 발전시킨 기능에 Hot Reloading, Time Travel Debugging과 같은 기능을 제공한다.

  • Hot Reloading : 애플리케이션 코드 변경사항이 즉시 적용 되도록하는 개발 도구.
  • Time Travel Debugging : 디버깅 과정에서 시간 여행을 하듯이 이전 단계의 상태를 탐색하고 분석할 수 있는 기능.



3-2. Redux의 3원칙

1. 애플리케이션 상태는 모두 한 곳에 집중 관리된다. (동기화 필요x)
애플리케이션의 모든 상태는 하나의 저장소 안에 하나의 객체 트리로 저장된다. 하나의 상태 트리만을 가지고 있기 때문에 이전에는 구현하기 어려웠던 실행취소/다시실행을 손쉽게 구현할 수 있다.

2. 상태는 불변(읽기 전용) 데이터이며, 오직 Action만이 상태 교체를 요청할 수 있다. (예측 가능)
이를 통해서 View나 Network Callback에서 결코 상태를 직접 바꾸지 못한다는 걸 보장할 수 있다. 모든 상태 변화는 중앙에서 관리되며 모든 Action은 엄격한 순서에 의해 실행된다. Action은 그저 평범한 객체이기 때문에 기록을 남길 수 있고, 시리얼라이즈할 수 있으며, 저장할 수 있고, 이후에 테스트나 디버깅을 위해서 재현하는 것도 가능하다.

3. 리듀서(함수)를 통해 상태의 최종 값만 설정한다. (단순화)
리듀서는 그저 이전 상태와 액션을 받아 다음 상태를 반환하는 순수 함수이다. 이전 상태를 변경하는 대신 새로운 상태 객체를 생성해서 반환해야 한다.



3-3. Redux를 사용하는 이유

1. state 종속성 탈피

useState를 사용할 경우 컴포넌트 내부에 state를 만들고, 함수로 state를 변경한다. 그렇기 때문에 state는 컴포넌트에 당연히 종속된다. 하지만 Redux는 컴포넌트에 종속되지 않고, 상태관리를 컴포넌트 밖에서 한다. 어플리케이션의 Root 단계에서 store에 state를 저장하고, 모든 컴포넌트는 store에 구독을 하면서 state와 그 state를 바꾸는 함수를 전달 받는다. 함수를 바꿈으로 state가 바뀌면 해당 state를 바라보고 있는 컴포넌트는 모두 리렌더링 된다.


2. props 지옥 탈출

state를 자식의 자식의 자식에서 사용한다면 props를 내리고 또 내리고 또 내리게 된다. 그 state를 바꾸는 함수 역시 또 내리고 내리고 내리게 된다. 하지만 Redux를 사용하면 Redux의 store는 어플리케이션의 root 레벨에 위치하고, 해당 store를 구독하는 컴포넌트는 모두 state와 state를 바꾸는 함수를 받을 수 있다. 어느 위치에 있든 상관없이 단 한번에 상태를 받을 수 있다.



참고

https://velog.io/@nomadhash/TIL-MVC-%ED%8C%A8%ED%84%B4-vs-Flux-%ED%8C%A8%ED%84%B4
https://bgradecoding.tistory.com/29
https://kyounghwan01.github.io/blog/React/redux/redux-basic/
https://ko.redux.js.org/understanding/thinking-in-redux/three-principles




0개의 댓글

관련 채용 정보