redux

Apr 26th 2020 by jyoon

vanilla-javascript로 숫자 증감 기능을 redux로 사용해서 구현해보면서 알아보겠습니다.

redux 설명

  • 리액트에서 사용되는 상태 관리 라이브러리중 하나
  • 컴포넌트 상태 업테이트 관련 로직을 다른 파일로 분리시켜 효율적으로 관리할 수 있다.
  • 컴포넌트끼리 똑같은 상태를 공유해야 할 때도 여러 컴포넌트를 거치지 않고 손쉽게 상태 값을 전달, 업데이트 할 수 있다.
  • 전역 상태를 관리할때 괸장히 효과적이다. 하지만 리덕스를 사용하는 것이 유일한 해결책은 아니다.
    단순히 전역 상태 관리만 한다면 Context API를 사용하는 것만으로도 충분하다.

    • 이렇기 때문에 프로젝트의 규모가 클 경우에는 리덕스를 사용하는 편이 좋다.
    • 코드 유지보수, 작업효율도 극대화해주기 때문
    • 추가적으로 미들웨어라는 기능을 제공하여 비동기 작업을 효율적으로 관리해준다.

redux 세가지 원칙

https://redux.js.org/introduction/three-principles

  • 한개의 어플리케이션에는 단일 store가 있어야 한다.

    • 이런상황에서 어플리케이션을 사용하게 쉽게한다.
    • 서버에서 받아온 데이터들을 클라이언트에 수고 없이 serialized, hydrated할 수 있다.
    • debug, inspect하기 쉽다.
    • 단일 state를 사용합으로 빠른 개발 사이클을 가능하게 한다.
    • 예전부터 구현하기 힘들었던 몇가지 기능(undo/redo)을 구현하기 쉽게 한다.
  • state는 오직 일기 전용이다.

    • state를 바꾸기 위한것은 action을 이용한 방법을 활용해야한다.
    • action은 plan object인데 이유는 log, serialized, stored, debugging, testing에서 활용될 목적이기 때문이다.
  • 리듀서는 pure function이다.

redux 용어

1. action

  • 객체로 표현되는 값
  • type 필드를 반드시 가지고 있어야 한다.

2. action creator function

  • 액션 객체를 만들어주는 함수
  • 함수를를 만들어 액션 객체를 만드는이유 : 번거로움, 액션을 만드는 과정에서 실수로 정보를 놓칠수도 있는 것을 방지하기 위해서

3. reducer

  • 변화를 일으키는 함수
  • action을 만들어서 발생시키면 reducer가 현재 상태와 전달받은 액션 객체를 파라미터로 받아온다.
  • 그리고 두 값을 참고하여 새로운 상태를 만들어 반환한다.

4. store

  • 한 개의 프로젝트는 단 하나의 스토어만 가질 수 있다.
  • store 안에는 현재 application 상태, reducer가 들어 있다.
  • 그 외에도 dispatch, subscribe과 같은 내장 함수를 가지고 있다.

5. dispatch

  • store의 내장 함수중 하나
  • action을 발생시킨다.

6. subscribe

  • store의 내장 함수중 하나
  • subscribe 함수 안에 listner함수를 파라미너로 넣어 호출하면, store 상태가 업데이트될 때마다 호출 된다.

redux 전체 코드/ 설명

  • 전체코드와 함께 설명을 작성함으로 부분 설명한 개념들을 한곳에서 확인 할 수 있다.
import { createStore } from "redux"

// #1. DOM reference 설정
const add = document.getElementById("add")
const minus = document.getElementById("minus")
const number = document.querySelector("span")
number.innerText = 0

// #2. DOM event 설정
//: event triiger시 dispatch 수행
add.addEventListener("click", handleAdd)
minus.addEventListener("click", handleMinus)

// #3. actions
// : dispatch에서 사용 됨(reduce에서 에러를 띄워준다. - 만약 dispatch에서 일반상수 사용시 에러러를 띄우지 않는다.)
const ADD = "ADD"
const MINUS = "MINUS"

// #4. reducer
// : 변화를 일으키는 함수로서 store의 상태가 변경된다.
// : 상태의 불변성을 지켜야 한다.
// : 객체 구조가 복잡해지는 경우 immer 라이브러리를 사용함으로 좀 더 쉽게 리듀서를 작성할 수 있다.
const countModifier = (count = 0, action) => {
  console.log({ count, action }) //eg) action = { type: "MINUS", count:1 }

  switch (action.type) {
    case "ADD":
      return count + 1
      break
    case "MINUS":
      return count - 1
      break
    default:
      return count
      break
  }
}

// #5. store
// : redux lib의 createStore 함수를 이용해서 store를 생성하며 생성시 reducer를 넣어주어야 한다.
const countStore = createStore(countModifier)

// #6. dispatch
// : 스토어의 내장객체 dispatch를 이용해서 액션을 발생시킨다.
// : dispatch 함수 내부에서는 액션을 스토어에게 넘깁니다.
const handleAdd = () => {
  countStore.dispatch({ type: ADD })
}
const handleMinus = () => {
  countStore.dispatch({ type: MINUS })
}

// #7. subscribe
// : 스토어 상태가 바뀔 때마다 subscribe 함수로 넘겨주는 파라미터 함수를 수행한다.
const unsubscribe = countStore.subscribe(onChange)

const onChange = () => {
  number.innerText = countStore.getState()
}

unsubscribe() // 구독을 비활성화할 때 함수를 호출
console.log(countStore.getState())
1. DOM reference 설정
2. DOM event 설정
- event triiger시 dispatch 수행

3. actions
- dispatch에서 사용 됨
(reduce에서 에러를 띄워준다.
만약 dispatch에서 일반상수 사용시 에러러를 띄우지 않는다.)

4. reducer
- 변화를 일으키는 함수로서 store의 상태가 변경된다.
- 상태의 불변성을 지켜야 한다.
- 객체 구조가 복잡해지는 경우 immer 라이브러리를 사용함으로
좀 더 쉽게 리듀서를 작성할 수 있다.

5. store
- redux lib의 createStore 함수를 이용해서 store를 생성하며
생성시 reducer를 넣어주어야 한다.

6. dispatch
- 스토어의 내장객체 dispatch를 이용해서 액션을 발생시킨다.
- dispatch 함수 내부에서는 액션을 스토어에게 넘깁니다.

7. subscribe

- 스토어 상태가 바뀔 때마다 subscribe 함수로 넘겨주는 파라미터 함수를 수행한다.

참고