1007 TIL-U

Lilac00xx·2024년 10월 7일

Section 13) 리액트와 최적화 테크닉 살펴보기

TIL1) 리액트의 컴포넌트 트리 생성/ 리액트가 시스템 뒷편에서 동작하는 방식

코드예시

const ParentComponent = () => {
  return (
    <div>
      <ChildComponent />
    </div>
  );
};

const ChildComponent = () => {
  return <div>Hello, I'm a child component!</div>;
};

리액트는 ParentComponent와 ChildComponent를 각각 트리의 노드로 생각해, 이를 바탕으로 가상 DOM을 만들고 실제 DOM에 반영하는 방식으로 동작함.
Fiber 구조를 통해 각 컴포넌트가 더 효율적으로 렌더링될 수 있음.

TIL2) useCallback()훅 이해하기

코드예시

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

const Counter = () => {
  const [count, setCount] = useState(0);

  // useCallback 사용: count가 변경될 때만 함수가 재생성됨
  const increment = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

useCallback을 사용함으로써 increment 함수가 불필요하게 재생성되는 것을 방지하고,
컴포넌트가 재렌더링될 때마다 새로운 함수가 만들어지지 않게 최적화할 수 있음.

useCallback은 함수가 불필요하게 재생성되지 않도록 메모이제이션을 통해 최적화하는 훅.
컴포넌트가 재렌더링될 때, 해당 함수를 다시 생성하지 않고 캐시된 값을 사용함.
함수형 컴포넌트에서 발생하는 성능 문제를 줄이는 데 유용하며, 자식 컴포넌트로 콜백을 전달할 때 최적화 효과를 볼 수 있음.

TIL3) 리액트의 가상 DOM 사용

가상 DOM(Virtual DOM)은 실제 DOM을 조작하기 전에 변경사항을 메모리 상에서 미리 계산해 실제 DOM 업데이트를 최소화함.

리액트는 변경된 부분만 실제 DOM에 반영하는 Diffing 알고리즘을 사용해 성능 최적화를 달성.
DOM 조작은 성능에 부담을 주기 때문에, 가상 DOM은 이를 줄이는 핵심 요소임.

import React, { useState } from 'react';

const VirtualDOMExample = () => {
  const [text, setText] = useState("Initial Text");

  const updateText = () => {
    setText("Updated Text");
  };

  return (
    <div>
      <p>{text}</p>
      <button onClick={updateText}>Update Text</button>
    </div>
  );
};

TIL4) State 관리할 때 Key의 역할

코드예시

import React, { useState } from 'react';

const ListWithKeys = () => {
  const [items, setItems] = useState([
    { id: 1, name: "Apple" },
    { id: 2, name: "Banana" },
    { id: 3, name: "Cherry" }
  ]);

  return (
    <ul>
      {items.map((item) => (
        // 고유한 key 값으로 리액트가 항목을 정확히 식별하게 함
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
};

Key는 리스트의 항목 식별자로, 리액트가 리스트를 효율적으로 렌더링하는 데 도움을 줌.
Key가 없거나 불량하면 리액트가 항목을 잘못 식별해 비효율적인 업데이트가 발생할 수 있음.
Key는 주로 고유한 값을 사용하며, 이를 통해 리스트 항목들이 올바르게 추가, 제거, 재배치될 수 있음.

TIL5) MillionJS로 리액트 최적화하기

MillionJS는 가상 DOM을 더욱 최적화해 대규모 애플리케이션에서 렌더링 성능을 크게 향상시키는 라이브러리로, 가상 DOM을 사용하지 않더라도 빠르게 렌더링이 가능함.
DOM요소를 효율적으로 처리하기 위해 설계된 자바스크립트 프레임워크임.

질문거리

  1. MillionJS 실제로 쓰는건가요? 관련 책을 읽거나, 검색해봤을 때 자주 못봤습니다
  2. 리스트 항목에 Key 값을 설정할 때, 고유 식별자가 없는 경우 어떻게 처리하는 것이 좋은가요? 예를 들어, 데이터가 불규칙하거나 고유한 ID가 없는 상황에서 Key 값을 어떻게 생성하는지
  3. useCallback과 useMemo를 지나치게 사용하면 오히려 메모리 누수나 GC(가비지 컬렉션) 문제로 이어질 수 있다고 들었는데, 그런 상황을 어떻게 피할 수 있나요? 메모이제이션을 효율적으로 사용하는 방법에 대한 가이드라인이 있나요?
    4.가상 DOM에서 큰 상태 변화가 발생했을 때, 리액트의 렌더링 성능이 급격히 저하되는 것을 방지하기 위한 디버깅 방법과 최적화 패턴은 무엇인가요? 대규모 데이터 세트를 처리할 때 Batching(일괄 처리) 기술을 적용하는 방법은 무엇인가요?
profile
Challenge & Change

1개의 댓글

comment-user-thumbnail
2024년 10월 16일
  1. MillionJS 저도 처음 들어보았는데요 ㅋㅋ..
    라이브러리의 유명세? 사용량이 궁금할 때 https://www.npmjs.com/package/million 여기서 weekly downloads를 다른 라이브러리들이랑 비교해보면 대충 알 수 있답니다.
  2. 리스트를 만드는 데이터가 외부 요인으로 인해서 변경되거나 직접 변경하는 경우가 아니라면 index를 써도 무방합니다. 고유 값을 사용해야 하는 이유는 가상 돔에서는 component의 key prop을 통해서 리렌더링 여부를 결정하기 때문인데, index를 사용하면 안되지만 고유 key 값이 필요한 경우에는 키 값을 생성해주는 라이브러리를 이용하기도 합니다(드문 케이스일 거 같아요)
  3. 간단히 얘기해서 메모이제이션 훅들은 꼭 필요할 때만 사용하는 게 좋은데요. 컴포넌트가 의도한 것보다 너무 자주 리렌더링되거나, 비교적 복잡한 값이나 함수가 특정 값들에 의존하는 게 확실한 경우 성능 개선을 위해 사용합니다.
    메모리 누수는 메모이제이션 훅이 오래된 값들을 참조하는 경우에 생길 수 있는데, 의존성 배열을 정확히 작성하는 것으로 방지할 수 있습니다.
  1. 특정 상태 변화가 큰 규모의 리렌더링을 발생시켜서 성능 저하가 있는 경우에 먼저 해야 하는 일은 정확히 어떤 상태 변화가 성능 저하에 영향을 미치고 있는지 파악하고, 그 상태에 영향을 받지 않아도 되는(않아야 하는) 컴포넌트들을 메모이제이션이나 코드 수정을(불필요한 prop 제거 등) 통해서 성능을 개선합니다.
    혹은 필요한 렌더링 자체가 많아서 성능에 영향이 있는 경우에는 가상화 등을 이용해서 개선할 수도 있어요!
    react-developer-tools 같은 도구를 이용하셔도 좋고, 코드 상으로 컴포넌트의 일부씩만 렌더링해보면서 어떤 부분이 문제를 일으키는지 파악해볼 수 있습니다.
    여러 상태를 한번에 업데이트 하는 경우 일반적으로는 자동으로 일괄 처리됩니다(React 18 이후. unstable_batchUpdates 같은 함수를 이용하는 경우도 있는데, 비교적 드문 케이스라고 보시면 될 거 같습니다.
답글 달기