학습정리 : Next.js
이 문서는 Next를 처음 공부하면서 작성한 글로 잘못된 정보가 있을 수 있습니다.
Next.js란?
Next.js는 React로 만드는 서버사이드 렌더링 프레임 워크이다.
서버사이드 렌더링을 하면 뭐가 좋은데?
- 클라이언트 렌더링의 경우 모든 js 파일을 로드하고 사용자는 웹을 보게 된다. 이때까지 사용자는 많은 시간을 대기해야한다.(첫 로딩 시간이 오래 걸린다.)
- seo 클라이언트 사이드의 경우 자바스크립트가 로드 되지 않은 경우 아무런 정보를 볼 수 없다. 검색엔진의 봇에 아무 페이지도 걸리지 않아, seo에 불리하다.
이런 두가지 문제점을 해결하는 것이 서버 사이드 렌더링이다.
해결
- 서버에서 자바스크립트를 로딩함으로 클라이언트 측에서는 자바스크립트를 로딩하는 시간이 줄어든다.(pre-rendering)
- 검색엔진이 자바스크립트를 읽은 것이 아닌, 서버측에서 자바스크립트, html, css를 만들어 컨텐츠를 직접 업로드해 검색엔진에 글이 걸리게 된다. 또한 meta 태그를 자유롭게 추가함으로 seo를 용이하게 할수 있습니다.
💡 초기 로딩, SEO 에서 SSR의 장점이 있다. Next는 CSR,SSR을 함께 사용할 수 있다.
next.js가 제공하는 주요 기능
페이지 기반 라우팅 (automatic routing)
pages 폴더에 있는 파일은 해당 파일 이름으로 라우팅됩니다. (pages/page1.tsx -> localhost:3000/page1)
다이나믹 라우팅
대괄호를 활용해서 동적으로 경로를 사용할 수 있다.
- pages/users/[username].tsx → pages/users/mocha → router.qeury.username = “macha”
- pages/users/[…data].tsx → pages/users/mocha/1 → router.query.data = [”mocha”,1]
Pre-rendering
(프론트) 서버에서 HTML 파일을 미리 구성한다.
주소창에 url 입력시 브라우저는 pre-rendering 된 HTML 파일을 받게된다.
- SSG (default) : 빌드 시 HTML 파일을 구성한다.
- SSR : 해당 page에서 getServerSideProps()를 사용할 시, 요청을 받을 때마다 서버에서 HTML을 새로 구성해 반환한다.
page 파일에서 getInitialProps() 나 getServerSideProps() 를 사용하지 않으면 기본적으로 SSG를 사용하게 된다. 따라서 url 입력을 통해 접근하는 페이지는 모두 pre-rendering 된 페이지이다.
💡 단, useEffect 등으로 데이터를 받아서 csr로 적용하는 부분은 pre-rendering이 적용되지 않는다.
Link next/Link
페이지간 빠르고 매끄러운 전환을 위한 clinet-side navigation을 제공한다.
HTML의 a 태그와 달리 페이지를 리로딩하지 않고도 페이지간 이동이 가능하고, link 컴포넌트가 뷰포트에 보였을 때 관련 페이지를 백그라운드에서 미리 가져다 놓기 때문에 사용자가 링크를 클릭했을 때 매우 빠르게 해당 페이지로 이동할 수 있게 해준다.
server landing
서버렌더링을 합니다. 클라이언트 렌더링과 다르게 서버렌더링을 한 페이지의 페이지 소스보기를 클릭하면 내부에 소스가 있습니다.
<aside> 💡 발표때는 실제 저희 프로젝트 소스코드로 확인해서 보여줬습니다.
</aside>
code splitting
코드 스플리팅은 내가 원하는 페이지에서 원하는 자바스크립트와 라이브러리를 렌더링 하는 것입니다. 모든 번들(chunk.js)이 하나로 묶이지 않고, 각각 나뉘어 좀 더 효율적으로 자바스크립트 로딩 시간을 개선할 수 있습니다.
코드 분할은 webpack, parcel, rollup 등의 모듈 번들러도 지원하고 있는 기능이지만, next.js를 사용하면 별도의 설정없이 자동으로 프로젝트에 적용된다.
💡 dynamic import? • ES2020에서 제공하는 dynamic import은, 해당 모듈을 애플리케이션의 빌드 타임에 불러오는 것이 아니라 런타임때 불러오는 것이다. 즉 처음 받아오는 모듈 (혹은 소스코드)의 용량을 줄임으로써 페이지의 초기 로딩 속도를 줄일 수 있다.(초기 페이지 로딩시 불필요한 모듈 fetch을 줄임으로써 성능 최적화를 할 수 있다.) https://blog.rhostem.com/posts/2020-05-10-nextjs-and-dynamic-import
next/Image
next/Image 적용 전, 후 (https://fe-developers.kakaoent.com/2022/220714-next-image/)
next/Image의 3가지 기능
- lazy loading
- 이미지 로드하는 시점을 필요할 때까지 지연시키는 기술
- 예를 들면 스크린 밖에 있는 이미지는 로딩을 지연시키고, 스크린 안에 있는 이미지만을 로드해서 필요한 이미지만 빠르게 로드할 수 있도록 하는 것
- 크롬 76버전 이상부터는 img 태그에 loading=“lazy” 속성을 추가하면 간단하게 적용 가능
- Next/Image는 자동으로 적용
- 이미지 사이즈 최적화
- 사이즈 최적화를 통해 총 용량을 많이 줄일 수 있고 페이지 로드 속도를 높일 수 있다.
- placeholder 제공
- CLS(Cumulative Layout Shift) 이미지가 로드되기 전까지 영역의 높이가 0이었다가, 로드된 후 레이아웃이 변경되는 현상
- Next/Image는 placeholder를 제공해 CLS현상이 일어나지 않도록 한다.
Redirect
redirect는 사용자가 변경된 path로 유입되면 새로운 경로고 안내하는데 아래와 같이 next.config.js 파일을 수정해주면 된다. 여기서 "/contact"라는 경로를 입력하면 "/form"이라는 새로운 경로로 리다이렉트 되는 것을 알 수 있다.
const nextConfig = {
reactStrictMode: true,
async redirects() {
return [
{
source: "/contact",
destination: "/form",
permanent: false,
}
]
},
}
module.exports = nextConfig
Rewrite
rewrite는 redirect처럼 리다이렉트 기능을 하지만 여기서 한가지 다른 점은 URL이 바뀌지 않은 상태로 이동한다는 점이다. 그렇기 때문에 API 키나 특정한 경로를 감추고 싶을 때 사용하면 된다.
const API_KEY = process.env.API_KEY;
const nextConfig = {
reactStrictMode: true,
async rewrites() {
return [
{
// source 주소를 입력하면 destination의 주소로 이동 but, 주소 url은 바뀌지 않음
source: "/api/movies",
destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
}
]
}
}
module.exports = nextConfig
hot reloading
개발 중 저장되는 코드는 자동으로 새로고침됩니다.
single file components
style jsx를 사용함으로 컴포넌트 내부에 해당 컴포넌트만 스코프를 가지는 css를 만들수 있습니다.
- <style jsx global>를 사용하면 글로벌로 스타일 정의 가능합니다.
// styled-jsx
function Heading(props) {
const variable = "red";
return (
<div className="title">
<h1>{props.heading}</h1>
<style jsx>
{`
h1 {
color: ${variable};
}
`}
</style>
</div>);
}
_app.tsx
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
- 이곳에서 렌더링 하는 값은 모든 페이지에 영향을 줍니다.
- 최초로 실행되는 것은 _app.tsx
- _app.tsx은 클라이언트에서 띄우길 바라는 전체 컴포넌트 → 공통 레이아웃임으로 최초 실행되며 내부에 컴포넌트들을 실행함
- 내부에 컴포넌트가 있다면 전부 실행하고 html의 body로 구성
- Component, pageProps를 받습니다.
- 여기서 props로 받은 Component는 요청한 페이지입니다. GET / 요청을 보냈다면, Component 에는 /pages/index.js 파일이 props로 내려오게 됩니다.
- pageProps는 페이지 getInitialProps를 통해 내려 받은 props들을 말합니다.
- 그 다음 _document.tsx가 실행됨
- 페이지를 업데이트 하기 전에 원하는 방식으로 페이지를 업데이트 하는 통로
- _app.tsx에서 console.log 실행시 client, server 둘다 콘솔 찍힙니다. (localhost:3000 웹과 터미널에서 둘다 콘솔 보임)
- Recoil,globalStyle 모두 _app.tsx에서 설정한다.
_document.tsx
meta 태그를 정의하거나, 전체 페이지에 관려하는 컴포넌트입니다.
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class CustomDocument extends Document {
render() {
return (
<Html>
<Head>
// 모든페이지에 아래 메타테크가 head에 들어감 // 루트파일이기에 가능한
적은 코드만 넣어야함 전역 파일을 엉망으로 만들면 안된다 // 웹 타이틀,
ga 같은것 넣음
<meta property="custom" content="123123" />
</Head>
<body>
<Main />
</body>
<NextScript />
</Html>);
}
}
- 이곳에서 console은 서버에서만 보이고 클라이언트에서는 안보입니다.
- render 요소는 반영하지만 페이지 구성 요소만 반영되고 js는 반영 하지 않기 때문에 console은 보이지 않습니다. 즉, componentDidMount 같은 훅도 실행 되지 않습니다. 정말 static한 상황에만 사용합니다.
정리
- Next.js로 만들어진 웹 페이지는 url로 접근시 pre-rendering(SSG, SSR) 된 페이지를 반환한다.
- pre-rendering 은 프론트엔드 서버(Next.js)에서 일어난다.
- Next.js 는 SSG가 기본이다. getServerSideProps() 을 사용하지 않은 페이지는 모두 SSG로, 빌드 타임에 미리 렌더링 된다.(CSR이 필요한 부분은 제외)→ 소스코드에서 확인 가능
- SSR을 하려면 getServerSideProps()를 사용해야한다.
- Link를 클릭하거나 router.push()를 통해 이동하면 CSR 방식으로 페이지를 전환한다.
Next.js를 프로젝트에 적용한 이유
- SEO에 신경쓰면서 개발할 수 있다.
- CSR, SSR 모두 사용할 수 있다.
- 리액트 기반 프레임워크로 코드 스타일을 맞추기 쉽다.
- Next의 여러가지 기능을 통한 성능 향상이 크다.
레퍼런스
- https://nextjs.org/docs/getting-started
- https://kyounghwan01.github.io/blog/React/next/basic/#next-js가-제공하는-주요-기능
- https://velog.io/@syoung125/Next.js-기본-개념-1-Next.js-란-Next.js를-왜-사용할까-Next.js의-장점은
- https://fe-developers.kakaoent.com/2022/220714-next-image/
- https://velog.io/@sj_dev_js/Next.js-에-대한-거의-모든-것
'Front-End' 카테고리의 다른 글
[학습정리] Webpack,Babel (0) | 2023.02.17 |
---|---|
[학습정리] Storybook (0) | 2022.12.16 |