Next.js, 개념에 대해 자세히 알아보자!

룸잉·2023년 5월 14일
1

cs

목록 보기
1/13

📌Next.js란?

웹 어플리케이션을 구축하기 위한 React 프레임워크


👇 그래서.. React랑 뭐가 다른건데!!
👇 React와의 차이를 알아보기 위해 CSR과 SSR에 대해 짚고 넘어가보자!


📌CSR vs SSR

✅ CSR (Client Side Rendering)

  • 클라이언트 쪽에서 렌더링을 진행하는 방식이다.
  • 서버는 요청을 받으면 클라이언트에 HTML과 JS를 보내주고 클라이언트에서는 이것을 받아서 렌더링을 시작한다.
  • 서버에서의 처리없이 클라이언트로 보내주기 때문에, 모든 JavaScript 파일을 다운로드하는 동안 제대로 된 화면을 볼 수 없다.
  • 브라우저가 JS를 다운로드하고 동적 DOM을 생성하기 위해 초기 로드 시간이 오래 걸린다.
  • 이후 렌더링은 서버에서 해당 데이터만 response 받아 사용하면 되기 대문에 첫 렌더링 이후 구동 속도는 빠른 편이다.
  • 검색 엔진 최적화(SEO)가 필요없거나, 데이터의 사전 렌더링이 필요없거나, 페이지의 내용이 실시간으로 자주 업데이트되어야 할 경우에는 유용하게 쓰이는 방식이다.

✅ SSR (Server Side Rendering)

  • 서버 쪽에서 렌더링 준비를 마친 상태로 클라이언트에 전달하는 방식이다.
  • 이미 렌더 가능한 상태로 서버에서 클라이언트로 전달되기 때문에, JavaScript 파일이 다운로드 되는 동안 사용자는 로딩 화면만 보고 있지 않아도 된다.
  • 검색 엔진은 자동화된 로봇인 '크롤러'로 웹 사이트를 읽게 되는데,서버에서 렌더링된 HTML 파일을 보내주는 SSR은 검색 엔진 최적화(SEO)에 유리하다.
  • JavaScript 파일 다운로드를 기다리지 않아도 되기 때문에 초기 구동 속도가 빠르다.
  • 그러나 서버 호출 시 페이지가 새로고침 되며 깜빡임이 발생하고, 요청이 생길 때마다 서버에서 렌더링되지 않아도 될 부분까지 준비하기 때문에 서버 부하를 일으키기도 한다.



📌React와 Next.js

React와 Next.js의 가장 큰 차이점 중 하나는 렌더링하는 방식에 있다.
React는 CSR, Next.js는 SSR 방식으로 렌더링한다.


✅ React (feat. CSR)

  • 대표적인 CSR 라이브러리인 React는 웹 사이트를 요청했을 때 빈 HTML을 가져와서 JS를 로딩하는 구조이다.
  • 로딩 시간이 SSR에 비해 오래 걸리고, 만약 JS를 다룰 줄 모르는 검색 엔진이 사이트를 크롤링한다면 텅 빈 HTML만 인식하게 된다.
  • 즉, CSR 방식을 사용하는 React는 로딩 시간도 비교적 오래걸리고 SEO에 취약하다는 단점이 있다.



✅ Next.js (feat. SSR)

반면, Next.js는 웹에 사이트를 요청했을 때 서버 측 렌더링을 거친 후 HTML과 JS를 따로 reponse한다.

💡 Next.js의 작동원리는 다음과 같다.

1. 초기에 사용자가 서버에 접속을 요청하면, SSR 방식으로 렌더링될 HTML을 보낸다.
2. 브라우저에서 JavaScript를 다운로드하고 React를 실행한다.
3. 사용자와 페이지가 서로 상호작용하며 다른 페이지로 이동하게 될 경우에는 CSR 방식으로 브라우저에서 처리한다.

  • Next.js는 모든 페이지를 pre-render(HTML을 JS 처리하기 전, 사전에 생성) 하기 때문에, 검색엔진 최적화가 가능해진다.
  • 사전 렌더링에 의해 만들어진 HTML은 해당 페이지에서 필요한 최소한의 JavaScript 코드와 연결된다.
  • 어떤 페이지의 HTML이 브라우저에 의해 로드되면 그 HTML에 연결된 JavaScript 코드가 실행되어 해당 페이지 상호작용이 가능해지며, 이런 과정을 Hydration이라고 부른다.
  • 즉, Next.js는 리액트 문법을 쓰는 프론트 문법을 쓸 수 있게 도와주 백엔드 프레임워크 라고 할 수 있다.



