๐Ÿ”Ž์ต์Šคํ”„๋ ˆ์Šค ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

์„œ๊ฐ€ํฌยท2021๋…„ 11์›” 6์ผ
0

Node.js

๋ชฉ๋ก ๋ณด๊ธฐ
5/15
post-thumbnail

์ต์Šคํ”„๋ ˆ์Šค ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ![]

1. Express ์†Œ๊ฐœ

http ๋ชจ๋“ˆ๋กœ ์›น ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ๋•Œ ์ฝ”๋“œ๊ฐ€ ๋ณด๊ธฐ ์ข‹์ง€ ์•Š๊ณ , ํ™•์žฅ์„ฑ๋„ ๋–จ์–ด์ง

  • ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ํ•ด๊ฒฐ
  • ๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์ด Express(์ต์Šคํ”„๋ ˆ์Šค), Koa(์ฝ”์•„), Hapi(ํ•˜ํ”ผ)
  • ์ฝ”๋“œ ๊ด€๋ฆฌ๋„ ์šฉ์ดํ•˜๊ณ  ํŽธ์˜์„ฑ์ด ๋งŽ์ด ๋†’์•„์ง

    express ์ˆœ์„œ: app->app๊ด€๋ จ ์„ค์ • ->๊ณตํ†ต ๋ฏธ๋“ค์›จ์–ด -> ๋ผ์šฐํ„ฐ (๋ฒ”์œ„ ๋„“์€ ์–˜๋“ค์€ ๋’ค๋กœ)-> ์—๋Ÿฌ ๋ฏธ๋“ค์›จ์–ด

๐Ÿ”ป tip: - ํ•œ router์— send ๋‘๋ฒˆ ์ด์ƒ ๋‚˜์˜ค๋ฉด ์—๋Ÿฌ
- res.json(json ์‘๋‹ต)์€ return์ด ์•„๋‹˜. ๋ฐ‘์˜ ์ฝ”๋“œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•จ
- res.render(์‘๋‹ต์„ ๋ณด๋‚ด๋Š” ๊ฒƒ)
- throw new err-> try catch์—์„œ error๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ ๐Ÿ‘‰next(์—๋Ÿฌ์ฒ˜ - ๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ)์— ๋„ฃ์–ด ์„œ ์ฒ˜๋ฆฌ
- next('route')๋Š” ๋‹ค์Œ ๋ผ์šฐํ„ฐ๋ฅผ ์‹คํ–‰

2. package.json ๋งŒ๋“ค๊ธฐ

