728x90
728x90

코드 분할(Code Splitting) : useTransition 훅, Suspense 컴포넌트, lazy 함수

들어가며

  • 리액트(React.js)에서 코드 분할(Code Splitting)의 장점과 함께 사용되는 useTransition 훅과 Suspense 컴포넌트, lazy 함수에 대해 정리해본다.

 

코드 분할(Code Splitting)

개념

  • 리액트 애플리케이션에서 코드의 일부분을 나눠서 필요한 시점에 로드하는 방식

 

장점

  • 애플리케이션을 더 작은 청크(Chunk)로 나눔으로써 초기 로드 시 필요한 자바스크립트 크기를 줄인다.
    • 이를 통해 첫 화면 렌더링 속도가 빨라지며, 느린 네트워크 환경에서도 빠르게 응답할 수 있다.
  • 사용자가 필요로 하지 않는 코드는 나중에 로드되며, 상호작용할 때만 필요한 코드가 동적으로 로드되어 매끄러운 사용자 경험을 제공한다.
  • 페이지 간 트래픽 비율에 따라 중요한 리소스를 우선적으로 로드하고, 덜 중요한 리소스는 나중에 로드할 수 있어 성능을 최적화(Optimization)할 수 있다.

 

useTransition 훅

개념

  • React 18에서 도입되었으며, 비동기 상태 업데이트를 처리할 때 UI의 응답성을 개선하는 데 사용된다.
  • 주로 UI 작업의 우선순위를 설정해 중요한 작업은 즉시 처리하고, 덜 중요한 작업은 비동기적으로 처리하는데 사용된다.
  • 복잡한 작업이나 데이터 로드 시 UI 성능을 유지하는 데 유용하다.

 

사용 방법

  • isPending비동기 작업진행 중인지를 나타낸다.
    • 전환이 완료되면 false가 된다.
  • startTransition우선순위가 낮은 작업을 비동기로 처리하여 UI 응답성을 유지한다.
import { useTransition } from 'react';
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(() => {
// 우선순위가 낮은 상태 업데이트
setState(someExpensiveOperation());
});
};

 

사용 예

  • 아래와 같이 useTransition 훅을 이용하여 UI가 버벅거리지 않고 필터링 작업이 완료될 때까지 로딩 메시지(isPending에 따른 상태)로 사용자에게 피드백을 제공할 수 있다.
