[TIL] 내일배움캠프 React 과정 2023.02.01_Next.js

Today I Learned

  • Next.js 기초 강의 수강

 


CSR vs SSR vs SSG vs ISR

 Client-Side Rendering 

브라우저에서 HTML file을 로드하면, Javascript를 이용하여 rendering 하는 방식이다.

 

 Server-Side Rendering 

브라우저에서 해당하는 페이지를 접속하면, 그 순간 서버에서 html을 렌더링 해서 전달해 주는 방식이다. 페이지를 요청할 때마다 렌더링 하기 때문에 오래 걸린다.

 

 Static-Site Generation 

SSR의 경우 페이지를 요청할 때마다 서버에서 렌더링하는 것에 반해, SSG의 경우에 정적인 페이지를 제공할 때는 빌드할 때 렌더링하고, 페이지를 요청할 때 이미 렌더링 된 페이지를 반환한다.

 

 Incremental Static Regeneration 

SSG의 단점은 컨텐츠가 업데이트되면 제대로 된 정보를 보여줄 수 없다는 것이다. 이를 보완하기 위해서 일정 주기마다 페이지를 빌드시켜주는 ISR이라는 방식이 있다.

 

  CSR SSR SSG ISR
빌드 시간 짧다 짧다 길다 길다
SEO 나쁨 좋음 좋음 좋음
페이지 요청에 따른 응답 시간 보통 길다 짧다 짧다
최신 정보인가? 맞음 맞음 아님 아닐 수 있음

 

 

SSG(Static-Site Generation) 실습

getStaticProps

export async function getStaticProps(context) {
  return {
    props: {}, // will be passed to the page component as props
  }
};
  • 따로 설정을 하지 않는다면, next.js는 프로젝트를 빌드할 때 페이지를 Static Generation 하려고 한다.
  • SSG를 원하는 페이지에 getStaticProps를 추가하면, 해당 페이지는 빌드할 때 렌더링 된다.
  • getStaticProps 함수는 Server에서만 실행된다. Browser에서는 실행되지 않는다.
  • getStaticProps 함수는 build 하는 그 순간만 실행된다.
  • getStaticProps에서는 getServerSideProps에서 context를 통해 쉽게 query에 접근한 것과는 다르게 dynamic routing을 지원하려면 특별한 방법이 필요하다.
  • getStaticProps의 return 값은 Post page의 props로 전달된다.

 

getStaticPaths

// pages/posts/[id].js

// Generates `/posts/1` and `/posts/2`
export async function getStaticPaths() {
  return {
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    fallback: false, // can also be true or 'blocking'
  }
}

// `getStaticPaths` requires using `getStaticProps`
export async function getStaticProps(context) {
  return {
    // Passed to the page component as props
    props: { post: {} },
  }
}

export default function Post({ post }) {
  // Render post...
}
  • getStaticProps을 이용하는 페이지에서 dynamic routes를 제공하기 위해서 사용하는데, 미리 어떤 paths를 Static Site Generation 할 지 정해두는 역할을 한다.
  • getStaticPaths에서는 getStaticProps 가 있어야 실행되고, getStaticPaths의 return 값은 getStaticProps의 props로 전달된다.

 

getStaticPaths fallback 설정

  • false: getStaticPaths에서 제공하지 않은 페이지는 모두 404로 연결한다.
  • true: getStaticPaths에서 제공하지 않은 페이지를 요청한 경우, fallback 페이지를 보여주고, 해당 페이지를 서버에서 생성한 후에 해당 페이지를 보여준다.
  • blocking: getStaticPaths에서 제공하지 않은 페이지를 요청한 경우, 페이지를 서버에서 생성을 한 이후 보여준다.

 

ISR(Incremental Static Regeneration) 실습

export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 10 seconds
    revalidate: 10, // In seconds
  }
}
  • ISR을 사용할 때는 getStaticProps에 revalidate 속성만 추가해주면 된다.
  • 이제 next.js는 해당 static page에 요청이 들어오고 나서 10초 이후에는 다시 한번 해당 페이지를 빌드하게 된다.

 

