React Lazy Initialization

김민기·2022년 12월 2일
0

React

목록 보기
3/8

useState

React를 공부하면서 상태는 컴포넌트에서 가장 중요한 요소다.

컴포넌트의 변할 수 있는 값을 만들기 위해서 클래스형 컴포넌트에서는

this.state를 활용하기도 하지만 가장 많이 사용하는 방법은

함수형 컴포넌트에서 useState hook을 사용하는 방법일 것이다.

import { useState } from 'react';

function App() {
  const [state, setState] = useState("");
  ...
}

useState를 사용하면 간단하게 컴포넌트의 state를 만들 수 있고, setState를 사용해서 상태를 변경할 수도 있다. 상태를 변경하면 리액트는 컴포넌트를 다시 렌더링 한다.

리렌더링이라고 불리는 현상은 컴포넌트의 상태가 변경될 때 컴포넌트를 생성하는 함수가 다시 실행되는 것이다.
이때 한 가지 문제가 발생한다.

위와같은 컴포넌트에서는 다시 렌더링이 된다고해서 사실상 성능에 큰 문제가 되지 않는다.

하지만 만약 무거운 작업을 해야한다면? 만약 초기 상태를 지정해야 하는 배열의 크기가 매우 클 경우

const [userIds, setUserIds] = useState(["123","12312","12345","ddasd",....,""])

컴포넌트가 리렌더링 될 때마다 매번 초기화를 실행하게 된다. 이럴 경우 성능에 큰 문제가 될 수 있다.

일반적으로 이런 성능 저하 문제를 해결하기 위해서 또 다른 훅인 useEffect를 사용해서 처음 렌더링 될 경우에만 상태를 초기화 하도록 만들수 있다.

const loadUserIds = () => {
  return ["123","12312","12345","ddasd",....,""];
}

function App() {
  const [state, setState] = useState([]);
  useEffect(()=>{
  	setState(loadUserIds);
  },[])
}

이렇게 처음 렌더링됬을 때만 state 값을 변경하도록 만들 수 있지만 새로운 문제가 발생하는데, 처음 컴포넌트가 렌더링 될때는 비어있는 배열이기 때문에, UI에서 빈 배열이 잠깐 보여질 수 있고 그럴 경우 별도의 로딩처리를 추가해야 할 수도 있다는 문제가 있다.

Lazy Initialize

useState에서 콜백 함수를 사용해서 Lazy Initialize를 만든다면 쉽게 해결할 수 있다.

const loadUserIds = () => {
  return ["123","12312","12345","ddasd",....,""];
}

function App() {
  const [state, setState] = useState(()=>loadUserIds());
}

그렇다면 언제 Lazy Initialize를 사용하는 것이 좋을까?

리액트 공식 문서에는 이렇게 나와 있다.

initialState 인자는 초기 렌더링 시에 사용하는 state입니다. 그 이후의 렌더링 시에는 이 값은 무시됩니다. 초기 state가 고비용 계산의 결과라면, 초기 렌더링 시에만 실행될 함수를 대신 제공할 수 있습니다.

고비용 계산의 결과? 쉽게 말해서 초기값 계산에 많은 비용이 필요할 때 비효율적인 부분을 최적화하는데 사용할 수 있다는 것이다.
위 처럼 기본적으로 상태에 유저의 id 값들을 미리 불러와야 하거나, 별도의 연산을 통해서 많은 상태값을 지정해야 하는 경우 Lazy Initialize를 사용하면 효율적으로 처리 할 수 있다는 것이다.

느낌

useState는 그냥 상태를 만드는 훅으로만 알고 있었고, 리렌더링될 때마다 발생하는 메모리 낭비를 막기 위해서는 useEffect, useCallback, useMemo 등의 훅을 사용한다고만 알고 있었는데, Lazy Initialize를 새롭게 배운것 같다. 리액트 훅에 대해서 처음부터 다시 공부를 하고 있는데, 알고 있다 생각했지만 놓치고 있던 부분이 상당히 많은것 같다.

0개의 댓글