📌Next.js, 어떤 특징/ 기능을 가지고 있을까?

다음은 공식 문서에서 가져온 Next.js 특징 중 일부이다.

- 직관적인 페이지 기반 라우팅 시스템
- 사전 렌더링, 정적 생성(SSG) 및 서버 측 렌더링(SSR)은 페이지 별로 지원
- 더 빠른 페이지 로드를 위한 자동 코드 분할
- 최적화된 프리패치를 사용한 클라이언트 측 라우팅(CSR)
- 내장 CSS 및 Sass 지원 및 모든 CSS-in-JS 라이브러리 지원


👇 좀 더 자세히 알아보자!


1. Automatic Routing

React와 달리, 별도의 세팅없이 페이지를 기반으로 한 라우팅을 지원한다. React에서는 별도의 라우터를 제공하지 않기 때문에, react-router-dom이라는 패키지를 설치하여 사용했다.

Next.js 13은 app 폴더 하위에page 파일을 추가하고 그 안에 레이아웃을 넣는 방식으로, 추가한 파일을 export하게 되면 폴더명이 페이지 route가 되어 해당 파일이 라우터 역할을 하게 된다!

ex1. app/blog/page.js/blog

ex2. app/blog/first-blog/page.js/blog/first-blog


2. Dynamic Routes

항상 미리 정의된 경로를 사용할 수 있는 것은 아니다. 예를 들어 블로그 게시물의 경로는 /blog1, /blog2, /blog3 … 과 같은데, 모든 경로를 미리 정의하거나 페이지 컴포넌트를 생성하는 일은 굉장히 비효율적이다.

이때 사용하는 것이 동적 라우팅이다. [folderName]과 같이 폴더 이름을 대괄호로 묶어주면 해당 페이지 컴포넌트가 동적으로 라우팅 된다.

클라이언트 사이드에서 동적 경로에 접근하고 싶다면 next/link를 사용해주면 되고, router.push 같은 메소드를 사용할 수 도 있다!


📍 [folderName]

app/category/[slug]/page.js

Next.js 13 Automatic Routing에 따라 app 폴더 하위에 category 폴더를 만들고, 그 안에 Dynamic Routes를 위한 [slug] 폴더를 만든 것이다.
/category/food, /category/study 등의 주소는 모두 /post/[pid].js로 매칭된다.
[id]나 [slug]처럼 동적인 부분은 Layout과 Page나 Head 컴포넌트들에게 params prop으로 전달된다.

/category/food{ slug: 'food' }

/category/study{ slug: 'study' }


📍 Catch-all Segment : [...folderName]

app/shop/[...slug]/page.js

[slug]에 ...을 추가하여 shop 하위의 모든 경로를 잡아낼 수 있다.

/shop/clothes{ slug: ['clothes'] }

/shop/clothes/pants{ slug: ['clothes', 'pants'] }

/shop/clothes/tops/t-shirts{ slug: ['clothes', 'tops', 't-shirts'] }


3. Code Splitting

코드 분할은 다른 페이지에 대한 코드는 처음에 제공하지 않고, 원하는 페이지에 접근하는데 필요한 chunk(작은 코드 조각)만을 로드한다.

여러 개의 페이지가 있는 웹 사이트일지라도 필요한 페이지만을 빠르게 로드할 수 있으며, 이는 JavaScript 페이로드를 최소화하고 애플리케이션 로드 시간을 개선할 수 있다.

초기 페이지 로드에 필요하지 않은 구성 요소가 있는 경우 다음(👇)과 같이 동적으로 가져올 수 있다. 이는 필요할 때만 Puppy를 로드하도록 지시하고 있다.


// import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

4. Client-Side Navigation

<Link /> 컴포넌트를 통한 페이지 이동이 빠르고 매끄럽다. HTML의 a 태그와 달리, 페이지를 리로딩하지 않는다. <Link />가 뷰포트에 보이면 관련 페이지를 백그라운드에서 미리 가져오기 때문에, 사용자가 링크를 클릭했을 때 매우 빠르게 해당 페이지로 이동할 수 있게 해준다.


5. TypeScript

TypeScript를 활용하기 위해서 웹팩이나 바벨을 만지지 않아도 된다. TypeScript를 설치하고 yarn run dev를 해주면 자동으로 tsconfig, next-end.d.ts가 생성되어 TypeScript를 사용할 수 있다.

yarn add typescript @types/node @types/react

yarn run dev

6. SSR + CSR

