์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[Node.js] 6์žฅ ์ต์Šคํ”„๋ ˆ์Šค ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

22-23/22-23 Node.js

by YUZ ์œ ์ฆˆ 2022. 11. 5. 10:00

๋ณธ๋ฌธ

728x90


๐Ÿ” ์ต์Šคํ”„๋ ˆ์Šค

npm์—๋Š” ์„œ๋ฒ„๋ฅผ ์ œ์ž‘ํ•˜๋Š” ๊ณผ์ •์—์„œ์˜ ๋ถˆํŽธํ•จ์„ ํ•ด์†Œํ•˜๊ณ  ํŽธ์˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•œ ์›น ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์žˆ๋Š”๋ฐ, ๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์ด ์ต์Šคํ”„๋ ˆ์Šค๋‹ค.

์ต์Šคํ”„๋ ˆ์Šค๋Š” http ๋ชจ๋“ˆ์˜ ์š”์ฒญ๊ณผ ์‘๋‹ต ๊ฐ์ฒด์— ์ถ”๊ฐ€ ๊ธฐ๋Šฅ๋“ค์„ ๋ถ€์—ฌํ–ˆ๋‹ค.

 

๐Ÿ“Œ ์ต์Šคํ”„๋ ˆ์Šค ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ

  1. learn-express ํด๋” ์ƒ์„ฑ
  2. package.json ์ƒ์„ฑ
// package.json
{
  "name": "learn-express",
  "version": "0.0.1",
  "description": "์ต์Šคํ”„๋ ˆ์Šค๋ฅผ ๋ฐฐ์šฐ์ž",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app"
  },
  "author": "seol",
  "license": "MIT",
}
// app.js
const express = require('express');

const app = express();
app.set('port', process.env.PORT || 3000);  // ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋  ํฌํŠธ ์„ค์ •

app.get('/', (req, res) => {  // req: ์š”์ฒญ ๊ด€ํ•œ ์ •๋ณด ๋“ค์–ด์žˆ๋Š” ๊ฐ์ฒด, res: ์‘๋‹ต ๊ด€ํ•œ ์ •๋ณด ๋“ค์–ด์žˆ๋Š” ๊ฐ์ฒด
  res.send('Hello, Express');  // ์ฃผ์†Œ์— ๋Œ€ํ•œ GET ์š”์ฒญ์ด ์˜ฌ ๋•Œ ์–ด๋–ค ๋™์ž‘์„ ํ• ์ง€
});

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

 

๐Ÿ” ๋ฏธ๋“ค์›จ์–ด

๐Ÿ“Œ ๋ฏธ๋“ค์›จ์–ด๋Š” ์ต์Šคํ”„๋ ˆ์Šค์˜ ํ•ต์‹ฌ

์š”์ฒญ๊ณผ ์‘๋‹ต ์ค‘๊ฐ„์— ์œ„์น˜ํ•˜์—ฌ ๋ฏธ๋“ค์›จ์–ด๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค. ๋˜ํ•œ, ๋’ค์— ๋‚˜์˜ค๋Š” ๋ผ์šฐํ„ฐ์™€ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ๋˜ํ•œ ๋ฏธ๋“ค์›จ์–ด์˜ ์ผ์ข…์ด๋ฏ€๋กœ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์ต์Šคํ”„๋ ˆ์Šค์˜ ์ „๋ถ€๋ผ๊ณ  ํ•ด๋„ ๊ณผ์–ธ์ด ์•„๋‹ˆ๋‹ค. ๋ฏธ๋“ค์›จ์–ด๋Š” ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์กฐ์ž‘ํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋„ ํ•˜๊ณ  ๋‚˜์œ ์š”์ฒญ์„ ๊ฑธ๋Ÿฌ๋‚ด๊ธฐ๋„ ํ•œ๋‹ค.

๋ฏธ๋“ค์›จ์–ด๋Š” app.use์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค. => app.use(๋ฏธ๋“ค์›จ์–ด)

 

// app.js
...
app.set('port', process.env.PORT || 3000);

app.use((req, res, next => {
  console.log('๋ชจ๋“  ์š”์ฒญ์— ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค');
  next();
}));
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'), () => {
...

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

 

