ISR(Incremental Static Regeneration) 단계적 정적 재생성

김종민·2022년 8월 28일
0

apple-market

목록 보기
34/37


ISR 단계적 정적 재생성에 대해서 알아보고
이를 통해서 웹의 속도를 향상시켜본다.
ISR은 페이지를 정적페이지로 만들어 주어서
(HTML페이지로 미리 빌드를 시켜버림)
속도가 엄청 상승하고 따로 loading이 필요가 없음.
community page에 적용시켜본다.
ISR을 사용하면, useSWR을 사용할 필요가 없음.

ex.)
await new Promise(resolve => setTimeout(resolve, 5000))
=>다음 부분 실행시키는데, 5초 지연시킴.

https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration

1. pages/community/index.tsx

import useCoords from '@libs/client/useCoords'
import client from '@libs/server/client'
import { Post, User } from '@prisma/client'
import type { NextPage } from 'next'
import Head from 'next/head'
import Link from 'next/link'
import useSWR from 'swr'
import FloatingButton from '../../components/floating-button'
import Layout from '../../components/layout'

interface PostWithUser extends Post {
  user: User
  _count: {
    wondering: number
    answers: number
  }
}
interface PostsResponse {
  // ok: boolean
  posts: PostWithUser[]
}

const Community: NextPage<PostsResponse> = ({ posts }) => {
///{posts}를 받는것은 밑의 getStaticProps로 API사용없이 이 page에서
///posts를 바로 불러와버림.
///NextPage옆에 type을 <>와 같이 넣어주어야 됨.

  // const { latitude, longitude } = useCoords()
  // const { data } = useSWR<PostsResponse>(
  //   latitude && longitude
  //     ? `/api/posts?latitude=${latitude}&longitude=${longitude}`
  //     : null
  // )
  ----->ISR을 사용하면, useSWR을 사용할 필요가 없음.
  
  return (
    <Layout hasTabBar title="동네생활">
      <div className="py-16 space-y-8">
        {posts?.map((post: any) => (
          <Link key={post.id} href={`/community/${post.id}`}>
            <a className="flex cursor-pointer flex-col items-start">
              <span className="flex ml-4 items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
                동네질문
              </span>
              <div className="mt-2 px-4 text-gray-700">
                <span className="text-orange-500 font-medium">Q .</span>
                {post.question}
              </div>
              <div className="mt-5 px-4 flex items-center justify-between w-full text-gray-500 font-medium text-xs">
                <span>{post.user.name}</span>
                <span>{post.createdAt}</span>
              </div>
              <div className="flex px-4 space-x-5 mt-3 text-gray-500 py-3 border-t w-full border-b-[2px] shadow-lg">
                <span className="flex space-x-2 items-center text-sm ">
                  <svg
                    className="w-4 h-4"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                    xmlns="http://www.w3.org/2000/svg"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
                    ></path>
                  </svg>
                  <span>궁금해요 {post._count?.wondering}</span>
                </span>
                <span className="flex space-x-2 items-center text-sm ">
                  <svg
                    className="w-4 h-4"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                    xmlns="http://www.w3.org/2000/svg"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
                    ></path>
                  </svg>
                  <span>답변 {post._count?.answers}</span>
                </span>
              </div>
            </a>
          </Link>
        ))}
        <FloatingButton href="/community/write">
          <svg
            className="w-6 h-6"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth="2"
              d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
            ></path>
          </svg>
        </FloatingButton>
      </div>
    </Layout>
  )
}


///ISR사용방법
export async function getStaticProps() {
  console.log('Building.........')
  const posts = await client.post.findMany({ include: { user: true } })
  return {
    props: {
      posts: JSON.parse(JSON.stringify(posts)),
    },
    //revalidate:10
  }
}
///this page에서 prisma를 사용해서 post를 불러와버린다.
///그리고 불러온 post data를 build를 통해서 바로 HTML로 만들어버린다.
///그래서 정적page가 됨. 하지만, update시 계속해서 build를 할 수 없다.
///그래서 두가지 방법이 있음.
///1. 이 페이지에서 revalidate:10 로 10초마다 update되게 설정하는 방법과
///2. /api/post/index.ts에 가서 새 글이 등록될떄마다 rebuild가 되게함.
///당근 2번이 훨씬 좋겠죠..

export default Community

2. pages/api/posts/index.ts

import withHandler, { ResponseType } from '@libs/server/withHandler'
import { NextApiRequest, NextApiResponse } from 'next'
import client from '@libs/server/client'
import { withApiSession } from '@libs/server/withSession'

async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseType>
) {
  if (req.method === 'POST') {
    const { question, latitude, longitude } = req.body
    const { user } = req.session
    const post = await client.post.create({
      data: {
        question,
        latitude,
        longitude,
        user: {
          connect: {
            id: user?.id,
          },
        },
      },
    })
    await res.revalidate('/community')
    ///POST부분에 위와같이 설정만 해주면, 새글이 등록될때마다, revalidate가 됨.
    ///어메이징함.
    
    res.json({ ok: true, post })
  }
  if (req.method === 'GET') {
    const {
      query: { latitude, longitude },
    } = req
    // const latitudeNumber = parseFloat(latitude?.toString())
    // const longitudeNumber = parseFloat(longitude.toString())
    const posts = await client.post.findMany({
      include: {
        user: {
          select: {
            id: true,
            name: true,
            avatar: true,
          },
        },
        _count: {
          select: {
            wondering: true,
            answers: true,
          },
        },
      },
      where: {
        latitude: {
          gte: Number(latitude) - 0.01,
          lte: Number(latitude) + 0.01,
        },
        longitude: {
          gte: Number(longitude) - 0.01,
          lte: Number(longitude) + 0.01,
        },
      },
    })

    res.json({ ok: true, posts })
  }
}

export default withApiSession(
  withHandler({
    methods: ['POST', 'GET'],
    handler,
  })
)
profile
코딩하는초딩쌤

0개의 댓글