Contents
see List작성일 2025. 11. 30.
React 18 Concurrent Features
React 18에서 도입된 Concurrent Rendering은 React가 여러 버전의 UI를 동시에 준비할 수 있게 해주는 핵심 기능입니다. 사용자 경험을 크게 향상시키는 새로운 훅과 API를 제공합니다.
언제 사용하나요?
- 대규모 리스트 렌더링 시 입력 지연 방지
- 페이지 전환 시 이전 페이지를 유지하며 로딩
- 검색 자동완성 등 빈번한 상태 업데이트
- 사용자 인터랙션 우선순위 관리
React 18 업그레이드
// React 18 설치
npm install react@18 react-dom@18
// index.js 변경
import { createRoot } from "react-dom/client";
const container = document.getElementById("root");
const root = createRoot(container);
root.render(<App />);useTransition - 우선순위 낮추기
import { useState, useTransition } from "react";
function SearchPage() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
// 긴급: 입력값 즉시 업데이트
setQuery(e.target.value);
// 낮은 우선순위: 검색 결과 업데이트
startTransition(() => {
setResults(searchItems(e.target.value));
});
};
return (
<div>
<input value={query} onChange={handleChange} />
{isPending ? (
<div>검색 중...</div>
) : (
<ResultList results={results} />
)}
</div>
);
}useDeferredValue - 값 지연
import { useDeferredValue, useMemo } from "react";
function ProductList({ searchQuery }) {
// searchQuery의 지연된 버전
const deferredQuery = useDeferredValue(searchQuery);
// 실제 필터링은 지연된 값으로
const filteredProducts = useMemo(
() => products.filter(p =>
p.name.includes(deferredQuery)
),
[deferredQuery]
);
// 지연 중일 때 시각적 피드백
const isStale = searchQuery !== deferredQuery;
return (
<div style={{ opacity: isStale ? 0.5 : 1 }}>
{filteredProducts.map(p => (
<ProductCard key={p.id} product={p} />
))}
</div>
);
}Suspense 향상
import { Suspense, lazy } from "react";
const Comments = lazy(() => import("./Comments"));
const Sidebar = lazy(() => import("./Sidebar"));
function App() {
return (
<div>
<Header />
<Suspense fallback={<Spinner />}>
<main>
<Content />
<Suspense fallback={<CommentSkeleton />}>
<Comments />
</Suspense>
</main>
<Suspense fallback={<SidebarSkeleton />}>
<Sidebar />
</Suspense>
</Suspense>
</div>
);
}Automatic Batching
// React 18에서는 모든 업데이트가 자동 배칭됨
function handleClick() {
// 이전: 각각 리렌더링
// React 18: 한 번만 리렌더링
setCount(c => c + 1);
setFlag(f => !f);
}
// 비동기 함수 안에서도 배칭됨
async function handleSubmit() {
await saveToServer();
setCount(c => c + 1); // 한 번만
setFlag(f => !f); // 리렌더링
}
// 배칭 해제가 필요한 경우
import { flushSync } from "react-dom";
flushSync(() => {
setCount(c => c + 1);
}); // 즉시 리렌더링
flushSync(() => {
setFlag(f => !f);
}); // 다시 리렌더링useId - SSR 안전한 ID 생성
import { useId } from "react";
function FormField({ label }) {
const id = useId();
return (
<div>
<label htmlFor={id}>{label}</label>
<input id={id} />
</div>
);
}
// 여러 ID가 필요한 경우
function ComplexForm() {
const id = useId();
return (
<>
<label htmlFor={id + "-name"}>이름</label>
<input id={id + "-name"} />
<label htmlFor={id + "-email"}>이메일</label>
<input id={id + "-email"} />
</>
);
}주의사항
- Strict Mode에서 컴포넌트가 두 번 렌더링됨
- Concurrent 기능은 createRoot 필수
- 클래스 컴포넌트에서는 일부 기능 제한
- IE 지원 중단됨
javascript
| No | 작성일 | Title |
|---|---|---|
| 2213 | 2026. 02. 11. | React Server Components 심화 패턴과 활용 |
| 2212 | 2026. 02. 11. | Next.js 15 App Router 완벽 가이드 |
| 2171 | 2026. 02. 11. | Astro vs Remix vs SvelteKit: 풀스택 프레임워크 비교 |
| 2170 | 2026. 02. 11. | 프론트엔드 테스트 전략: Vitest + Testing Library + Playwright |
| 2169 | 2026. 02. 11. | React 19 신기능: use(), Actions, 서버 컴포넌트 개선 |
| 2168 | 2026. 02. 11. | Web API 최신 트렌드: View Transitions, Popover, Container Queries |
| 2167 | 2026. 02. 11. | Vite 6.0: 차세대 프론트엔드 빌드 도구 |
| 2166 | 2026. 02. 11. | Tailwind CSS 4.0과 모던 CSS 프레임워크 동향 |
| 2165 | 2026. 02. 11. | Zustand vs Jotai vs Recoil: React 상태 관리 비교 2025 |
| 2164 | 2026. 02. 11. | TypeScript 5.x 신기능과 타입 시스템 고급 활용 |