728x90
SSG 기반 웹사이트 구현하기

 

❓상황

SSG기반으로 웹사이트를 구현하기위해 사용하는 next.js를 확실하게 공부하고 싶어서 정리하게 되었음.

 

📖 next.js 이란?

Next.js는 빠른 웹 응용 프로그램을 만들 수 있는 구성 요소를 제공하는 유연한 React 프레임워크입니다.

 

웹사이트를 구현할때, 고려할 사항은 다음과 같습니다.

 

사용자 인터페이스 - 사용자가 응용프로그램을 사용하고 상호 작용하는 방식.
라우팅 - 사용자가 응용프로그램의 다른 부분을 탐색하는 방법.
데이터 가져오기 - 데이터가 저장되는 위치와 데이터를 가져오는 방법.
렌더링 - 정적 또는 동적 콘텐츠를 렌더링할 때와 장소를 지정합니다.
통합 - 사용하는 타사 서비스(CMS, 인증, 결제 등) 및 이러한 서비스에 연결하는 방법.
인프라 - 애플리케이션 코드(Serverless, CDN, Edge 등)를 배포, 저장 및 실행할 수 있습니다.
성능 - 최종 사용자를 위해 애플리케이션을 최적화하는 방법.
확장성 - 팀, 데이터 및 트래픽 증가에 따라 애플리케이션이 적응하는 방식
개발자 환경 - 응용 프로그램을 구축하고 유지 관리하는 팀의 환경입니다.

 

Next.js는 React에 필요한 툴링과 구성을 처리하고 애플리케이션에 대한 추가 구조, 기능 및 최적화를 제공합니다.

 

🐸 설치

// npm
npm install create-next-app <프로젝트 파일명>

// yarn
yarn create next-app <프로젝트 파일명>

// typescript로 생성 : --template typescript 옵션 추가
yarn create next-app <프로젝트 파일명> --typescript

 

🧮 실습 : 공식문서 따라하기

next.js blog 설치하기

npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"

 

Route 

React의 경우에는 페이지 이동시, react-router-dom 라이브러리를 추가 설치 및 사용하여 페이지를 이동시키곤 했다.

Next.js의 경우에는 route 기능이 내장되어 있어 추가로 라이브러리를 설치할 필요가 없다.

 

그렇다면 어떻게 route를 할 수 있을까?

바로 pages 폴더 아래에 나열된 폴더명과 파일명이 URL이 된다.

 

예를 들어 localhost:3000/post/first-post 라는 페이지를 추가하고 이동하고 싶다면,

 

pages 폴더 아래에 posts라는 폴더를 생성하고, posts 폴더안에 first-post.js 파일을 생성하면 된다.

 

※ URL은 파일명과 연관이 있지, 파일의 export된 함수명과 연관이 있지는 않다.

이렇게 해도, URL은 first-post이다.

 

※ 주의사항으로, pages의 파일을 export할때는 default로 내보내야 정상적으로 작동한다.

 

<Link> 컴포넌트를 이용하여 Route 

react-router-dom을 이용할때도, <Link to="">를 이용한다는 사실을 알고 있을 것이다.

 

Next.js에서도 <Link> 컴포넌트를 사용한다.

 

import는 다음과 같다.

import { Link } from 'next/link';

 

react-router-dom에 사용되는 <Link>와는 조금 다른 점이 있다.

react-router-dom은 <Link to="~~">을 사용한다면, Next.js는 <Link href="~~">를 사용한다는 것이다.

 

자세한 예시는 아래와 같다.

 

※ <a> 태그의 href 속성은 <Link> 컴포넌트의 속성으로 넣어줘야한다.

※ className은 <Link> 컴포넌트가 아닌, <a> 태그에 부여해야한다.

※ <Link> 컴포넌트 안에는 <a> 태그가 들어가야한다. (forwardRef를 이용하면 다른 태그들도 넣을 수 있다.)

 

정적파일 다루기

이미지 파일과 같은 정적파일은 특별히 지정된 폴더가 있지는 않지만, public 폴더안에 넣는 것을 권한다.

이유는, public 폴더안에 넣은 정적파일들을 바로 참조가 가능하기 때문이다.

 

또한, public 폴더는 robot.txt에 유익하다.

 

그리고 정적파일을 불러올때는 <img> 태그를 이용하는데, Next.js에서는 최적화가 이루어진 <Image> 컴포넌트 사용을 권하고 있다.

 

import하는 방법은 다음과 같다.

import { Image } from 'next/image';

 

<Image> 컴포넌트는 필수 속성이 부여되어야한다.

src : 이미지 파일의 경로
width : 이미지 파일의 너비
height : 이미지 파일의 높이

 

 

<head> 커스텀

<head> 태그 안에는 <meta>, <title> 등 또다른 태그들을 넣을 수 있다.

 

Next.js에서는 페이지마다 <meta>, <title> 등을 다르게 지정할 수 있다.

 

