렌더링 이해하기

shooting star·2024년 7월 10일
post-thumbnail

렌더링 이해하기

리액트 애플리케이션에서 렌더링이란, 컴포넌트가 현재 가지고 있는 props와 state 값을 기반으로 UI를 구성하고 이를 DOM에 반영하는 과정을 의미합니다. 이 과정은 브라우저가 HTML과 CSS 리소스를 기반으로 웹페이지 UI를 그리는 전통적인 렌더링과 구별됩니다. 이번 블로그에서는 리액트의 렌더링 과정과 이를 최적화하는 방법을 예제를 통해 살펴보겠습니다.

렌더링의 기본 개념

리액트의 렌더링 과정은 크게 두 가지로 나눌 수 있습니다: 렌더 단계커밋 단계.

  1. 렌더 단계: 컴포넌트를 렌더링하고 변경 사항을 계산하는 단계입니다. 컴포넌트를 실행하여 그 결과를 이전 가상 DOM과 비교하여 변경이 필요한 컴포넌트를 체크합니다.
  2. 커밋 단계: 렌더 단계에서 확인된 변경 사항을 실제 DOM에 반영하는 단계입니다. 이 단계가 완료되어야 브라우저에서 실제로 UI가 업데이트됩니다.

렌더링이 발생하는 경우

렌더링이 발생하는 주요 시점은 다음과 같습니다:

  1. 최초 렌더링: 사용자가 처음 애플리케이션에 진입하면 리액트는 최초 렌더링을 수행하여 초기 UI를 브라우저에 제공합니다.
  2. 리렌더링: 최초 렌더링 이후, props, state, 또는 기타 렌더링 트리거에 의해 발생하는 모든 렌더링을 의미합니다.

리렌더링이 발생하는 경우

  • 클래스 컴포넌트의 setState가 실행되는 경우: setState 호출을 통해 상태가 변경되면 리렌더링이 발생합니다.
  • 클래스 컴포넌트의 forceUpdate가 실행되는 경우: 상태나 props가 아닌 다른 값에 의해 렌더링이 필요할 때 강제로 리렌더링을 발생시킵니다.
  • 함수 컴포넌트의 useState의 setter가 실행되는 경우: useState의 두 번째 배열 요소인 setter 함수가 실행되면 리렌더링이 발생합니다.
  • 함수 컴포넌트의 useReducer의 dispatch가 실행되는 경우: useReducer의 dispatch 함수가 실행되면 리렌더링이 발생합니다.
  • 컴포넌트의 key props가 변경되는 경우: key는 리렌더링 동안 컴포넌트를 고유하게 식별하는 값으로, key가 변경되면 리렌더링이 발생합니다.
  • props가 변경되는 경우: 부모 컴포넌트로부터 전달받은 props가 변경되면 자식 컴포넌트도 리렌더링이 발생합니다.
  • 부모 컴포넌트가 리렌더링되는 경우: 부모 컴포넌트가 리렌더링되면 자식 컴포넌트도 자동으로 리렌더링됩니다.

렌더링 최적화

렌더링 과정을 최소화하고 최적화하는 것은 사용자 경험을 향상시키는 중요한 요소입니다. 리액트에서 제공하는 다양한 최적화 기법 중 일부를 살펴보겠습니다.

1. 메모이제이션

메모이제이션은 동일한 입력에 대해 함수의 결과를 저장하여 불필요한 계산을 피하는 기술입니다. 리액트에서는 React.memouseMemo 훅을 사용하여 컴포넌트와 함수의 메모이제이션을 구현할 수 있습니다.

React.memo

React.memo는 함수 컴포넌트를 메모이제이션하여 동일한 props로 재호출될 때, 리렌더링을 방지합니다.

import React from 'react';

const MyComponent = React.memo(({ value }) => {
  console.log('렌더링 발생');
  return <div>{value}</div>;
});

export default MyComponent;

useMemo

useMemo는 함수의 결과를 메모이제이션하여 불필요한 계산을 방지합니다.

import React, { useState, useMemo } from 'react';

function ExpensiveComponent({ value }) {
  const expensiveCalculation = useMemo(() => {
    console.log('비싼 계산 수행');
    return value * 2;
  }, [value]);

  return <div>{expensiveCalculation}</div>;
}

export default ExpensiveComponent;

2. shouldComponentUpdateReact.PureComponent

클래스 컴포넌트에서 shouldComponentUpdate 메서드를 사용하여 리렌더링 여부를 제어할 수 있습니다. React.PureComponent를 사용하면 기본적으로 shouldComponentUpdate 메서드에서 얕은 비교를 수행하여 리렌더링을 최적화합니다.

import React, { PureComponent } from 'react';

class MyPureComponent extends PureComponent {
  render() {
    console.log('렌더링 발생');
    return <div>{this.props.value}</div>;
  }
}

export default MyPureComponent;

렌더링 최적화에 대한 두 가지 주장

주장 1: 섣부른 최적화는 독이다

모든 부분을 최적화하려는 시도는 오히려 코드의 복잡성을 증가시키고 유지보수를 어렵게 만들 수 있습니다. 따라서 꼭 필요한 부분에만 메모이제이션을 추가하는 것이 좋습니다.

주장 2: 렌더링 과정의 비용은 비싸다

렌더링 비용이 높은 애플리케이션의 경우, 최적화를 통해 성능을 크게 향상시킬 수 있습니다. 모든 부분에 메모이제이션을 적용하여 불필요한 렌더링을 방지하는 것도 하나의 방법입니다.

결론

리액트 애플리케이션의 렌더링 과정을 이해하고 이를 최적화하는 것은 사용자 경험을 향상시키는 중요한 요소입니다. 메모이제이션을 통해 불필요한 렌더링을 방지하고, 필요한 경우에만 최적화를 적용하여 성능을 향상시킬 수 있습니다.

0개의 댓글