※ 강의를 듣고 제가 이해한 내용을 바탕으로 정리한 것이라서 오류가 있을 수 있습니다.

 

리덕스 모듈 만들기

리덕스 모듈을 만들어 볼건데 리덕스 모듈이란 다음 항목들이 모두 들어있는 자바스크립트 파일을 의미 한다.

  • 액션 타입

  • 액션 생성함수

  • 리듀서

리덕스를 사용하기 위해 필요한 위 항목들은 각각 다른 파일에 저장 할 수도 있다.

리덕스 GitHub 레포에 등록되어있는 예제 프로젝트를 보면 다음과 같이 코드가 분리되어 있다.

  • actions

    • index.js

  • reducers

    • todos.js

    • visibilityFilter.js

    • index.js

 예제 프로젝트에서는 액션과 리듀서가 서로 다른 파일에 정의 되어있다. 하지만 이 코드들이 꼭 분리되어있을 필요는 없고 자유롭게 해도 된다. 

이 코드들이 서로 다른 디렉터리에 그리고 서로 다른 파일에 분리가 되어있으면 개발을 하는데 꽤나 불편하다. 그래서 리듀서와 액션 관련 코드들을 하나의 파일에 몰아서 작성해보도록 하겠다. 이를 Ducks 패턴이라고 부른다.

 

counter 모듈 만들기

src 디렉터리에 modules 디렉터리를 만들고 그 안에 counter.js 파일을 생성하여 다음 코드를 작성한다.

modules/counter.js

/* 액션 타입 만들기 */
// Ducks 패턴을 따를땐 액션의 이름에 접두사를 넣어준다.
// 이렇게 하면 다른 모듈과 액션 이름이 중복되는 것을 방지 할 수 있다.
const SET_DIFF = 'counter/SET_DIFF';
const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASE';

/* 액션 생성함수 만들기 */
// 액션 생성함수를 만들고 export 키워드를 사용해서 내보내준다.
export const setDiff = diff => ({ type: SET_DIFF, diff });
export const increase = () => ({ type: INCREASE });
export const decrease = () => ({ type: DECREASE });

/* 초기 상태 선언 */
const initialState = {
  number: 0,
  diff: 1
};

/* 리듀서 선언 */
// 리듀서는 export default 로 내보내준다.
export default function counter(state = initialState, action) {
  switch (action.type) {
    case SET_DIFF:
      return {
        ...state,
        diff: action.diff
      };
    case INCREASE:
      return {
        ...state,
        number: state.number + state.diff
      };
    case DECREASE:
      return {
        ...state,
        number: state.number - state.diff
      };
    default:
      return state;
  }
}

 

todos 모듈 만들기

modules/todos.js

/* 액션 타입 선언 */
const ADD_TODO = 'todos/ADD_TODO';
const TOGGLE_TODO = 'todos/TOGGLE_TODO';

/* 액션 생성함수 선언 */
let nextId = 1; // todo 데이터에서 사용 할 고유 id
export const addTodo = text => ({
  type: ADD_TODO,
  todo: {
    id: nextId++, // 새 항목을 추가하고 nextId 값에 1을 더해줌
    text
  }
});
export const toggleTodo = id => ({
  type: TOGGLE_TODO,
  id
});

/* 초기 상태 선언 */
// 리듀서의 초기 상태는 꼭 객체타입일 필요 없다.
// 배열이여도 되고, 원시 타입 (숫자, 문자열, 불리언 이여도 상관 없다.
const initialState = [
  /* 앞으로 다음과 같이 구성된 객체를 이 배열 안에 넣을 것이다.
  {
    id: 1,
    text: '예시',
    done: false
  } 
  */
];

export default function todos(state = initialState, action) {
  switch (action.type) {
    case ADD_TODO:
      return state.concat(action.todo);
    case TOGGLE_TODO:
      return state.map(
        todo =>
          todo.id === action.id // id 가 일치하면
            ? { ...todo, done: !todo.done } // done 값을 반전시키고
            : todo // 아니라면 그대로 둠
      );
    default:
      return state;
  }
}

 

루트 리듀서 만들기

우리는 현재 두가지의 리덕스 모듈을 만들었다. 그래서 리듀서도 두개인데 한 프로젝트에 여러개의 리듀서가 있을때는 이를 한 리듀서로 합쳐서 사용한다. 합쳐진 리듀서를 루트 리듀서라고 부른다.

 

리듀서를 합치는 작업은 리덕스에 내장되어있는 combineReducers라는 함수를 사용한다.

이제 modules 디렉터리에 index.js 를 만들고 다음과 같이 코드를 작성한다.

modules/index.js

import { combineReducers } from 'redux';
import counter from './counter';
import todos from './todos';

const rootReducer = combineReducers({
  counter,
  todos
});

export default rootReducer;

제 리듀서가 합쳐졌다. 루트 리듀서가 만들어졌으면 이제 스토어를 만들어본다.

리덕스 스토어를 만드는 작업은 src 디렉터리의 index.js 에서 해주겠다.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { createStore } from 'redux';
import rootReducer from './modules';

const store = createStore(rootReducer); // 스토어를 만든다.
console.log(store.getState()); // 스토어의 상태를 확인해본다.

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();

스토어를 만들고 스토어의 상태를 출력해보았는데 이제 브라우저에서 어떤 결과가 나타났는지 확인해본다.

 

실행 결과

counter, todos 서브 리듀서의 상태가 합쳐졌다.

상태가 잘 출력된것을 확인 했으니 console.log(store.getState()); 코드는 이제 지워주면 된다.

 

리액트 프로젝트에 리덕스 적용하기

리액트 프로젝트에 리덕스를 적용 할 때에는 react-redux 라는 라이브러리를 사용해야한다.

해당 라이브러리를 설치하면 된다.

설치

npm install react-redux

 

그 다음에는 index.js 에서 Provider라는 컴포넌트를 불러와서 App 컴포넌트를 감싸주고 Provider의 props 에 store 를 넣어준다.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from './modules';

const store = createStore(rootReducer); // 스토어를 만든다.

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();

Provider로 store를 넣어서 App 을 감싸게 되면 우리가 렌더링하는 그 어떤 컴포넌트던지 리덕스 스토어에 접근 할 수 있게 된다.

 

+ Recent posts