NEXT.JS 13버전의 공식문서를 통해 앱라우팅, 데이터패칭을 이해하고 NEXT.JS를 제대로 써보자

✅ App Router

  • app 디렉토리를 최상위 디렉토리로 가지고 page.js or route.js 파일명을 가진 파일들이 라우팅됨
  • 중첩라우팅은 그냥 하나의 상위폴더에 하위폴더를 여러개 만들면됨

📌 File Conventions

  • layout ➡️ 여러 페이지에 공유되는 UI(레이아웃 끼리 중첩가능, 리렌더링 ❌)
  • loading ➡️ 로딩페이지, 스켈레톤 구현가능 / Suspense로도 구현가능(점진적 랜더링)
  • not-found ➡️ 404 화면 구현
  • error ➡️ 중첩 라우팅에서 예상치 못한 에러 핸들링 ➡️ 개별 컴포넌트에 에러라고 띄울수있음(복구도 구현가능)
  • global-error ➡️ 전역으로 에러 핸들링 가능
  • route ➡️ API 생성, 해당 폴더구조로 API호출가능(ex. app/auth)동적으로 API 호출, API 응답 캐싱
  • template ➡️ layout과 비슷하나 상태가 유지되지않고 페이지 이동시마다 새 인스턴스 생성함(DOM 재생성)

✅ Data Fetching

📌 사용법

1️⃣ server + fetch

async function getData() {
  const res = await fetch('https://api.example.com/...')
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
 
  if (!res.ok) {
    // This will activate the closest `error.js` Error Boundary
    throw new Error('Failed to fetch data')
  }
 
  return res.json()
}
 
export default async function Page() {
  const data = await getData()
 
  return <main></main>
}

2️⃣ server + 라이브러리

3️⃣ client + Route Handler

4️⃣ client + 라이브러리

📌 Cashing Data

  • 기본적으로 자동으로 서버 Data Fetching 캐싱
  • 메서드로 사용되는 Data Fetching도 캐싱(POST 메서드는 Route Handler 내부에 있으면 캐싱❌)
// 'force-cache' 는 기본값으로 굳이 써줄필요가 없음
fetch('https://...', { cache: 'force-cache' })

📌 Revalidating Data

  • 캐시 데이터를 최신화

1️⃣ Time-based Revalidating Data

  • 시간 설정으로 자동으로 데이터 재검증
fetch('https://...', { next: { revalidate: 100 } })

2️⃣ On-demand Revalidating Data

export default async function Page() {
  const res = await fetch('https://...', { next: { tags: ['collection'] } })
  const data = await res.json()
}

3️⃣ 캐쉬 사용 ❌

fetch('https://...', { cache: 'no-store' })
// or
fetch('https://...', { next: { revalidate: 0 } })

✅ Data Fetching 패턴

📌 server + fetch

  • 백엔드 데이터 리소스(예: 데이터베이스)에 직접 액세스 가능
  • 액세스 토큰 및 API 키와 같은 민감한 정보가 클라이언트에 노출되는 것을 방지하여 애플리케이션을 더욱 안전하게 보호 가능
  • 동일한 환경에서 Data Fetching 및 렌더링. 클라이언트와 서버 간의 주고받는 통신은 물론 클라이언트의 메인 스레드 작업도 감소
  • 클라이언트에서 여러 번의 개별 요청 대신 한 번의 왕복으로 여러 Data Fetching를 수행
  • 클라이언트-서버 워터폴 감소.
  • 지역에 따라 Data Fetching를 데이터 소스와 더 가까운 곳에서 수행하여 지연 시간을 줄이고 성능을 개선가능

📌 데이터가 필요한곳에서 fetch

  • fetch 요청이 자동으로 memoization
  • 트리 내 여러 컴포넌트에서 동일한 데이터(예: 로그인 인가)를 사용해야 하는 경우, 데이터를 전역적으로 가져오거나 컴포넌트 간에 프로퍼티를 전달할 필요가 없음
  • 과다한 요청에 의한 성능하락을 걱정할 필요없이 데이터가 필요한 컴포넌트에서 fetch 또는 React 캐시 사용가능

📌 스트리밍 + 서스펜션

  • UI를 단계별로 랜더링(서버컴포넌트 + 중첩레이아웃 사용시)

📌 병렬, 순차 Data Fetching

  • 병렬 Data Fetching ➡️ 비동기적, 비종속적, 비의존적, 빠름 ➡️ 될때까지 기다리지 않고 preload로 최적화 가능
  • 순차 Data Fetching ➡️ 동기적, 종속적, 의존적, 오래걸림 ➡️ 스트리밍 + 서스펜션으로 순차적으로 UI 제공가능
    업로드중..
  • 병렬 데이터 요청
import Albums from './albums'
 
async function getArtist(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}`)
  return res.json()
}
 
async function getArtistAlbums(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}/albums`)
  return res.json()
}
 
export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {
  // Initiate both requests in parallel
  const artistData = getArtist(username)
  const albumsData = getArtistAlbums(username)
 
  // Wait for the promises to resolve
  const [artist, albums] = await Promise.all([artistData, albumsData])
 
  return (
    <>
      <h1>{artist.name}</h1>
      <Albums list={albums}></Albums>
    </>
  )
}
  • 순차적 데이터 요청
async function Playlists({ artistID }: { artistID: string }) {
  // Wait for the playlists
  const playlists = await getArtistPlaylists(artistID)
 
  return (
    <ul>
      {playlists.map((playlist) => (
        <li key={playlist.id}>{playlist.name}</li>
      ))}
    </ul>
  )
}
 
export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {
  // Wait for the artist
  const artist = await getArtist(username)
 
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<div>Loading...</div>}>
        <Playlists artistID={artist.id} />
      </Suspense>
    </>
  )
}

🚨 요약

  1. 서버(컴포넌트) Data Fetching ➡️ 백엔드 리소스 직접 엑세스 & 안정성 향상(🌟권장)
  2. 순차적 Data Fetching ➡️ 요청간 워터폴 효과생성(동기적으로 실행되지만 앞선 요청을 기다려야함)
  3. 병렬적 Data Fetching 가져오기: 병렬로 데이터를 가져와 로딩 시간을 최소화
  4. layout, page 자동 Data Fetching 및 중복 처리:Data Fetching 시 요청 중복 자동처리로 성능향상
  5. fetch() APIfetch() API 기반 Data Fetching / async/await를 사용하여 서버 컴포넌트를 통해 Data Fetching
  6. 정적 및 동적 Data Fetching: 정적 데이터는 빌드를 통해 캐시되고 재사용, 동적 데이터는 Data Fetching 을 통해 업데이트
  7. 캐싱과 재유효화: 데이터 캐싱을 통해 요청 최소화로 성능향상, 재유효화를 통해 최신 데이터를 쉽게 업데이트
  8. 스트리밍과 서스펜스: UI의 점진적인 렌더링과 데이터 로딩을 통해 사용자 경험을 개선할 수 있음.

📚 참고문헌

Data Fetching
Routing
File Conventions(앱 라우팅)
Fetch

0개의 댓글

Powered by GraphCDN, the GraphQL CDN