app.use(๋ฏธ๋“ค์›จ์–ด) ๋ชจ๋“  ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰
app.use('/abc', ๋ฏธ๋“ค์›จ์–ด) abc๋กœ ์‹œ์ž‘ํ•˜๋Š” ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰
app.post('/abc', ๋ฏธ๋“ค์›จ์–ด) abc๋กœ ์‹œ์ž‘ํ•˜๋Š” POST ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด ์‹คํ–‰

 

app.use๋‚˜ app.get ๊ฐ™์€ ๋ผ์šฐํ„ฐ์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ์žฅ์ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ err, req, res, next๋กœ ๋„ค ๊ฐœ๋‹ค. ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๋„ค ๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค.

 

๐Ÿ“Œ morgan

์‚ฌ์šฉ๋ฒ•: app.use(morgan('dev'));

์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฝ˜์†”์— ๊ธฐ๋กํ•œ๋‹ค.

dev ๋ชจ๋“œ ๊ธฐ์ค€์œผ๋กœ GET / 500 7.409ms - 50์€ ๊ฐ๊ฐ [HTTP ๋ฉ”์„œ๋“œ] [์ฃผ์†Œ] [HTTP ์ƒํƒœ ์ฝ”๋“œ] [์‘๋‹ต ์†๋„] - [์‘๋‹ต ๋ฐ”์ดํŠธ]๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ํ•œ ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์–ด ํŽธ๋ฆฌํ•˜๋‹ค.

dev ์™ธ์— combined, common, short, tiny ๋“ฑ์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“Œ static

static ๋ฏธ๋“ค์›จ์–ด๋Š” ์ •์ ์ธ ํŒŒ์ผ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ๋ผ์šฐํ„ฐ ์—ญํ• ์„ ํ•œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณต๋˜๊ธฐ์— ๋”ฐ๋กœ ์„ค์น˜ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

app.use('์š”์ฒญ ๊ฒฝ๋กœ', express.static('์‹ค์ œ ๊ฒฝ๋กœ'));

app.use('/', express.static(path.join(__dirname, 'public')));

 

๐Ÿ“Œ body-parser

์š”์ฒญ์˜ ๋ณธ๋ฌธ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด์„ํ•ด์„œ req.body ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๋ฏธ๋“ค์›จ์–ด๋‹ค. ํผ ๋ฐ์ดํ„ฐ๋‚˜ AJAX ์š”์ฒญ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฉ€ํ‹ฐํŒŒํŠธ(์ด๋ฏธ์ง€, ๋™์˜์ƒ, ํŒŒ์ผ) ๋ฐ์ดํ„ฐ๋Š” ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋ฏ€๋กœ ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ๋Š” multer ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

app.use(express.json());  // JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๋ฐฉ์‹
app.use(express.urlencoded({extended: false}));  // ์ฃผ์†Œ ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹
// {extended: false}๋ฉด querystring ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ํ•ด์„ํ•˜๊ณ ,
// true๋ฉด qs ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ํ•ด์„

 

๐Ÿ“Œ cookie-parser

cookie-parser๋Š” ์š”์ฒญ์— ๋™๋ด‰๋œ ์ฟ ํ‚ค๋ฅผ ํ•ด์„ํ•ด req.cookies ๊ฐ์ฒด๋กœ ๋งŒ๋“ ๋‹ค.

ํ•ด์„๋œ ์ฟ ํ‚ค๋“ค์€ req.cookie ๊ฐ์ฒด์— ๋“ค์–ด๊ฐ„๋‹ค. ๋งŒ์•ฝ name=seol์„ ๋ณด๋ƒˆ๋‹ค๋ฉด req.cookie๋Š” {name: 'seol'}๊ฐ€ ๋œ๋‹ค. ์œ ํšจ๊ธฐ๊ฐ„์ด ์ง€๋‚œ ์ฟ ํ‚ค๋Š” ์•Œ์•„์„œ ๊ฑธ๋Ÿฌ๋‚ธ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋น„๋ฐ€ ํ‚ค๋ฅผ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ฟ ํ‚ค๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ„์กฐํ•˜๊ธฐ ์‰ฌ์šฐ๋ฏ€๋กœ ๋น„๋ฐ€ ํ‚ค๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค์–ด๋‚ธ ์„œ๋ช…์„ ์ฟ ํ‚ค ๊ฐ’ ๋’ค์— ๋ถ™์ธ๋‹ค. name=seol.sign๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๊ฐ€ ๋˜๋ฉฐ, req.signedCookies ๊ฐ์ฒด์— ๋“ค์–ด์žˆ๋‹ค.

