[React 숙련] RTK란?

조아영·2025년 3월 5일

📌

리덕스 툴킷(Redux Toolkit, RTK)은 기존 리덕스를 개량한 공식 도구.

기존 리덕스 사용 시 문제점

  • ducks 패턴으로 인한 코드 증가
  • 반복 코드 많음
  • 설정 복잡함

리덕스 팀이 이를 해결하기 위해 RTK 제공. Redux의 공식 권장 방식.
코드는 줄이고, 사용성은 개선한 버전.

기존 리덕스와 구조 동일. 새로운 개념 아님.
달라진 점은 API. Action, Action Creator, Reducer 요소들을 자동화해서
개발자가 직접 작성할 코드 감소함.

컴포넌트 사용 방식 동일. useSelector, useDispatch 그대로 사용함.
변경 대상은 모듈 파일뿐.

◼ 일반 리덕스와 RTK 코드비교

툴킷 설치

npm add react-redux @reduxjs/toolkit

counter 코드 비교

일반 리덕스

  • Action Type, Action Creator 별도 생성.
  • Reducer에서 값을 어떻게 변화시킬지 작성.
// Action Value
const ADD_NUMBER = "ADD_NUMBER";
const MINUS_NUMBER = "MINUS_NUMBER";

// Action Creator
export const addNumber = (payload) => {
  return {
    type: ADD_NUMBER,
    payload,
  };
};

export const minusNumber = (payload) => {
  return {
    type: MINUS_NUMBER,
    payload,
  };
};

// Initial State
const initialState = {
  number: 0,
};

// Reducer
const counter = (state = initialState, action) => {
  switch (action.type) {
    case ADD_NUMBER:
      return {
        number: state.number + action.payload,
      };
    case MINUS_NUMBER:
      return {
        number: state.number - action.payload,
      };
    default:
      return state;
  }
};

// export default reducer
export default counter;

RTK

  • Action Value, Action Creator 직접 생성 X.
  • Action Value, Action Creator, Reducer가 통합됨.

세가지 요소 통합을 위해 createSlice 사용함. Slice 하나로 세 요소 생성됨.

// src/redux/slices/counterSlice.js

import { createSlice } from "@reduxjs/toolkit"; // ✅️ 파일위치추가

// Initial State
const initialState = {
  number: 0,
};

// ✅️ createSlice
const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    addNumber: (state, action) => {
      state.number = state.number + action.payload;
    },

    minusNumber: (state, action) => {
      state.number = state.number - action.payload;
    },
  },
});

// ✅️ Action Creator는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;
// ✅️ Reducer는 configStore에 등록하기 위해 export default
export default counterSlice.reducer;

슬라이스는 createSlice 라는 API를 통해 만듬.
인자로 설정정보를 객체로 받는데,
필수값 name, initialState, reducers가 있음.

// createSlice API 뼈대
const counterSlice = createSlice({
	name: '', // 모듈의 이름
	initialState : {}, // 모듈의 초기상태 값
	reducers : {}, // 모듈의 Reducer 로직
})

counterSlice의 reducers 객체 안 함수는 두 가지 역할을 가짐.
리듀서 로직 역할, Action Creator 역할임.
그리고 함수 이름을 따서 Action Value도 자동 생성 됨.
따라서 Reducer만 작성하면 됨.

// counterSlice.js의 Slice구조
const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    // 리듀서 안에서 만든 함수 자체가 리듀서의 로직이자 Action Creator가 됨.
    addNumber: (state, action) => {
      state.number = state.number + action.payload;
    },

    minusNumber: (state, action) => {
      state.number = state.number - action.payload;
    },
  },
});

일반 리덕스에서는 Action Creator를 각각 export 했음. RTK에서는 아래 코드로 동일하게 처리 가능함.
리듀서 로직을 추가하면 함수만 추가하면 됨. 추가된 함수는 Action Creator로 함께 export 가능함.

// ✅️ Action Creator는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;
// ✅️ Reducer는 configStore에 등록하기 위해 export default
export default counterSlice.reducer;

configStore 비교

일반 리덕스

일반 리덕스에서는 createStore와 combineReducers 사용함.
여러 리듀서를 하나로 합친 뒤 store 생성함.

import { createStore, combineReducers } from "redux";
import counter from "../modules/counter";

const rootReducer = combineReducers({
  counter,
});
const store = createStore(rootReducer);
export default store;

RTK

