header-cover

SSG, SSR의 차이점을 문제를 통해 정리

NextJS를 사용하여 현재 블로그를 개발하던 중 발생했던 문제와 해결과정을 작성하였습니다

2022-11-10·
 
 

요약 🖊️

노션을 사용한 블로그 개발을 Nextjs로 진행하던 중 초기 Notion API를 사용하는 부분에서 어려움을 겪어 유튜브를 참고하여 진행하였습니다.
이때 유튜브에서 진행하는대로getStaticProps를 사용하여 구현하였는데 나중에 성능 테스트를 위해 배포해보니 아주 빠르게 구현이 되어 만족했지만 이후 여러가지 문제가 발생하였습니다.
 
  1. 동적으로 업데이트 되지 않음 → 공개/비공개 설정이 적용되지 않음
  1. 이미지가 사라짐(Notion API는 1시간 후에 만료되는 AWS 링크를 사용해서 이미지가 배포 후 1시간 후에 만료됩니다.)
 
이후 SSR로 구현을 변경하였고 SSR과 Static Generation의 차이와 진행사항을 작성하였습니다.
 

 
 

개요 📜

이전에 NextJS를 사용할 때는 SSRStatic Generation의 차이를 이해하기 어려웠는데 이번에 블로그를 스스로 개발해보면서 이해한 부분을 작성하였습니다
 

getStaticProps와 getServerSideProps 정리

 
우선 이 둘은 Pre-Rendering이라고 하는 방식을 가진다는 공통점이 있는데 이 때 Pre-Rendering이란 쉽게말해 서버에서 미리 렌더링을 한다고 할 수 있습니다
 
우리가 흔히 아는 리액트에 CSR방식과 비교해보면 초기에 많은 양의 JS파일을 서버에서부터 받아오는 방식을 사용함으로써 초기 데이터 불러오는 시간이 길어지지만 부드러운 페이지 이동이 가능하게 하는 것이 장점이라면 SSR은 초기에 서버에서 HTML파일로 렌더링해서 먼저 보내준 뒤 JS를 적용하는 방식입니다. 이러한 SSR방식을 사용하면 사용자가 느끼기에 초기 응답시간이 줄어 빠르게 보여진다는 것과 동시에 JS를 하이드레이션(HTML 보낸 것 위에 JS를 덮음)시키면서 CSR의 장점까지 사용할 수 있다는 것입니다(하지만 초기에 다 받아오는 CSR에 비해서 요청 처리시간이 발생하게 됨)
 
이때 이러한 Pre-Rendering에서도 Static GenerationSSR로 나뉘어지게 됩니다
이 둘의 차이는 HTML이 어느 시점에 만들어지느냐에 대한 차이가 있습니다

Static Generation (getStaticProps)

💡
HTML 파일이 빌드(build)시 생성됨(정적으로 생성된다)
하나의 프로젝트를 배포하기 위해 build로 생성→ 이후에 배포하게 된다면 build 안에 있는 파일들이 배포되는데, 이 build 파일이 만들어질 때 클라이언트에게 넘겨줄 HTML 파일이 만들어집니다
 
장점
  • 이미 만들어져있기 때문에 요청시 응답하는 속도가 매우 빠름
단점
  • 이미 만들어져있는 페이지기 때문에 만약 업데이트하고자 한다면 다시 빌드시켜야 함
 
미리 만들어져야할 때 만약 해당 페이지가 동적인 요청에 의존한다면 getStaticPaths를 통하여 미리 만들어지는 정적인 페이지들의 범위를 정해줘야 함

SSR (getServerSideProps)

💡
HTML 파일이 요청시 생성됨
 
흔히 알려진 SSR 특징으로 페이지 요청시 HTML을 먼저 받아오고나서 JS를 받아오는 방식으로 초기에 CSR보다 빠르게 응답해줄 수 있다
 
장점
  • Static Generation과 비교했을 때 동적인 처리가 가능
    • ex) 블로그 글 업데이트, 수정 등..
단점
  • 요청이 왔을 때 처리시간이 발생하면서 미리 만들어지는 것에 비해 느림
 

발생한 문제 🚨

  1. Notion에서 사용 중인 DB에서 Published설정을 했을 때 업데이트 되지 않음
    1. - Published가 체크되어 있는데 목록에서는 보이지 않는다.
      notion image
      notion image
 
  1. 블로그 이미지가 AWS 링크를 사용해서 이미지가 배포된 후 1시간 후에 만료됨
    1. notion image
 

해결과정 😀

처음 vercel을 통해 배포해서 로딩시간 체크를 해봤을 때 상당히 빨라서 문제가 없구나 했는데 이후에 위 문제가 발생하면서 데이터 가져오는 방식과 fetching 방식을 좀 더 찾아보게 되었고 이후에 NextJS에서 데이터를 가져오는 방식이 조금씩 다르다는 것을 깨닫고 나중에 또다시 헷갈리지 않기 위해서 문서로 정리하였습니다. 우선은 Static Generation → SSR 방식으로 변경하게 되었습니다
기존 방식보다 많이 느려졌습니다.  응답받는 데이터가 무겁다보니 1초정도 소요됨
기존 방식보다 많이 느려졌습니다. 응답받는 데이터가 무겁다보니 1초정도 소요됨
const Post = ({ title, recordMap, }: InferGetServerSidePropsType<typeof getServerSideProps>) => { return ( <> //... Post HTML </> ); }; export const getServerSideProps: GetServerSideProps = async (context) => { // ================getStaticProps => getServerSideProps const notionService = new NotionService(); // @ts-ignore const recordMap = await notionService.getSingleBlogPost(context.params?.slug); const title = getPageTitle(recordMap); if (!recordMap) { throw ''; } return { props: { recordMap, title, }, }; }; export default Post;
 
 

회고 🔍

결론적으로는 응답 속도가 많이 느려졌지만 모든 컨텐츠를 보여주는게 중요하기 때문에 SSR 방식으로 변경을 하였습니다. 이렇게 변경을 함으로써 응답시간(1초정도 걸린다..)이 많이 느려져서 이후에 스켈레톤, 로딩바같이 응답 처리 중이라는 것을 알려주는 방식을 적용시켜볼 예정입니다.
 
추가적으로 이 문서를 작성하면서 봤던 재밌는 글이 있었는데 어떤 게임에 빗대어 공부하는 방식을 알려준 글이 있었습니다.
이 글에서 5번 문항에 있는 실전에서 죽어가면서 몸에 익히자라는 방식, 즉 실제로 사용을 해보면서 이해되지 않는 부분을 챙기고 익혀두는 방식이 계속해서 공부하는 여러 방법들 중에서 효과가 좋다는 것을 다시 한번 느끼게 되었습니다