app.use(cookieParser(๋น„๋ฐ€ํ‚ค));

์ฟ ํ‚ค๋ฅผ ์ง€์šฐ๋ ค๋ฉด ํ‚ค์™€ ๊ฐ’ ์™ธ์˜ ์˜ต์…˜๋„ ์ •ํ™•ํ•˜๊ฒŒ ์ผ์น˜ํ•ด์•ผ ์ฟ ํ‚ค๊ฐ€ ์ง€์›Œ์ง„๋‹ค.

 

๐Ÿ“Œ express-session

์„ธ์…˜ ๊ด€๋ฆฌ์šฉ ๋ฏธ๋“ค์›จ์–ด๋‹ค. ๋กœ๊ทธ์ธ ๋“ฑ์˜ ์ด์œ ๋กœ ์„ธ์…˜์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ž„์‹œ์ ์œผ๋กœ ์ €์žฅํ•ด๋‘˜ ๋•Œ ์œ ์šฉํ•˜๋‹ค. ์„ธ์…˜์€ ์‚ฌ์šฉ์ž๋ณ„๋กœ req.session ๊ฐ์ฒด ์•ˆ์— ์œ ์ง€๋œ๋‹ค.

app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',
}));

express-session์€ ์„ธ์…˜ ๊ด€๋ฆฌ ์‹œ ํด๋ผ์ด์–ธํŠธ์— ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ธ๋‹ค.

 

๐Ÿ“Œ multer

์ด๋ฏธ์ง€, ๋™์˜์ƒ ๋“ฑ์„ ๋น„๋กฏํ•œ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํŒŒ์ผ๋“ค์„ ๋ฉ€ํ‹ฐํŒŒํŠธ ํ˜•์‹์œผ๋กœ ์—…๋กœ๋“œํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋‹ค. ๋ฉ€ํ‹ฐํŒŒํŠธ ํ˜•์‹์ด๋ž€ enctype์ด multipart/from-data์ธ ํผ์„ ํ†ตํ•ด ์—…๋กœ๋“œํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ํ˜•์‹์„ ์˜๋ฏธํ•œ๋‹ค.

 

๐Ÿ” ๋ฏธ๋“ค์›จ์–ด์˜ ํŠน์„ฑ

  • ๋ฏธ๋“ค์›จ์–ด๋Š” req, res, next๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜(์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋งŒ ์˜ˆ์™ธ์ ์œผ๋กœ err, req, res, next๋ฅผ ๊ฐ€์ง„๋‹ค.)๋กœ์„œ app.use๋‚˜ app.get, app.post ๋“ฑ์œผ๋กœ ์žฅ์ฐฉํ•œ๋‹ค.
  • ํŠน์ •ํ•œ ์ฃผ์†Œ์˜ ์š”์ฒญ์—๋งŒ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋˜๊ฒŒ ํ•˜๋ ค๋ฉด ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ฃผ์†Œ๋ฅผ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.
  • ๋™์‹œ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์žฅ์ฐฉํ•  ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ€๋ ค๋ฉด next()๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ฏธ๋“ค์›จ์–ด๋Š” ์žฅ์ฐฉ ์ˆœ์„œ์— ๋”ฐ๋ผ ์–ด๋–ค ๋ฏธ๋“ค์›จ์–ด๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค.
  • ํ˜„์žฌ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋™์•ˆ req.data๋ฅผ ํ†ตํ•ด ๋ฏธ๋“ค์›จ์–ด ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ณ , ์ƒˆ๋กœ์šด ์š”์ฒญ์ด ์˜ค๋ฉด req.data๋Š” ์ดˆ๊ธฐํ™”๋œ๋‹ค.
  • ๋ฏธ๋“ค์›จ์–ด ์•ˆ์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋„ฃ๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํŒจํ„ด์€ ๊ธฐ์กด ๋ฏธ๋“ค์›จ์–ด์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์œ ์šฉํ•˜๋‹ค.
