An open API service indexing awesome lists of open source software.

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

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 ํด๋”๋Š” ์ •์  ํŒŒ์ผ์„ ์ €์žฅ, ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ํด๋”์ด๋‹ค.
```
logo ์‹์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
```


## ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป 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 ( ... )
}
```