참고 : use server
📍fetch 동작
nextjs14버전으로 들어오면서 useQuery(react query), useSWR과 같은 훅을 사용하지 않고 손쉽게 fetch동작을 효율적으로 구현할 수 있게 되었다.
우선 normal한 react버전으로 fetch하는 과정과 nextjs14의 신기술을 이용하는 과정을 비교해보자.
1. Normal React Fetch
useEffect를 사용하여 fetch를 진행한다.fetch해서 가져온 데이터값을 useState를 이용하여 저장한다.useState에서 값을 꺼내 실제로 사용한다.
단점
- 우선 useState, useEffect과정은 CSR로 이루어진다. 따라서 fetch를 하는 과정도 화면에 그 페이지가 뿌려진다음 이루어지기 때문에, 만약 fetch하는 과정이 오래걸리면 loading state에 빠질 수 있다. => 따라서 사용자에게 빈 화면을 보여주고 싶지 않으면 useState를 이용해 또 loading state를 만들어야 한다.
- 다른 페이지로 갔다가 돌아오면 fetch로 받아온 정보가 바뀌지 않았음에도 불구하고 useEffect때문에 또 api호출을 해서 새로 값을 받아온다. cache 기능이 없기 때문!!
2. Nextjs14
컴포넌트 밖에 fetch를 진행하는 함수를 제작하고 return값으로 정보를 넘겨받는다.Nextjs상에서 그 정보를 캐시에 저장한다.다시 컴포넌트 함수로 돌아가서 fetch를 진행하는 함수를 호출해서 return받은 데이터를 저장한다.그 데이터를 사용한다.
이 기능을 이용하면 위에서 발생했던 단점들을 해결할 수 있다.
해결
- useState, useEffect를 사용하지 않는, 즉 SSR과정에서 모든 fetch동작이 이루어지는 것이기 때문에 사용자가 loading state에 빠지지 않는다. => 즉 서버상에서 렌더링 될 때 fetch를 진행해서 정보들을 전부 가져온 후 사용자에게 뿌려준다.
- cache기능이 동작하고 있기 때문에 만약 fetch로 불러온 값이 이미 cache값에 존재하면 fetch하는 함수 자체를 실행시키지 않는다. => 따라서 사용자가 한번 갔던 페이지로 다시 돌아오면 즉시 페이지를 볼 수 있고, 불필요한 api호출도 방지할 수 있다.
- 사용자의 브라우저에서 fetch동작이 진행되는 것이 아니기 때문에 api호출을 통해 우회해서 db에 접근하는 것이 아니라 api없이 direct로 db호출을 할 수 있다(보안적인 측면).
예시 코드
export const API_URL = "호출할 api url작성"; async function getMovies() { console.log("getMovies start"); await new Promise((resolve) => setTimeout(resolve, 5000)); const response = await fetch(API_URL); const json = response.json(); return json; } export default async function HomePage() { const movies = await getMovies(); return <h6>{JSON.stringify(movies)}</h6>; }
위 코드에서 최초로 HomePage를 갔을 때 getMovies함수가 실행된다(5s delay). 다른 url로 갔다가 다시 이 url로 돌아오면 getMovies함수가 실행되지 않는다.
🧐 문제점
위 과정들을 통해 Nextjs의 기능을 이용하는 것이 유리하다는 것을 알게되었다.
하지만 이 방법도 한가지 문제가있다. 만약 위 코드처럼 데이터의 크기가 너무 커서 fetch하는데 시간이 오래걸린다고 생각을 해보겠다. 그렇다면 사용자가 그 페이지를 들어가려고 하면 fetch가 끝날때 까지 그 페이지 자체를 볼 수 없게 된다.
이 상황은 썩 마음에들지 않는다. 사용자에게 지금 fetch하려는 데이터 이외에 다른 ui들은 보여주고 싶기 때문이다. 이 문제를 해결하기 위해서 나온것이 Nextjs의 loading component이다.
📍Loading component
우선 저렇게 loading이 필요한 페이지에 같은 경로폴더내에 loading.tsx파일을 생성한다.
그 후 이렇게 코드를 작성하면 끝이다. 상당히 간단하다.
export default function Loading() { return <div>Loading...</div>; }
이렇게 되면
return <h6>{JSON.stringify(movies)}</h6>;
fetch를 통해 데이터가 들어와서 이 코드가 실행되기 전까지
return <div>Loading...</div>;
이 코드를 실행시켜주다 나중에 자동으로 바꿔치기해준다.
loading상태를 관리해주는 것이 엄청나게 편리하다!!!