1. use 훅이란?
use는 React 19에서 정식으로 도입된 새로운 훅이다.
Promise나 Context와 같은 리소스의 값을 쉽게 읽을 수 있게 해주는 기능이다.
1.1. 기본 문법
import { use } from 'react';
// 사용 예시
const value = use(resource);
use 훅은 일반 훅과 마찬가지로 컴포넌트나 커스텀 훅 내부에서만 호출해야 한다.
다른 훅들과 달리 조건문이나 반복문 내부에서도 호출할 수 있어 더 유연한 코드 작성이 가능하다.
1.2. 일반 훅과의 차이점
기존 훅들(useState, useEffect 등)은 컴포넌트 최상위 레벨에서만 호출해야 한다.
반면 use 훅은 조건문(if)이나 반복문(for) 내부에서도 호출할 수 있다.
이는 내부 구현 방식의 차이 때문이며, React의 Suspense 시스템과 통합되어 있어 더 유연하게 설계되었다.
2. use 훅의 주요 활용
2.1. Context와 함께 사용
use 훅으로 Context를 사용할 때는 useContext보다 더 유연하게 사용할 수 있다.
조건부로 Context 값에 접근할 수 있어 코드 구조의 자유도가 높아진다.
ex)
function HorizontalRule({ show }) {
// if 문 안에서도 Context 사용 가능
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}
2.2. Promise와 함께 사용
use 훅을 Promise와 함께 사용하면 비동기 데이터 처리가 훨씬 간단해진다.
Suspense와 자동으로 통합되어 복잡한 로딩 상태 관리 로직이 필요 없다.
Promise가 대기(pending) 상태일 때 컴포넌트를 자동으로 일시 중단(suspend)한다.
Suspense 경계로 컴포넌트를 감싸면 자동으로 fallback UI가 표시된다.
ex)
// 클라이언트 컴포넌트
'use client';
import { use } from 'react';
export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
}
// 사용 예시
<Suspense fallback={<p>로딩 중...</p>}>
<Message messagePromise={fetchMessage()} />
</Suspense>
2.3. Promise 거부(rejection) 처리
Promise가 거부될 경우 두 가지 방법으로 처리할 수 있다.
1) Error Boundary 사용
<ErrorBoundary fallback={<p>오류가 발생했습니다</p>}>
<Suspense fallback={<p>로딩 중...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
</ErrorBoundary>
2) Promise.catch로 대체 값 제공
const messagePromise = new Promise((resolve, reject) => {
reject();
}).catch(() => {
return "메시지를 찾을 수 없습니다.";
});
3. 주의사항
3.1. 사용 시 제한사항
1) try-catch 블록 내에서 직접 호출 불가
use 훅은 try-catch 블록 내에서 직접 호출할 수 없다.
대신 Error Boundary나 Promise의 .catch 메서드를 사용해야 한다.
2) 서버 컴포넌트 vs 클라이언트 컴포넌트
서버 컴포넌트에서는 use 대신 async/await을 사용하는 것이 권장된다.
// 서버 컴포넌트
export default async function App() {
const messagePromise = fetchMessage();
return (
<Suspense fallback={<p>로딩 중...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}
3) 렌더링 중 Promise 생성은 지양
렌더링 중에 직접 Promise를 생성하는 것은 피해야 한다.
클라이언트에서 Promise를 생성하도록 하면 컴포넌트가 리렌더링 될때마다 새로운 Promise가 생성되어 캐싱이 어렵고 성능 문제가 발생한다.
그러므로 서버 컴포넌트에서 생성한 Promise를 클라이언트 컴포넌트로 전달하는 패턴이 성능상 더 좋다.
// 리렌더링마다 새로운 Promise가 생성
use(fetch('/api/data').then(r => r.json()))
3.2. 기존 방식과의 비교
기존 방식에서는 상태(state)를 사용하고 useEffect에서 Promise를 처리하는 복잡한 로직이 필요했다.
// 기존 방식
function MyComponent() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
somePromise
.then(result => {
setData(result);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, []);
if (loading) return <p>로딩 중...</p>;
if (error) return <p>에러 발생!</p>;
return <div>{data}</div>;
}
use 훅을 사용하면 이 모든 로직이 간소화된다.
// use 사용 방식
function MyComponent({ dataPromise }) {
const data = use(dataPromise);
return <div>{data}</div>;
}
// 사용할 때
<Suspense fallback={<p>로딩 중...</p>}>
<ErrorBoundary fallback={<p>에러 발생!</p>}>
<MyComponent dataPromise={somePromise} />
</ErrorBoundary>
</Suspense>
4. 결론
use 훅은 React에서 비동기 데이터 처리와 Context 사용을 더 간단하고 유연하게 만들어주는 강력한 도구이다.
기존 방식에 비해 코드량을 줄이고 가독성을 향상시키며 에러 처리도 더 직관적으로 할 수 있게 해준다.
1) 더 유연한 Context 사용
- 조건부 Context 접근 가능
- 코드 구조의 자유도 증가
2) 비동기 데이터 처리 단순화
- Promise 처리를 위한 보일러플레이트 코드 감소
- Suspense와의 자연스러운 통합
3) 서버 → 클라이언트 데이터 스트리밍
- 서버 컴포넌트에서 클라이언트 컴포넌트로 Promise 전달
- 렌더링 차단 없이 데이터 로딩
출처 :
https://ko.react.dev/reference/react/use#reading-context-with-use
https://github.com/reactjs/react.dev/blob/main/src/content/reference/react/use.md
'학습 > React' 카테고리의 다른 글
리액트 기초 - 강의 정리 3 : Prop Drilling, useEffect (0) | 2025.04.04 |
---|---|
useImperativeHandle (0) | 2025.03.23 |
useRef (0) | 2025.03.23 |
React 컴포넌트에서 변수와 함수의 스코프 차이 (0) | 2025.03.07 |
리액트 컴포넌트의 Props 전달 방식 - Forwarded Props 패턴 (Proxy Props) (0) | 2025.02.27 |