21 FUTURE: REACT 18
21.0 Suspense
21.1 Server Components
21.2 Promise Me Your Love
21.3 Throwing Our Promise
21.4 Parallelism
21.5 Recap

현재는 SWR, Prisma와 사용불가 (alpha에서)

페이지에 대해 신경 쓸 필요없다. 컴포넌트에 대해 신경 쓴다.
몇몇 컴포넌트를 서버에서 만들 수 있다.
SSR이 아니다. SSR은 페이지에 접속하면 페이지가 서버에서 렌더링이 되는거.
페이지 전체 로딩하는데 시간이 많이 걸림. 

서버컴포넌트를 사용하면 페이지 접근 시
클라이언트에서 렌더링된 모든 컴포넌트를 볼 수 있음. 
뒤에서 서버가 리액트 서버 컴포넌트를 렌더링 한다.
렌더링이 끝나면 HTTP를 이용해 렌더링 결과물을 보내준다.


브라우저 상단의 로딩은
서버에서 브라우저 페이지로 다 전송했는지 알려주는 로딩표시


핵심은 컴포넌트 단위로 서버에서 렌더링 할지 클라이언트에서 할지 고를 수 있게된다는 것.
컴포넌트 단위로 SQL을 사용 할 수 도 있다는 것.
https://reactjs.org/blog/2022/03/29/react-v18.html

server component 아직도 개발중.
next.js 13.0에서는 이름을 xxx.server.js로 짓는다고 servercomponent 안됨.
/app 폴더 안에 있는 컴포넌트만 server component임.
https://nextjs.org/blog/layouts-rfc#react-server-components

서버쪾에서 렌더링을 하니까, 유저쪽에서 처리해야 하는 일은 적어짐.
큰 javascript 들 import할일이 적게 됨.
즉 서버컴포넌트 사용하면 서버에서 렌더링이 이뤄지고 결과물만 프론트로 스트림 됨

코인 list를 주는  API를 콜하고, 불려진 코인의 가격을 알아오는 API를 또 각 코인마다 부를 경우를 예를 들어보자.

CoinsServer라는 서버컴포넌트는 그 안에서 List컴포넌트를 불러온다.
여기서 일단 1차 로딩이 되면
List 컴포넌트 안의 Coin 컴포넌트에서 각 코인의 id를 사용해 가격을 불러오는 수십번의 api콜을 한다.
그리고 각 코인들은 로딩이 되는 순서대로 `Coin ${Coin.name} is loading`에서 각자의 가격을 보여주게 된다.

Suspense는 코드에서 로딩 상태를 나타내는 부분을 제거할 수 있게 해주는 API다.
코드에서 로딩 상태에 대해 신경쓰지 않아도 유저가 로딩 상태 화면을 볼 수 있는것.

getStaticProps, getStaticPaths, getServerSideProps와는 사용 못함.
getStaticProps에는 로딩화면이 없으니까!

그러니 위 props나 nextjs를 사용하지 않는 곳에 사용하면 좋음.

<SWRConfig
      value={{
        suspense: true,
      }}
    >

suspense를 사용하면, SWR을 사용한 컴포넌트를 찾는다.그리고 그 컴포넌트는 로딩이 완료 될 때 까지 보이지 않는다.
그래서, header,footer같은 곳에 SWR을 쓰면 로딩 할 때 전체 화면안보이게 됨.
그래서 컴포넌트 추출해서 그곳에서 SWR써라.

<Layout hasTabBar title="나의 캐럿" seoTitle="Profile">
    <div className="px-4">
      <Suspense fallback="Loading Mini Profile">
        <MiniProfile />
      </Suspense>
	</div>
</Layout>

next.js에서 Suspense를 지원하니 저렇게 쓰는거고, 
다른 라이브러리에서는 다르게 써야 할 것이야.

ODR(On Demand Revalidation)
getStaticProps
: 빌드 시 최초 한번만 실행 됨. 그래서 데이터가 담긴 HTML이 생성 됨.
아래처럼 revalidate를 쓰면 페이지가 최신인지 아닌지 판단 가능.
nextjs 내부의 타이머가 20초로 맞춰지고, 그 때 까진 모든 사용자에게 같은 페이지를 보여줌. 20초 이후에 방문자가 오면 그 사람에게 역시 같은 페이지를 보여주고, nextjs 내부에서 새 버전의 페이지를 만듦. 그래서 그 다음 방문자에게 새 버전을 보여줌. 역시 로딩이 필요없지.