app.use(morgan('dev'));
๋˜๋Š”
app.use((req, res, next) => {
  morgan('dev')(req, res, next);
});

 

๐Ÿ” Router

app.get ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋Š” ๋ผ์šฐํ„ฐ ๋ถ€๋ถ„์ด๋‹ค. ๋ผ์šฐํ„ฐ๋ฅผ ๋งŽ์ด ์—ฐ๊ฒฐํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๋ฏ€๋กœ ์ต์Šคํ”„๋ ˆ์Šค๋Š” ๋ผ์šฐํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

// 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');
});
// app.js
...
const indexRouter = require('./routes');
const userRouter = require('./routes/user);
...

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

app.use๋กœ ์—ฐ๊ฒฐํ•  ๋•Œ๋Š” ์ฃผ์†Œ๊ฐ€ ํ•ฉ์ณ์ง„๋‹ค.

 

router.get('/user/:id', function(req, res) {
  console.log(req.params, req.query);
});

์œ„์˜ ์ฃผ์†Œ๋Š” ์ž์ฃผ ์“ฐ์ด๋Š” ํŒจํ„ด์ด๋‹ค. ์ฃผ์†Œ์— :id๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด ๋ถ€๋ถ„์—๋Š” ๋‹ค๋ฅธ ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค. /user/1์ด๋‚˜ /user/123 ๋“ฑ์˜ ์š”์ฒญ๋„ ์ด ๋ผ์šฐํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๋ฐฉ์‹์˜ ์žฅ์ ์€ :id์— ํ•ด๋‹นํ•˜๋Š” 1์ด๋‚˜ 123์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋ฉฐ, req.params ๊ฐ์ฒด ์•ˆ์— ๋“ค์–ด ์žˆ๋‹ค. ๋‹ค๋งŒ ์ฃผ์˜ํ•  ์ ์€ ์ผ๋ฐ˜ ๋ผ์šฐํ„ฐ๋ณด๋‹ค ๋’ค์— ์œ„์น˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

 

๐Ÿ” req, res ๊ฐ์ฒด

์ต์Šคํ”„๋ ˆ์Šค์˜ req, res ๊ฐ์ฒด๋Š” http ๋ชจ๋“ˆ์˜ req, res ๊ฐ์ฒด๋ฅผ ํ™•์žฅํ•œ ๊ฒƒ์ด๋‹ค. ๊ธฐ์กด์˜ http ๋ชจ๋“ˆ์˜ ๋ฉ”์„œ๋“œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ์ต์Šคํ”„๋ ˆ์Šค๊ฐ€ ์ถ”๊ฐ€ํ•œ ๋ฉ”์„œ๋“œ๋‚˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

  • req ๊ฐ์ฒด
    • req.app: req ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด app ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. req.app.get('port')์˜ ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
    • req.body: body-parser ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋งŒ๋“œ๋Š” ์š”์ฒญ์˜ ๋ณธ๋ฌธ์„ ํ•ด์„ํ•œ ๊ฐ์ฒด๋‹ค.
    • req.cookie: cookie-parser ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋งŒ๋“œ๋Š” ์š”์ฒญ์˜ ์ฟ ํ‚ค๋ฅผ ํ•ด์„ํ•œ ๊ฐ์ฒด๋‹ค.
    • req.id: ์š”์ฒญ์˜ ip ์ฃผ์†Œ๊ฐ€ ๋‹ด๊ฒจ์žˆ๋‹ค.
    • req.params: ๋ผ์šฐํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด๋‹ค.
    • ๋“ฑ๋“ฑ
  • res ๊ฐ์ฒด
    • res.app: req.app์ฒ˜๋Ÿผ res ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด app ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
    • res.cookie(ํ‚ค, ๊ฐ’, ์˜ต์…˜): ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋‹ค.
    • res.clearCookie(ํ‚ค, ๊ฐ’, ์˜ต์…˜): ์ฟ ํ‚ค๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๋ฉ”์„œ๋“œ๋‹ค.
    • res.end(): ๋ฐ์ดํ„ฐ ์—†์ด ์‘๋‹ต์„ ๋ณด๋‚ธ๋‹ค.
    • res.json(JSON): JSON ํ˜•์‹์˜ ์‘๋‹ต์„ ๋ณด๋‚ธ๋‹ค.
    • res.send(๋ฐ์ดํ„ฐ): ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์‘๋‹ต์„ ๋ณด๋‚ธ๋‹ค. ๋ฌธ์ž์—ด์ผ์ˆ˜๋„ HTML, ๋ฒ„ํผ, ๊ฐ์ฒด, ๋ฐฐ์—ด์ผ์ˆ˜๋„ ์žˆ๋‹ค.
    • ๋“ฑ๋“ฑ

 

๐Ÿ” ํ…œํ”Œ๋ฆฟ ์—”์ง„

ํ…œํ”Œ๋ฆฟ ์—”์ง„์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ HTML์„ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ HTML๊ณผ๋Š” ๋ฌธ๋ฒ•์ด ์‚ด์ง ๋‹ค๋ฅผ ์ˆ˜๋„ ์žˆ๊ณ , ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์ด ๋“ค์–ด ์žˆ๊ธฐ๋„ ํ•˜๋‹ค.

๐Ÿ“Œ ํผ๊ทธ(Pug)

๋ฌธ๋ฒ•์ด ๊ฐ„๋‹จํ•ด ์ฝ”๋“œ์˜ ์–‘์ด ์ค„์–ด๋“ค์ง€๋งŒ, HTML๊ณผ๋Š” ๋ฌธ๋ฒ•์ด ๋งŽ์ด ๋‹ฌ๋ผ ํ˜ธ๋ถˆํ˜ธ๊ฐ€ ๋‹ฌ๋ฆฐ๋‹ค.

 

๊ธฐ์กด HTML๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ํ™”์‚ด๊ด„ํ˜ธ(<>)์™€ ๋‹ซ๋Š” ํƒœ๊ทธ๊ฐ€ ์—†๋‹ค. ํƒญ ๋˜๋Š” ์ŠคํŽ˜์ด์Šค๋กœ๋งŒ ํƒœ๊ทธ์˜ ๋ถ€๋ชจ ์ž์‹ ๊ด€๊ณ„๋ฅผ ๊ทœ๋ช…ํ•œ๋‹ค.

ํผ๊ทธ HTML
doctype html
html
  head
    title = title
    linke(rel='stylesheet', href='/stylesheets/style.css')
<!DOCTYPE html>
<html>
  <head>
    <title>์ต์Šคํ”„๋ ˆ์Šค</title>
    <link rel="stylesheet" href="/style.css" />
  </head>
</html>

 

์†์„ฑ ์ค‘ ์•„์ด๋””์™€ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํ‘œํ˜„ํ•˜๋ฉฐ, div ํƒœ๊ทธ์ธ ๊ฒฝ์šฐ div ๋ฌธ์ž๋Š” ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋‹ค.

ํผ๊ทธ HTML
#login-button
.post-imagee
span#highlight
p.hidden.full
<div id="login-button"></div>
<div class="post-image"></div>
<span id="highlight"></span>
<p class="hidden full"></p>

 

HTML ํ…์ŠคํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํƒœ๊ทธ ๋˜๋Š” ์†์„ฑ ๋’ค์— ํ•œ ์นธ์„ ๋„๊ณ  ์ž…๋ ฅํ•œ๋‹ค.

ํผ๊ทธ HTML
p Welcome to Express
button(type='submit') ์ „์†ก
<p>Welcome to Express</p>
<button type="submit">์ „์†ก</button>

 

์—๋””ํ„ฐ์—์„œ ํ…์ŠคํŠธ๋ฅผ ์—ฌ๋Ÿฌ ์ค„ ์ž…๋ ฅํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํŒŒ์ดํ”„(|)๋ฅผ ๋„ฃ๋Š”๋‹ค.

ํผ๊ทธ HTML
p
  | ์•ˆ๋…•ํ•˜์„ธ์š”.
  | ์—ฌ๋Ÿฌ ์ค„์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  br
  | ํƒœ๊ทธ๋„ ์ค‘๊ฐ„์— ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<p>์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ ์ค„์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  <br />
  ํƒœ๊ทธ๋„ ์ค‘๊ฐ„์— ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
</p>

 

style์ด๋‚˜ script ํƒœ๊ทธ๋กœ CSS ๋˜๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํƒœ๊ทธ ๋’ค์— ์ (.)์„ ๋ถ™์ธ๋‹ค.

ํผ๊ทธ HTML
style.
  h1 {
    font-size: 30px;
  }
script.
  const message = 'Pug';
  alert(message);
<style>
  h1 {
    font-size: 30px;
  }
</style>
<script>
  const message = 'Pug';
  alert(message);
</script>

 

ํผ๊ทธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ณ€์ˆ˜๋ฅผ ํ…œํ”Œ๋ฆฟ์— ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });  // render(ํ…œํ”Œ๋ฆฟ, ๋ณ€์ˆ˜ ๊ฐ์ฒด)
});

 

