개발 방법론 & 아키텍쳐

Redux 단점 보완: 성능 개선

atomicdev 2024. 10. 15. 15:55
728x90

Redux Toolkit을 활용하여 Redux의 성능 문제를 해결하는 방법을 중심으로 설명드리겠습니다. Redux Toolkit은 Redux의 공식 도구로, 성능 최적화 및 초기 설정의 복잡성을 줄이는 데 큰 도움을 줍니다. 성능 문제를 해결하는 핵심은 불필요한 상태 업데이트와 리렌더링을 줄이는 것이며, Redux Toolkit을 통해 쉽게 이를 달성할 수 있습니다.

React 애플리케이션에서 Redux Toolkit으로 성능 개선

1. createSlice로 상태 관리 간소화 및 불필요한 렌더링 방지

Redux Toolkit의 createSlice 함수는 액션과 리듀서를 하나로 결합하여 더 간단하고 명확하게 상태를 관리할 수 있습니다. 이를 통해 코드의 복잡성을 줄이고, 상태를 효율적으로 관리함으로써 성능 최적화가 가능합니다.

예시 코드:

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

const initialState = {
  isAuthenticated: false,
  userData: null,
};

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    login: (state, action) => {
      state.isAuthenticated = true;
      state.userData = action.payload;
    },
    logout: (state) => {
      state.isAuthenticated = false;
      state.userData = null;
    },
  },
});

export const { login, logout } = userSlice.actions;
export default userSlice.reducer;
 

createSlice를 사용하면 상태와 리듀서를 하나의 슬라이스로 묶어 불필요한 코드 작성을 줄이고, 상태 변경 시 불변성을 자동으로 유지해줍니다. 이는 상태 관리가 더 간단해질 뿐 아니라 성능적으로도 효율적입니다.

2. configureStore로 DevTools 및 미들웨어 설정 최적화

Redux Toolkit의 configureStore는 Redux DevTools 및 미들웨어 설정을 자동으로 처리해 줍니다. 이로 인해 별도의 설정 없이도 DevTools를 사용한 디버깅과 성능 모니터링이 가능하며, 미들웨어인 redux-thunk가 기본적으로 포함되어 있어 비동기 액션 처리도 간편합니다.

예시 코드:

import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';

const store = configureStore({
  reducer: {
    user: userReducer,
  },
});

export default store;
 

configureStore는 DevTools를 자동으로 포함하여 성능 분석과 상태 변화를 시각적으로 쉽게 확인할 수 있습니다. 또한 기본적으로 redux-thunk가 포함되어 있어 비동기 작업 처리 시 성능 최적화를 위한 별도의 설정이 필요 없습니다.

3. useSelector 최적화

Redux Toolkit을 사용할 때도 상태를 선택할 때 useSelector 훅을 활용할 수 있습니다. 그러나 상태의 일부분만 선택하는 방식으로 최적화해야 성능 문제가 발생하지 않습니다. 전체 상태를 선택하지 말고, 필요한 부분만 선택하는 것이 중요합니다.

최적화 예시:

import { useSelector } from 'react-redux';

const userName = useSelector((state) => state.user.userData?.name);
 

불필요하게 전체 상태를 선택하게 되면 상태가 변경될 때마다 컴포넌트가 다시 렌더링됩니다. Redux Toolkit과 함께 필요한 상태만 선택해 불필요한 리렌더링을 방지하는 것이 성능 최적화의 중요한 방법입니다.

4. createAsyncThunk를 활용한 비동기 액션 최적화

Redux Toolkit은 비동기 액션을 처리할 때 createAsyncThunk를 제공하여 성능 최적화를 돕습니다. 비동기 로직을 더 깔끔하게 관리하고, 상태 변화에 대한 로직을 자동으로 처리할 수 있습니다.

예시 코드:

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

// 비동기 작업 생성
export const fetchUserData = createAsyncThunk('user/fetchUserData', async (userId) => {
  const response = await fetch(`/api/user/${userId}`);
  return response.json();
});

const userSlice = createSlice({
  name: 'user',
  initialState: {
    isLoading: false,
    userData: null,
    error: null,
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserData.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(fetchUserData.fulfilled, (state, action) => {
        state.isLoading = false;
        state.userData = action.payload;
      })
      .addCase(fetchUserData.rejected, (state, action) => {
        state.isLoading = false;
        state.error = action.error.message;
      });
  },
});

export default userSlice.reducer;
 

createAsyncThunk는 비동기 상태(pending, fulfilled, rejected)를 자동으로 관리해주어, 비동기 로직을 더욱 간단하고 명확하게 처리할 수 있습니다. 이를 통해 비동기 작업 시 성능을 최적화할 수 있습니다.

5. Reselect을 사용한 셀렉터 성능 최적화

Redux Toolkit과 함께 Reselect 라이브러리를 사용하면 상태 선택 시 메모이제이션을 통해 성능을 더욱 개선할 수 있습니다. 이는 상태가 변경되지 않았을 때 불필요한 계산과 리렌더링을 방지합니다.

예시 코드:

npm install reselect
 
import { createSelector } from 'reselect';

const selectUser = (state) => state.user;

export const selectUserName = createSelector(
  [selectUser],
  (user) => user.userData?.name
);

 

Reselect을 사용하면 상태가 변경되지 않는 한 셀렉터를 메모이제이션하여 불필요한 리렌더링과 상태 계산을 방지할 수 있습니다. 이 방식은 특히 대규모 애플리케이션에서 성능에 큰 이점을 제공합니다.

결론

Redux Toolkit을 활용하면 Redux의 복잡한 초기 설정과 성능 문제를 크게 개선할 수 있습니다. **createSlice, configureStore, createAsyncThunk**와 같은 도구를 사용하면 코드를 간결하게 유지하면서도 성능을 최적화할 수 있습니다. 또한 Reselect을 사용하여 상태 선택을 최적화하고 불필요한 렌더링을 방지하는 것도 성능 향상에 중요한 방법입니다.

728x90