C
React/API연동/Lesson 15

데이터 패칭

30분·theory
이 챕터
1/2
JavaScript

데이터 패칭

💡 왜 배워야 할까요?

🎯 서버의 데이터베이스에서 실시간 정보를 가져와 화면에 표시할 수 있습니다.
💼 캐싱으로 불필요한 요청을 줄여 앱 속도를 크게 향상시킵니다.
네이버, 쿠팡 같은 대기업 채용에서 필수 스킬입니다.
🏢 실무에서는
쿠팡의 상품 목록, 토스의 계좌 정보, 당근마켓의 게시물 같은 모든 실시간 데이터는 API 데이터 패칭으로 구현됩니다. 효율적인 캐싱 전략을 모르면 수백만 사용자를 처리할 수 없습니다.

개념

Next.js 14+의 App Router에서 제공하는 고급 캐싱과 ISR(Incremental Static Regeneration) 기능은 현대 웹앱의 필수 기술입니다. 대용량 트래픽 처리와 사용자 경험 최적화에 직결되어 네이버, 쿠팡, 토스 같은 대기업에서 핵심 성능 지표로 평가받습니다.

왜 중요한가?

커머스 상품 목록처럼 자주 변경되는 데이터를 매번 서버에서 가져오면 응답 시간이 3초를 넘어 이탈률이 50% 증가합니다. 또한 뉴스 사이트나 블로그처럼 콘텐츠 업데이트는 필요하지만 실시간성이 덜 중요한 경우, 적절한 revalidate 전략으로 CDN 비용을 70% 절약할 수 있습니다.

핵심 개념

Next.js의 데이터 패칭은 '똑똑한 냉장고'와 같습니다. 냉장고가 음식의 유통기한을 체크해서 상한 것만 새로 사오듯, Next.js는 데이터의 '신선도'를 관리해서 오래된 것만 서버에서 새로 가져옵니다. fetch 캐싱은 데이터를 저장하는 냉장고 역할이고, revalidate는 유통기한 체크하는 센서 역할입니다.

핵심 포인트

  • fetch()는 기본적으로 Request Memoization과 Data Cache 두 단계로 캐싱됨
  • revalidate 옵션으로 데이터 신선도 주기를 컨트롤 (초 단위)
  • App Router에서는 generateStaticParams와 결합해 동적 라우팅까지 최적화 가능
💻 나쁜 예시 - 캐싱 없는 매번 데이터 요청
// app/products/page.tsx - 안티패턴
export default async function ProductsPage() {
  // 매번 서버 요청 - 느리고 비효율적
  const res = await fetch('https://api.example.com/products', {
    cache: 'no-store' // 캐시 비활성화
  });
  const products = await res.json();

  return (
    <div>
      {products.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  );
}
💻 좋은 예시 - 2025 권장 캐싱 전략
// app/products/page.tsx - 최적화된 패턴
export default async function ProductsPage() {
  // 1시간마다 데이터 갱신, 그 사이엔 캐시 사용
  const res = await fetch('https://api.example.com/products', {
    next: { 
      revalidate: 3600, // 1시간 = 3600초
      tags: ['products'] // 캐시 태그로 선택적 무효화
    }
  });
  const products = await res.json();

  return (
    <div>
      {products.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  );
}

// app/admin/actions.ts - 관리자가 상품 업데이트시 캐시 무효화
'use server';
import { revalidateTag } from 'next/cache';

export async function updateProduct(formData: FormData) {
  // 상품 업데이트 로직...
  
  // 특정 태그만 캐시 무효화
  revalidateTag('products');
}
💻 고급 예시 - 동적 라우팅과 결합한 최적화
// app/products/[id]/page.tsx
interface Props {
  params: { id: string };
}

// 인기 상품 100개는 빌드타임에 미리 생성
export async function generateStaticParams() {
  const products = await fetch('https://api.example.com/popular-products')
    .then(res => res.json());
  
  return products.map((product: any) => ({
    id: product.id.toString()
  }));
}

export default async function ProductPage({ params }: Props) {
  // 상품 상세는 30분마다 갱신
  const product = await fetch(`https://api.example.com/products/${params.id}`, {
    next: { 
      revalidate: 1800, // 30분
      tags: [`product-${params.id}`]
    }
  }).then(res => res.json());

  return (
    <div>
      <h1>{product.name}</h1>
      <p>가격: {product.price}원</p>
    </div>
  );
}

💡 ⚠️ 흔한 실수

  • revalidate 시간을 너무 짧게 설정해서 캐싱 효과를 못 보는 경우 (5초 이하는 대부분 불필요)
  • 캐시 태그를 안 써서 전체 캐시를 날려야 하는 비효율적 운영 (revalidatePath 남발)
  • generateStaticParams와 revalidate를 함께 안 써서 동적 라우팅 최적화를 놓치는 경우

💡 🎯 면접 준비

Q: Next.js에서 ISR과 SSG의 차이점과 언제 각각 사용하는지 설명해보세요
Q: 대용량 트래픽 상황에서 Next.js 캐싱 전략을 어떻게 수립하겠습니까?
Q: revalidateTag와 revalidatePath의 차이점과 사용 시나리오를 말해보세요

힌트: ISR은 빌드 후에도 데이터 갱신이 가능한 하이브리드 방식이라고 설명하고, 실무 사례(커머스 상품 목록 등)를 들어 설명. 캐싱 레벨별 차이점(Request Memoization vs Data Cache)과 태그 기반 무효화의 장점을 구체적으로 언급하면 고득점.

⚛️ React 패턴 — 데이터 패칭

데이터 패칭을 React에서 어떻게 쓰는지 코드와 함께 단계별로 익혀보세요.
1 🧩 1. 데이터 패칭 사용 시나리오
이 기능이 필요한 상황.
2 💻 2. 코드 작성
데이터 패칭의 기본 사용법.
3 🎨 3. 렌더링 결과
사용자가 보는 화면.
4 💡 4. 실무 팁
흔한 함정과 베스트 프랙티스.

🎮 데이터 패칭 — 단계별 이해

각 단계를 클릭해 내용을 읽고 ✓ 이해했어요 버튼으로 진행률을 확인하세요.
🖥️ 실행 결과 — 렌더링된 React 컴포넌트
✏️ React 코드 수정하기 (클릭해서 열기)
⚛️ React 18 + Babel Standalone — 결과 먼저 확인 후 코드 편집기에서 직접 수정해볼 수 있습니다.

확인 퀴즈

React에서 컴포넌트 마운트 시 API를 호출하는 올바른 Hook은?
💡 useEffect(fn, [])는 컴포넌트가 처음 마운트될 때 한 번만 실행돼요. API 호출, 이벤트 리스너 등록 등 사이드 이펙트는 useEffect에서 처리해요. 렌더링 중 직접 호출하면 무한 루프가 생길 수 있어요.
먼저 읽으면 좋은 개념: React Router
데이터 패칭 - React