๋ณ€์ˆ˜๋ฅผ ํ…์ŠคํŠธ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํƒœ๊ทธ ๋’ค์— =๋ฅผ ๋ถ™์ธ ํ›„ ๋ณ€์ˆ˜ ์ž…๋ ฅํ•˜๊ณ , ํ…์ŠคํŠธ ์ค‘๊ฐ„์— ๋ณ€์ˆ˜๋ฅผ ๋„ฃ์œผ๋ ค๋ฉด #{๋ณ€์ˆ˜}๋ฅผ ์ž…๋ ฅํ•œ๋‹ค.

ํผ๊ทธ HTML
- const node = 'Node.js'
- const js = 'Javascript'
p #{node}์™€ #{js}
<p>Node.js์™€ Javascript</p>

 

๋ฐ˜๋ณต๋ฌธ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ๋ณ€์ˆ˜์ธ ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น๋œ๋‹ค. each๋กœ ๋ฐ˜๋ณต๋ฌธ ๋Œ๋ฆด ์ˆ˜ ์žˆ์œผ๋ฉฐ, for๋ฅผ ๋Œ€์‹  ์จ๋„ ๋œ๋‹ค.

ํผ๊ทธ HTML
ul
  each fruit in ['์‚ฌ๊ณผ', '๋ฐฐ', '์˜ค๋ Œ์ง€', '๋ฐ”๋‚˜๋‚˜', '๋ณต์ˆญ์•„']
    li = fruit
