React 18 Suspense와 Server Component 실험
배경
3월에 React 18이 정식 릴리즈됐다. Concurrent Rendering이 핵심이지만, 당장 눈에 띄는 건 Suspense for Data Fetching과 Server Components였다. 사내 어드민 프로젝트에 적용 가능성을 검토하기 위해 간단한 POC를 진행했다.
Suspense for Data Fetching
기존에는 컴포넌트 내부에서 loading 상태를 관리했다.
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUsers().then(data => {
setUsers(data);
setLoading(false);
});
}, []);
if (loading) return <Spinner />;
return <ul>{users.map(u => <li>{u.name}</li>)}</ul>;
}
Suspense를 사용하면 로딩 상태를 상위로 위임할 수 있다.
function UserList() {
const users = use(fetchUsers()); // Suspense 통합
return <ul>{users.map(u => <li>{u.name}</li>)}</ul>;
}
// 사용
<Suspense fallback={<Spinner />}>
<UserList />
</Suspense>
여러 컴포넌트의 로딩 상태를 조율하기 편해졌다. 특히 중첩된 데이터 페칭에서 waterfall 문제를 해결하는 데 유용했다.
Server Components
Next.js 12에서 알파로 제공 중이다. 서버에서만 실행되는 컴포넌트로, 번들 사이즈를 줄이고 직접 DB 접근이 가능하다.
// UserList.server.jsx
import db from 'db';
export default function UserList() {
const users = db.query('SELECT * FROM users');
return <ul>{users.map(u => <li>{u.name}</li>)}</ul>;
}
아직 안정화되지 않아 프로덕션 적용은 보류했지만, GraphQL 없이도 백엔드 로직을 컴포넌트에 통합할 수 있다는 점이 흥미로웠다.
결론
React 팀이 제시하는 방향은 명확하다. 데이터 페칭 로직을 선언적으로 작성하고, 서버와 클라이언트의 경계를 프레임워크가 관리하게 하는 것. 당장은 실험적이지만, 1~2년 내 표준이 될 것 같다.