Redux with React

HEYDAY7·2021년 4월 5일
0

React

목록 보기
1/1
post-thumbnail

이 글은 https://medium.com/dailyjs/when-do-i-know-im-ready-for-redux-f34da253c85f 를 참고하였습니다.

Redux란

Redux란 애플리케이션의 상태를 관리하기 위한 도구로, React 앱에서는 매우 일반적으로 사용된다고 할 수 있다.
다음은 Redux 공식 홈페이지에 들어가면 나오는 문구로, JS App을 위한 예측이 가능한 상태 컨테이너라는 의미이다. 즉 Redux는 비단 React 뿐만이 아니라 다른 Framework들 과도 잘 작동한다는 것이다.
(Vue에서 생각해 봤을 때 vuex와 유사하다고 느꼈다.)

Redux를 왜 사용할까?

React는 각 클래스 컴포넌트들이 자신만의 state를 가지고 있고, 하위 컴포넌트에게 props를 통해 정보를 전달해 줄 수 있는 구조를 가지고 있다.
그래서 하위 컴포넌트 에서도 상위 컴포넌트의 props를 받아서 조작하거나 사용하는 것이 가능하다. 그러나 이 과정에서 중간에 data(props로 받는 여러 값들)를 필요로 하지 않는component가 아주 많아 진다면 어떻게 될까?

위와 같이 사이사이 불필요한 props의 전달(과도한 prop drilling)이 이뤄지고 여러 container 들 중 한 곳에서만이라도 props의 전달이 의도치 않게 끊어지면 실질적으로 필요한 component에서는 props를 전달받지 못하게 되는 것이다.

따라서 이러하게 좋치않은? 구조를 해결하기 위하여 Redux를 사용하는 것이다. 가장 대표적인 사용 예시로는 "로그인"이 있을 것이다.

즉 Redux는 상태 관리의 로직을 컴포넌트 별이 아니라 컴포넌트 밖에서 global하게 저장하고 사용할 수 있게 해준다.

Flux pattern

이 Redux의 구조를 알기 전에 먼저 알아야 하는 것이 Flux pattern이다. 이 패턴은 Facebook에서 MVC pattern의 한계점을 극복하고자 새로운 단방향 데이터 흐름의 만들어 낸 것이다. Flux 패턴에 대한 글은 여기를 참고하면 된다.
여하튼 Redux는 이러한 Flux pattern을 기반으로 하고 있다.

Redux의 구조와 흐름

Redux의 구조를 크게 Actions, Reducers, Store로 구분할 수 있다.

component에서 Action을 dispatch하고, 이 동작은 Reducer function을 작동시키며, 결국 Store의 state가 update되고, 이 store를 구독중이던 component 또한 upddate 되는 것이 Redux의 flow이다.

Actions

앱에서 어떠한 일이 일어날지를 정의해 두는 객체이며, state를 어떻게 변경하려는지에 대한 내용을 담고 있다.

action은 기본적으로 아래와 같은 형태를 띄고 있다.

const ADD_TODO = 'ADD_TODO'
const REMOVE_TODO = 'REMOVE_TODO'
const LOAD_ARTICLE = 'LOAD_ARTICLE'

export function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

가장 위쪽과 같이 action 타입을 상수로도 정의해두는 것이 일반적이다. 그 바로 아래는 실질적으로 action 객체를 만들어주는 action creator이며 실제 사용에서는 이 action creator를 통해 action 객체를 reducer로 dispatch 시키게 된다.

Reducers

쉽게 말해 상태를 변화시키는 로직이 존재하는 함수입니다.

어찌보면 Redux에서 가장 핵심적인 역할을 한다고 볼 수 있으며 앞서 나온 action creator를 통해 Reducer로 전달된 action의 type에 따라 state를 변화시킵니다.
아래는 한 가지 예제입니다. 완벽히 마무리된 reducer는 아니지만 Reducer의 동작을 이해하는데는 충분합니다.

export const authReducer = (state=initialState, action) => {
  switch(action.type) {
    case CALL_LOGIN:
      return {...state}
    case CALL_LOGIN_SUCCESS:
      return {
        isLogin: true,
        username: action.user.username
      }
    case CALL_LOGIN_FAIL:
      return {...state}
      
      ...
      
    default:
      return state

Reducer는 state와 action 객체를 건네받습니다. 그리고 switch 문을 통해 action.type을 확인하고 각 action마다 미리 작성되어 있는 상태변화 로직을 실행시키는 것이 Reducer의 역할입니다.

Reducer의 특징을 정리하고 넘어가자.

  • Reducer는 순수함수로 작성되어야 한다.

    순수함수란 함수가 실행되는 곳이 어디든, 언제든 외부의 상태를 변경하지 않으면서 동일한 입력값에는 동일한 결과값을 반환해야 하는 함수를 말한다.

  • Reducer는 반드시 이전의 state와 Action을 parameter로 받는다.
  • Reducer는 결과값으로 이전의 데이터를 변경시키지 않고 새로운 데이터(객체)를 만들어 반환한다.

Store

actions와 reducers에 반해 Store만 s가 붙어있지 않은데, 이는 Redux에서 store는 Flux와 달리 하나의 root에 하나의 store만 존재하기 때문이다.

Store에서는 state들이 object의 형태로 저장된다. 각 component들은 Store를 구독할 수 있고, 이 경우 Store가 변화하면 component들도 업데이트 되게 된다.

정리

불필요한 데이터의 흐름을 제어할 수 있으며, 전체적인 서비스의 UI가 앱의 상태에 따라 크게 바뀐다면(로그인 유무와 같이) Redux를 적용하는 것은 많은 이득을 취할 수 있기에 일찍이 도입하는 것을 긍정적으로 생각해보는게 좋다.

아래 여러 링크들을 추가로 읽어보는 것도 도움이 된다.
When do I know I'm ready for Redux?
윗 글의 번역본
Redux 공식 문서

React에서의 Redux의 실제적인 코드 작성은 Redux-saga와 함께 다음 글에서 자세히 알아보겠다!

profile
(전) Junior Android Developer (현) Backend 이직 준비생

0개의 댓글