탕구리's 블로그

[React.js] #7 Redux(리덕스) 따라해보기! 본문

javascript/React.js

[React.js] #7 Redux(리덕스) 따라해보기!

탕구리당 2020. 12. 20. 16:50
반응형

 

지난 포스팅에서 리덕스에 대한 내용을 간단히 알아보았습니다.

이번 포스팅에서는 간단한 예제들을 따라 해 보며 리덕스에 조금 더 익숙해지는 시간을 가져보도록 합시다.

 

 

지난 포스팅에서 리덕스의 세 가지 핵심 개념에 대해서 언급했었는데요.

 

 

가장 먼저 액션에 대해서 알아봅시다.

 

액션은 애플리케이션에서 스토어로 보내는 데이터 묶음입니다. 이들이 스토어의 유일한 정보원이 됩니다.

여러분은  store.dispatch()를 통해 이들을 보낼 수 있습니다.

 

라고 나와 있습니다.

 

액션이 생성되면 상태가 변화될 때 dispatch를 통해 reducer로 보내주게 되는 구조라고 언급했었습니다. 액션을 다루면서 해주어야 할 작업은 "액션 타입 선언"과 "액션 생성 함수"를 만들어 주는 것입니다.

 

 

액션 타입 선언

 

# 액션 타입
const INCREMENT = 'counter/INCREMENT';
const DECREMENT = 'counter/DECREMENT';

# 액션
{ type: INCREMENT,
  text: 'hello world'
}

{ type: DECREMENT }

 

액션을 선언하는 방법은 어렵지 않습니다.

 

액션은 자바스크립트 객체입니다. type을 반드시!! 포함해야 하고 이외의 부분은 마음대로 정의하면 된다고 합니다.

액션은 스토어에 데이터를 넣을 수 있는 유일한 방법이기 때문에 어떤 방식을 사용하더라도 최종적으로는 액션을 통해 스토어에 전달됩니다.

 

액션 생성자

 

function increse(value) {
  return {
    type: INCREMENT,
    value
  }
}

const increse = (value) => ({
    type: INCREMENT,
    value
  })

 

액션 생성자는 우리가 위에서 만들었던 액션이 실제도 동작할 수 있도록 도와주는 함수입니다.

이렇게 액션 생성자를 생성한 후 dispatch를 통해 reducer로 전달시켜 상태(state)와 액션(action)을 조합하는 과정이 진행됩니다.

 

dispatch(increment(value))
dispatch(decrement(value))

 

요로코롬 액션 생성자를 디스패치 시켜줄 수 있습니다.

 

 

액션 다루기

 

액션을 다루기 위해서는 reducer를 사용해야 합니다. 제가 처음 reducer 함수를 접했을 때는 이해가 잘 안 갔었는데, 진짜 간단하게 이야기하면 "파라미터를 조합하여 하나의 결과물로 만든다." 정도로 이해하고 있었습니다. 

 

리액트에서는 이전 상태와 액션을 통해 다음 상태를 반환하는 순수 함수로 이해하시면 좋을 것 같습니다.

 

(previousState, action) => newState

 

 

그리고 한번 더 말씀드리지만 "리듀서는 순수 함수"여야 합니다.

 

export default function reducer(state = initalState, action) {
  
  switch(action.type) {
    case INCREMENT:
      return { number: state.number+1 }
    case DECREMENT:
      return { number: state.number-1 }
    default:
      return state
  }

}

 

문서에서는 swtich문을 선호하지는 않는 것 같습니다. switch문 외에도 여러 가지 방법이 있으니 차차 알아가 보도록 하겠습니다.

 

카운트 값을 조작하는 액션 외에도 생뚱맞지만 로그인 여부를 구분하는 액션도 있다고 가정해 봅시다.

 

export const LOG_IN = 'log/IN'
export const LOG_OUT = 'log/OUT'

export const INCREMENT = 'counter/INCREMENT';
export const DECREMENT = 'counter/DECREMENT';


const initialState = {
  isLogged : true,
  number : 0
}

export const login = () => ({ type: LOG_ON })
export const logout = () => ({ type: LOG_OUT })
export const increase = (value) => ({ type: INCREMENT })
export const decrease = (value) => ({ type: DECREMENT })

export default function reducer(state = initalState, action) {
  
  switch(action.type) {
    case INCREMENT:
      return { number: state.number+1 }
    case DECREMENT:
      return { number: state.number-1 }
    case LOG_IN:
      return { isLogged : true }
    case LOG_OUT:
      return { isLogged : false }
    default:
      return state
  }

}

 

이렇게 전혀 연관성이 없는 increase와 decrease 그리고 login과 logout이 하나의 리듀서에 있습니다. 지금은 굉장히 단순한 로직을 담고 있지만 코드가 복잡해지게 된다면 관리하기 굉장히 불편하고 가독성이 떨어집니다. 그래서 리듀서를 각각 분리하여 관리할 수 있도록 수정해 보겠습니다.

 

function counter(state, action) {
  
  switch(action.type) {
    case INCREMENT:
      return state+1
    case DECREMENT:
      return state-1 
    defualt:
      return state
  }
}

function logged( state, action) {
  switch(action.type) {
    case LOG_IN:
      return true
    case LOG_OUT:
      return false
    default:
      return false
  }
    
}

export default function reducer(state = initalState, action) {
  return {
    counter : counter(state.number, action),
    isLogged: logged(state.isLogged, action)
  }
}

 

이렇게 하나의 리듀서를 용도에 따라 여러 개로 분리할 수 있고 여러 개의 리듀서를 하나의 리듀서로 합칠 수도 있습니다.

 

또한, 리덕스는 보일러 플레이트 로직을 지원하는 combineReducers()라는 유틸리티를 제공합니다. conbineReducers()를 활용하면 다음과 같이 재작성할 수 있습니다.

 

import { combineReducers } from 'redux';

const counter_logged = combineReducers({
  counter,
  logged
});

export defualt counter_logged


===========================같은 코드 입니다===========================


export default function reducer(state = initalState, action) {
  return {
    counter : counter(state.number, action),
    isLogged: logged(state.isLogged, action)
  }
}

 

 

이번 포스팅에서는 액션과 액션 생성자를 만들어보고 이후 리듀서를 조작해보는 부분까지 간단한 예제를 만들어 보면서 정리해보았는데 여러 번 보다 보니 어느정도 이해는 가는데 아직 손에 그렇게 익은 상태는 아닌 것 같아요. 앞으로도 계속 하나씩 따라 해 가며 기초를 탄탄하게 다져보도록 하겠습니다.

 

 

저의 포스팅은 주관적인 내용이 상당히 많이 존재합니다.

그렇기 때문에 설명이 잘못되거나 모자란 부분이 존재할 수 있음을 양해하여 읽어주시면 감사하겠습니다.

 

 

탕빠이!

 

 

 

반응형
Comments