<ul>
  <li>์‚ฌ๊ณผ</li>
  <li>๋ฐฐ</li>
  <li>์˜ค๋ Œ์ง€</li>
  <li>๋ฐ”๋‚˜๋‚˜</li>
  <li>๋ณต์ˆญ์•„</li>
</ul>

 

๋ฐ˜๋ณต๋ฌธ ์‚ฌ์šฉ์‹œ ์ธ๋ฑ์Šค๋„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

ํผ๊ทธ HTML
ul
  each fruit in ['์‚ฌ๊ณผ', '๋ฐฐ', '์˜ค๋ Œ์ง€', '๋ฐ”๋‚˜๋‚˜', '๋ณต์ˆญ์•„']
    li = (index + 1) + '๋ฒˆ์งธ ' + fruit
<ul>
  <li>1๋ฒˆ์งธ ์‚ฌ๊ณผ</li>
  <li>2๋ฒˆ์งธ ๋ฐฐ</li>
  <li>3๋ฒˆ์งธ ์˜ค๋ Œ์ง€</li>
  <li>4๋ฒˆ์งธ ๋ฐ”๋‚˜๋‚˜</li>
  <li>5๋ฒˆ์งธ ๋ณต์ˆญ์•„</li>
</ul>

 

์กฐ๊ฑด๋ฌธ์œผ๋กœ ํŽธํ•˜๊ฒŒ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , if, else if, else ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

ํผ๊ทธ HTML
if isLoggedIn
  div ๋กœ๊ทธ์ธ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
else
  div ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
<!-- isLoggedIn์ด true์ผ ๋•Œ -->
<div>๋กœ๊ทธ์ธ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.</div>
<!-- isLoggedIn์ด false์ผ ๋•Œ -->
<div>๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค</div>

 

case๋ฌธ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

