2026-01-08


리액트 성능 최적화 방법

리액트 성능 이슈의 본질

리렌더링이 불필요하게 많이 발생하는 것

  • 상태 변경 → 컴포넌트 리렌더링
  • 부모 리렌더링 → 자식도 함께 리렌더링
  • 계산, 렌더, DOM 업데이트 비용 누적

React.memo – 컴포넌트 리렌더링 방지

컴포넌트 다시 그릴까 말까?

부모가 리렌더링돼도 자식에게 내려준 props가 같으면 자식을 다시 안 그림

컴포넌트의 props가 변경되지 않았을 때, 리렌더링을 방지하여 성능을 최적화

    const Child = React.memo(({ value }) => {
    console.log('Child 렌더');
    return <div>{value}</div>;
    });
  • value가 이전과 같으면
  • Child는 리렌더링 안 됨
  • 얕은 비교(shallow compare): 객체/배열/함수 -> 참조 비교 (React.memo는 props참조가 중요)


useMemo – 값(계산 결과) 메모이제이션

계산 결과 다시 구할까 말까?

렌더링 중에 하는 계산 결과를 기억해두고 deps가 안 바뀌면 다시 계산 안 함

값의 재계산을 방지하여 성능을 최적화

const filteredList = useMemo(() => {
return list.filter(item => item.active);
}, [list]);
  • list가 바뀔 때만 다시 filter 실행

useCallback – 함수 메모이제이션

함수 새로 만들까 말까?

리렌더링돼도 함수의 참조값을 유지

함수를 메모이제이션하여 불필요한 함수 재생성을 방지

```javascript const onClick = useCallback(() => { setCount(c => c + 1); }, []);
``` - 매 렌더마다 새 함수 생성 X - 같은 함수 재사용 O

이를 통해 자식 컴포넌트로 전달되는 함수나 값이 변경되지 않으면 리렌더링을 피할 수 있음


key 최적화 – 리스트 렌더링의 핵심

index는 아이템의 위치값일 뿐 고유한 식별자가 아님

-> 리스트에 추가, 삭제, 정렬이 발생하면 index가 변경됨 (잘못된 컴포넌트 재사용, 불필요한 리렌더링)

-> 데이터 자체가 가진 고유한 값(id) 사용

-> 렌더링 순서가 바뀌어도 동일한 컴포넌트로 인식 가능

{list.map((item, index) => (
    <Item key={index} />
))}

아래처럼 바꾸기

{list.map(item => (
<Item key={item.id} />
))}
  • key는 리액트가 컴포넌트를 식별하는 기준
  • index 사용 시 DOM 재사용 꼬임 → 성능 + 버그


상태 위치 최적화

  • 상위 컴포넌트에 모든 상태 몰아넣기 → 전체 리렌더링
  • 상태를 사용하는 컴포넌트 근처로 분리
  • 지역 상태(Local State) 활용


렌더링 최적화 패턴

  • 조건부 렌더링
      {isOpen && <Modal />}
    
  • 컴포넌트 분리 (작은 단위로 쪼개기): 리렌더링 범위 축소


비동기 & 이벤트 최적화

  • debounce / throttle: 스크롤, 입력 이벤트에서 필수
      const onScroll = useCallback(
      throttle(() => {
          // 처리
      }, 200),
      []
      );
    


React.lazy & Suspense – 코드 스플리팅

큰 애플리케이션을 여러 개의 작은 코드 파일로 나누고,사용자가 실제로 필요한 화면에 들어왔을 때 해당 코드만 불러와 초기 로딩 시간을 줄임

페이지별로 코드를 분리해, 처음에는 필요한 코드만 로드하고 이후에 필요한 코드를 추가로 불러오는 방식

초기 로딩 시간이 길어지는 경우,라우트별 코드 분할이 필요한 경우 사용

참고자료

results matching ""

    No results matching ""