관리 메뉴

거니의 velog

(32) 리덕스 툴킷 1 본문

SpringBoot_React 풀스택 프로젝트

(32) 리덕스 툴킷 1

Unlimited00 2024. 3. 6. 16:51

* 컴포넌트로 개발할 때 가장 주의를 기울여야 하는 설계컴포넌트들의 전체적인 구조와 컴포넌트 간의 통신이라고 할 수 있다. 리액트의 컴포넌트는 고유한 상태를 유지할 수 있지만, 여러 컴포넌트 사이에서 발생하는 공유가 필요한 상태 데이터를 관리하기 위해서는 Context나 Redux(이하, 리덕스) 등을 활용한다.

* 리덕스를 활용한 상태 관리는 개발을 좀 더 쉽게 할 수 있는 리덕스 툴킷(Redux toolkit)이라는 라이브러리를 활용할 수 있는데 예제에서는 이를 이용해서 사용자의 로그인 상태를 처리하고 JWT를 사용하는 API 서버의 접근 방식에 관해서 알아본다.

* 이번 장의 개발 목표는 다음과 같다.

1. 리덕스 툴킷 설정

2. 컴포넌트 간의 상태 공유

3. 비동기 처리와 리덕스 툴킷

4. 쿠키를 활용한 상태 보관

1. 리덕스 툴킷 설정

* 리덕스는 리액트에서 가장 많이 사용하는 애플리케이션 내에서 상태를 관리하는 라이브러리이다. 애플리케이션 내에서의 상태라는 의미가 조금 낯설다면 모바일 앱에서 여러 화면이 있고, 앱 내에 특정한 데이터가 있다면 여러 화면에서 같이 사용되거나 변경되는 것과 유사하다고 생각하면 된다.

* 리덕스는 아래 주소에서 개념과 사용법을 배울 수 있다.

https://ko.redux.js.org/

 

Redux - 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너. | Redux

자바스크립트 앱을 위한 예측 가능한 상태 컨테이너.

ko.redux.js.org

* 리덕스는 현재 리덕스 툴킷이라는 것을 이용하도록 권장하고 있다.

* 프로젝트에 리덕스 툴킷을 설치하려면 @reduxjs/toolkit과 react-redux 라이브러리를 추가해야 한다. 프로젝트에서 아래 CLI를 이용해서 라이브러리를 추가한다.

$ npm install @reduxjs/toolkit react-redux

* 추가 후에는 package.json 에서 설치된 버전을 확인한다.


(1) 스토어 설정

* 리덕스의 가장 간단한 개념은 '애플리케이션당 하나의 스토어'와 컴포넌트들의 데이터 공유이다.

* 스토어는 마치 집안에 있는 금고와 같아서 집안 구성원(컴포넌트)이 함께 사용하는 메모리 공간이다. 따라서 애플리케이션에는 하나의 스토어를 지정해서 사용하게 된다.

* 프로젝트 src 폴더 내에 store.js 파일을 추가한다.

* store.js 파일은 Store 객체를 생성하기 위한 함수로 리덕스 툴킷의 configureStore()를 사용한다.

import { configureStore } from "@reduxjs/toolkit";

export default configureStore({
  reducer: {},
});

* configureStore() 의 파라미터에는 설정에 필요한 정보들을 객체로 전달하는데 reducer 라는 속성으로 리듀서(Reducer)라고 불리는 함수들을 지정해서 사용하게 된다. configureStore() 에서 생성되는 Store를 애플리케이션에 적용하기 위해서 프로젝트의 index.js 파일을 아래와 같이 수정한다.

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./store";

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

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

* 이 상태에서 프로젝트를 실행해 보면 개발자 도구 내에서 에러가 발생하는데 원인은 스토어의 설정은 되었지만 아직 상태 데이터 관리를 담당하는 리듀서가 없기 때문이다.


(2) 슬라이스와 리듀서

* 스토어가 애플리케이션 내의 공유되는 상태 데이터(이하, 애플리케이션 상태)를 의미한다면 이에 대한 처리를 담당하는 것은 리듀서라는 함수이다. 리듀서는 비유하자면 금고를 지키는 사람과 비슷하다. 누군가 금고에 어떤 물건을 넣거나 빼듯이 리듀서는 현재 스토어에 있는 애플리케이션의 상태를 가공하는 역할을 한다.

* 컴포넌트들은 액션(Action)이라는 것을 이용해서 리듀서를 호출하게 되는데 리듀서에서는 액션의 페이로드(payload) 값을 처리해서 앞으로 보관해야 할 애플리케이션 상태 데이터를 반환하게 된다. 예전에는 리듀서에게 액션과 리듀서를 별도로 작성했지만, 리덕스 툴킷에서는 슬라이스(slice)라는 이름으로 한 번에 작성할 수 있다.

* 프로젝트 내에 slices 폴더를 생성하고 loginSlice.js 파일을 작성한다.

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

const initState = {
  email: "",
};

const loginSlice = createSlice({
  name: "LoginSlice",
  initialState: initState,
  reducers: {
    login: (state, action) => {
      console.log("login.....");
    },
    logout: (state, action) => {
      console.log("logout....");
    },
  },
});

export const { login, logout } = loginSlice.actions;

export default loginSlice.reducer;

* loginSlice에는 애플리케이션이 유지해야 하는 상태와 이를 처리하기 위한 리듀서 함수들을 정의할 수 있다. 예제는 email 속성을 가진 객체를 사용해서 email 값이 있는 경우에는 로그인한 상태로 간주하고, 그렇지 않으면 로그인이 되지 않은 상태로 간주한다. loginSlice 내부에 선언된 함수들을 외부에 노출하기 위해서 export 처리한다.

* 작성된 슬라이스는 store.js에 설정해 준다.

import { configureStore } from "@reduxjs/toolkit";
import loginSlice from "./slices/loginSlice";

export default configureStore({
  reducer: {
    loginSlice: loginSlice,
  },
});

* 프로젝트를 실행하고 브라우저에서 이전의 에러 데이터가 없어졌는지 확인한다.