RTK에서도 역할은 동일함. store 설정 방식만 간결해짐.
기존의 combineReducers + createStore 조합이
configureStore 하나로 대체됨.
여러 Slice를 reducer 객체에 등록하면 됨.

// src/redux/slices/config/configStore.js

import { configureStore } from "@reduxjs/toolkit";
// import 해온 것은 slice.reducer
import counter from "../slices/counterSlice";
import todos from "../slices/todosSlice";

// 모듈(Slice)이 여러개인 경우
// 추가할때마다 reducer 안에 각 모듈의 slice.reducer를 추가해줘야 함.
// 아래 예시는 하나의 프로젝트 안에 counter 기능과 todos 기능이 모두 있고
// 이것을 각각 모듈로 구현한 다음에 아래 코드로 2개의 모듈을 스토어에 연결해준 것.
 
const store = configureStore({
  reducer: { 
	  counter: counter, 
	  todos: todos 
	},
});

export default store;

폴더 구조

위에서 작성한 파일들의 구조. slices 폴더 내부 파일명은 자유.

  • counter.js, todos.js
  • counterSlice.js, todosSlice.js

둘다 가능. 팀 컨벤션에 맞추는것이 중요함.

├node_modules
├public
├src
│├redux
││├config
│││└configStore.js
││└slices
││ ├counterSlice.js
││ └todoSlice.js
│├App.js
│└index.js
├.gitignore
├package.json
└README.md

◼ Redux Devtools

리덕스를 사용하면 Redux Devtools 사용 가능.
상태 관리 전용 개발 도구. 다른 상태 관리 라이브러리에서는 보기 힘든 개발툴.
현재 프로젝트의 state 상태, 어떤 액션이 일어났을 때 그 액션이 무엇이고 그것으로 인해 state가 어떻게 변경되었는지 등을 확인할 수 있음.
상태 흐름을 한눈에 확인 가능함. 디버깅에 매우 유용함.

사용법

  1. 구글 웹스토어에서 플러그인 설치.
    🔗 Redux Devtools설치 : 링크 바로가기
  2. 리액트 프로젝트에서 리덕스 사용 시 플러그인 아이콘에 녹색 표시됨. 개발자도구 탭에서 Redux라는 탭 생성됨.
  3. Redux Devtools를 켜둔 상태로 실행.
  4. 더하기 버튼 클릭 시 addNumber액션이 dispatch 됨. devtools에서 액션 로그확인 가능. 해당 액션으로 변경된 state 확인 가능.

프로젝트 규모가 커질수록 로그 확인 어려움. Redux Devtools 사용 시 상태 추적 쉬움. 디버깅 효율 크게 향상됨.
RTK는 Devtools 기본 포함됨. 추가 설정 필요 없음. 일반 리덕스는 별도 설정 필요함.

◼ Flux 패턴

Facebook에 의해 개발된 애플리케이션 아키텍처로 주로 React와 함께 사용.
데이터의 단방향 흐름을 강조.

Q : 단방향 흐름이란?
A : Action → Dispatcher → Store → View
위 순서로 데이터가 흐름. 상태 변경 흐름 예측 가능함.
복잡한 애플리케이션 관리에 유리함.

  1. Action : 상태변경 요청 객체.
    상태 변화를 일으킬 때 사용하는 간단한 객체.
    사용자 인터페이스에서 발생한 사용자의 행동을 액션으로 표현하고
    이를 디스패처를 통해 스토어로 전달.
  2. Dispatcher : 중앙전달자.
    애플리케이션 내 모든 데이터 흐름을 관리하는 중앙 허브 역할.
    액션들이 발생하면 디스패처를 통해 스토어로 전달.
  3. Store : 상태와 로직관리.
    애플리케이션의 상태(데이터)와 로직을 보유.
    스토어는 디스패처를 통해 전달된 액션에 반응하여 상태를 변경하고
    변경 사항을 뷰에 알림.
  4. View (React Components) : UI 컴포넌트.
    사용자 인터페이스를 구성하는 React 컴포넌트들.
    스토어에서 상태가 변경 시 뷰는 이를 반영하여 사용자 인터페이스를 업데이트.

Ducks 패턴과 Flux 패턴

Ducks 패턴 : 코드 구조 단순화 목적.

Flux 패턴 : 데이터 흐름 체계화 목적.

공통점 : 상태 관리 구조화, 데이터 흐름 정리

0개의 댓글