Redux

한대희·2023년 5월 26일
1

Redux

목록 보기
1/3
post-thumbnail

Redux

  • redux는 자바스크립트 어플리케이션을 위한 상태 관리 라이브러리다.
  • redux는 어플리케이션에 필요한 모든 데이터를 하나의 상태, 즉 하나의 객체에 담아 관리하여 어플리케이션의 복잡성을 획기적으로 낮출 수 있는 도구 이다.
  • redux를 사용하면 props dirilling 없이 state를 간편하게 관리할 수 있다.

Redux의 구조

  • redux의 구성 요소는 4가지로 볼 수 있다.

  • render함수, action객체, reducer 함수, store, middleware

  • ui를 구성하는 render함수에서 state를 어떻게 해달라는 action을 dispatch함수를 통해 reducer에 전달 한다.

  • action객체 안에는 type과, payload를 전달 할 수 있다. type은 어떤 일을 해달라고 하는 것인지 입력해 주고, 특정 값을 전달할 필요가 있을 때 payload를 전달한다.

  • action을 전달 받은 reducer는 전달 받은 action에 맞게 state를 변경하여 새롭게 변경된 state를 리턴 한다.

1. store & reducer

  • redux의 핵심은 store 다. store를 생성하면 여기에 어플리케이션에 필요한 모든 데이터를 담아 관리 할 수 있다.
  • 여기서 데이터를 store안에 있는 state라고 생각하면 된다.
  • 그리고 store를 만들 때 reducer 를 함께 전달 해야 하는데 reducer는 state를 가공하는 역할을 한다.

2. getState & subscribe & dispatch

  • redux는 데이터의 안정성을 위해 데이터에 쉽게 접근 하거나 수정할 수 없도록 되어 있다.
  • 따라서 특정 함수를 이용하여 데이터에 접근 해야 한다. 해당 함수는 아래와 같다.
  • getState를 통해 state를 가져올 수 있고, subscribe를 통해 state가 변경이 될 때 마다 state를 가져와 ui를 업데이트 할 수 있다. 그리고 dispatch를 통해 state를 업데이트 할 수 있다.
  • dispatch를 통해 state를 업데이트 할 때는 action 객체를 전달을 해야 한다.
  • dispatch 함수는 reducer 호출 하여 state를 바꾸게 되는데 reducer를 호출 할때 현재의 state와 전달 받은 action객체를 전달 한다.
  • 이렇게 현재 state와 action객체를 전달 받은 reducer는 새로운 state를 리턴해 준다.
  • 이렇게 state가 바뀌면 다시 subscribe가 호출 되어 reder함수도 호출이 되고 다시 getState를 통해 state를 가져와 ui가 변경이 되게 되는 것이다.

예제

  • redux를 이용한 간단한 어플리케이션을 만들어 보자.

1.먼저 store를 만들어야 하는데 store 만들 때 reducer함수를 같이 전달해 줘야 하므로 먼저 reducer함수를 만들고 store에 전달해 보자.

  <script>
  // 1. reducer함수를 만들어 주었고
      function reducer(state, action) {
        // 아래와 같은 방식으로 state 초기값 설정
        if (state === undefined) {
          return { color: 'orange' }
        }
      }
  // 2. Redux.createStore로 store만들 때 reducer함수를 전달 했다.
      const store = Redux.createStore(reducer)
      console.log(store.getState()) //  {color: 'orange'}
  </script>

2. 간단한 html을 만들어 현재 store에 저장된 state를 배경색으로 지정해 보자

<body>
  <div id="practice"></div>
  <script>
      function reducer(state, action) {
        // 아래와 같은 방식으로 초기값 설정
        if (state === undefined) {
          return { color: 'orange' }
        }
      }
      const store = Redux.createStore(reducer)

// test라는 함수를 만들어서 id가 practice인 요소에 div를 하나 추가 하고 해당 div의 색을 
// store에 저장된 state로 지정
      function test () {
      let state = store.getState()
      document.querySelector('#practice').innerHTML = `
        <div style="background-color:${state.color}">
          <h1> TEST </h1>  
        </div>
      `
    }
    test ()
  </script>
</body>
  • 배경색이 바뀌는 것이 확인이 되면 store의 state값을 수정했을 때 배경색도 다른 색으로 수정되는 것을 확인할 수 있을 것이다.

3. 이번에는 직접 state를 바꾸지 말고 dispatch를 이용해서 state를 변경해 보자.

  • dispatch에 action객체를 전달을 하면 dispatch는 reducer를 호출 할때 현재 state와 전달 받은 action 객체를 전달하게 될 것이다.
  • reducer 함수는 현재 state와 action객체를 전달 받아 새로운 state를 리턴한다.
// 먼저 innerHTML에 버튼을 하나 추가 하여 해당 버튼을 클릭하면 dispatch함수를 호출 하고
// action객체를 전달 하였다.
      document.querySelector('#practice').innerHTML = `
        <div style="background-color:${state.color}">
          <h1> TEST </h1>
          <input 
            type="button" 
            value='change'
            onClick='store.dispatch({type:'CHANGE_COLOR', color: 'blue'})'
            >  
        </div>
      `
  • 자 이제 reducer함수의 인자로 action 객체가 들어 왔는지 확인해 보면 정상적으로 들어온 것을 확인할 수 있을 것이다.
      function reducer(state, action) {
        console.log(action) // {type: '@@redux/INIT1.s.x.y.3.6'}
        if (state === undefined) {
          return { color: 'orange' }
        }
      }
  • 그럼 이제 조건을 추가하여 전달받은 action의 타입별로 값을 리턴해 주면 된다.
      function reducer(state, action) {
        let newState
        if (state === undefined) {
          return { color: 'orange' }
  // action의 타입이 CHANGE_COLOR면 기존의 state를 복사한 다음 color를 전달 받은 
  // action.color로 바꿔 state를 변경한다. 이렇게 복사를 하는 이유는 불변성을 유지하기 위함
        } else if (action.type === 'CHANGE_COLOR') {
          newState = Object.assign({}, state, {color: action.color})
        }
        return newState
      }
  • 여기 까지 하면 버튼을 클릭하여 store의 state를 바꿔 주었다. 이제는 state가 변경이 될 때 subscribe를 통해 ui를 자동으로 바꿔 보자
      
    // 기존 로직을 함수로 만들고  
    function test () {
      let state = store.getState()

        document.querySelector('#practice').innerHTML = `
          <div style="background-color:${state.color}">
            <h1>TEST</h1>
            <input type='button' value='blue' onclick="store.dispatch({type:'CHANGE_COLOR', color: 'blue'})"> 
          </div>
        `
      }
      test()
      // store.subscribe에 넣어 주면 된다.
      store.subscribe(test)

combineReducers

  • 어플리케이션에서 관리해야 하는 state는 여러가지 일 것이다.
  • 따라서 각각의 state를 업데이트 할 수 있는 reducer도 state의 갯수 만큼 존재 하게 된다.
  • 이러한 여러가지 reducer를 묶어 주는 것이 combineReducers다.

예제

  • counter를 올리고 내리는 reducer를 만들고, todo를 추가하고 제거 할 수 있는 reducer 이렇게 2개의 reducer가 있다고 가정해 보자.
  • 그러면 이 둘을 묶어 줄 수 있는 root reducer가 필요하다.
  • reducer들을 모아 둔 reducer폴더에 총 3가지의 reducer파일을 만들어 보자.
profile
개발 블로그

0개의 댓글