export async function getStaticProps() {
  console.log("building comming, statically");
  const posts = await client.post.findMany({ include: { user: true } });
  return {
    props: {
      posts: JSON.parse(JSON.stringify(posts)),
    },
    revalidate: 20,
  };
}

아니면 특정 액션 이후에 revalidate를 동작케 할 수 있다. 
api 폴더 내에 revalidate.ts를 만들고 .env에 나만의 TOKEN을 저장한다.
그리고 api/posts에서 post를 작성 할 때, 특정 TOKEN을 포함한 URL로 request를 날려주면
revalidate.ts에서 토큰을 비교해서 revalidate를 해준다.

 

ISR(Incremental Static Regenertion)
그럼 동적인 페이지들도 정적페이지로 만들수는 없을까? (/products/[id] 페이지의 동작방식에서 구현함.)
getStaticPaths에서 paths에 빈 array를 넘기면 됨.
그러면 아래 사진처럼 products폴더 안에 빨간 박스 부분 없이 build됨.
그리고 /products/1로 최초 request가 오면, 1.html을 생성한다.
그 다음 request에는 이미 생성된 HTML을 주게 되니 로딩없이 바로 페이지가 렌더링된다.
이렇게 incremental하게 static 페이지를 generate하는 방식여서 ISR이라고 부른다.


여기서 fallback 옵션을 어떤 것을 주느냐에 따라
페이지를 생성할 동안 사용자에게 어떤 화면을 보여줄지 정할 수 있다.
true,'blocking',false

export const getStaticPaths: GetStaticPaths = () => {
  return {
    paths: [], //페이지 빌드 할 때 아무런 HTML페이지도 미리 생성하지 않는다는 뜻. 그러나 사용자의 요청에 따라 미리 만들어지기 시작할꺼고, 여기서 fallback이 활용된다.
    fallback: true,
    //GetStaticProps or GetStaticPaths이 있는 페이지에 왔을 때, HTML이 아직 없으면,
    //유저를 잠깐 blocking하고 그동안 백그라운드에서 페이지를 만들어서 유저를 줌.
    //blocking 할동안 유저는 아무것도 못보지
    //이는 딱 한번만 일어남. 기본적으로 SSR임.

    //false면 어떤 페이지든 프로젝트의 빌드과정에서 만들어지는 것만이 가질 수 있는것. 추가하지못함
    //그래서 이 경우 404 return됨

    //true면 page generate될 때 까지 무언갈 보여줌
  };
};

1. fallback: true
router에 접근해서 router.isFallbck이라는 변수를 이용해서 페이지 생성 동안 대신 보여줄 html을 지정해준다.

참고로 ISR 이면 위 코드에서 GET방식의 /api/products/ 컨트롤러는 필요 없겠지. 이미 생성된 페이지를 보여주기 때문에. POST는 데이터 변경해야 하기 때문에 필요하고.

2. fallback: false
404 페이지가 리턴됨. 
프로젝트가 build 될 때 생성된 페이지들만 보여준다는 뜻임.

3. fallback: 'blocking'
GetStaticProps or GetStaticPaths이 있는 페이지에 왔을 때, HTML이 아직 없으면,
유저를 잠깐 blocking하고 그동안 백그라운드에서 페이지를 만들어줌.
blocking 할동안 유저는 아무것도 못봄. 이는 딱 한번만 일어남. 기본적으로 SSR임.


참고 할 것들.
ISR은 user의 정보에 의존적인 페이지(account,profile,dashboard 등)에는 적합하지 않음.
사용자별로 페이지를 만들어 놓는게 불가능하니까.
이 때는 그냥 normal fetching을 사용해야 함.

그리고 SSR(getServerSideProps)은 DB가 빠르면 고려해볼만 하다. 다만 blank 페이지를 보게되겠지.




20.7 Code Challenge
community/[id] 부분을 
getStaticProps, getStaticPaths, 그리고 fallback을 사용해서 HTML로 만들어봐.
필요할 때, revalidate도 해야하고.
궁금해요 기능을 위해서 SWR도 해야 함. profile/index에서 사용했었음. 이거 똑같이 하면 됨.

+ Recent posts