Blog

Read

Redux

Nov 15, 2020

Redux


리덕스는 actions 이벤트를 사용하여 어플리케이션의 상태를 관리하고 업데이트 하는 패턴 및 라이브러리 입니다. 리덕스는 상태관리를 컴포넌트 밖에서 합니다. 앱의 상태 전부는 하나의 store 안에 있는 객체 트리에 저장됩니다. 상태 트리를 변경 하는 방법은 action을 보내는 것 뿐입니다. 액션이 상태트리를 어떻게 변경할지 명시하기 위해 reducers를 작성해야 합니다.


리덕스를 언제 사용해야 할까요

I would like to amend this: don't use Redux until you have problems with vanilla React. - Dan Abramov

  • 앱의 여러 위치에 필요한 많은 양의 상태를 갖고 있을 때
  • 앱의 상태가 자주 업데이트 될때
  • 상태 업데이트 로직이 복잡할때
  • 많은 사람들이 작업하고, 중간 또는 큰 사이즈의 코드 베이스를 가질때

컴포넌트를 만들때, UI를 만들고 해당 UI 에서는 button 이나 Input등의 이벤트를 발생시키고, 이를 통해 상태를 변경 할텐데, Redux로 해당 UI에서 상태가 변경되었다를 알리기 위해서 Action을 Dispatch를 합니다. (말 그대로 일어난 이벤트를 보낸다) 그러면 store에 있는 리듀서가 해당 액션을 처리하여 새로운 상태로 값을 반환할텐데, 이때 리듀서는 어떤 액션이 들어왔는지 구분하기 위해서 type이라는 속성을 갖게 됩니다.

Actions

action은 객체 형태로 애플리케이션에서 스토어로 보내는 데이터 묶음 입니다. store.dispatch()를 통해서 보냅니다. 반드시 type 속성을 가져야 합니다. type 속성값은 리듀서에 액션 객체를 구분할 때도 사용되기 때문에 상수 변수로 만드는것이 좋습니다. 액션은 어플리케이션에서 발생한 작업을 설명하는 이벤트라고 생각하면 됩니다. payload 필드에는 추가적인 정보가 담겨있습니다.

React 자체의 상태관리를 할때에는 해당 함수 안에서 상태를 관리하는데 반해 redux는 global store를 통해 모든 앱에서의 상태를 공유 하게 됩니다. 이는 곧, 해당 상태가 바뀌었다는 정보를 global store에 전달해줘야 한다는 얘기이며, 이를 위해 action을 dispatch 합니다.


Reducers

reducer는 이전 상태값과, 액션 객체를 입력으로 받아 새로운 상태값을 만드는 순수함수 입니다. (state, action) => newState 리듀서를 액션 타입을 기준으로 이벤트를 처리 하는 이벤트 리스너라고 생각할 수 있습니다. 사이드 이펙트를 일으켜서는 안되며, state를 직접적으로 변경해서는 안됩니다. 불변성을 유지하며 상태를 업데이트 해야 합니다.

const initialState = { value: 0 };

function counterReducer(state = initialState, action) {
    // Check to see if the reducer cares about this action
    if (action.type === "counter/increment") {
        // If so, make a copy of `state`
        return {
            ...state,
            // and update the copy with the new value
            value: state.value + 1,
        };
    }
    // otherwise return the existing state unchanged
    return state;
}

Middleware

미들웨어는 리듀서가 액션을 처리하기전에 실행되는 함수 입니다. 디버깅 목적으로 상탯값 변경시 로그를 출력하거나, API 호출 등의 목적으로 활용 가능합니다.


Selector

useSelector 훅을 활용하면 store에 있는 데이터를 읽어올 수 있습니다. selector 함수는 모든 state object를 받고, 값으로 반환해야 합니다. selector 함수는 리덕스 스토어가 업데이트 되면 언제든지 재실행 됩니다. 그리고 만약 데이터가 변경된 경우 컴포넌트는 다시 렌더링 됩니다. 즉, 리렌더링이 언제든지 일어날 수 있기 때문에, 컴포넌트들은 항상 스토어로부터 필요한 최소한의 데이터를 select 하여 실제 필요한 경우에만 렌더링 되도록 해야 합니다. 이를 방지하기 위해 RTK 는 createSelector 함수를 제공합니다. reselet 라이브러리의 기능으로 메모이제이션을 지원하여, 무분별한 렌더링을 방지 합니다.