
개요
React 19의 use 훅은 비동기 데이터 처리 코드를 간소화합니다. 기존의 useEffect + useState 패턴을 제거하고 비동기 데이터를 간단하게 처리할 수 있습니다.
학습 목표
- use 훅으로 Promise와 Context 읽기
- 조건부 데이터 fetching과 에러 처리 구현
- 기존 useEffect 패턴 대비 코드량 50% 이상 단축
- 프로젝트 도입 여부 판단
use 훅이 해결하는 문제
React에서 비동기 데이터를 처리할 때 발생하는 주요 문제들입니다.
복잡한 상태 관리
// 기존 방식: 15줄의 보일러플레이트 코드 function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; fetchUser(userId) .then(userData => { if (!cancelled) { setUser(userData); setLoading(false); } }) .catch(err => { if (!cancelled) { setError(err); setLoading(false); } }); return () => { cancelled = true; }; }, [userId]); if (loading) return <div>로딩 중...</div>; if (error) return <div>오류: {error.message}</div>; return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> ); }
use 훅 방식: 5줄로 단축
function UserProfile({ userPromise }) { const user = use(userPromise); return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> ); }
use 훅을 사용하면 컴포넌트는 데이터 표시에만 집중합니다. 로딩과 에러 처리는 Suspense와 Error Boundary가 담당합니다.
기본 사용법
Promise 읽기
use 훅은 Promise를 받아서 resolve된 값을 반환합니다.
import { use, Suspense } from 'react'; function UserProfile({ userPromise }) { const user = use(userPromise); return ( <div> <h1>{user.name}</h1> <p>{user.email}</p> </div> ); } function App() { const userPromise = fetch('/api/user').then(res => res.json()); return ( <Suspense fallback={<div>로딩 중...</div>}> <UserProfile userPromise={userPromise} /> </Suspense> ); }
Context 읽기
use 훅은 useContext의 대안으로 사용할 수 있습니다.
import { createContext, use } from 'react'; const ThemeContext = createContext(); function Button() { const theme = use(ThemeContext); return ( <button style={{ backgroundColor: theme.primaryColor }}> 클릭하세요 </button> ); }
고급 활용법
조건부 데이터 fetching
use 훅은 조건문 내에서 사용할 수 있습니다.
function ProductDetails({ productId, shouldLoadReviews }) { const product = use(fetchProduct(productId)); // 조건부로 리뷰 데이터 가져오기 const reviews = shouldLoadReviews ? use(fetchReviews(productId)) : null; return ( <div> <h1>{product.name}</h1> <p>{product.description}</p> {reviews && ( <div> <h3>리뷰</h3> {reviews.map(review => ( <div key={review.id}>{review.comment}</div> ))} </div> )} </div> ); }
에러 처리
use 훅에서 발생한 에러는 가장 가까운 Error Boundary에서 처리됩니다.
import { ErrorBoundary } from 'react-error-boundary'; function ErrorFallback({ error }) { return ( <div> <h2>문제가 발생했습니다</h2> <p>{error.message}</p> </div> ); } function App() { return ( <ErrorBoundary FallbackComponent={ErrorFallback}> <Suspense fallback={<div>로딩 중...</div>}> <UserProfile userPromise={fetchUser()} /> </Suspense> </ErrorBoundary> ); }
도입 시 고려사항
use 훅 도입을 권장하는 경우
- 애플리케이션 전체에서 일관된 로딩과 에러 UI가 필요할 때
- 여러 비동기 데이터를 병렬로 처리해야 할 때
- 조건부 데이터 fetching이 필요할 때
- 새로운 프로젝트를 시작할 때
기존 방식을 유지하는 것이 좋은 경우
- 컴포넌트별로 세밀한 로딩 상태 제어가 필요할 때
- React Query나 SWR이 잘 구축된 기존 프로젝트에서
- 컴포넌트별로 다른 에러 처리 로직이 필요할 때
use 훅은 React의 새로운 패러다임을 제시하지만 모든 상황의 만능 해결책은 아닙니다. 프로젝트 요구사항에 따라 적절히 선택하여 사용하세요.