React/Redux 마스터

Redux Toolkit 성능개선 예제: 실제 애플리케이션 생성부터 실행까지

atomicdev 2024. 10. 25. 10:38
728x90

Redux Toolkit을 사용한 성능 최적화

Redux Toolkit을 사용하여 복잡한 설정 과정을 간소화하고, 각 기능을 사용하여 성능을 최적화하는 방법을 알아보겠습니다. 이번 포스팅에서는 React 애플리케이션 생성부터 실행까지의 세부 과정과 파일 구조를 함께 설명하겠습니다.

1. React 애플리케이션 생성 및 Redux Toolkit 설치

먼저 Redux Toolkit을 사용할 애플리케이션을 생성합니다.

npx create-react-app my-redux-toolkit-app
cd my-redux-toolkit-app
npm install @reduxjs/toolkit react-redux

2. 전체 파일 구조

애플리케이션의 전체 파일 구조는 다음과 같습니다:

my-redux-toolkit-app/
├── src/
│   ├── app/
│   │   └── store.js
│   ├── components/
│   │   └── Counter.js
│   ├── features/
│   │   ├── counter/
│   │   │   └── counterSlice.js
│   │   └── user/
│   │       └── userSlice.js
│   ├── selectors/
│   │   └── counterSelectors.js
│   ├── App.js
│   └── index.js
└── package.json

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

createSlice를 사용하여 상태 관리를 간소화하고 리듀서와 액션을 함께 정의하여 코드의 복잡성을 줄입니다.

  • src/features/counter/counterSlice.js 파일을 생성하고 다음과 같이 작성합니다:
// src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    count: 0,
  },
  reducers: {
    increment: (state) => {
      state.count += 1;
    },
    decrement: (state) => {
      state.count -= 1;
    },
  },
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

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

configureStore를 사용하면 기본적으로 DevTools와 미들웨어가 설정되어 있어 별도의 설정 없이도 사용이 가능합니다.

rc/app/store.js 파일을 생성하고 다음과 같이 작성합니다:

// src/app/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';

const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

export default store;

 

5. useSelector로 필요한 상태만 구독하여 최적화

useSelector를 사용하여 컴포넌트에서 필요한 상태만 선택적으로 구독함으로써 불필요한 리렌더링을 줄일 수 있습니다.

  • src/components/Counter.js 파일을 생성하고 다음과 같이 작성합니다:
    // src/components/Counter.js
    import React from 'react';
    import { useSelector, useDispatch } from 'react-redux';
    import { increment, decrement } from '../features/counter/counterSlice';
    
    function Counter() {
      const count = useSelector((state) => state.counter.count);
      const dispatch = useDispatch();
    
      return (
        <div>
          <h1>{count}</h1>
          <button onClick={() => dispatch(increment())}>Increment</button>
          <button onClick={() => dispatch(decrement())}>Decrement</button>
        </div>
      );
    }
    
    export default Counter;

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

createAsyncThunk를 사용하여 비동기 작업을 간단하게 관리할 수 있으며, 상태 관리가 더욱 직관적입니다.

  • src/features/user/userSlice.js 파일을 생성하고 다음과 같이 작성합니다:
    // src/features/user/userSlice.js
    import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
    
    export const fetchUser = createAsyncThunk('user/fetchUser', async (userId) => {
      const response = await fetch(`/api/user/${userId}`);
      return response.json();
    });
    
    const userSlice = createSlice({
      name: 'user',
      initialState: {
        user: null,
        status: 'idle',
      },
      reducers: {},
      extraReducers: (builder) => {
        builder
          .addCase(fetchUser.pending, (state) => {
            state.status = 'loading';
          })
          .addCase(fetchUser.fulfilled, (state, action) => {
            state.status = 'succeeded';
            state.user = action.payload;
          })
          .addCase(fetchUser.rejected, (state) => {
            state.status = 'failed';
          });
      },
    });
    
    export default userSlice.reducer;

7. Reselect를 사용한 셀렉터 성능 최적화

Reselect을 사용하여 메모이제이션된 셀렉터를 생성함으로써, 상태 변경이 있을 때 불필요한 계산을 방지하고 성능을 개선할 수 있습니다.

src/selectors/counterSelectors.js 파일을 생성하고 다음과 같이 작성합니다:

// src/selectors/counterSelectors.js
import { createSelector } from 'reselect';

const selectCounter = (state) => state.counter;

export const selectCount = createSelector(
  [selectCounter],
  (counter) => counter.count
);

8. 전체 애플리케이션 통합 및 실행

이제 애플리케이션을 통합하여 실행 가능한 상태로 만듭니다.

  1. src/index.js 파일에서 스토어를 애플리케이션에 제공하도록 수정합니다:
    // src/index.js
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { Provider } from 'react-redux';
    import store from './app/store';
    import App from './App';
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <Provider store={store}>
        <App />
      </Provider>
    );
  2. src/App.js 파일에서 Counter 컴포넌트를 추가합니다:
    // src/App.js
    import React from 'react';
    import Counter from './components/Counter';
    
    function App() {
      return (
        <div className="App">
          <h1>Redux Toolkit Counter App</h1>
          <Counter />
        </div>
      );
    }
    
    export default App;
  3. 애플리케이션 실행하기
    npm start
    브라우저에서 http://localhost:3000으로 접속하면 간단한 카운터 애플리케이션이 실행됩니다. 증가 및 감소 버튼을 눌러 상태가 변경되는 것을 확인할 수 있습니다.
  4. 이제 애플리케이션을 실행하여 최적화된 카운터 기능을 테스트해 봅시다.
    Redux Toolkit을 사용한 React 애플리케이션의 개선된 워크플로우

요약

  • 기존 방식: 복잡한 스토어 설정, 비동기 액션 처리의 어려움, 상태 구독의 비효율성 등으로 인해 성능이 저하될 수 있었습니다.
  • Redux Toolkit 방식: createSlice, configureStore, useSelector, createAsyncThunk, Reselect 등을 사용하여 코드의 복잡성을 줄이고 성능을 최적화할 수 있었습니다.

실습 코드 요약

기존 방식에서 발생할 수 있는 성능 문제를 해결하기 위해 Redux Toolkit의 다양한 도구들을 사용하여 최적화할 수 있었습니다. 이러한 도구들을 사용하면 코드가 간결해지고 유지보수가 쉬워지며, 성능도 크게 향상됩니다.

728x90