< html>, <body> 커스텀

만일 <html lang="ko"> 또는 <body> 태그에 className을 부여하고 싶다면, pages/_document.js 파일을 생성하고 커스텀을 진행하면 된다.

 

Html, Head, Main, NextScript 모두 필수 컴포넌트이다.

 

※ 여기에 사용된 <Head> 컴포넌트는 next/head 에서 사용되는 <Head> 컴포넌트와 다르다. 여기에 사용된 <Head> 컴포넌트는 공통 <head> 태그라고 생각하면 된다.

 

 

※ 나머지 태그들은 속성 부여 불가!

 

<Script> 태그

html의 <script> 태그 대신, next.js의 <Script> 태그를 이용하여, Javascript SDK이 필요한 페이지만 실행되도록 실행할 수 있다.

 

옵션 속성

src : JavaScript SDK 파일 경로
strategy : JavaScript SDK 파일 다운로드하는 시점 설정
onLoad : JavaScript SDK 파일 다운로드 완료 후, 실행시키는 코드
onError : JavaScript SDK 파일 다운로드 실패 후, 실행시키는 코드

 

 

Global Style 적용하기

기존에 react에서 Global Style을 적용하려면, index.js 파일에서 style을 import했다.

 

Next.js는 index.js 파일의 역할을 하는 _app.js 파일에 style을 import하면 된다.

 

_app.js

글로벌 스타일을 적용하기위해, _app.js 파일을 생성하여 스타일을 적용했다.

그렇다면, _app.js 파일은 무엇일까?

 

_app.js 파일은, 모든 page들이 거쳐가는 최상위 페이지이다.

 

예를 들어 홈페이지에서 posts/first-post 페이지로 이동할때, 홈페이지 → _app.js → first-post.js 파일로 이동한다는 뜻이다.

 

그래서 _app.js파일에 글로벌 스타일을 적용하는 이유이기도 하다.

 

_app.js파일은 2개의 props를 갖는다.

<Component> 컴포넌트는 page을 의미한다.

<pageProps> 컴포넌트는 page들이 가진 모든 props를 의미한다.

 

그래서 <Component> 안에 spread 연산자로 pageProps를 넘겨주는 이유이기도 하다.

 

SSR vs SSG

기본적으로 Next.js는 모든 페이지를 미리 렌더링한다.

즉, Next.js는 클라이언트 측 JavaScript에서 모든 작업을 수행하는 대신 각 페이지에 대한 HTML을 미리 생성한다.

미리 렌더링을 진행하면 성능 및 SEO를 향상시킬 수 있다.

pre-render가 발생하면 왜 SEO가 좋은지 보여주는 사진이다.

 

SSR과 SSG의 차이점에 대해서 설명해 주고 있다.

SSR은 사용자가 요청하면 그때마다 서버에서 화면을 만들어서 보내주고,

SSG는 pre-render를 이용하여 서버가 미리 화면을 만들어서 가지고 있다

 

서버단에서 만든 화면을 브라우저에서 표시해주고, JavaScript를 로드하여 실행한다.

이 과정을 완전한 상호작용이라고 하며, hydration이라고 한다.

 

만약 JavaScript를 브라우저에서 다운로드 할 수 없는 상황(disable)이라면

HTML은 pre-render가 진행이 되나(SEO 최적화), CSS는 안된다.

 

SSG를 기본으로 갖고 있는 Next.js으로 인해, 사용자는 조금 더 빠르게 화면에 접속할 수 있다.

 

pre-render : SSG

기존에 내가 공부한 것으로는 pre-render를 한다는 얘기는 정적인 파일을 생성할때만 가능하다.

 

그렇다는 얘기는 fetch를 이용하여 데이터를 가져올 수는 없다는 얘기다.

 

그러나, Next.js는 pre-fetch를 지원해준다.

그것은 바로 getStaticProps!!

 

 

prefetch가 일어날 페이지에 getStaicProps라는 함수를 정확히 추가해준다.

그리고, getStaicProps 함수 안에 fetch할 데이터를 입력해주고, return을 props 객체로 전달해준다.

 

page를 담당하는 파일이 아니라면, getStaticProps 함수가 실행되지 않는다.

 

그럼 해당 페이지는 props를 받도록 파라미터를 작성해주면 된다. 

 

만약 getStaticProps 함수를 아래와 같이 정의했다면

 

props라는 매개변수 대신, 구조분해할당으로 가져올 수도 있다.

 

정리해보자면 getStaticProps 함수는 server단에서 실행하여, pre-render를 구현할 수 있게 도와준다.

만약 pre-render를 하지 않는 페이지를 구성했다면(CSR), 또, pre-redner를 지원하는데 사용자 요청에 따라서 요청을 진행하는 SSR 으로 페이지를 구성했다면, getStaticProps 함수는 어떻게 될까?

 

결론적으로 SSR, SSG, CSR 마다 사용해야하는 함수가 다 다르다.