ํผ๊ทธ HTML
case fruit
  when 'apple'
    p ์‚ฌ๊ณผ์ž…๋‹ˆ๋‹ค.
  when 'apple'
    p ๋ฐ”๋‚˜๋‚˜์ž…๋‹ˆ๋‹ค.
  when 'apple'
    p ์˜ค๋ Œ์ง€์ž…๋‹ˆ๋‹ค.
  when 'apple'
    p ์‚ฌ๊ณผ๋„ ๋ฐ”๋‚˜๋‚˜๋„ ์˜ค๋ Œ์ง€๋„ ์•„๋‹™๋‹ˆ๋‹ค.
<!-- fruit์ด apple์ผ ๋•Œ -->
<p>์‚ฌ๊ณผ์ž…๋‹ˆ๋‹ค.</p>
<!-- fruit์ด banana์ผ ๋•Œ -->
<p>๋ฐ”๋‚˜๋‚˜์ž…๋‹ˆ๋‹ค.</p>
<!-- fruit์ด orange์ผ ๋•Œ -->
<p>์˜ค๋ Œ์ง€์ž…๋‹ˆ๋‹ค.</p>
<!-- ๊ธฐ๋ณธ๊ฐ’ -->
<p>์‚ฌ๊ณผ๋„ ๋ฐ”๋‚˜๋‚˜๋„ ์˜ค๋ Œ์ง€๋„ ์•„๋‹™๋‹ˆ๋‹ค.</p>

 

๐Ÿ“Œ ๋„Œ์ ์Šค(Nunjucks)

๋„Œ์ ์Šค๋Š” ํผ๊ทธ์˜ HTML ๋ฌธ๋ฒ• ๋ณ€ํ™”์— ์ ์‘ํ•˜๊ธฐ ํž˜๋“  ๋ถ„์—๊ฒŒ ์ ํ•ฉํ•œ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ด๋ฉฐ, HTML ๋ฌธ๋ฒ•์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋˜ ์ถ”๊ฐ€๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ํŒŒ์ด์ฌ์˜ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ธ Twig์™€ ๋ฌธ๋ฒ•์ด ์ƒ๋‹นํžˆ ์œ ์‚ฌํ•˜๋‹ค.

 

res.render ํ˜ธ์ถœ ์‹œ ๋ณด๋‚ด๋Š” ๋ณ€์ˆ˜๋ฅผ ๋„Œ์ ์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค.

router.get('/', function(req, res, next) {
  res.render('index', {title: 'Express'});
});

 

๋„Œ์ ์Šค์—์„œ ๋ณ€์ˆ˜๋Š” {{ }}๋กœ ๊ฐ์‹ผ๋‹ค.

๋„Œ์ ์Šค HTML
<h1>{{title}}</h1>
<p>Welcome to {{title}}</p>
<button class="{{title}}" type
<h1>Express</h1>
<p>Welcome to Express</p>
<button class="Express" type="submit">์ „์†ก</button>
<input placeholder="Express ์—ฐ์Šต" />

 

๋‚ด๋ถ€์— ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ๋Š” {% set ๋ณ€์ˆ˜ = '๊ฐ’' %}๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋„Œ์ ์Šค HTML
{% set node = 'Node.js' %}
{% set js = 'Javascript' %}
<p>{{node}}์™€ {{js}}</p>
<p>Node.js์™€ Javascript</p>

 

HTML์„ ์ด์Šค์ผ€์ดํ”„ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด {{๋ณ€์ˆ˜ | safe}}๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋„Œ์ ์Šค HTML
<p>{{'<strong>์ด์Šค์ผ€์ดํ”„</strong>'}}</p>
<p>{{'<strong>์ด์Šค์ผ€์ดํ”„ํ•˜์ง€ ์•Š์Œ</strong>' | safe}}</p>
<p>&lt;strong&gt;์ด์Šค์ผ€์ดํ”„&lt;/strong&gt;</p>
<p><strong>์ด์Šค์ผ€์ดํ”„ํ•˜์ง€ ์•Š์Œ</strong></p>

 

๋„Œ์ ์Šค์—์„œ๋Š” ํŠน์ˆ˜ํ•œ ๊ตฌ๋ฌธ์„ {% %} ์•ˆ์— ์“ด๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ˜๋ณต๋ฌธ๋„ ์ด ์•ˆ์— ๋„ฃ์œผ๋ฉด ๋œ๋‹ค. for in๋ฌธ๊ณผ endfor ์‚ฌ์ด์— ์œ„์น˜ํ•˜๋ฉด ๋œ๋‹ค.