์ง์ ‘ ๋งŒ๋“ค๊ฑฐ๋‚˜ npm init ๋ช…๋ น์–ด ์ƒ์„ฑ

  • nodemon์ด ์†Œ์Šค ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ์„œ๋ฒ„๋ฅผ
    ์žฌ์‹œ์ž‘ํ•ด์คŒ
    ๐Ÿ”ปpackage.json
{
  "name": "chapter6",
  "version": "1.0.0",
  "description": "์ต์Šคํ”„๋ ˆ์Šค ๋ฐฐ์šฐ์ž",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "seokahi",
  "license": "MIT",
  "devDependencies": {
    "nodemon": "^2.0.14"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

3. app.js ์ž‘์„ฑํ•˜๊ธฐ

์„œ๋ฒ„ ๊ตฌ๋™์˜ ํ•ต์‹ฌ์ด ๋˜๋Š” ํŒŒ์ผ

  • app.set(โ€˜portโ€™, ํฌํŠธ)๋กœ ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋  ํฌํŠธ ์ง€์ •
  • app.get(โ€˜์ฃผ์†Œโ€™, ๋ผ์šฐํ„ฐ)๋กœ GET ์š”์ฒญ์ด ์˜ฌ ๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ• ์ง€ ์ง€์ •
  • app.listen(โ€˜ํฌํŠธโ€™, ์ฝœ๋ฐฑ)์œผ๋กœ ๋ช‡ ๋ฒˆ ํฌํŠธ์—์„œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ• ์ง€ ์ง€์ •

๐Ÿ”ปapp.js

const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.get('/', (req, res) => {
  // res.send('Hello, Express');
  res.sendFile(path.join(__dirname, '/index.html'));
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

4. ์„œ๋ฒ„ ์‹คํ–‰ํ•˜๊ธฐ

app.js: ํ•ต์‹ฌ ์„œ๋ฒ„ ์Šคํฌ๋ฆฝํŠธ
public: ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ํŒŒ์ผ๋“ค ๋ชจ์•„๋‘ 
views: ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ์„ ๋ชจ์•„๋‘ 
routes: ์„œ๋ฒ„์˜ ๋ผ์šฐํ„ฐ์™€ ๋กœ์ง์„ ๋ชจ์•„๋‘ 

  • ์ถ”ํ›„์— models๋ฅผ ๋งŒ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ

5. ์ต์Šคํ”„๋ ˆ์Šค ์„œ๋ฒ„ ์‹คํ–‰ํ•˜๊ธฐ

npm start(package.json์˜ start ์Šคํฌ๋ฆฝํŠธ) ์ฝ˜์†”์—์„œ ์‹คํ–‰
localhost:3000

6. HTML ์„œ๋น™ํ•˜๊ธฐ

res.sendFile๋กœ HTML ์„œ๋น™ ๊ฐ€๋Šฅ

๐Ÿ”ปindex.html

<html>
<head>
  <meta charset="UTF-8" />
  <title>์ต์Šคํ”„๋ ˆ์Šค ์„œ๋ฒ„</title>
</head>
<body>
  <h1>์ต์Šคํ”„๋ ˆ์Šค</h1>
  <p>๋ฐฐ์›Œ๋ด…์‹œ๋‹ค.</p>
</body>
</html>

์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด

1. ๋ฏธ๋“ค์›จ์–ด

์ต์Šคํ”„๋ ˆ์Šค๋Š” ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ตฌ์„ฑ๋จ

  • ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ ์ค‘๊ฐ„์— ์œ„์น˜ํ•˜์—ฌ ๋ฏธ๋“ค์›จ์–ด
  • app.use(๋ฏธ๋“ค์›จ์–ด)๋กœ ์žฅ์ฐฉ๐Ÿ‘‰๊ณตํ†ต๋œ ์ฝ”๋“œ๋“ค์„ ๋ชจ๋“  ๋ผ์šฐํ„ฐ์—์„œ ์‹คํ–‰ํ•ด์คŒ
  • ์œ„์—์„œ ์•„๋ž˜๋กœ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰๋จ.
  • ๋ฏธ๋“ค์›จ์–ด๋Š” req, res, next๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜์ธ ํ•จ์ˆ˜๐Ÿ‘‰next ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด์ค˜์•ผ ๋‹ค์Œ ๋ผ์šฐํ„ฐ ์ค‘ ์ผ์น˜ํ•˜๋Š”๊ฑธ ์ฐพ์•„์คŒ
  • req: ์š”์ฒญ, res: ์‘๋‹ต ์กฐ์ž‘ ๊ฐ€๋Šฅ
  • next()๋กœ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ.

2. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด

์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ

  • err, req, rs, next๊นŒ์ง€ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ 4๊ฐœ ๐Ÿ˜ƒ์ค‘์š”๐Ÿ˜ƒ
  • ์ฒซ ๋ฒˆ์งธ err์—๋Š” ์—๋Ÿฌ๊ฐ€ ๊ด€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊น€
  • res.status ๋ฉ”์„œ๋“œ๋กœ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ง€์ • ๊ฐ€๋Šฅ(๊ธฐ๋ณธ๊ฐ’ 200)
  • ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์•ˆ ์—ฐ๊ฒฐํ•ด๋„ ์ต์Šคํ”„๋ ˆ์Šค๊ฐ€ ์—๋Ÿฌ๋ฅผ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธด ํ•จ.
  • ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ฐ€์žฅ ์•„๋ž˜์— ์œ„์น˜ํ•˜๋„๋ก ํ•จ.
    ๋ณดํ†ต router๋“ค์€ res.send ํ•˜๋ฉด ๊ฑฐ๊ธฐ์—์„œ ๋๋‚ด์ค˜์•ผํ•จ

    ๐Ÿ”ปapp.js
...
app.use((err, req, res, next) => {
  console.error(err); ๐Ÿ‘‰์„œ๋ฒ„์— ์–ด๋–ค ์—๋Ÿฌ์ธ์ง€ ์•Œ๋ ค์คŒ
  res.send('์—๋Ÿฌ๋‚ฌ์–ด'); ๐Ÿ‘‰ ์›น์—” ์–ด๋–ค ์—๋Ÿฌ์ธ์ง€ ์•Œ๋ ค์ฃผ๋ฉด ๋ณด์•ˆ ๋ฌธ์ œ ์ƒ๊ธธ์ˆ˜๋„ ใ…‡
  res.status(500).send(err.message);๐Ÿ‘‰status(500)๋ผ๊ณ  ๋ธŒ๋ผ์šฐ์ €์— ๋œธ(๋ปฅ์น ์ˆ˜๋„ o)
});

๐Ÿ‘‰ app.use((err, req, res, next) ๋ฐ”๋กœ ์œ„์— app.use(req,res,next)=>{res.send('404์ง€๋กฑ')} ์“ฐ๋ฉด 404 ์—๋Ÿฌ์ž„์„ ์˜๋ฏธ

3. ์ž์ฃผ ์“ฐ๋Š” ๋ฏธ๋“ค์›จ์–ด

morgan, cookie-parser, express-session ์„ค์น˜

  • app.use๋กœ ์žฅ์ฐฉ
  • ๋‚ด๋ถ€์—์„œ ์•Œ์•„์„œ next๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ

๐Ÿ”ปapp.js<์ด ์ฝ”๋“œ>

const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');

dotenv.config();
const app = express();
app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

const multer = require('multer');
const fs = require('fs');

try {
  fs.readdirSync('uploads');
} catch (error) {
  console.error('uploads ํด๋”๊ฐ€ ์—†์–ด uploads ํด๋”๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.');
  fs.mkdirSync('uploads');
}
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads/');
    },
    filename(req, file, done) {
      const ext = path.extname(file.originalname);
      done(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 },
});
app.get('/upload', (req, res) => {
  res.sendFile(path.join(__dirname, 'multipart.html'));
});
app.post('/upload', upload.single('image'), (req, res) => {
  console.log(req.file);
  res.send('ok');
});

app.get('/', (req, res, next) => {
  console.log('GET / ์š”์ฒญ์—์„œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.');
  next();
}, (req, res) => {
  throw new Error('์—๋Ÿฌ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋กœ ๊ฐ‘๋‹ˆ๋‹ค.')
});
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

4. dotenv

.env ํŒŒ์ผ์„ ์ฝ์–ด์„œ process.env๋กœ ๋งŒ๋“ฆ

  • dot(์ ) + env
  • process.env.COOKIE_SECRET์— cookiesecret ๊ฐ’์ด ํ• ๋‹น๋จ(ํ‚ค=๊ฐ’ ํ˜•์‹)
  • ๋น„๋ฐ€ ํ‚ค๋“ค์„ ์†Œ์Šค ์ฝ”๋“œ์— ๊ทธ๋Œ€๋กœ ์ ์–ด๋‘๋ฉด ์†Œ์Šค ์ฝ”๋“œ๊ฐ€ ์œ ์ถœ๋˜์—ˆ์„ ๋•Œ ๋น„๋ฐ€ ํ‚ค๋„ ๊ฐ™์ด ์œ ์ถœ๋จ
  • .env ํŒŒ์ผ์— ๋น„๋ฐ€ ํ‚ค๋“ค์„ ๋ชจ์•„๋‘๊ณ  .env ํŒŒ์ผ๋งŒ ์ž˜ ๊ด€๋ฆฌํ•˜๋ฉด ๋จ

5. morgan

์„œ๋ฒ„๋กœ ๋“ค์–ด์˜จ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ธฐ๋กํ•ด์ฃผ๋Š” ๋ฏธ๋“ค์›จ์–ด

  • ๋กœ๊ทธ์˜ ์ž์„ธํ•œ ์ •๋„ ์„ ํƒ ๊ฐ€๋Šฅ(dev, tiny, short, common, combined)
  • ์˜ˆ์‹œ) GET / 200 51.267 ms โ€“ 1539
  • ์ˆœ์„œ๋Œ€๋กœ HTTP์š”์ฒญ ์š”์ฒญ์ฃผ์†Œ ์ƒํƒœ์ฝ”๋“œ ์‘๋‹ต์†๋„ โ€“ ์‘๋‹ต๋ฐ”์ดํŠธ
  • ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ๋Š” dev, ๋ฐฐํฌํ™˜๊ฒฝ์—์„œ๋Š” combined๋ฅผ ์• ์šฉํ•จ.<์ข€ ๋” ์ž์„ธํ•œ ์ •๋ณด ์ œ๊ณต>

6. static

์ •์ ์ธ ํŒŒ์ผ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด

  • ์ธ์ˆ˜๋กœ ์ •์  ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ์ œ๊ณต
  • ํŒŒ์ผ์ด ์žˆ์„ ๋•Œ fs.readFile๋กœ ์ง์ ‘ ์ฝ์„ ํ•„์š” ์—†์Œ
  • ์š”์ฒญํ•˜๋Š” ํŒŒ์ผ์ด ์—†์œผ๋ฉด ์•Œ์•„์„œ next๋ฅผ ํ˜ธ์ถœํ•ด ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ
  • ํŒŒ์ผ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค๋ฉด ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Œ

์ปจํ…์ธ  ์š”์ฒญ ์ฃผ์†Œ์™€ ์‹ค์ œ ์ปจํ…์ธ ์˜ ๊ฒฝ๋กœ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

  • ์š”์ฒญ ์ฃผ์†Œ localhost:3000/stylesheets/style.css
  • ์‹ค์ œ ์ปจํ…์ธ  ๊ฒฝ๋กœ /public/stylesheets/style.css
  • ์„œ๋ฒ„์˜ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์›Œ์ ธ์„œ ๋ณด์•ˆ์— ๋„์›€์ด ๋จ

9. body-parser

์š”์ฒญ์˜ ๋ณธ๋ฌธ์„ ํ•ด์„ํ•ด์ฃผ๋Š” ๋ฏธ๋“ค์›จ์–ด

  • ํผ ๋ฐ์ดํ„ฐ๋‚˜ AJAX ์š”์ฒญ์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
  • json ๋ฏธ๋“ค์›จ์–ด๋Š” ์š”์ฒญ ๋ณธ๋ฌธ์ด json์ธ ๊ฒฝ์šฐ ํ•ด์„, urlencoded ๋ฏธ๋“ค์›จ์–ด๋Š” ํผ ์š”์ฒญ ํ•ด์„
  • put์ด๋‚˜ patch, post ์š”์ฒญ ์‹œ์— req.body์— ํ”„๋ŸฐํŠธ์—์„œ ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์คŒ

    ๋ฒ„ํผ ๋ฐ์ดํ„ฐ๋‚˜ text ๋ฐ์ดํ„ฐ์ผ ๋•Œ๋Š” body-parser๋ฅผ ์ง์ ‘ ์„ค์น˜ํ•ด์•ผ ํ•จ

    Multipart ๋ฐ์ดํ„ฐ(์ด๋ฏธ์ง€, ๋™์˜์ƒ ๋“ฑ)์ธ ๊ฒฝ์šฐ๋Š” ๋‹ค๋ฅธ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ
  • multer ํŒจํ‚ค์ง€(9์žฅ์—์„œ)

์š”์ฒญ ํ—ค๋”์˜ ์ฟ ํ‚ค๋ฅผ ํ•ด์„ํ•ด์ฃผ๋Š” ๋ฏธ๋“ค์›จ์–ด

  • parseCookies ํ•จ์ˆ˜์™€ ๊ธฐ๋Šฅ ๋น„์Šท
  • req.cookies ์•ˆ์— ์ฟ ํ‚ค๋“ค์ด ๋“ค์–ด์žˆ์Œ
  • ๋น„๋ฐ€ ํ‚ค๋กœ ์ฟ ํ‚ค ๋’ค์— ์„œ๋ช…์„ ๋ถ™์—ฌ ๋‚ด ์„œ๋ฒ„๊ฐ€ ๋งŒ๋“  ์ฟ ํ‚ค์ž„์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Œ

    ์‹ค์ œ ์ฟ ํ‚ค ์˜ต์…˜๋“ค์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Œ
  • expires, domain, httpOnly, maxAge, path, secure, sameSite ๋“ฑ
  • ์ง€์šธ ๋•Œ๋Š” clearCookie๋กœ(expires์™€ maxAge๋ฅผ ์ œ์™ธํ•œ ์˜ต์…˜๋“ค์ด ์ผ์น˜ํ•ด์•ผ ํ•จ)

11. express-session

์„ธ์…˜ ๊ด€๋ฆฌ์šฉ ๋ฏธ๋“ค์›จ์–ด

  • ์„ธ์…˜ ์ฟ ํ‚ค์— ๋Œ€ํ•œ ์„ค์ •(secret: ์ฟ ํ‚ค ์•”ํ˜ธํ™”, cookie: ์„ธ์…˜ ์ฟ ํ‚ค ์˜ต์…˜)
  • ์„ธ์…˜ ์ฟ ํ‚ค๋Š” ์•ž์— s%3A๊ฐ€ ๋ถ™์€ ํ›„ ์•”ํ˜ธํ™”๋˜์–ด ํ”„๋ŸฐํŠธ์— ์ „์†ก๋จ
  • resave: ์š”์ฒญ์ด ์™”์„ ๋•Œ ์„ธ์…˜์— ์ˆ˜์ •์‚ฌํ•ญ์ด ์ƒ๊ธฐ์ง€ ์•Š์•„๋„ ๋‹ค์‹œ ์ €์žฅํ• ์ง€ ์—ฌ๋ถ€
  • saveUninitialized: ์„ธ์…˜์— ์ €์žฅํ•  ๋‚ด์—ญ์ด ์—†๋”๋ผ๋„ ์„ธ์…˜์„ ์ €์žฅํ• ์ง€
  • req.session.save๋กœ ์ˆ˜๋™ ์ €์žฅ๋„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ํ•  ์ผ ๊ฑฐ์˜ ์—†์Œ![

12. ๋ฏธ๋“ค์›จ์–ด์˜ ํŠน์„ฑ

req, res, next๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜
์ต์Šคํ”„๋ ˆ์Šค ๋ฏธ๋“ค์›จ์–ด๋“ค๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ•์•ฝ ๊ฐ€๋Šฅ

  • ์ˆœ์„œ๊ฐ€ ์ค‘์š”
  • static ๋ฏธ๋“ค์›จ์–ด์—์„œ ํŒŒ์ผ์„ ์ฐพ์œผ๋ฉด next๋ฅผ ํ˜ธ์ถœ ์•ˆ ํ•˜๋ฏ€๋กœ json, urlencoded, cookieParser๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Œ

13. next

next๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ๋‹ค์Œ ์ฝ”๋“œ๋กœ ๋„˜์–ด๊ฐ

  • next๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๋ฉด ์‘๋‹ต์ด ์ „์†ก๋˜์ง€ ์•Š์Œ
  • ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด(๋ผ์šฐํ„ฐ ๋ฏธ๋“ค์›จ์–ด)๋กœ ๋„˜์–ด๊ฐ€์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ
  • next์— ์ธ์ˆ˜๋กœ ๊ฐ’์„ ๋„ฃ์œผ๋ฉด ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋„˜์–ด๊ฐ(โ€˜routeโ€™์ธ ๊ฒฝ์šฐ ๋‹ค์Œ ๋ผ์šฐํ„ฐ๋กœ)

14. ๋ฏธ๋“ค์›จ์–ด๊ฐ„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌํ•˜๊ธฐ

req๋‚˜ res ๊ฐ์ฒด ์•ˆ์— ๊ฐ’์„ ๋„ฃ์–ด ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๊ฐ€๋Šฅ

  • app.set๊ณผ์˜ ์ฐจ์ด์ : app.set์€ ์„œ๋ฒ„ ๋‚ด๋‚ด ์œ ์ง€, req, res๋Š” ์š”์ฒญ ํ•˜๋‚˜ ๋™์•ˆ๋งŒ ์œ ์ง€
  • req.body๋‚˜ req.cookies๊ฐ™์€ ๋ฏธ๋“ค์›จ์–ด์˜ ๋ฐ์ดํ„ฐ์™€ ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ์กฐ์‹ฌ

15. ๋ฏธ๋“ค์›จ์–ด ํ™•์žฅํ•˜๊ธฐ

๋ฏธ๋“ค์›จ์–ด ์•ˆ์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋„ฃ๋Š” ๋ฐฉ๋ฒ•

  • ์•„๋ž˜ ๋‘ ์ฝ”๋“œ๋Š” ๋™์ผํ•œ ์—ญํ• 
  • ์•„๋ž˜์ฒ˜๋Ÿผ ๋‹ค์–‘ํ•˜๊ฒŒ ํ™œ์šฉ ๊ฐ€๋Šฅ

16. ๋ฉ€ํ‹ฐํŒŒํŠธ ๋ฐ์ดํ„ฐ ํ˜•์‹

form ํƒœ๊ทธ์˜ enctype์ด multipart/form-data์ธ ๊ฒฝ์šฐ

  • body-parser๋กœ๋Š” ์š”์ฒญ ๋ณธ๋ฌธ์„ ํ•ด์„ํ•  ์ˆ˜ ์—†์Œ
  • multer ํŒจํ‚ค์ง€ ํ•„์š”

17. multer ์„ค์ •ํ•˜๊ธฐ

multer ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ

  • storage๋Š” ์ €์žฅํ•  ๊ณต๊ฐ„์— ๋Œ€ํ•œ ์ •๋ณด
  • diskStorage๋Š” ํ•˜๋“œ๋””์Šคํฌ์— ์—…๋กœ๋“œ ํŒŒ์ผ์„ ์ €์žฅํ•œ๋‹ค๋Š” ๊ฒƒ
  • destination์€ ์ €์žฅํ•  ๊ฒฝ๋กœ
  • filename์€ ์ €์žฅํ•  ํŒŒ์ผ๋ช…(ํŒŒ์ผ๋ช…+๋‚ ์งœ+ํ™•์žฅ์ž ํ˜•์‹)
  • Limits๋Š” ํŒŒ์ผ ๊ฐœ์ˆ˜๋‚˜ ํŒŒ์ผ ์‚ฌ์ด์ฆˆ๋ฅผ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Œ.
  • ์‹ค์ œ ์„œ๋ฒ„ ์šด์˜ ์‹œ์—๋Š” ์„œ๋ฒ„ ๋””์Šคํฌ ๋Œ€์‹ ์— S3๊ฐ™์€ ์Šคํ† ๋ฆฌ์ง€ ์„œ๋น„์Šค์— ์ €์žฅํ•˜๋Š” ๊ฒŒ ์ข‹์Œ
    ๐Ÿ‘‰ Storage ์„ค์ •๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋จ

18. multer ๋ฏธ๋“ค์›จ์–ด๋“ค

single๊ณผ none, array, fields ๋ฏธ๋“ค์›จ์–ด ์กด์žฌ

  • single์€ ํ•˜๋‚˜์˜ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  ๋•Œ, none์€ ํŒŒ์ผ์€ ์—…๋กœ๋“œํ•˜์ง€ ์•Š์„ ๋•Œ
  • req.file ์•ˆ์— ์—…๋กœ๋“œ ์ •๋ณด ์ €์žฅ
  • array์™€ fields๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ์„ ์—…๋กœ๋“œ ํ•  ๋•Œ ์‚ฌ์šฉ
  • array๋Š” ํ•˜๋‚˜์˜ ์š”์ฒญ body ์ด๋ฆ„ ์•„๋ž˜ ์—ฌ๋Ÿฌ ํŒŒ์ผ์ด ์žˆ๋Š” ๊ฒฝ์šฐ
  • fields๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์š”์ฒญ body ์ด๋ฆ„ ์•„๋ž˜ ํŒŒ์ผ์ด ํ•˜๋‚˜์”ฉ ์žˆ๋Š” ๊ฒฝ์šฐ
  • ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ ์ •๋ณด๊ฐ€ req.files ์•„๋ž˜์— ์กด์žฌ

Router ๊ฐ์ฒด๋กœ ๋ผ์šฐํ„ฐ ๋ถ„๋ฆฌํ•˜๊ธฐ

1. express.Router

app.js๊ฐ€ ๊ธธ์–ด์ง€๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Œ
userRouter์˜ get์€ /user์™€ /๊ฐ€ ํ•ฉ์ณ์ ธ์„œ GET /user/๊ฐ€ ๋จ

๐Ÿ”ปroutes/index.js

const express = require('express');

const router = express.Router();

// GET / ๋ผ์šฐํ„ฐ
router.get('/', (req, res) => {
  res.send('Hello, Express');
});

module.exports = router;

๐Ÿ”ปroutes/user.js

const express = require('express');

const router = express.Router();

// GET /user ๋ผ์šฐํ„ฐ
router.get('/', (req, res) => {
  res.send('Hello, User');
});

module.exports = router;

๐Ÿ”ปapp.js

const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');

dotenv.config();
const indexRouter = require('./routes');
const userRouter = require('./routes/user');

const app = express();
app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

app.use('/', indexRouter);
app.use('/user', userRouter);

app.use((req, res, next) => {
  res.status(404).send('Not Found');
});

app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

2. ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜

:id๋ฅผ ๋„ฃ์œผ๋ฉด req.params.id๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

  • ๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋งŒ๋“ฆ

  • ์ผ๋ฐ˜ ๋ผ์šฐํ„ฐ๋ณด๋‹ค ๋’ค์— ์œ„์น˜ํ•ด์•ผ ํ•จ
  • /users/123?limit=5&skip=10 ์ฃผ์†Œ ์š”์ฒญ์ธ ๊ฒฝ์šฐ

3. 404 ๋ฏธ๋“ค์›จ์–ด

์š”์ฒญ๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ผ์šฐํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด 404 ๋ผ์šฐํ„ฐ๋ฅผ ๋งŒ๋“ค๊ธฐ

  • ์ด๊ฒŒ ์—†์œผ๋ฉด ๋‹จ์ˆœํžˆ Cannot GET ์ฃผ์†Œ ๋ผ๋Š” ๋ฌธ์ž์—ด์ด ํ‘œ์‹œ๋จ

4. ๋ผ์šฐํ„ฐ ๊ทธ๋ฃนํ™”ํ•˜๊ธฐ

์ฃผ์†Œ๋Š” ๊ฐ™์ง€๋งŒ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ๋•Œ

router.route๋กœ ๋ฌถ์Œ

req, res ๊ฐ์ฒด ์‚ดํŽด๋ณด๊ธฐ

1. req

req.app: req ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด app ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. req.app.get('port')์™€ ๊ฐ™์€ ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
req.body: body-parser ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋งŒ๋“œ๋Š” ์š”์ฒญ์˜ ๋ณธ๋ฌธ์„ ํ•ด์„ํ•œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
req.cookies: cookie-parser ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋งŒ๋“œ๋Š” ์š”์ฒญ์˜ ์ฟ ํ‚ค๋ฅผ ํ•ด์„ํ•œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
req.ip: ์š”์ฒญ์˜ ip ์ฃผ์†Œ๊ฐ€ ๋‹ด๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.
req.params: ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
req.query: ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
req.signedCookies: ์„œ๋ช…๋œ ์ฟ ํ‚ค๋“ค์€ req.cookies ๋Œ€์‹  ์—ฌ๊ธฐ์— ๋‹ด๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.
req.get(ํ—ค๋” ์ด๋ฆ„): ํ—ค๋”์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค![

2. res

res.app: req.app์ฒ˜๋Ÿผ res ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด app ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
res.cookie(ํ‚ค, ๊ฐ’, ์˜ต์…˜): ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.
res.clearCookie(ํ‚ค, ๊ฐ’, ์˜ต์…˜): ์ฟ ํ‚ค๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.
res.end(): ๋ฐ์ดํ„ฐ ์—†์ด ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
res.json(JSON): JSON ํ˜•์‹์˜ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
res.redirect(์ฃผ์†Œ): ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•  ์ฃผ์†Œ์™€ ํ•จ๊ป˜ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
res.render(๋ทฐ, ๋ฐ์ดํ„ฐ): ๋‹ค์Œ ์ ˆ์—์„œ ๋‹ค๋ฃฐ ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ๋ Œ๋”๋งํ•ด์„œ ์‘๋‹ตํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.
res.send(๋ฐ์ดํ„ฐ): ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋Š” ๋ฌธ์ž์—ด์ผ ์ˆ˜๋„ ์žˆ๊ณ H TML์ผ ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, ๋ฒ„ํผ์ผ ์ˆ˜๋„ ์žˆ๊ณ  ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
res.sendFile(๊ฒฝ๋กœ): ๊ฒฝ๋กœ์— ์œ„์น˜ํ•œ ํŒŒ์ผ์„ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.
res.setHeader(ํ—ค๋”, ๊ฐ’): ์‘๋‹ต์˜ ํ—ค๋”๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
res.status(์ฝ”๋“œ): ์‘๋‹ต ์‹œ์˜ HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

3. ๊ธฐํƒ€

๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ์ง€์›ํ•จ

์‘๋‹ต์€ ํ•œ ๋ฒˆ๋งŒ ๋ณด๋‚ด์•ผ ํ•จ

ํ…œํ”Œ๋ฆฟ ์—”์ง„ ์‚ฌ์šฉํ•˜๊ธฐ

1. ํ…œํ”Œ๋ฆฟ ์—”์ง„

HTML์˜ ์ •์ ์ธ ๋‹จ์ ์„ ๊ฐœ์„ 

  • ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ๋ณ€์ˆ˜ ๋“ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
  • ๋™์ ์ธ ํŽ˜์ด์ง€ ์ž‘์„ฑ ๊ฐ€๋Šฅ
  • PHP, JSP์™€ ์œ ์‚ฌํ•จ

2. Pug(๊ตฌ Jade)

๋ฌธ๋ฒ•์ด Ruby์™€ ๋น„์Šทํ•ด ์ฝ”๋“œ ์–‘์ด ๋งŽ์ด ์ค„์–ด๋“ฆ

  • HTML๊ณผ ๋งŽ์ด ๋‹ฌ๋ผ ํ˜ธ๋ถˆํ˜ธ๊ฐ€ ๊ฐˆ๋ฆผ
  • ์ต์Šคํ”„๋ ˆ์Šค์— app.set์œผ๋กœ ํผ๊ทธ ์—ฐ๊ฒฐ![]
    ๐Ÿ”ปapp.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');
const nunjucks = require('nunjucks');

dotenv.config();
const indexRouter = require('./routes');
const userRouter = require('./routes/user');

const app = express();
app.set('port', process.env.PORT || 3000);
nunjucks.configure('views', {
  express: app,
  watch: true,
});

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

app.use('/', indexRouter);
app.use('/user', userRouter);

app.use((req, res, next) => {
  res.status(404).send('Not Found');
});

app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

3. Pug โ€“ HTML ํ‘œํ˜„

4. Pug โ€“ HTML ํ‘œํ˜„

5. Pug - ๋ณ€์ˆ˜

res.render์—์„œ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜ ๊ฐ์ฒด์— Pug ๋ณ€์ˆ˜๋ฅผ ๋„ฃ์Œ

  • res.locals ๊ฐ์ฒด์— ๋„ฃ๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅ(๋ฏธ๋“ค์›จ์–ด๊ฐ„ ๊ณต์œ ๋จ)
  • =์ด๋‚˜ #{}์œผ๋กœ ๋ณ€์ˆ˜ ๋ Œ๋”๋ง ๊ฐ€๋Šฅ(= ๋’ค์—๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ• ์‚ฌ์šฉ ๊ฐ€๋Šฅ)

6. Pug โ€“ ํŒŒ์ผ ๋‚ด ๋ณ€์ˆ˜

ํผ๊ทธ ํŒŒ์ผ ์•ˆ์—์„œ ๋ณ€์ˆ˜ ์„ ์–ธ ๊ฐ€๋Šฅ

  • -๋’ค์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ
  • ๋ณ€์ˆ˜ ๊ฐ’์„ ์ด์Šค์ผ€์ดํ”„ ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Œ(์ž๋™ ์ด์Šค์ผ€์ดํ”„)

7. Pug โ€“ ๋ฐ˜๋ณต๋ฌธ

for in์ด๋‚˜ each in์œผ๋กœ ๋ฐ˜๋ณต๋ฌธ ๋Œ๋ฆด ์ˆ˜ ์žˆ์Œ

  • ๊ฐ’๊ณผ ์ธ๋ฑ์Šค ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ

8. Pug โ€“ ์กฐ๊ฑด๋ฌธ

if else if else๋ฌธ, case when๋ฌธ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

9. Pug โ€“ include

ํผ๊ทธ ํŒŒ์ผ์— ๋‹ค๋ฅธ ํผ๊ทธ ํŒŒ์ผ์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Œ

  • ํ—ค๋”, ํ‘ธํ„ฐ, ๋‚ด๋น„๊ฒŒ์ด์…˜ ๋“ฑ์˜ ๊ณตํ†ต ๋ถ€๋ถ„์„ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ํŽธ๋ฆฌ
  • include๋กœ ํŒŒ์ผ ๊ฒฝ๋กœ ์ง€์ •

10. Pug โ€“ extends์™€ block

๋ ˆ์ด์•„์›ƒ์„ ์ •ํ•  ์ˆ˜ ์žˆ์Œ

  • ๊ณตํ†ต๋˜๋Š” ๋ ˆ์ด์•„์›ƒ์„ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์ข‹์Œ, include์™€๋„ ๊ฐ™์ด ์‚ฌ์šฉ

11. ๋„Œ์ ์Šค

Pug์˜ ๋ฌธ๋ฒ•์— ์ ์‘๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋„Œ์ ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์Œ

  • Pug๋ฅผ ์ง€์šฐ๊ณ  Nunjucks ์„ค์น˜
  • ํ™•์žฅ์ž๋Š” html ๋˜๋Š” njk(view engine์„ njk๋กœ)

12. ๋„Œ์ ์Šค - ๋ณ€์ˆ˜

{{๋ณ€์ˆ˜}}


๋‚ด๋ถ€ ๋ณ€์ˆ˜ ์„ ์–ธ ๊ฐ€๋Šฅ {%set ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ตฌ๋ฌธ }

13. ๋„Œ์ ์Šค - ๋ฐ˜๋ณต๋ฌธ

{% %} ์•ˆ์— for in ์ž‘์„ฑ(์ธ๋ฑ์Šค๋Š” loop ํ‚ค์›Œ๋“œ)

14. ๋„Œ์ ์Šค - ์กฐ๊ฑด๋ฌธ

{% if %} ์•ˆ์— ์กฐ๊ฑด๋ฌธ ์ž‘์„ฑ

15. ๋„Œ์ ์Šค - include

ํŒŒ์ผ์ด ๋‹ค๋ฅธ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Œ

  • include์— ํŒŒ์ผ ๊ฒฝ๋กœ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ์Œ

16. ๋„Œ์ ์Šค - ๋ ˆ์ด์•„์›ƒ

๋ ˆ์ด์•„์›ƒ์„ ์ •ํ•  ์ˆ˜ ์žˆ์Œ

  • ๊ณตํ†ต๋˜๋Š” ๋ ˆ์ด์•„์›ƒ์„ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์ข‹์Œ, include์™€๋„ ๊ฐ™์ด ์‚ฌ์šฉ

17. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด

์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ํ…œํ”Œ๋ฆฟ ์—”์ง„๊ณผ ์ƒ๊ด€์—†์ด ํ…œํ”Œ๋ฆฟ ์—”์ง„ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ  error ํ…œํ”Œ๋ฆฟ์„ ๋ Œ๋”๋งํ•จ

  • res.locals.๋ณ€์ˆ˜๋ช…์œผ๋กœ๋„ ํ…œํ”Œ๋ฆฟ ์—”์ง„ ๋ณ€์ˆ˜ ์ƒ์„ฑ ๊ฐ€๋Šฅ
  • process.env.NODE_ENV๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ์ธ์ง€ ๋ฐฐํฌํ™˜๊ฒฝ์ธ์ง€ ๊ตฌ๋ถ„ํ•ด์ฃผ๋Š” ์†์„ฑ
    ๐Ÿ”ปapp.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');
const nunjucks = require('nunjucks');

dotenv.config();
const indexRouter = require('./routes');
const userRouter = require('./routes/user');

const app = express();
app.set('port', process.env.PORT || 3000);
app.set('view engine', 'html');
nunjucks.configure('views', {
  express: app,
  watch: true,
});

app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

app.use('/', indexRouter);
app.use('/user', userRouter);

app.use((req, res, next) => {
  const error =  new Error(`${req.method} ${req.url} ๋ผ์šฐํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.`);
  error.status = 404;
  next(error);
});

app.use((err, req, res, next) => {
  res.locals.message = err.message;
  res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
  res.status(err.status || 500);
  res.render('error');
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘');
});

๐Ÿ˜ƒ์ถœ์ฒ˜๐Ÿ˜ƒ
Node.js ๊ต๊ณผ์„œ - ๊ธฐ๋ณธ๋ถ€ํ„ฐ ํ”„๋กœ์ ํŠธ ์‹ค์Šต๊นŒ์ง€
https://www.inflearn.com/course/%EB%85%B8%EB%93%9C-%EA%B5%90%EA%B3%BC%EC%84%9C/dashboard

0๊ฐœ์˜ ๋Œ“๊ธ€