data fetch

조바이블·2024년 2월 15일

Client Side

export default function Page() {
  const [isLoading, setIsLoading] = useState(true)
  const [movies, setMovies] = useState()
  const getMovies = async () => {
    const response = await fetch(
      'http://url/movies',
    )
    const json = await response.json()
    setMovies(json)
    setIsLoading(false)
  }
  useEffect(() => {
    getMovies()
  }, [])
  return <div>{isLoading ? 'Loading' : JSON.stringify(movies)}</div>
}
  • client side에서 api가 동작하기 때문에 사용자에게 로딩상태를 보여줌
  • fetch는 항상 client 에서 일어난다는 의미
  • 이는 브라우저가 API에 요청을 보낸다는 의미
  • 이는 api key나 보안에 필요한 데이터를 넣을수 없다는 의미
  • 값을 보관할 state, useState, useEffect

Server Side

export const metadata = {
  title: 'Home',
}
const URL = 'url'
async function getMovies() {
  const response = await fetch(URL)
  return await response.json()
}

export default async function HomePage() {
  const movies = await getMovies()
  return <div>{JSON.stringify(movies)}</div>
}
  • useState, useEffect 는 없다!
  • next.JS는 fetch된 URL을 알아서 캐싱해준다. 그래서 한번만 가져오면 끝!
  • 첫번째 fetchAPI에 요청한다.
  • 하지만 Loading 상태는 있다. 다만 client에서 server로 옮겨졌다.
  • fetch 작업이 끝나지 않으면 UI가 뜨지 않는다

이 코드는 사용자에게 전달 되지 않는다. 이는 안전하다는 의미이다.
어떤 데이터는 fetch, api키 사용 db와 통신이 가능
사용자는 여기 있는 코드를 볼 수 없다.

이는 사용자는 fetch가 완료될때 까지 화면을 볼수 없다는 의미이다.

Loading

export default function Loading() {
  return <h2>Loading...</h2>
}
  • Next.js는 웹사이트의 일부를 천천히 보낼 수 있다.
  • 첫번째로 보내는 일부분은 layout이나 navigation
  • 그 다음 loading component를 보낸다.
  • next.js는 아직 작업이 끝나지 않았다고 이야기하고 브라우저는 대기한다.
  • 그다음 fetch등의 작업이 완료 되면 완료된 값을 브라우저에게 보낸다.
  • 프론트엔드의 프레임워크는 loading component 대신 결과 값을 렌더링 한다.

http streaming으로 nextJS는 페이지를 작은 html 부분으로 나눠서 준비된 부분을 브라우저에게 전달하는 것이다.

Parallel Requests

import { API_URL } from '../../../(home)/URL'
async function getMovie(id: string) {
  const response = await fetch(`${API_URL}/${id}`)
  return response.json()
}
async function getVideos(id: string) {
  const response = await fetch(`${API_URL}/${id}/videos`)
  return response.json()
}

export default async function MovieDetail({
  params: { id },
}: {
  params: { id: string }
}) {
  const movie = await getMovie(id)
  const videos = await getVideos(id)
  return <h1>{movie.title}</h1>
}
  • 이 코드의 경우 2개의 data fetch를 진행하고 있다.
  • getMovie, getVideos
  • 순차적으로 실행되기 때문에 만약 getMovie가 20초, getVideos가 0.5초가 걸리면
  • 뒤의 getVideos는 20.5초가 소요된다.

Promise.all

Promise.all을 이용하면 동시에 fetch 작업이 가능하다.

export default async function MovieDetail({
  params: { id },
}: {
  params: { id: string }
}) {
  const [movie, video] = await Promise.all([getMovie(id), getVideos(id)])

  return <h1>{movie.title}</h1>
}

다만 이렇게 진행할경우 fetch작업이 동시에 시작하지만 결국에는 2개의 fetch가 모두 응답받은 뒤에 UI를 확인할 수 있다.

suspense

import MovieInfo from '../../../../components/movie-info'
import MovieVideos from '../../../../components/movie-videos'
import { Suspense } from 'react'

export default async function MovieDetail({
  params: { id },
}: {
  params: { id: string }
}) {
  return (
    <div>
      <Suspense fallback={<h1>Loading movie info</h1>}>
        <MovieInfo id={id} />
      </Suspense>
      <Suspense fallback={<h1>Loading movie videos</h1>}>
        <MovieVideos id={id} />
      </Suspense>
    </div>
  )
}
  • 각각의 컴포넌트를 분리하고 Suspense를 사용하면 각각 로딩할 수 있다.
  • 나는 선언해서 사용했을뿐 어떠한 처리를 해준적이 없다.... wow
profile
개발 공부를 해보자.. 취업은.. 어렵겠지만 그래도 공부는 해보자

0개의 댓글