핵심 답변
React가 직접 비동기 런타임을 제공하는 것은 아니고, 브라우저(JavaScript 런타임)의 이벤트 루프 위에서 동작합니다. 비동기 작업(fetch, timer, Promise)이 완료되면 콜백이 실행되고, 그 안에서 setState를 호출하면 React가 변경 사항을 스케줄링해 필요한 시점에 렌더링합니다.
React 18에서는 자동 배칭(automatic batching)으로 비동기 콜백 안의 여러 상태 변경도 한 번에 묶어 렌더링 비용을 줄일 수 있고, startTransition으로 우선순위가 낮은 업데이트를 분리해 UI 응답성을 높일 수 있습니다.
예시 코드
typescript
import { useEffect, useState, startTransition } from 'react';
export default function UserList() {
const [users, setUsers] = useState<string[]>([]);
const [keyword, setKeyword] = useState('');
useEffect(() => {
const controller = new AbortController();
async function loadUsers() {
const res = await fetch('/api/users', { signal: controller.signal });
const data: string[] = await res.json();
startTransition(() => {
setUsers(data);
});
}
loadUsers().catch(() => {});
return () => controller.abort();
}, []);
const filtered = users.filter((u) => u.includes(keyword));
return (
<>
<input value={keyword} onChange={(e) => setKeyword(e.target.value)} />
<ul>{filtered.map((u) => <li key={u}>{u}</li>)}</ul>
</>
);
}핵심 용어
Event Loop: 비동기 작업 완료 후 콜백 실행 순서를 관리하는 런타임 메커니즘
State Update Scheduling:
setState 호출 시 즉시 DOM을 바꾸는 것이 아니라 React가 업데이트를 조정함Automatic Batching: 여러 상태 변경을 묶어서 렌더링 횟수를 줄이는 최적화