22.4 Preview Deployments

바로 배포 시키기 전에 preview 할 수 있어야 하겠지?
깃에서 브랜치 따서 push 하면 알아서 배포가 된다.
일단  enter-message라는 이름의 깃 브랜치를 따자.

git checkout -b enter-message

그리고 코드 수정하고 바로 커밋하면

git add .
git commit -m "New Welcome Msg"
git push origin enter-message

브랜치에서 보낸 코드가 빌드 되고, 볼 수 있는 preview 도메인이 생긴다.
그리고 prod로 배포 하려면
promote to production 누르면 끝!



22.5 Limits in Vercel
https://vercel.com/docs/concepts/limits/overview

<Image> 태그 사용할 때만 해당.

Edge Middleware Invocations는 middleware.ts임
한달에 100만회로 제한. 알아서 잘 활용해라.

역시 제한이 있다.

아래로 가면 내 앱의 사용현황을 볼 수 있다.
https://vercel.com/dashboard/usage

근데 serverless function은 revalidate할 때도 카운팅 되기 때문에 조심해라.
https://vercel.com/docs/concepts/limits/usage#invocations

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를 지원하니 저렇게 쓰는거고, 
다른 라이브러리에서는 다르게 써야 할 것이야.

20.0 Introduction

ISR = 단계적 정적 재생성
NextJS에서 최고의 기능!!

페이지를 렌더링하는 방법들
1. CSR - 완성된 초기 html먼저 보여줌, ReactJS가 데이터 알아서 불러오고.
2. SSR - all or nothing, 완성된 HTML 보여주고, ReactJS는 필요없음.(getServerSideProps)
3. 빌드 될 때 파일 미리 생성해두기(getStaticProps, getStaticPath), interaction없는 static page(F&Q 같은 곳)에 사 - 직전 포스트의 내용

이제는 페이지 불러 올 때 getServerSideProps없이도 로딩상태를 완전히  안보여줄 수 있다.


20.1 ISR part One
ISR사용하면 로딩 안보이고, 서버에서 렌더링 할 필요 없음(getServerSideProps사용 안함). 페이지 즉시 불러 올 수 있음.
유저가 페이지 열면 서버단에서 렌더링 되는게 아님. 이미 랜더링 된 상태.

getStaticProps()의 return 객체에 revalidate에 시간(초)을 넣으면
그 시간마다 페이지가 다시 빌드 됨.

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,
  };
}
export default Community;

좀더 정확히 말하면,
1. revalidate에는 20초라는 타이머가 설정되고
2. 유저 몇명이 오든 20초 안에 오면 같은 버전의 페이지를 보여줌.
3. 그리고 20초가 지나서 유저가 오면, 여전히 2번의 유저들과 같은 페이지를 보여주지만, 이 때 revalidate를 해서 다시 빌드를 시작한다.
4. 그리고 그 다음에 온 유저는 그 빌드된 새 버전의 페이지를 보게 됨.
즉, revalidate시간이 지나도 사람 안오면 굳이 빌드 안함.
https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration

이를 테스트 해보려면 npm run dev로는 안됨.
개발자 모드이기 때문에 계속 최신 화면 보여주기 때문. 
그러니 npm run build 하고, npm run start해야 함.

19.13 Dynamic getStaticProps

일단 설치

npm i unified remark-parse remark-html

https://www.npmjs.com/package/remark-html

설치하고 아래처럼 사용하면 된다.

import { unified } from "unified";
import remarkParse from "remark-parse/lib";
import remarkHtml from "remark-html";


getStaticPath를 통해 파일 읽고, 파일 이름 읽어서 params에 {slug:name} 객체를 전달한다.
이것들을 페이지로 만들어주세요~하는거지

그러면 getStaticProps에서 context객체를 통해 위 params에 접근 가능하게 되고, 
슬러그 id들을 접수 받고, 이 슬러그(post)들을 HTML로 바꿔주고
화면을 그린다. 아래 사진 참고.

아래는 결과물

 

19.14 Inner HTML
ReacJS는 위처럼 받은 데이터가 html태그여도 그냥String으로 받는다.
보안에 상당히 취약하기 때문이다. 댓글로 <script>태그를 넣어 사용자 정보를 빼올 수도 있다.
그러니 이를 막아놨다.
다만 위 경우, data source를 신뢰 할 수 있기 때문에 dangerouslySetInnerHTML이라는 옵션을 사용하면 된다.
dangerouslySetInnerHTML은 브라우저 DOM에서 innerHTML을 사용하기 위한 React의 대체 방법,__html 키로 객체를 전달한다.