๋„Œ์ ์Šค HTML
<ul>
  {% set fruits = ['์‚ฌ๊ณผ', '๋ฐฐ', '์˜ค๋ Œ์ง€', '๋ฐ”๋‚˜๋‚˜', '๋ณต์ˆญ์•„'] %}
  {% for item in fruits %}
  <li>{{item}}</li>
  {% endfor %}
</ul>
<ul>
  <li>์‚ฌ๊ณผ</li>
  <li>๋ฐฐ</li>
  <li>์˜ค๋ Œ์ง€</li>
  <li>๋ฐ”๋‚˜๋‚˜</li>
  <li>๋ณต์ˆญ์•„</li>
</ul>

 

๋ฐ˜๋ณต๋ฌธ์—์„œ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด loop.index๋ผ๋Š” ํŠน์ˆ˜ํ•œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋„Œ์ ์Šค HTML
<ul>
  {% set fruits = ['์‚ฌ๊ณผ', '๋ฐฐ', '์˜ค๋ Œ์ง€', '๋ฐ”๋‚˜๋‚˜', '๋ณต์ˆญ์•„'] %}
  {% for item in fruits %}
  <li>{{loop.index}}๋ฒˆ์งธ {{item}}</li>
  {% endfor %}
</ul>
<ul>
  <li>1๋ฒˆ์งธ ์‚ฌ๊ณผ</li>
  <li>2๋ฒˆ์งธ ๋ฐฐ</li>
  <li>3๋ฒˆ์งธ ์˜ค๋ Œ์ง€</li>
  <li>4๋ฒˆ์งธ ๋ฐ”๋‚˜๋‚˜</li>
  <li>5๋ฒˆ์งธ ๋ณต์ˆญ์•„</li>
<ul>

 

์กฐ๊ฑด๋ฌธ์€ {% if ๋ณ€์ˆ˜ %} {% elif %} {% endif %}๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

๋„Œ์ ์Šค HTML
{% if isLoggedIn %}
<div>๋กœ๊ทธ์ธ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.</div>
{% else %}
<div>๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.<div>
{% endif %}
<!-- isLoggedIn์ด true์ผ ๋•Œ -->
<div>๋กœ๊ทธ์ธ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.</div>
<!-- isLoggedIn์ด false์ผ ๋•Œ -->
<div>๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.</div>

 

case๋ฌธ ์—†์ง€๋งŒ elif(else if ์—ญํ• )๋ฅผ ํ†ตํ•ด ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋„Œ์ ์Šค HTML
{% if fruit === 'apple' %}
<p>์‚ฌ๊ณผ์ž…๋‹ˆ๋‹ค.</p>
{% elif fruit === 'banana' %}
<p>๋ฐ”๋‚˜๋‚˜์ž…๋‹ˆ๋‹ค.</p>
{% elif fruit === 'banana' %}
<p>์˜ค๋ Œ์ง€์ž…๋‹ˆ๋‹ค.</p>
{% else %}
<p>์‚ฌ๊ณผ๋„ ๋ฐ”๋‚˜๋‚˜๋„ ์˜ค๋ Œ์ง€๋„ ์•„๋‹™๋‹ˆ๋‹ค.</p>
{% endif %}

<!-- fruit๊ฐ€ apple์ผ ๋•Œ -->
<p>์‚ฌ๊ณผ์ž…๋‹ˆ๋‹ค.</p>
<!-- fruit๊ฐ€ banana์ผ ๋•Œ -->
<p>๋ฐ”๋‚˜๋‚˜์ž…๋‹ˆ๋‹ค.</p>
<!-- fruit๊ฐ€ orange์ผ ๋•Œ -->
<p>์˜ค๋ Œ์ง€์ž…๋‹ˆ๋‹ค.</p>
<!-- ๊ธฐ๋ณธ๊ฐ’ -->
<p>์‚ฌ๊ณผ๋„ ๋ฐ”๋‚˜๋‚˜๋„ ์˜ค๋ Œ์ง€๋„ ์•„๋‹™๋‹ˆ๋‹ค.</p>

 

728x90

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