import { useState, useTransition } from "react";
// 랜덤 아이템 생성 함수
function generateItems() {
return Array.from({ length: 5000 }, (_, i) => `Item ${i + 1}`);
}
function FilterableList() {
const [query, setQuery] = useState(""); // 검색어 상태
const [list, setList] = useState(generateItems()); // 검색어 리스트
const [isPending, startTransition] = useTransition();
// 검색어 변경 시 필터링 작업을 처리
const handleInputChange = (e) => {
const inputValue = e.target.value;
setQuery(inputValue); // 검색어 상태 즉시 업데이트
// '필터링' 작업은 우선순위가 낮은 작업으로 처리하기
startTransition(() => {
const filteredList = generateItems().filter((item) =>
item.toLowerCase().includes(inputValue.toLowerCase())
);
setList(filteredList); // (필터링 작업 후) 검색어 리스트 업데이트
});
};
return (
<div>
<input
type="text"
value={query}
onChange={handleInputChange}
placeholder="Search..."
/>
{isPending ? <p>Updating List...</p> : null} {/* isPending으로 로딩 상태 표시하기 */}
<ul>
{list.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
export default FilterableList;

 

Suspense 컴포넌트

개념

  • 코드 분할이나 비동기 로딩 시, 컴포넌트가 로드될 때까지의 대기 상태를 처리하는 리액트 컴포넌트
  • 주로 동적 임포트나 비동기 렌더링이 필요한 상황에서 로딩 중 UI를 지정할 수 있게 해준다.

 

사용 방법

  • fallback 속성에 로드 중에 표시할 컴포넌트를 지정한다.
    • 로딩 중 스피너(Spinner)나 텍스트 등을 지정할 수 있다.
import { Suspense } from 'react';
<Suspense fallback={<div>Loading...</div>}>
<LazyLoadedComponent />
</Suspense>

 

lazy 함수

개념

  • 동적으로 컴포넌트를 로드하는 데 사용된다.
  • 코드 분할을 통해 애플리케이션의 특정 컴포넌트를 필요한 시점에 로드할 수 있게 해준다.
  • Suspense 컴포넌트와 함께 사용된다.
  • lazy를 사용하면, 해당 컴포넌트가 필요할 때만 동적으로 import 된다.
    • 이를 통해 처음부터 모든 코드를 불러오지 않고, 사용자가 특정 동작을 했을 때만 관련 코드를 로드하는 방식으로 애플리케이션의 성능을 크게 향상시킬 수 있다.

 

사용 방법

const LazyLoadedComponent = lazy(() => import('./LazyComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyLoadedComponent />
</Suspense>
);
}

 

정리

  • 코드 분할(Code Splitting)
    • 성능 최적화 및 사용자 경험 개선에 도움이 되는 기법
    • 초기 로드 시 모든 코드를 불러오는 대신, 필요한 시점에 코드를 동적으로 로드하여 성능을 향상시킨다.
  • useTransition
    • 우선 순위가 낮은 작업을 비동기 처리한다.
    • 사용자 인터페이스가 버벅거리는 것을 방지한다.
  • Suspense 컴포넌트
    • 비동기적으로 로드되는 컴포넌트가 준비될 때까지 로딩 상태를 처리해준다.
    • 로딩 중에 표시할 UI를 제공한다.
  • lazy 함수
    • 동적으로 컴포넌트를 로드하여 불필요한 코드가 한 번에 로드되는 것을 방지한다.
    • 코드 분할을 쉽게 할 수 있도록 도와준다.

 

종합 사용 예제
import { useState, useTransition, lazy, Suspense } from 'react';
const SlowComponent = lazy(() => import('./components/SlowComponent'));
const UseTransitionSuspenseExample = () => {
const [text, setText] = useState('');
const [items, setItems] = useState([]);
const [show, setShow] = useState(false);
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
setText(e.target.value);
startTransition(() => {
const newItems = Array.from({ length: 200 }, (_, index) => {
return (
<div key={index}>
<img
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSlGmKtrnxElpqw3AExKXPWWBulcwjlvDJa1Q&s"
alt=""
/>
</div>
);
});
setItems(newItems);
});
};
return (
<div className="section">
<h1>useTransition and Suspense Example</h1>
<Suspense fallback={<h4>Loading...</h4>}>
<section>
<form className="form">
<input
type="text"
className="form-input"
value={text}
onChange={handleChange}
/>
</form>
<h4>Items Below</h4>
{/* 다 불러와지기 전에 Loading... 표시하기 */}
{isPending ? (
'Loading...'
) : (
<div
style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr 1fr',
marginTop: '2rem',
}}
>
{items}
</div>
)}
<button onClick={() => setShow(!show)} className="btn">
toggle
</button>
{show && <SlowComponent />}
</section>
</Suspense>
</div>
);
};
export default UseTransitionSuspenseExample;

 

 

 

참고 사이트

 

useTransition – React

The library for web and native user interfaces

ko.react.dev

 

<Suspense> – React

The library for web and native user interfaces

ko.react.dev

 

lazy – React

The library for web and native user interfaces

ko.react.dev

 

728x90
728x90

코드 분할(Code Splitting) : useTransition 훅, Suspense 컴포넌트, lazy 함수들어가며코드 분할(Code Splitting)개념장점useTransition 훅개념사용 방법사용 예Suspense 컴포넌트개념사용 방법lazy 함수개념사용 방법정리참고 사이트