서버에서 데이터 가져오기 — fetch와 async
useEffect 안녕. 컴포넌트 함수 자체가 async — 데이터 가져오는 코드가 짧아진다.
옛 React 에선 데이터 가져오기가 이런 패턴이었다 — useState 로 빈 상태 만들고, useEffect 안에서 fetch 호출하고, 로딩 분기 처리하고, 에러 분기 처리하고… 코드 30줄이 데이터 가져오기에만 들어갔다.
App Router 의 답은 컴포넌트 함수 자체를 async 로. async function Page() { const data = await fetch(...) } 가 끝. 로딩 UI 는 loading.tsx, 에러는 error.tsx — 별도 파일이 분담한다.
1. 가장 단순한 fetching — async + await
서버 컴포넌트는 함수 시그니처에 async 를 붙일 수 있다. 안에서 await 자유롭게.
이 한 함수가 서버에서 실행되고, 결과 HTML 만 브라우저로 전송된다. 클라이언트엔 데이터 fetching JS 가 일절 안 들어가니까 번들이 가벼워진다.
useEffect 안 fetch + setState) 은 더 이상 표준이 아니다.
2. DB 직접 호출 — fetch 가 아니어도 OK
서버 컴포넌트는 어차피 서버에서 도니까 fetch HTTP 만 쓸 이유가 없다. DB 클라이언트를 직접 import 해도 된다.
네트워크 한 단계가 빠지므로 더 빠르다. 외부 마이크로서비스가 없는 한 DB 직호출이 권장. 빌드된 JS 가 클라이언트로 안 가므로 DB 자격증명 노출 위험도 없다.
3. 병렬 vs 순차 — Promise.all 활용
두 데이터를 같이 가져올 때 — 그냥 await 두 번 하면 순차다. 둘이 독립적이면 시간 낭비.
독립적인 두 fetch 는 무조건 Promise.all. 페이지 첫 로딩 시간을 결정하는 가장 흔한 차이.
예외 — 두 번째 fetch 가 첫 번째 결과에 의존하면 (waterfall) 어쩔 수 없이 순차.
4. 캐시 옵션 — 3가지 모드
Next.js 의 fetch 는 일반 브라우저 fetch 가 아니다. Next 가 감싼 버전으로, 빌드 캐시·요청 캐시를 추가로 처리한다.
| 옵션 | 의미 | 실전 사용 |
|---|---|---|
cache: 'force-cache' | 빌드 타임 캐시 (SSG 동작) | 변하지 않는 콘텐츠 (블로그·문서) |
cache: 'no-store' | 매 요청 새로 (SSR) | 실시간 데이터 (대시보드·재고) |
next: { revalidate: 60 } | 60초마다 갱신 (ISR) | 자주 안 바뀌는 동적 (인기 글) |
Next 14 까지는 force-cache 가 기본이었는데, Next 15 부터 no-store 가 기본으로 바뀌었다. 옛 코드 마이그레이션할 때 가장 자주 부딪치는 변화. 빌드 시 캐시 받고 싶으면 명시적으로 cache: 'force-cache'.
5. revalidatePath·revalidateTag — 캐시 무효화
캐시는 좋지만 — 글을 새로 썼는데 옛 캐시가 남아있으면? 손으로 무효화한다.
revalidateTag 는 fetch 호출 시 next: { tags: ['posts'] } 로 태그 붙여둔 모든 캐시를 한 번에 폐기. 글 발행할 때 인덱스·태그 페이지·연관 글이 다 같이 갱신되게 하는 표준 패턴.
async 함수 export 하면 에러. 클라이언트 컴포넌트의 데이터 fetching 은 여전히 useEffect 또는 TanStack Query 같은 라이브러리 필요. 서버 컴포넌트만 async OK.
요약 — 8편 좌표
여기까지 정리. 서버 컴포넌트는 async function + await 만으로 데이터 가져오기 — useState·useEffect 불필요. fetch 가 아니어도 DB 직호출 가능. 독립적인 fetch 는 Promise.all 로 병렬. 캐시 모드 3가지 — force-cache(SSG) · no-store(SSR, Next 15 기본) · revalidate: N(ISR). 무효화는 revalidatePath·revalidateTag. 다음 편에선 데이터 쓰기 방향 — Server Actions.
다음 편 예고 — Server Actions
서버 함수를 폼·버튼에서 직접 호출. 9편.