Post

리액트의 렌더링 성능 향상을 위해 어떻게 해야 하나?

안녕하세요! 오늘은 React 애플리케이션에서 렌더링 성능을 향상시키기 위한 방법에 대해 알아보겠습니다. 성능 최적화는 사용자 경험을 향상시키고 애플리케이션의 반응성을 높이는 데 매우 중요합니다.

리액트의 렌더링 성능 향상을 위해 어떻게 해야 하나?

1. 컴포넌트 리렌더링 최소화

1.1 React.memo

React.memo를 사용하여 함수형 컴포넌트의 불필요한 리렌더링을 방지할 수 있습니다. React.memo는 props가 변경되지 않으면 컴포넌트를 리렌더링하지 않습니다.

1
2
3
4
5
6
7
8
import React from 'react';

const MyComponent = React.memo(({ value }) => {
    console.log('Component rendered');
    return <div>{value}</div>;
});

export default MyComponent;

1.2 shouldComponentUpdate

클래스형 컴포넌트에서는 shouldComponentUpdate 메서드를 사용하여 리렌더링을 제어할 수 있습니다. 이 메서드는 컴포넌트가 리렌더링되어야 할지 여부를 결정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { Component } from 'react';

class MyComponent extends Component {
    shouldComponentUpdate(nextProps, nextState) {
        return nextProps.value !== this.props.value;
    }

    render() {
        console.log('Component rendered');
        return <div>{this.props.value}</div>;
    }
}

export default MyComponent;

2. 최적화된 상태 관리

2.1 불필요한 상태 제거

상태는 최소한으로 유지하고, 필요한 데이터만 상태로 관리합니다. 불필요한 상태는 컴포넌트의 리렌더링을 초래할 수 있습니다.

2.2 useReducer 사용

상태가 복잡해지면 useReducer를 사용하여 상태 관리 로직을 컴포넌트 외부로 분리할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
    switch (action.type) {
        case 'increment':
            return { count: state.count + 1 };
        case 'decrement':
            return { count: state.count - 1 };
        default:
            throw new Error();
    }
}

function Counter() {
    const [state, dispatch] = useReducer(reducer, initialState);

    return (
        <div>
            <p>Count: {state.count}</p>
            <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
            <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
        </div>
    );
}

export default Counter;

3. 리소스 최적화

3.1 코드 스플리팅

코드 스플리팅을 통해 애플리케이션의 초기 로딩 시간을 줄일 수 있습니다. React.lazy와 Suspense를 사용하여 동적으로 컴포넌트를 임포트할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Suspense, lazy } from 'react';

const Header = lazy(() => import('./Header'));

function App() {
    return (
        <Suspense fallback={<div>Loading...</div>}>
            <Header />
        </Suspense>
    );
}

export default App;

3.2 이미지 최적화

이미지는 적절한 크기로 조정하고, 웹에서 사용하기 좋은 형식으로 변환하여 로딩 시간을 줄입니다. 또한, lazy loading을 사용하여 이미지가 화면에 나타날 때 로드되도록 합니다.

1
2
3
const ImageComponent = () => (
    <img src="image.jpg" alt="description" loading="lazy" />
);

4. 메모이제이션

4.1 useMemo

useMemo 훅을 사용하여 연산 비용이 큰 계산의 결과를 메모이제이션할 수 있습니다. 이 훅은 의존성 배열의 값이 변경되지 않는 한, 이전 계산 결과를 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
import React, { useMemo } from 'react';

function ExpensiveComputation({ num }) {
    const compute = (n) => {
        console.log('Computing...');
        return n * 2;
    };

    const result = useMemo(() => compute(num), [num]);

    return <div>Result: {result}</div>;
}

4.2 useCallback

useCallback 훅을 사용하여 함수의 메모이제이션을 통해 성능을 최적화할 수 있습니다. 이 훅은 의존성 배열의 값이 변경되지 않는 한, 이전에 생성된 함수를 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { useState, useCallback } from 'react';

const Button = React.memo(({ handleClick }) => {
    console.log('Button rendered');
    return <button onClick={handleClick}>Increment</button>;
});

function App() {
    const [count, setCount] = useState(0);

    const increment = useCallback(() => {
        setCount(count + 1);
    }, [count]);

    return (
        <div>
            <p>Count: {count}</p>
            <Button handleClick={increment} />
        </div>
    );
}

5. 불필요한 렌더링 방지

5.1 Key Props 사용

리스트를 렌더링할 때 고유한 key를 사용하여 React가 각 요소를 고유하게 식별하고, 불필요한 리렌더링을 방지할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' },
];

const List = () => (
    <ul>
        {items.map(item => (
            <li key={item.id}>{item.name}</li>
        ))}
    </ul>
);

결론

React 애플리케이션의 성능을 최적화하기 위해서는 컴포넌트의 리렌더링을 최소화하고, 최적화된 상태 관리를 구현하며, 리소스를 효율적으로 관리하는 것이 중요합니다. 메모이제이션과 불필요한 렌더링 방지 기법을 활용하면 애플리케이션의 성능을 크게 향상시킬 수 있습니다. 이러한 방법들을 적용하여 더욱 빠르고 반응성 높은 React 애플리케이션을 개발해 보세요.

오늘도 제 글을 읽어주셔서 감사합니다. 다음 시간에 더 유익한 주제로 찾아뵙겠습니다.

This post is licensed under CC BY 4.0 by the author.