[React] CRA에서 redux-toolkit과 redux-saga 초기 설정하기
Front-End/React

[React] CRA에서 redux-toolkit과 redux-saga 초기 설정하기

 

 

create-react-app

create-react-app은 사용자가 쉽게 개발을 할 수 있도록 개발 환경을 제공해주는 도구이다. CRA에는 브라우저 호환성을 위한 바벨과 웹팩과 등의 다양한 패키지가 포함되어 있으며, 테스트 시스템, ES6+ 문법, CSS 후처리 등 거의 필수라고 할 수 있는 개발 환경도 구축해 준다.

npx create-react-app '프로젝트 이름'

위의 명령어로 우리는 바로 실행 가능한 react앱을 생성할 수 있다.

 

 


이제 create-react-app으로 리액트 프로젝트를 생성하고, redux와 redux-saga 셋팅까지 완료해보자.

 

 

React 프로젝트 생성

먼저, CRA로 새로운 프로젝트를 만들어준다.

 

다음과 같은 메세지가 나오면 성공적으로 프로젝트가 만들어졌다는 뜻이다.

 

 

 

 

 

필요없는 파일들은 지워줘야한다.

// package.json

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
  },

package.json파일 scripts부분에서 test, eject를 지워주었다.

 

 

src폴더에 파일을 App.js, index.js만 남기고 모두 제거해준다.

위 절차를 마치면 디렉터리 구조는 다음과 같다.



 

각각의 파일 내용도 필요한 부분만을 남겨준다.

// index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
    <App />,
  document.getElementById("root")
);
// App.js

function App() {
  return <div className="App"></div>;
}

export default App;

 

 

이제 프로젝트가 정상적으로 작동하는지 확인해보자.

고리타분하지만 개발의 첫 시작에 빠질 수 없는 문장인 “Hello World”를 화면에 표시할 것이다.

// App.js

function App() {
  return <div className="App"> Hello World! </div>;
}

App.js를 다음과 같이 바꿔주고, 터미널에 npm start를 실행한다.

 

브라우저에 Hello World! 가 아주 선명하게 찍혀있는 걸 확인할 수 있다.

 

 

이제 redux-toolkit과 saga를 프로젝트에 셋팅해보자.

 

 

 

redux-toolkit과 saga 초기설정


우선, redux, redux-tookit, redux-saga 이 세가지를 npm을 통해 설치해야한다.

 npm install redux @reduxjs/toolkit redux-saga

 

코드를 작성하기 전에, redux와 관련된 모든 코드를 넣을 폴더를 생성해준다. 여기서는 redux라는 이름의 폴더를 만들어주었다.

이 redux 폴더 안에서 코드를 나누는 방법은 다양하지만, 본인은 기능별로 폴더를 나누는 방식을 선호하기 때문에 여기에서도 기능별로 나누겠다.


modal창을 띄우는 예제를 만드는 중이었기 때문에 modal 이라는 폴더를 생성한 후 그 안에 slice.jssaga.js 파일을 각각 생성해준다.

 

 

 

redux slice 만들기

// slice.js

import { createSlice } from '@reduxjs/toolkit';

// 초기 state
const initialState = {

};

// slice
const modal = createSlice({
  name: 'modal',
  initialState,
  reducers: {
    openModal : (state, action) => {

    },
    closeModal : (state, action) => {

    }
  }
});

export const { openModal, closeModal } = modal.actions;
export const modalReducer = modal.reducer;

* redux-toolkit의 createSlice는 초기 상태값, 액션, 리듀서를 하나의 객체에 담아 전달받는다.

 

 

saga 만들기

// saga.js

import { createAction } from "@reduxjs/toolkit";
import { takeLatest } from "redux-saga/effects";

export const deleteSomething = createAction("modal/deleteSomething");

function* deleteSaga() {
  try {
    yield console.log(" connect saga...");
  } catch (error) {}
}

export function* modalSaga() {
  yield takeLatest(deleteSomething, deleteSaga);
}

deleteSomething 이라는 액션이 발생하면, deleteSaga 제너레이터를 실행해준다.

* redux-sagatakeLatest는 가장 마지막으로 발생한 액션에 대해서만 응답한다.

 

그리고 index.js

export * from "./slice";
export * from "./saga";

modal/index.js 파일 안에는 위와 같이 작성한다.

 

디렉토리 별로 index 파일을 만들어주면 여러 이점이 있는데, 그 중 하나는 다른 파일에서 slice나 saga를 import시 import * from '../modal/slice' 가 아닌 'import * from '../modal' 로 경로를 줄여서 작성할 수 있다는 점이다.

 

 

 

루트 reducer 만들기

프로젝트가 커질수록 📁redux 폴더 안에는 기능별로 분류된 많은 양의 slice와 saga들이 존재할 것이다. 이들을 통틀어 관리하는 루트 Reducer를 생성해줘야한다.

📁redux 폴더에 index.js를 생성해준다.

import { configureStore } from '@reduxjs/toolkit';
import { modalReducer } from './modal';

const store = configureStore({ reducer: modalReducer});

 

 

 

루트 saga 만들기

루트 saga 또한 redux/index.js 파일 내에 만들어준다.

import createSagaMiddleware from 'redux-saga';
import { all } from 'redux-saga/effects';
import { modalReducer, modalSaga } from './modal';

const sagaMiddleware = createSagaMiddleware();

// root saga 정의
const rootSaga = function* () {
    yield all([ modalSaga() ]);
};


// saga 실행
sagaMiddleware.run(rootSaga);

createSagaMiddleware를 통해 saga 미들웨어 인스턴스를 생성해준다.
* redux-sagaall 함수는 여러 사가를 합쳐주는 역할을 한다.

export const store = configureStore({
  reducer: modalReducer,
  middleware: [sagaMiddleware],
});

앞서 만든 store에 sagaMiddleware를 연결시켜준다.

/ redux/index.js

import { configureStore } from "@reduxjs/toolkit";
import createSagaMiddleware from "@redux-saga";
import { modalReducer, modalSaga } from "./modal";
import { all } from "redux-saga/effects";

const sagaMiddleware = createSagaMiddleware();

const createStore = () => {
  const store = configureStore({
    reducer: modalReducer,
    middleware: [sagaMiddleware],
  });

  const rootSaga = function* () {
    yield all([modalSaga()]);
  };

  sagaMiddleware.run(rootSaga);

  return store;
};

export default createStore;

전체적인 코드는 위와 같다.

 

 

 

이제 최상위의 index.js에 store를 연결해준다.

// src/index.js

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import App from "./App";
import createStore from "./redux";


const store = createStore();
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

 

 

 

 

 

이렇게 초기 설정이 끝났다.

여기에 나온 코드는 정말 필요한 뼈대만을 연결해준 거고, 이제 프로젝트를 진행하면서 필요한 것들을 하나씩 붙여나가면 된다.