https://github.com/ssi02014/next-tutorial
๐ Next.js ๊ธฐ๋ณธ Tutorial
https://github.com/ssi02014/next-tutorial
csr javascript next react ssr
Last synced: 3 months ago
JSON representation
๐ Next.js ๊ธฐ๋ณธ Tutorial
- Host: GitHub
- URL: https://github.com/ssi02014/next-tutorial
- Owner: ssi02014
- Created: 2021-04-14T08:00:04.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-04-19T16:35:38.000Z (over 4 years ago)
- Last Synced: 2024-12-30T06:45:12.476Z (9 months ago)
- Topics: csr, javascript, next, react, ssr
- Language: JavaScript
- Homepage:
- Size: 507 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ๐ป Next-tutorial
### Next.js Tutorial ์ ์ฅ์
## ๐จ๐ปโ๐ป Next.js Start
๐ Next.js: https://nextjs.org/
### ๐ Install
- create-next-app์ผ๋ก ์ค์นํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ด ์๋ค.
1. ์ปดํ์ผ๊ณผ ๋ฒ๋ค๋ง์ด ์๋์ผ๋ก ๋๋ค.(webpack, babel)
2. ์๋ ๋ฆฌํ๋ ์ฌ ๊ธฐ๋ฅ์ผ๋ก ์์ ํ๋ฉด ํ๋ฉด์ ๋ฐ๋ก ๋ฐ์๋๋ค.
3. ์๋ฒ์ฌ์ด๋ ๋ ๋๋ง์ด ์ง์๋๋ค.
4. ์คํํฑ ํ์ผ(์ ์ ํ์ผ)์ ์ง์ํ๋ค.
```javascript
//Install
1. npx create-next-app
2. yarn create next-app
```
### ๐ Start
- dev (dev ํ๊ฒฝ)
- build, start (production ํ๊ฒฝ)```json
//package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
}
```## ๐จ๐ปโ๐ป Next.js Routing
- ๋ณ๋ค๋ฅธ ์ค์ ์์ด pages ํด๋์์ jsํ์ผ์ ๋ง๋ค๋ฉด ์๋์ผ๋ก Routing ๋๋ค.
- Next.js๋ [] ๋ฌธ๋ฒ์ผ๋ก ๋์ url์ ๋ง๋ค ์ ์๋ค.
```javascript
//pages/view/[id].js
import {useRouter} from 'next/router';export default function About() {
const router = useRouter();return
ID: {router.query.id}
}
```
- ์์ฒ๋ผ ์์ฑํ๊ณ localhost:3000/view/123์ผ๋ก ์ ์์ ID: 123์ด ์ถ๋ ฅ๋จ์ ํ์ธ ํ ์ ์์ต๋๋ค.
- router.query.id์ ๊ฐ์ URL(localhost:3000/view/123)์ 123์ด๋ค.
- ๋ง์ฝ ํ์ผ ์ด๋ฆ์ด [title].js์๋ค๋ฉด router.query.title ์ด๋ค.
## ๐จ๐ปโ๐ป _app.js
- ๋ ์ด์์์ ๋ง๋๋ ค๋ฉด _app.js๋ฅผ ์ด์ฉํด์ผ ํ๋ค.
- _app.js
1. ํ์ด์ง ์ ํ ์ ๋ ์ด์์์ ์ ์งํ ์ ์๋ค.
2. ํ์ด์ง ์ ํ์ ์ํ๊ฐ์ ์ ์งํ ์ ์๋ค.
3. componentDidCatch๋ฅผ ์ด์ฉํด์ ์ปค์คํ ์๋ฌ ํธ๋ค๋ง์ ํ ์ ์๋ค.
4. ์ถ๊ฐ์ ์ธ ๋ฐ์ดํฐ๋ฅผ ํ์ด์ง๋ก ์ฃผ์ ์ํค๋๊ฒ ๊ฐ๋ฅํ๋ค.
5. ๊ธ๋ก๋ฒ CSS๋ฅผ ์ด๊ณณ์ ์ ์ธํ๋ค.
```javascript
//props๋์ด์จ Component๋ ํ์ฌ page๋ฅผ ์๋ฏธ ์ฆ, ํ์ด์ง ์ ํ์ ์ด Component๊ฐ ๋ณํํจ
//pageProps๋ ๋ฐ์ดํฐํจ์นญ ๋ฉ์๋๋ฅผ ํตํด ๋ฏธ๋ฆฌ ๊ฐ์ ธ์จ ์ด๊ธฐ ๊ฐ์ฒด
function MyApp({ Component, pageProps }) {
return
}
```
## ๐จ๐ปโ๐ป _document.js
- next์์ ์ ๊ณตํ๋ document๋ฅผ custom ํ ์ ์๋ค.
- next.js๋ ๋งํฌ์ ์ ์๋ฅผ ๊ฑด๋๋ฐ๊ธฐ ๋๋ฌธ์ ์ด ํ์ผ์ ์์ฑํด์ custom ํด์ฃผ์ด์ผ ํ๋ค. (์ฆ, htmlํ๊ทธ, headํ๊ทธ, body ํ๊ทธ)
```javascript
import Document, { Html, Head, Main, NextScript } from 'next/document'class MyDocument extends Document {
render() {
return (
)
}
}export default MyDocument
```
- _document์์์ Head์ next/head์ Head ํ๊ทธ์ ๋ค๋ฅด๋ค.
```javascript
//pages/index.js
import Head from 'next/head'export default function Home() {
return (
{/* Head ํ๊ทธ๋ก ํ์ด์ง ํ์ดํ์ ์์ ํ ์ ์๋ค. */}
HOME | ์ ๋ฏผ์ฌ
(...)
)
}
```## ๐จ๐ปโ๐ป public ํด๋
- public ํด๋๋ ์ ์ ํ์ผ์ ์ ์ฅ, ์ ๊ณตํ ์ ์๋ ํด๋์ด๋ค.
```
์์ผ๋ก ํธ์ถํ ์ ์๋ค.
```
## ๐จ๐ปโ๐ป Next.js ๋ชจ๋ ํ์ด์ง ์ฌ์ ๋ ๋๋ง (Pre-rendering)
- pre-rendering์ด๋, ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ํ์ด์ง pre-render ์ฆ, ์ฌ์ ์ HTML ํ์ผ๋ค์ ๋ง๋ ๋ค๋ ์๋ฏธ์ด๋ค.
- ๋ ์ข์ ํผํฌ๋จผ์ค, ๊ฒ์์์ง์ต์ ํ(SEO)
1. ์ ์ ์์ฑ
2. Server Side Rendering (SSR)
- ์ ์ ์์ฑ๊ณผ SSR์ ์ฐจ์ด์ ์ ์ธ์ html ํ์ผ์ ์์ฑํ๋๊ฐ ์ด๋ค.
### ๐ ์ ์ ์์ฑ(Static Genration)
- next์์๋ ๋ง์ผํ ํ์ด์ง, ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ, ์ ํ ๋ชฉ๋ก, ๋์๋ง ๊ณผ ๋ฌธ์ ๋ฑ๊ณผ ๊ฐ์ ํ์ด์ง์ ์ ์ ์์ฑ์ ์ฌ์ฉํ๋ผ๊ณ ๊ถ๊ณ
- ํ๋ก์ ํธ๊ฐ ๋น๋ํ๋ ์์ ์ htmlํ์ผ๋ค์ด ์์ฑ
- ๋ชจ๋ ์์ฒญ์ ์ฌ์ฌ์ฉ
- ์ ์ ์์ฑ๋ ํ์ด์ง๋ค์ CDN์ ์บ์
- getStaticPrors / getStaticPaths
### ๐ SSR
- ๋งค ์์ฒญ๋ง๋ค html์ ์์ฑ
- ํญ์ ์ต์ ์ํ ์ ์ง๋ฅผ ํด์ผ ํ๋ ๊ฒฝ์ฐ SSR์ ์ฌ์ฉ
- ๊ด๋ฆฌ์ ํ์ด์ง, ๋ถ์ ์ฐจํธ ๋ฑ์ ํ์ด์ง์ ์ฌ์ฉ
- getServerSideProps
```js
//view/[id].js
//getServerSideProps return ๊ฐ์ธ item์ Post์ props๋ก ๋ฐ์์ฌ ์ ์๋ค.
export default function Post({ item }) {
return (
<>
{item && (
)}
>
);
};//getServerSideProps
//context props๋ ํ๋ง๋ฆฌํฐ, ์์ฒญ, ์๋ต ์ฟผ๋ฆฌ๊ฐ ๋ด๊ฒจ์ ธ ์จ๋ค.
export async function getServerSideProps(context) {
const id = context.params.id;
const apiUrl = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`;
const res = await axios.get(apiUrl);
const data = res.data;return {
props: {
item:data,
}
}
};
```
## ๐จ๐ปโ๐ป Page ์ด๋: Link, router
- Page๋ฅผ ์ด๋ํ ๋ Link๋ router๋ฅผ ์ฌ์ฉํ๋ค.
- aํ๊ทธ๋ location.href๋ฅผ ์ฌ์ฉํด๋ ๋์ง๋ง ์ด๋, ํ์ด์ง๊ฐ ์๋ก ๊ณ ์นจ๋๋ฏ๋ก SPA์ ์ฅ์ ์ด ์ฌ๋ผ์ง๋ ์ฌ์ฉํ์ง ์๋๊ฒ ์ข๋ค.
### ๐ Link
```js
//import
import Link from "next/link";//Link ์ปดํฌ๋ํธ
(...)
```
### ๐ router
```js
//import
import { useRouter } from "next/router";//router ์์ฑ
const router = useRouter();//router.push๋ฅผ ํตํด ์นํ์ด์ง ์ด๋
const goLink = (e, data) => {
if (data.name === "home") {
router.push("/");
} else if (data.name === "about") {
router.push("/about");
}
};
```
## ๐จ๐ปโ๐ป Error Page
### ๐ 404Page
- 404.js ํ์ผ์ ๋ง๋ค์ด 404 ํ์ด์ง๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค.
```js
//404.js
import React from "react";
import { Icon } from "semantic-ui-react";const Error404 = () => {
return (
404Page: ํด๋น ํ์ด์ง๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
);
};export default Error404;
```
### ๐ Sever Error Page
- _error.js ํ์ผ์ ๋ง๋ค์ด ์๋ฌ ํ์ด์ง๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค. (500error ๋ฑ)
- ์ฌ๊ธฐ์ 404page๋ ๊ด๋ฆฌํ ์ ์์ง๋ง 404Page๋ static์ผ๋ก ์ ๊ณตํ๋๊ฒ ์ข๊ธฐ ๋๋ฌธ์ 404.js ํ์ผ์ ๋ง๋ค์ด ๊ด๋ฆฌํ๋ค.
```js
//_error.js
import React from "react";const Error = ({ statusCode }) => {
return (
{statusCode
? `An error ${statusCode} occurred on sever`
: `An error occurred on client`}
);
};Error.getInitailProps = ({ res, req }) => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;return { statusCode };
};export default Error;
```
## ๐จ๐ปโ๐ป ํ๊ฒฝ ๋ณ์
- next.js๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๊ฒฝ ๋ณ์๋ฅผ ๊ด๋ฆฌํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
- .env.development (๊ฐ๋ฐ ํ๊ฒฝ), .env.production (๋ฐฐํฌ ํ๊ฒฝ)
- node.js ํ๊ฒฝ์ ๋ํ์ ์ผ๋ก [id].js ํ์ผ์ ์๋ getServerSideProps ๋ฉ์๋ ์ ์ด ๋ฉ์๋ ์์์ window ๋ฉ์๋๋ฅผ ์ฐ๋ฉด ์๋ฌ๊ฐ ๋จ
```
//node.js ํ๊ฒฝ ์ฌ์ฉ๋ฒ ex) [id].js ํ์ผ์ getServerSideProps ๋ฉ์๋
process.env.๋ณ์๋ช//browser ํ๊ฒฝ ์ฌ์ฉ๋ฒ index.js ํ์ผ
process.env.NEXT_PUBLIC_๋ณ์๋ช//.env.production
name=PRODUCTION
NEXT_PUBLIC_API_URL=http://makeup-api.herokuapp.com/api/v1/products.json?brand=dior
```## ๐จ๐ปโ๐ป Dynamic Router์ Static Generation?
- Dynamic Router Static Generation์ ์ ์ฉํ๋ ค๋ฉด getStaticPaths() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. ๋จ, params๊ฐ ์์ธก๋๊ณ ์ฌ์ ์ ๋ฏธ๋ฆฌ ์ง์ ํด๋์ผ๋ง ๊ฐ๋ฅํ๋ค.
- getStaticPaths() fallback์ true๋กํ๋ฉด paths๋ฅผ ์ง์ ํด์ค ๊ฒ๋ค์ ์ ์ธํ๊ณ ์ต์ด ์ ์์ props์ ๋น ๋ฐ์ดํฐ๋ก ๋ณด์ฌ์ง๋ค๊ฐ ํ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ ์ ํ์ผ์ธ html๊ณผ css๋ฅผ ์์ฑํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ next.js๋ pre-rendering ๋ชฉ๋ก์ ์ถ๊ฐํ๋ค. ๋ฐ๋ผ์ 2๋ฒ์งธ ์ ์๋ถํฐ๋ static generation์ ํ ๊ฒ๊ณผ ๋์ผํด์ง๋ค.
- paths๋ ๋น ๋ฐฐ์ด์ด์ฌ๋ ์๊ด์๋ค.
```js
export async function getStaticPaths() {
const apiUrl = process.env.apiUrl;
const res = await axios.get(apiUrl);
const data = res.data;return {
paths: data.slice(0, 9).map((item) => ({
params: {
id: item.id.toString(),
},
})),
fallback: true,
};
}
```
- (+a)๋ก Link ํ๊ทธ์ prefetch ๊ธฐ๋ฅ์ ํตํด ์คํฌ๋กค์ ํตํด ๋ฏธ๋ฆฌ ์ ์ ํ์ด์ง๋ฅผ ๋ง๋ค ์ ์๋ค.
## ๐จ๐ปโ๐ป isFallback
- useRouter์์ isFaillback์ด ์๋ค. ๊ธฐ๋ฅ์ ๋ก๋ฉ ์ ์๋ true์๋ค๊ฐ ๋ก๋ฉ์ด ๋๋๋ฉด false๋ก ๋ฐ๋๋ค. ์ด๊ฒ์ผ๋ก loading์ ๊ตฌํํ ์ ์๋ค.```js
//์ฌ์ฉ๋ฒ
import { useRouter } from "next/router";
import { Loader } from "semantic-ui-react";
export default function Post({ item, name }) {
const router = useRouter();if (router.isFallback) {
return (
);
}return ( ... )
}
```