초기 페이지 로딩에서는 SSR 방식을 이용하여 처리하고, 이후의 요청에 대해서는 CSR 방식으로 처리하기 때문에 SSR 방식의 장점(SEO에 유리)과 CSR의 이점을 모두 활용할 수 있다.


7. Pre-rendering

Next.js는 모든 페이지를 사전 렌더링한다.




📌Next.js 13

👉 app/ Directory

  • 기존 버전에서는 Automatic Routing 사용 시, pages 안에 파일 생성하여 별도의 라우터 없이도 애플리케이션 내부에서 즉시 경로 생성이 가능했다. 하지만 Next.js 13 버전부터는 app/ 디렉토리가 등장하여 라우팅 및 레이아웃 기능을 개선했다.
  • 현재는 pages 디렉토리와 app 디렉토리가 공존할 수 있는 베타 버전으로 제공되고 있다.

👉 Streaming

  • app/ 디렉토리에서 loading.js 예약 파일을 생성하면 렌더링이 되기 전에 로딩 중인 화면을 표시할 수 있는 기능이 추가됐다.
  • 아래 코드처럼 엄청 간단하게 만들어볼 수 있다!
export default function Loading() {
	return(
		<div>Loading...</div>
	)
}

👉 Data Fetching

  • 기존 버전에서는 데이터를 가져올 때 getServerSideProps()나 getStaticProps()를 사용했지만, Next.js 13 버전부터는 이 문법들을 사용하지 않는다.

  • 공식문서에 따르면, 현재 Client Component에서의use() 사용은 권장되지 않으며, 이는 무수한 리렌더를 유발할 것이라고 언급하고 있다. Client Component에서 fetch 데이터가 필요하다면, SWR과 React Query와 같은 라이브러리 사용을 추천한다고 한다.


  • 정적 데이터 가져오기
fetch('https://...'); // cache: 'force-cache' is the default
  • 캐시된 데이터의 유효성을 주기적으로 다시 검사하려면 next.revalidate 옵션을 사용해서 리소스의 캐시 유효시간(초)을 설정할 수 있다.
fetch('https://...', { next: { revalidate: 10 } });
  • 동적 데이터 가져오기
fetch('https://...', { cache: 'no-store' });

  • fetch 구문의 URL 뒤에 { cache: '' } 를 넣어줄 수 있다. cache에 들어가는 내용에 따라 기존의 getServerSideProps(), getStaticProps()의 기능을 구현할 수 있다.

// Similar to `getStaticProps`.
fetch(URL, { cache: 'force-cache' });

// Similar to `getServerSideProps`.
fetch(URL, { cache: 'no-store' });

// Similar to `getStaticProps` with the `revalidate` option.
fetch(URL, { next: { revalidate: 10 } });

👉 etc..

이 외에도 Next.js 13에서 변경된 부분이 다수 있다. 자세한 내용은 nextjs.org를 참고해보자!



📘참고자료
How Next.js Works
What is Next.js?
Next.js를 사용하면서 리액트랑 별반 다르지 않다고 느꼈던 이유
[Next.js] 기본 개념 : Next.js 란? Next.js를 왜 사용할까? Next.js의 장점은?
Next.js 13
Next.js 13 신버전 발표회 요약
Next.js의 Routing
Next.js Dynamic Import(동적 가져오기): 성능 및 사용자 경험 개선
dynamic-routes

5개의 댓글

comment-user-thumbnail
2023년 5월 18일

와우 이해도 쉽고 간결하게 정말 잘 써주셨네요!

설명해주신 Next.js의 작동원리에 따르면, Next.js는 처음에 SSR 방식으로 초기 구동 속도를 줄이면서, 이후에는 CSR 방식으로 이후 구동 속도를 빠르게 해주므로 혼합된 방식을 사용하면서 렌더링 측면에서 정말 매력 있다는 생각이 드네요!

[...slug]처럼 ...으로 그 하위 모든 경로까지 잡아내는 것도 한번 더 상기하고 갑니다!

dynamic에 대해서는 처음 알게 되었는데요, 필요시에 동적으로 가져올 수 있도록 쉽게 관리할 수 있는 좋은 기능인 것 같아요!! 이전에 성능 최적화를 할 때 사용한 lazy랑 비슷한 기능을 하는 것 같네용 잘 활용해야겠어요!

가 뷰포트에 보이면 관련 페이지를 백그라운드에서 미리 가져온다는 점도 처음 알았어요!! 이 동작 방식을 이해하고 나니까 왜 빠르게 이동할 수 있는지 확 와닿네요!!! ` loading.js`도 편히 사용할 수 있다는 점에서 너무 매력적이에요..!!