SEO(Search Engine Optimization)

검색 엔진 최적화란?

  • 구글, 네이버 등 검색 엔진에서 사이트를 찾기 쉽도록 사이트를 개선하는 작업을 말한다. Next.js을 이용하는 이유도 SSR와 SSG을 통해 검색 엔진 최적화를 하기 위해서이다. 

 

크롤링

  • robots.txt 파일 설정
    • 웹 크롤러와 같은 로봇들의 접근을 제어하기 위한 규칙 파일
    • /public 폴더 안에 넣어준다.
  • sitemap.xml 제출
    • next-sitemap같은 라이브러리를 이용해 생성
    • Google Search Console에 제출

 

인덱싱

  • Meta tag 설정
    • <Head> 컴포넌트를 이용해서 _app.js 파일 및 페이지 파일에 Meta tag 설정
  • Open Graph 설정 (링크 미리보기)
  • 참고 사이트: https://www.opengraph.xyz/
  • semantic tag 사용
    • 의미를 가지는 태그 사용: header/footer/section/nav 등

 

 


Programmers 문제 풀기

k의 개수

나의 풀이

function solution(i, j, k) {
    let array = [];
    for (i = i; i <= j; i++) {
        array.push(...i.toString().split(""))
    }
    return array.filter((num) => num === k.toString()).length
}

풀이가 좀 복잡해서 실행 시간이 전체적으로 오래 걸렸다ㅜㅜ

 

 

다른 사람의 풀이 01

function solution(i, j, k) {
    let a ='';
    for(i;i<=j;i++){
        a += i;
    }

    return a.split(k).length-1;
}

배열 안 쓰고 k로 split 하면 되는 거였구나...😯

 

 

7의 개수

나의 풀이

function solution(array) {
    return array.join("").split("7").length-1
}

위에 문제에서 배웠던 방법 바로 써먹었다!

 

 

컨트롤 제트

나의 풀이

function solution(s) {
    let answer = 0;
    let array = s.split(" ")
    array.map((n, i) => n === "Z" ? answer -= parseInt(array[i - 1]) : answer += parseInt(array[i]))
    return answer;
}

 

다른 사람의 풀이 01

function solution(s) {
    const stack = []

    s.split(' ').forEach((target) => {
        if(target === 'Z') stack.pop();
        else stack.push(+target)
    })

    return stack.length ? stack.reduce((pre, cur) => pre + cur) : 0;
}

 

pop 메서드는 처음 보는 거라서 검색해 봤다. 마지막 요소를 제거하는 메서드 같은데 생각해 보니까 'Z'가 나올 경우에는 더했다고 빼는 게 아니라 그 숫자를 아예 계산을 안 해도 되는 거였다. 그래서 forEach를 돌렸을 때 target이 "Z"가 나온다면 직전에 넣었던 배열의 마지막 요소를 빼주는 것이다.

 

const plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];

plants.pop();

console.log(plants);
// Expected output: Array ["broccoli", "cauliflower", "cabbage", "kale"]

 

function solution(s) {
    let array = [];
    s.split(" ").forEach((item) => item === "Z" ? array.pop() : array.push(+item));
    return array.reduce((acc, cur) => acc + cur, 0)
}

다른 사람 풀이 보고 다시 한번 풀어봤다. 근데 내가 원래 풀었던 방법보다 실행 시간이 더 오래 걸린다. 나는 map 한 번 돌렸는데 여기에는 forEach에 reduce까지 사용해서 그런 거 같다.

 


회고

2일 차 Next.js 강의 듣고, 어제 다 못 들은 throttling and debouncing 강의도 마저 듣고 사이트 프로젝트도 조금 수정했다. 저녁에는 오랜만에 프로그래머스 문제도 풀었다! 그리고 최종 프로젝트에 Next.js를 사용할지 팀원 분이랑 얘기를 나눠봤는데 생각보다 적용할 내용이 많아서 나흘 안에 배워서 하기에는 어려운 거 같긴 하다. 이건 나중에 팀이 정해지면 팀원들이랑 얘기를 나눠봐야겠다.