SSG에대해서는 정리했으니, 이번에는 SSR에 대해 확인해보자

 

pre-render : SSR

SSR은 사용자가 요청할때마다 서버단에서 HTML을 생성한다.

 

SSG와 마찬가지로 서버단에서 data를 fetch할 수 있도록 지원해준다.

 

SSG에는 getStaticProps가 있다면, SSR에는 getServerSideProps 함수가 있다.

 

근데 getStaticProps와 다르게, context라는 매개변수를 받는다.

context라는 매개변수에서 요청(req), 응답(res)를 구조분해할당으로 사용할 수 있다.

 

요청과 응답을 사용하는 예시는 다음과 같다.

export async function getServerSideProps({ req, res }) {
  // 만약 요청의 method가 GET이라면,
  const { method } = req;
  if (method === "GET") {
      props = ~~~
  } else {
      res.status(500).json({ error: 'failed to load data' })
  }

  return {
    props,
  }
}

 

 

이런식으로 요청을 체크하고 데이터를 보내 줄수도 있다.

 

fetch after load : CSR

CSR은 클라이언트단에서 페이지를 생성한다.

 

SSG, SSR이 pre-render를 지원하는 함수를 사용하는 것처럼, CSR은 hook을 사용한다

정확히는, Next.js에서 지원해주지 않고 라이브러리를 이용하여 CSR을 지원하는 것 같다.

 

CSR을 지원하는 라이브러리는 바로 SWR이다!

 

SWR이라는 라이브러리를 처음보게 되어서 당황하게 되었다.

나중에 SWR 라이브러리를 사용할 기회가 생긴다면 정리해봐야겠다.

 

우선 CSR은 SWR이라는 라이브러리를 이용하여 fetch를 진행한다는 것을 기억하면 좋을 것 같다.

 

Dynamic Route

이번에는 데이터값에 따라 URL이 변경되고 페이지를 이동시키는 동적 라우트에 대해 알아보겠다.

 

이전에 URL에 영향을 주는 것은 폴더명과 파일명이라는 것을 알고 있다.

그렇다면, 변화하는 URL값에 따라 어떻게 데이터를 fetch할까?

 

우선 파일명에 [데이터명].js 처럼 파일을 생성한다.

예를 들어 localhost:3000/posts/1 URL에 이동하고 싶다면, pages 폴더안에 posts 폴더를 생성하고, posts 폴더안에 [id].js 파일을 생성하면 된다.

 

getStaticPaths 함수를 통해 URL의 데이터를 가져온다.

정확히는 getStaticPaths 함수안에 URL의 데이터를 가져올 수 있는 useRoute를 사용한다.

import { useRouter } from 'next/router'

export default function Home(){...}

export function getStaticPaths() {
  const router = useRouter()
  const { id } = router.query

  return {
    paths: [
      { params: { id } }
    ],
    fallback: true // false or 'blocking'
  };

}

 

fallback이 false인 경우에는 paths에 없는 페이지를 요청한 경우에, 404페이지로 이동시킨다는 것이다.

fallback이 true인 경우에는 paths에 없는 페이지를 요청한 경우에, Fallback 페이지로 이동시킨다.

 

 

getStaticPaths에서 return된 값은 getStaticProps 함수에 인수로 받게되어 getStaticProps에서 데이터 fetch를 한다.

 

getStaticPaths는 getStaticProps와 함께 사용되어야한다.

 

getStaticProps, getServerSideProps, getStaticPaths는 export와 async가 포함되어야한다.

 

다이나믹 라우트 기능을 실행하기 위해서는 getStaticProps, getStaticPaths 두 개 다, 페이지에 연관되어 있는 컴포넌트에 넣어져야한다.

 

fetch 또는 URL의 값을 가져오는 코드들은 lib 폴더안에 생성하여, getStaicPaths 또는 getStaticProps에 사용하여 가독성을 높이면 좋다.

 

간단한 API 만들기...?

Next.js에는 API를 만들 수 있다.

 

API를 구현하려면, pages 폴더안에 api 폴더를 생성하고, 파일을 만들어주면 API 준비 완료이다.

 

getServerSideProps를 이용한것과 비슷하게, req, res를 이용하여 요청을 받으면 응답을 해줄 수 있다.

 

vercel으로 배포하기

기본적으로 github에 원격저장소를 생성해야한다.

 

vercel이라는 플랫폼은 Next.js으로 개발된 것들을 쉽게 배포할 수 있도록 도와준다.

특히 무료이다!

'공부 > 프론트엔드' 카테고리의 다른 글

공부 | swr 정리(ft. react)  (0) 2022.08.04
공부 | recoil 정리(ft. react)  (0) 2022.07.30
공부 | Line Awesome 정리  (0) 2022.07.16
공부 | react-icons 정리  (0) 2022.07.12
공부 | React Hook Form 정리  (0) 2022.07.09
복사했습니다!