참고, css파일에서 @apply를 사용하면 tailwind 문법 사용가능하다.

19.15 Recap
getStaticProps가 잘 동작하는지 보려면, .next 폴더 지우고 build다시 해야 함.
getStaticProps처럼 페이지 빌드할 때 미리 다 해놓는걸 Backend or CRM or Admin pannel 이라고 부른다(?)

이번에는 세션을 어떻게 가져올거냐?
핵심은 NextPageContext

19.6 getServerSideProps

NextJS 데이터 fetching을 어떻게 하나?

유저에게 화면을 어떻게 보여줄지는 두가지로 나뉜다.
1. 다 로딩되면 한번에 보여주자. SSR (server side rendering)
2. 로딩 전에 뭐라도 보여주자. CSR (client side rendering)

1번 방식을 구현하려면 getServerSideProps()를 사용하면된다.
페이지에서 getServerSideProps(서버 측 렌더링)라는 함수를 export 하면 Next.js는 getServerSideProps에서 반환된 데이터를 사용하여 각 요청에서 이 페이지를 미리 랜더링한다고함.

useSWR을 안쓰고 index.tsx에 getServerSideProps()를 다음과 같이 넣어주면
서버에서 먼저 실행한다. 그럼 잘 작동하는데 이 때 useSWR의 다양한 기능을 못씀.
static optimization이나 cache 못함.
그리고 getServerSideProps() 실행 도중 에러나면 아무것도 보지 못한다.

export async function getServerSideProps() {
  const products = await client.product.findMany({});
  console.log(products);
  return {
    props: {
      products: JSON.parse(JSON.stringify(products)),
    },
  };
}

이제, 서버사이드랜더링 + useSWR사용을 알아보자.

19.7 SSR + SWR
위 방식 만으로 prototype
페에지는 SSR로 불러오지만, 클라이언트 단에서 페이지 열릴 때 useSWR이 백그라운드에서 API로 최신 데이터 불러서 업데이트 하는 것.

이 예에서는 getServerSideProps()에서 product의 count를 불러오지 않음.
새로고침 하면 SSR로 한번에 뜨는데
나중에 SWR에서 API로 불러온 product의 count가 업데이트 됨.


여러개도 됨

<SWRConfig
      value={{
        fallback: {
          "/api/products": {
            ok: true,
            products,
          },
        fallback: {
          "/api/user": {
            ok: true,
            products,
          },
        },
      }}
    >
      <Home />
    </SWRConfig>



import Document, { Head, Html, Main, NextScript } from "next/document";

class CustomDocument extends Document {
  render(): JSX.Element {
    console.log("Document is running");
    return (
      <Html lang="ko">
        <Head>
          <link
            href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main></Main>
          <NextScript></NextScript>
        </body>
      </Html>
    );
  }
}

export default CustomDocument;
//NextJS앱의 html 뼈대를 짜주는 역할
//안의 Main은 Nextjs가 앱 컴포넌트를 랜덩링 해주는 것.
//HTML 뼈대를 짜주는 역할을 하는 파일이라 서버에서 단 한번 실행 됨.
//<Main>안에서 _app.tsx가 들어간다.

_document.tsx의 역할.
이 페이지는 단 한번 렌더링 됨.
그리고 아래 html은 크롤라나 bot이 올 때 이미 완성되어있다. SEO에 좋다.

아래는 위치

 

_document.tsx


NextJS의 폰트 최적화는 구글 폰트에 한정되어있기 때문에 구글폰트 링크를 써야 함.
어떻게 최적화 해줄까?
개발자모드에선 확인 안됨.
빌드해야 함

일단 구글폰트를 불러오는 링크(<linkhref="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap"rel="stylesheet"/>)에는 폰트를 불러올 링크들이 또 있다.
따라서 빌드 시에 이 링키들을 열어서 한군데 모아줌. 그러니 이미 폰트들을 불러와 두는거지. 두단계를 건너 뛴다고 보면 되나? 꽤나 도움이 될듯하다.

 

+ Recent posts