흥미롭게 잘 읽었습니다!!

답글 달기
comment-user-thumbnail
2023년 5월 18일

Next.js 에 대한 깔끔한 정리 감사합니다!!

특히, Next.js를 프론트 문법을 쓸 수 있게 도와주는 백엔드 프레임워크라고 정리해주신 부분이 가장 와 닿았던 것 같아요.

Next.js는 자체적으로 백엔드 구현이 가능하고, 최근 공개된 Next13의 기능들을 살펴보았을 때 ‘풀스택 프레임워크’에 가까워지고 있다는 느낌이 강한 것 같아요.

특히 Nested Routing과 Dynamic Routing의 경우 Next를 사용하는 개발자의 경험을 크게 향상시켜주는 좋은 기능이라고 생각이 되네요! 최근에 Next 13에서 공개된 app/Directory 를 직접 사용해보았었는데, 사용성이 확연히 개선되었음을 알 수 있었어요!!

또한 최근 Next13에서 선보인 기술 중 React use 훅을 이용한 Data Fetching을 흥미롭게 보았었는데, 리렌더 관련 이슈가 해결된다면 추가적인 라이브러리에 의존하지 않아도 훌륭한 ㅡ론트엔드 메타 프레임워크로 자리매김할 수 있겠다는 생각이 들었어요!

좋은 글 감사합니다!! 수고하셨어요 :)

답글 달기
comment-user-thumbnail
2023년 5월 18일

우와 넥제 항상 써보자는 이야기만 해보고 실제로 써본 적이 없었는데, 이렇게 개념 잘 설명해주셔서 감사합니다. 여러모로 넥스트 코드가 아직 익숙하지 않은 것들도 꽤 있는 듯 해요. 실습 열심히 복습해보겠습니다!!

답글 달기
comment-user-thumbnail
2023년 5월 28일

잘 정리된 글 덕분에 NEXT.js와 SSR에 대한 기초지식을 확실히 알고가는 것 같아요!
SSR로 렌더하는 것이 CSR보다 속도적인 측면에서 얼마나 더 유리한가 를공부해보았는데 아무래도 첫 페이지 로딩은 SSR처럼 서버에서 프리패치를 한 후 데이터를 보내주기 때문에 SSR로 처리하는 것이 유리한 것 같네요. CSR과 SSR을 섞어쓰는 하나의 예시로는 헤더나 GNB푸터 등은 SSR로 구현해두고 컨텐츠부분만 CSR로 구현해두어서 사용하는 방법이 있다는 것도 새로 알았습니다!
사실 이 두가지의 방법을 선택하려면 어떤 기술이 얼마나 어느부분에서 뛰어난지를 고민해봐야하는데 크롬 개발자도구에 LightHouse라는 도구를 사용하면 FCP FMP 등의 지표등을 확인할 수 있으니 추후에 사용해볼 기회가 오면 좋겠습니다!

LightHouse에대한 아티클 - https://velog.io/@dell_mond/Lighthouse-%EC%82%AC%EC%9A%A9%EB%B2%95
CSR과 SSR의 속도 비교에 대해 - https://medium.com/wantedjobs/%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-ssr-cache-%EC%A0%81%EC%9A%A9%EA%B8%B0-bf022e3a1a72#:~:text=SSR%20%ED%8F%89%EA%B7%A0%EC%84%B1%EB%8A%A5%2059%EC%A0%90&text=LCP%20%EC%84%B1%EB%8A%A5%EC%9D%80%201%EC%B4%88,%EB%9E%9C%EB%8D%94%EB%A7%81%EC%9D%B4%20%EC%9E%98%20%EB%8F%99%EC%9E%91%ED%95%A9%EB%8B%88%EB%8B%A4.

답글 달기
comment-user-thumbnail
2023년 5월 28일

너무 꼼꼼한 아티클 감사합니다!

Next.js 는 vercel 에서 만든 리액트 기반 프레임 워크라고 하네요!
그래서 vercel 로 deploy 하는 것을 권장한다고 하네요!

정말 신기했던게 라우팅도 Router로 설정해주는게 아니라 폴더로 자동 라우팅 되는것도 너무 신기했습니다. 이외에도 넥제 강의를 조금씩 들어보고 있는데 아티클의 내용이 조금씩 더 이해가 되어가고 있는것 같습니다. 이제 정말 리액트 js 만으로 풀스택을 하는 날이 얼마 안남은거 같은데 그때까지 열심히 해보겠습니다 감사합니다!

답글 달기