IT's Jenna

리액트 상태관리 - 리덕스 & 리듀서 본문

Frontend

리액트 상태관리 - 리덕스 & 리듀서

developer Jenna 2021. 3. 7. 14:11

리액트에서 상태 관리를 할 때 사용하는 방식은 state를 props로 넘겨주고 값을 공유하는 top-down 방식이다. 본 구조는 컴포넌트가 많아지고 구조가 복잡해질수록 관리가 어렵다는 단점이 있다. 특히 depth가 깊어질수록 초기 상태 및 상태 변화를 확인하기 위해서 타고 들어가야 하는 파일들이 많아지기 때문에 오류 핸들링이 굉장히 어렵다.

 

코드 복잡성의 증가는 개발자들의 협업에 많은 이슈를 발생시키고 효율적인 코드 관리도 어려운 critical한 문제이다.

 

이러한 지역적인 상태 관리에 한계점을 느끼고 개발된 것이 전역적인 상태 관리 방식이다. 전역적인 상태 관리란 상태를 별도의 공간에 모아 두고 모든 컴포넌트들이 해당 공간에서 상태를 받아오는 것이다. 아래 그림은 지역적인 상태 관리와 전역적인 상태 관리를 비교해둔 것이다.

 

전역적 상태 관리를 사용할 수 있는 대표적인 라이브러리가 ReduxMobx이다. 추가로 리액트가 기본적으로 장착하고 있는 모듈인 context API도 있다. 이번 포스팅은 이 중에서 Redux라이브러리를 어떻게 활용하는지 설명해 보도록 하겠다.

 

Redux 라이브러리란, 자바스크립트 어플리케이션을 위한 예측 가능한 상태 보관소이다. 즉, 어플리케이션의 복잡성을 낮춰서 상태 변화를 예측 가능하게끔 만들어준다는 의미이다.

 

리덕스는 기본적으로 전역 데이터에 하나의 초기 상태를 가진다. 이 전역 데이터를 외부와 차단해서 임의로 상태가 변하는 것을 방지하는 게 리덕스의 역할이다. 전역 데이터가 임의로 변경된다면 개발자는 해당 결과를 점점 예측하기 어려워질 것이다.

 

따라서 리덕스에선 특정 함수를 이용해야만 데이터의 상태 변화가 가능하다. 이렇게 리덕스 내에서 전역 데이터에 접근하여 상태 변화를 할 수 있게끔 만들어주는 함수가 바로 dispatchreducer이다. 디스패치와 리듀서로부터 상태 변화 내용을 전달받은 리덕스가 전역 데이터의 상태를 변화시킨다. 또한 subscribe함수를 통해서 state가 바뀔 때마다 state가 변경되었다는 내용을 컴포넌트에게 전달할 수 있다. 리덕스 내의 상태를 변화시키는 것뿐만 아니라 리덕스로부터 데이터를 받아오는 것도 getstate라는 특정 함수를 통해서만 가능하다. 

 

생활코딩에서 리덕스 구조를 그림으로 나타낸 것이 있는데 가장 이해가 잘 되는 것 같아 가져와보았다.

<리덕스 구조>

store라는 은행이 있고 생각해보자. action과 render는 은행을 찾은 고객이고, dispatch, subscribe, getState는 은행 창구 직원이다. 그리고 reducer는 은행 뒤편에서 은행 장부를 실질적으로 관리하는 직원이고 state는 은행 장부이다.

 

submit을 누르면 submit에 걸려있는 action이 dispatch에게 전달된다. dispatch는 현재 state와 action을 reducer에게 전달한다. reducer는 실질적으로 state를 변화시킬 수 있는 함수를 가지고 있다. reducer안에는 각 action에 대응하는 함수들이 있고 그 함수는 새로운 state를 return 한다. 즉 reducer는 새로운 state를 가공하는 가공자라고 볼 수 있다.

 

client가 화면을 요청하면 render는 getState를 통해서 state를 받아와서 ui를 표시한다. 이때 reducer로 인해서 state가 변경되면 변경된 state에 맞춰서 새로운 ui가 렌더링 되어야 한다. 하지만 state가 바뀌었는지 render 입장에선 알 수 있는 방법이 없기 때문에 subscribe를 이용하게 된다.

 

render함수들을 subscribe에 등록해둘 수 있다. dispatch가 동작할 때마다 subscribe의 구독자들에게 알려주면서 render가 다시 getState를 요청하고 새로운 state에 맞게 다시 렌더링 된다.


정리해보자면,

Redux는 createStore를 통해서 단일 store를 생성한다. Redux는 매개변수로 reducer를 받아오면서 store에 reducer들을 넣어준다.

reducer현재 상태와 액션 함수를 매개변수로 받아오면서 상태를 변경시킨다.

dispatchreducer를 호출하면서 현재 상태와 action함수를 reducer에게 전달한다. 디스패치는 매개변수로 action함수를 받아온다.

 

action 함수 동작 → dispatch 전달  reducer 호출  최종 state return


리덕스를 사용하면 state가 전역적으로 관리되기 때문에 다른 컴포넌트와의 연관관계(Coupling) 없이 독립적으로(Decoupleing) 동작할 수 있다. 이러한 점이 코드의 복잡성을 굉장히 낮출 수 있다.

 

또한 redux-dev tool을 사용하면 stored에게 전달된 action들을 logging이 가능하다. redux-dev tool을 사용해서 굉장히 편한 점은 동작들을 되돌리기가 가능하단 것이다. 이전 state로 돌려보면서 에러 debugging이 용이하다.

 

<참고>

opentutorials.org/module/4078/24935

'Frontend' 카테고리의 다른 글

NVM 설치 및 사용방법 (.nvmrc)  (0) 2023.10.05
CSR vs SSR  (0) 2021.03.02
CRA & Next.js  (0) 2021.02.25
클래스형 컴포넌트 & 함수형 컴포넌트  (0) 2021.02.22
리액트  (0) 2021.02.08
Comments