ํ’€์Šคํƒ ์›น๐ŸŒ ๊ฐœ๋ฐœ์ž ์ง€๋ง์ƒ ๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป
โž• ์ธ๊ณต์ง€๋Šฅ ๊ด€์‹ฌ ๐Ÿค–


Categories


Recent views

  • 1
  • 2
  • 3
  • 4
  • 5

ExpressJs ํ•™์Šต

  1. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๋ฐ ๊ธฐ๋ณธ ๊ตฌ๋™ ์„ค์ • (Configure Dev settings.)
  2. ๊ธฐ๋Šฅ
  3. ๋ฏธ๋“ค์›จ์–ด(Middleware)

Express.js


Fast, unopinionated, minimalist web framework for Node.js

Node.js ๊ธฐ๋ฐ˜์˜ ์‹ฌํ”Œํ•œ ์›น ํ”„๋ ˆ์ž„์›Œํฌ, ์ฃผ๋กœ ๋ฒก์—”๋“œ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

์ •๋ง ๊ธฐ๋ณธ์ ์ธ ์„œ๋ฒ„์ด๊ณ , MIT ๋ผ์ด์„ผ์Šค ์ด๋ฏ€๋กœ, ์ข‹๊ฒŒ ๋งํ•˜๋ฉด ๊ฐ€๋ณ๊ณ  ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์„ ์ œ์•ฝ์—†์ด ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฌ์šฐ๋ฉฐ, ๋‚˜์˜๊ฒŒ ๋งํ•˜๋ฉด ๋งŽ์€ ๋ถ€๋ถ„์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

๋”์šฑ ์ž์„ธํ•œ ์‚ฌํ•ญ์€ Express.js ๊ณต์‹ ๋ฌธ์„œ ์ฐธ์กฐ ๋ฐ”๋žŒ.

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๋ฐ ๊ธฐ๋ณธ ๊ตฌ๋™ ์„ค์ • (Configure Dev settings.)


์„ค์น˜(Install)


๊ธฐ๋ณธ์ ์œผ๋กœ ์ตœ์‹  ๋ฒ„์ „์˜ Node.js๊ฐ€ ์„ค์น˜๊ฐ€ ๋๋‚œ ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹ค.

$ mkdir myapp # ํ”„๋กœ์ ํŠธ ํด๋” ์ƒ์„ฑ
$ cd myapp # ํ”„๋กœ์ ํŠธ ํด๋” ์ด๋™
$ npm init # ๊ธฐ๋ณธ์ ์ธ ํ”„๋กœ์ ํŠธ ์„ค์ •, package.json ์ƒ์„ฑ
$ npm install express --save # node_modules์— express ์„ค์น˜ ๋ฐ dependency ์„ค์ •

โœ note

์ด ๊ธ€์—์„œ๋Š” package.json ์ƒ์„ฑ ์„ค์ •์˜ ๊ธฐ๋ณธ๊ฐ’์„ ์ „์ œ๋กœ ํ•œ๋‹ค. ์ถ”๊ฐ€์ ์ธ ์„ค์ •์— ๋”ฐ๋ผ ์ผ๋ถ€ ์šฉ์–ด๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด,

  • main ํ•ญ๋ชฉ์„ index.js ๋Œ€์‹  app.js๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, app.js๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
  • Javascript ๋Œ€์‹  Typescript๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  • ์ž์„ธํ•œ ์‚ฌํ•ญ์€ Node.js ์ฐธ์กฐ

๊ธฐ๋ณธ ์„ธํŒ…(Default setting)

์ดํ›„, index.js ํŒŒ์ผ์„ ํ˜•์„ฑํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

์ดํ›„ node index.js ๋ฅผ ์ฝ˜์†”์— ์ž…๋ ฅํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.

$ node index.js
Example app listening at http://localhost:3000

http://localhost:3000 ์ฃผ์†Œ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ๋“ค์–ด๊ฐ€๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์ฐฝ์ด ํ‘œ๊ธฐ๋œ๋‹ค.

์ถ”๊ฐ€์ ์œผ๋กœ Nodemon์ด๋‚˜ Typescript ์„ค์ •์„ ํ•ด์ฃผ๋Š” ๊ฒƒ๋„ ๋‚˜์˜์ง€ ์•Š๋‹ค.

๊ธฐ๋Šฅ

๋ผ์šฐํŒ…(routing) ์„ค์ •


๋ผ์šฐํŒ… ๊ธฐ๋ณธ(Basic Routing)

Express.js๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ๋ผ์šฐํŒ…ํ•œ๋‹ค.

app.METHOD(PATH, HANDLER)

  • app์€ express์˜ ์ธ์Šคํ„ด์Šค์ด๋‹ค.

  • METHOD๋Š” get, post ๋“ฑ์˜ ์›ํ•˜๋Š” HTTP ์š”์ฒญ ๋ฉ”์†Œ๋“œ์ด๋‹ค.

  • PATH๋Š” ๋ผ์šฐํŒ…ํ•  ๊ฒฝ๋กœ์ด๋‹ค.

  • HANDLER๋Š” ํ•ด๋‹น ์ฃผ์†Œ๋กœ ๋ผ์šฐํŒ…๋ฌ์„ ๋•Œ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

์ด๋Ÿฌํ•œ ๋ผ์šฐํŒ… ์„ค์ •์„ app.listen(path, [callback]) ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋๋งˆ์น˜๋ฉด ๋œ๋‹ค.

app.post('/', function (req, res) {
  res.send('Got a POST request')
}) // post ์š”์ฒญ
app.listen(port, () => { // backend ์‹คํ–‰
  console.log(`Example app listening at http://localhost:${port}`)
})

๋ผ์šฐํŒ… ์ธ์ž (Route parameters)

๋‹ค์Œ๊ณผ ๊ฐ™์ด :๋ฅผ ์ด์šฉํ•ด url ์ธ์ž๋ฅผ ์–ป์–ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

app.get('/users/:userId/books/:bookId', function (req, res) { // ex) http://localhst:3000//users/42/books/21
  res.send(req.params) //":userId"(="42") ๋ถ€๋ถ„๊ณผ ":bookId"(="21") ๋ถ€๋ถ„์— ์กด์žฌํ•˜๋Š” ๊ฐ’๋“ค์ด string ํƒ€์ž…์œผ๋กœ ํ‘œ์‹œ.
})

โœ note

์ด๋•Œ ์ธ์ž์˜ ์ด๋ฆ„์œผ๋กœ ์ˆซ์ž์™€ ์˜์–ด ๋Œ€์†Œ๋ฌธ์ž๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

์ฆ‰, ํŠน์ˆ˜๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ํŠน์ˆ˜๋ฌธ์ž ์ด์ „๊นŒ์ง€๋งŒ ์ธ์ž์˜ ์ด๋ฆ„์œผ๋กœ ์ธ์ •๋œ๋‹ค.

app.get('/flights/:to-:from', function (req, res) { // ex) http://localhst:3000/flights/LAX-SFO
res.send(req.params) //":to-:from" ์ „์ฒด๋ฅผ ๋ณ€์ˆ˜๋ช…์œผ๋กœ ์ธ์‹ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ :to"(="LAX") ๋ถ€๋ถ„๊ณผ ":from"(="SFO") ๋ถ€๋ถ„์— ์กด์žฌํ•˜๋Š” ๊ฐ’๋“ค์ด string ํƒ€์ž…์œผ๋กœ ํ‘œ์‹œ.
}) 

๋ผ์šฐํŒ… Extras (Routing extras)

๋ผ์šฐํŒ… ์ •๊ทœ ํ‘œํ˜„์‹(Routing Regular Expression)

๋ผ์šฐํŒ…์— ์ •๊ทœ ํ‘œํ˜„์‹ ์ด๋‚˜ ๋ฌธ์ž์—ด ํŒจํ„ด์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฌธ์ž์—ด ?,+,*, (),$์€ ๋ฌธ์ž์—ด ํŒจํ„ด์œผ๋กœ ์ด์šฉ๋˜๋ฉฐ, ํŠนํžˆ $์„ ์ด์šฉํ•˜๊ณ  ์‹ถ์œผ๋ฉด [\$]๋กœ ๋Œ€์‹  ์ž…๋ ฅํ•ด์•ผํ•œ๋‹ค.

?์€ ๋ฐ”๋กœ ์•ž ๋ฌธ์ž ํ•˜๋‚˜๋ฅผ optionalํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

app.get('/ab?cd', function (req, res) {// acd, abcd๋กœ ์—ฐ๊ฒฐ
  res.send('ab?cd')  
})

+๋Š” ๋ฐ”๋กœ ์•ž ๋ฌธ์ž ํ•˜๋‚˜๋ฅผ ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

app.get('/ab+cd', function (req, res) {// abcd, abbcd, abb..bcd ๋กœ ์—ฐ๊ฒฐ
  res.send('ab+cd')
})

*์€ ๋ชจ๋“  ๊ธธ์ด์˜ ๋ชจ๋“  ๋ฌธ์ž์—ด์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•œ๋‹ค.

app.get('/ab*cd', function (req, res) {// ab์™€ cd ์‚ฌ์ด์— ๋ฌด์Šจ ๋ฌธ์ž๊ฐ€ ๋“ค์–ด๊ฐ€๋“  ์—ฐ๊ฒฐ(ex) ab/์ด๊ฒƒ๋„์—ฐ๊ฒฐ๊ฐ€๋Šฅ/cd)
  res.send('ab*cd')
})

()์€ ์•ž์˜ ๋ฌธ์ž์—ด ํŒจํ„ด๋“ค๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋ฉฐ, ๋Œ€์ƒ์„ ๋ฌธ์ž ํ•˜๋‚˜ ๋Œ€์‹ , () ์‚ฌ์ด์— ์กด์žฌํ•˜๋Š” ๋ฌธ์ž์—ด์„ ๋Œ€์ƒ์œผ๋กœ ํ•œ๋‹ค.

app.get('/ab(cd)?e', function (req, res) {//abcde, abe๋กœ ์—ฐ๊ฒฐ
  res.send('ab(cd)?e')
})

ํ‰๋ฒ”ํ•œ ์ •๊ทœ ํ‘œํ˜„์‹ ๋˜ํ•œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

app.get(/.*fly$/, function (req, res) {//fly๋กœ ๋๋‚˜๋Š” ์ฃผ์†Œ๋กœ ์—ฐ๊ฒฐ
  res.send('/.*fly$/')
})

route ํ•จ์ˆ˜(route function)

๋งŒ์•ฝ์— ๋™์ผํ•œ ์ฃผ์†Œ๋กœ ์—ฌ๋Ÿฌ ๋ฉ”์†Œ๋“œ์— ๋”ฐ๋ผ ๋™์ž‘์„ ๋‹ฌ๋ฆฌํ•˜๋ฉด์„œ, ํ•จ์ˆ˜ ์ฒด์ด๋‹์„ ํ†ตํ•ด ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ด๊ณ  ์‹ถ๋‹ค๋ฉด, route(path) ํ•จ์ˆ˜๋‚˜ all(path, callback, [,callback ...])์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

app.route('/book')
  .get(function (req, res) { // get ์š”์ฒญ ์‹œ์˜ ๋™์ž‘
    res.send('Get a random book')
  })
  .post(function (req, res) { // post ์š”์ฒญ ์‹œ์˜ ๋™์ž‘
    res.send('Add a book')
  })
  .put(function (req, res) { // put ์š”์ฒญ ์‹œ์˜ ๋™์ž‘
    res.send('Update the book')
  })

app.all('/user', function(req, res, next){
    res.send('Accessing the user section')
    next()
})

Router ํด๋ž˜์Šค(Router Class)

express.Router ํด๋ž˜์Šค๋Š” ๋ผ์šฐํŒ…์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ์ถ”๊ฐ€์ ์ธ ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ๋ผ์šฐํ„ฐ๋ฅผ ๋ชจ๋“ˆํ™”, ํŒŒ์ผ ๊ตฌ์กฐ ๋ผ์šฐํŒ… ๋“ฑ์„ ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.

๐Ÿ”ต ํŒŒ์ผ ๊ตฌ์กฐ ๋ผ์šฐํŒ…(File-system Routing) : Next.js์˜ ๊ธฐ๋Šฅ์ฒ˜๋Ÿผ ํด๋”์™€ ํŒŒ์ผ๊ฒฝ๋กœ๋ฅผ url ์ฃผ์†Œ๋กœ ์ด์šฉํ•˜์—ฌ ๋ผ์šฐํŒ… ํ•˜๋Š” ๋ฐฉ๋ฒ•.

var express = require('express')
var router = express.Router()

// ๋ผ์šฐํ„ฐ๊ฐ€ ์‚ฌ์šฉํ•  ๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜ ์ •์˜, ํ˜„์žฌ ์ด ๋ผ์šฐํ„ฐ ์ธ์Šคํ„ด์Šค๋กœ ์ „๋‹ฌ๋˜๋Š” ์š”์ฒญ๋งˆ๋‹ค ์‹คํ–‰๋จ
router.use(function timeLog (req, res, next) {
  console.log('Time: ', Date.now()) // ํ˜„์žฌ ์‹œ๊ฐ„ ์ถœ๋ ฅ
  next() //next ํ•จ์ˆ˜ : ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด ๊ธฐ๋Šฅ(=์—ฌ๊ธฐ์„  ๋ผ์šฐํŒ…)์„ ๋ถˆ๋Ÿฌ์˜ฎ.
})
// ํ™ˆํŽ˜์ด์ง€ ๊ฒฝ๋กœ ์„ค์ •
router.get('/', function (req, res) {
  res.send('Birds home page')
})
// /about ๊ฒฝ๋กœ ์„ค์ •
router.get('/about', function (req, res) {
  res.send('About birds')
})

module.exports = router

์ดํ›„, ํ•ด๋‹น ๋ผ์šฐํŒ… ํด๋ž˜์Šค๋ฅผ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋ถ€๋ฅธ ๋’ค, ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด์ฃผ๋ฉด, ํ•จ์ˆ˜๊ฐ€ ์ ์šฉ๋œ ํŒŒ์ผ ๊ตฌ์กฐ ๋ผ์šฐํŒ…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

var birds = require('./birds')

app.use('/birds', birds)
// "birds/" ๊ฒฝ๋กœ์™€ "birds/about/"๊ฒฝ๋กœ๊ฐ€ ์ด์šฉ ๊ฐ€๋Šฅํ•ด์ง. 

router.all(path, callback, [,callback ...]) ํ•จ์ˆ˜์™€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋“ค์„ ์ด์šฉํ•˜๋ฉด ์ „์—ญ ์ธ์ฆ ๋“ฑ์„ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค, ๋ชจ๋“ˆํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณค, app.all(path, callback, [,callback ...])๊ณผ ๋‹ค๋ฅธ์  ์—†์–ด๋ณด์ธ๋‹ค.

router.all('*', requireAuthentication, loadUser) // '*'๋ฅผ ์ด์šฉํ•œ ๋ผ์šฐํ„ฐ๋ฅผ ๋ชจ๋“  ๋ผ์šฐํ„ฐ๋ณด๋‹ค ๋จผ์ € ์ •์˜ํ•˜๋ฉด ๋ชจ๋“  url์— ์ ์šฉ๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.
// requireAuthentication : ์ธ์ฆ์— ๊ด€๋ จ๋œ ํ•จ์ˆ˜
// loadUser : ์œ ์ € ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜

router.all(path, callback, [,callback ...])์„ ํฌํ•จํ•ด router.METHOD(path, [callback, ...] callback) ํ•จ์ˆ˜๋“ค์€ ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ url, ๋‘๋ฒˆ์งธ๋ถ€ํ„ฐ๋Š” ์ฐจ๋ก€๋Œ€๋กœ next()๋ฅผ ๋ถ€๋ฅผ ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค.

// ์œ„์˜ ์˜ˆ์‹œ ์ฝ”๋“œ์™€ ๋™์ผํ•œ ๋™์ž‘์„ ํ•˜๋Š” ์ฝ”๋“œ
router.all('*', requireAuthentication)
router.all('*', loadUser)

์‘๋‹ต ๋ฐฉ๋ฒ•(Response methods)

ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต์„ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜, ์ด ํ•จ์ˆ˜๋ฅผ ๋ถ€๋ฆ„์œผ๋กœ์จ, ํด๋ผ์ด์–ธํŠธ๋Š” ๋Œ€๊ธฐ ์ƒํƒœ๋ฅผ ๋๋‚ด๊ณ  ์š”์ฒญ-์‘๋‹ต ์‚ฌ์ดํด์ด ์ข…๋ฃŒ๋œ๋‹ค.

  • res.send([body]) : HTTP ์‘๋‹ต์„ ๋ณด๋ƒ„. ์ฃผ๋กœ ๋น„์ŠคํŠธ๋ฆผ ์‘๋‹ต์— ์‚ฌ์šฉ๋จ
app.get('/', (req, res) => {
  res.send('Hello World!') // Hello World! ๋ผ๋Š” ์‘๋‹ต์„ ๋˜๋Œ๋ฆผ
})
app.get('/json', (req, res) => {
  res.send({messange: "ok"})// Json ํ˜•์‹์œผ๋กœ ์‘๋‹ต์„ ๋˜๋Œ๋ฆผ
})
app.get('/octet', (req, res)=>{
    res.set('Content-Type', 'text/html')// Content-Type์„ text ํ˜•ํƒœ๋กœ ๊ฐ•์ œ
    res.status(500).send('unavailable') // 500 ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์‘๋‹ต
})

๋งŒ์•ฝ, ์‘๋‹ต์ด JSON ํ˜•์‹์— ๋งž์ง€ ์•Š์•„ ๊ตณ์ด res.set(field[, value])ํ˜•์‹์„ ๋ฐ”๊ฟ”์ค˜์•ผ ํ•œ๋‹ค๋ฉด, ์ฐจ๋ผ๋ฆฌ res.json()๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฝ”๋“œ์˜ ๊ธธ์ด๋ฅผ ์ค„์ด์ž.

app.get('/', (req, res) => {
  res.json('Hello World!') // string์ž„์—๋„ Content-Type์€ application/json;
})


  • res.append(field[, value]): HTTP ์‘๋‹ต ํ—ค๋”์˜ ํ•„๋“œ์™€ ๊ฐ’์„ ์ถ”๊ฐ€, res.set(field[, value])==res.header(field[, value])์„ ์ด์šฉํ•˜๋ฉด obeject๋ฅผ ์ฃผ์–ด ์—ฌ๋Ÿฌ ๊ฐ’์„ ๋™์‹œ์— ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>'])
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly')

res.attachment([filename])์„ ํ†ตํ•˜์—ฌ Content-Disposition ํ—ค๋”๋ฅผ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

res.attachment('path/to/logo.png')
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png

์ข€ ๋” ์ฟ ํ‚ค๋ฅผ ์„ธ๋ถ„ํ™”ํ•˜์—ฌ ์ •ํ•ด์ฃผ๋ ค๋ฉด res.cookie(name, value [, options]) ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , res.clearCookie(name, value [, options])ํ•จ์ˆ˜๋กœ ์ง€์›Œ์ค„ ์ˆ˜ ์žˆ๋‹ค.

res
  .status(201)
  .cookie('access_token', 'Bearer ' + token, {
    expires: new Date(Date.now() + 8 * 3600000) // cookie will be removed after 8 hours
  })
  .cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })
  .redirect(301, '/admin')


  • res.redirect([status,] path) : ๋‹ค๋ฅธ URL๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ํ•ด์ค€๋‹ค. ๊ธฐ๋ณธ status ์ฝ”๋“œ๋Š” 302 Found์ด๋‹ค.
res.redirect(301, 'http://example.com')
res.redirect('../login')
res.redirect('back')//์ด์ „ referer๋กœ ๋Œ๋ฆผ


  • res.render(view [, locals] [, callback]) : HTML view๋ฅผ ๋ณด๋‚ธ๋‹ค.
    • view: html ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š” ํŒŒ์ผ ๊ฒฝ๋กœ
    • locals: view์—์„œ ์ด์šฉํ•  ๋กœ์ปฌ ๋ณ€์ˆ˜๋“ค์˜ object ํ˜•ํƒœ
    • callback: ์—๋Ÿฌ์™€ html ํŒŒ์ผ์˜ ๋ฌธ์ž์—ด์„ ์ธ์ž๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜
// view์—๊ฒŒ ๋กœ์ปฌ ๋ณ€์ˆ˜ ์ „๋‹ฌํ•˜๊ธฐ
res.render('html/user', { name: 'Tobi' }, function (err, html) {  
    if (err) {
        res.status(400).send('error!')
    } else {
          res.send(html)            
    }
})


  • res.download(path [, filename] [, options] [, fn]) : path์— ์กด์žฌํ•˜๋Š” ํŒŒ์ผ์„ attachment๋กœ ๋ณด๋‚ด๋ฉฐ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ค์šด๋กœ๋“œ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค. filename ์ธ์ž๋Š” ๋‹ค์šด๋กœ๋“œ ๋  ํŒŒ์ผ ๋ช…์œผ๋กœ, ์ฃผ์–ด์ง€์ง€ ์•Š์•˜๋‹ค๋ฉด, Content-Disposition ํ•„๋“œ์˜ filename= ์ธ์ž๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์ด๋‹ค.
res.download('/report-12345.pdf', 'report.pdf', function (err) {
  if (err) {
      // ์—๋Ÿฌ ํ•ธ๋“ค๋ง
  } else {

  }
})

์ด์™ธ์˜ ์ถ”๊ฐ€์ ์ธ ๋ฉ”์†Œ๋“œ๋“ค์€ ์—ฌ๊ธฐ ์ฐธ์กฐ

์ •์  ํŒŒ์ผ(static file) ์„ค์ •


Express.js๋Š” serve-static ๋ชจ๋“ˆ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“  ๋นŒํŠธ์ธ ๋ฏธ๋“ค์›จ์–ด(built-in middleware) ํ•จ์ˆ˜์ธ express.static์ด ์กด์žฌํ•œ๋‹ค.

์ด๋ฅผ ์ด์šฉํ•ด ์ด๋ฏธ์ง€, CSS ํŒŒ์ผ, JS ํŒŒ์ผ ๋“ฑ์˜ ์ •์  ํŒŒ์ผ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

express.static(root, [options])

  • root ์ธ์ž๋Š” ์ •์  ์—์…‹๋“ค์ด ์œ„์น˜ํ•œ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•œ๋‹ค.

  • [options] ์ธ์ž๋Š” static ํ•จ์ˆ˜๊ฐ€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด

    • dotfiles : .์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํŒŒ์ผ๊ณผ ํด๋”๋Š” ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃฐ ๊ฒƒ์ธ๊ฐ€? ex) "ignore" : ์—†๋Š” ๊ฑธ๋กœ ์ทจ๊ธ‰. (default : "allow", ํŠน๋ณ„ํ•œ ์กฐ์น˜ ์ทจํ•˜์ง€ ์•Š์Œ)
    • etag: HTTP ์‘๋‹ต ํ—ค๋”์— ETag ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. (default: "true", weak ETag)
    • lastModified: HTTP ์‘๋‹ต ํ—ค๋”์— Last-Modified ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. (default: "true")

    ๋“ฑ์ด ์กด์žฌํ•œ๋‹ค.

app.use(express.static('public'))

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ์ผ ๊ฒฝ์šฐ, ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ๋กœ์˜ public ํด๋”์˜ ํŒŒ์ผ๋“ค์„ url์„ ํ†ตํ•ด ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 |-public/
 | |-hello.html
 | |-css/
 | | |-main.css
 | |-images/
 | | |-dog.png
 | |-js/
 | | |-SPA.js

http://localhost:3000/hello.html
http://localhost:3000/css/main.css
http://localhost:3000/images/dog.jpg
http://localhost:3000/js/SPA.js

์ถ”๊ฐ€๋กœ, ๊ฒฝ๋กœ ์ ‘๋‘์–ด๋ฅผ ์ด์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

app.use('/static', express.static('public'))

http://localhost:3000/static/hello.html
http://localhost:3000/static/css/main.css
http://localhost:3000/static/images/dog.jpg
http://localhost:3000/static/js/SPA.js

DB ์—ฐ๊ฒฐ(DB Connection)


DB ์—ฐ๊ฒฐ ๋ฐฉ๋ฒ•์€ ๊ณต์‹ ๋ฌธ์„œ ์— DB ๋ณ„๋กœ ์ƒ์„ธํžˆ ์„ค๋ช…๋˜์–ด ์žˆ๋‹ค.

๊ฐ๊ธฐ DB์—์„œ ์ง€์›ํ•˜๋Š” ๋ชจ๋“ˆ์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰๋˜๋ฉฐ, ์—ฌ๊ธฐ์„œ๋Š” MySQL๊ณผ MongoDB์˜ ์˜ˆ์‹œ๋ฅผ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

MySQL

npm install mysql

mysql์—์„œ ์ง€์›ํ•˜๋Š” npm ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•œ๋‹ค. mysqljs github ์—์„œ ์ข€๋” ์ž์„ธํ•œ ์‚ฌํ•ญ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

var mysql = require('mysql')
var connection = mysql.createConnection({
  // ์‹ค์ œ๋กœ๋Š” env ์„ค์ •ํ• ๊ฒƒ!
  host: 'localhost',
  port: '3306',
  user: 'dbuser',
  password: 's3kreee7',
  database: 'my_db',
  debug: ENV.PRODUCTION, // true ์‹œ, ์ฝ˜์†” ์ฐฝ์— SQL ์ฟผ๋ฆฌ ์ง„ํ–‰์ด ์ถœ๋ ฅ๋จ
  supportBigNumbers: true, // db์˜ BIGINT๋‚˜ DECIMAL ํƒ€์ž…์€ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ์ƒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋ฌธ์ž์—ด ํ˜•์‹์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์˜ต์…˜
  ssl: {
      // ssl ์—ฐ๊ฒฐ ์„ค์ •์„ ์œ„ํ•œ ์˜ต์…˜
  }
})

connection.connect() // ์—ฐ๊ฒฐ ์‹œ์ž‘

connection.query('SELECT 1 + 1 AS solution', function (err, rows, fields) { // SQL Mapping, ์‹ค์ œ๋กœ๋Š” ORM์œผ๋กœ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœ
  if (err) throw err

  console.log('The solution is: ', rows[0].solution)
})

connection.end() // ์—ฐ๊ฒฐ ์ข…๋ฃŒ

MongoDB

npm install mongodb

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, MongoDB NodeJS๋ฅผ ์œ„ํ•œ ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

var MongoClient = require('mongodb').MongoClient

MongoClient.connect('mongodb://localhost:27017/animals', function (err, client) {
  if (err) throw err

  var db = client.db('animals')

  db.collection('mammals').find().toArray(function (err, result) {
    if (err) throw err

    console.log(result)
  })
})

Node.js์™€ MongoDB๋ฅผ ํ•จ๊ป˜ ์“ธ๋•Œ๋Š”, Mongoose์™€ ํ•จ๊ป˜ ์“ฐ๋Š” ๊ฒƒ๋„ ๊ณ ๋ คํ•ด๋ณผ๋งŒ ํ•˜๋‹ค.

Mongoose๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋‹ฌ๋ฆฌ ์ž์œ ๋กœ์šด ํ˜•์‹์„ ๊ฐ€์ง€๋Š” ์ฝœ๋ ‰์…˜(Collection)๋“ค์˜ ํ˜•์‹์„ ์ •์˜ํ•˜๊ณ , ์ œ์•ฝ(Constraint)์„ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

npm install mongoose validator

Mongoose๊ฐ€ ๋Œ€์‹  MongoDB์™€ ์—ฐ๊ฒฐ์„ ํ•˜๋ฏ€๋กœ, MongoDB ์—ฐ๊ฒฐ์€ ํ•„์š”์—†๋‹ค.

let mongoose = require('mongoose');

const server = '127.0.0.1:27017'; // DB ์„œ๋ฒ„ ์ฃผ์†Œ
const database = 'fcc-Mail';      // DB ๋ช…

class Database {
  constructor() {
    this._connect()
  }

_connect() {
     mongoose.connect(`mongodb://${server}/${database}`)
       .then(() => {
         console.log('Database connection successful')
       })
       .catch(err => {
         console.error('Database connection error')
       })
  }
}

module.exports = new Database()

ํ”„๋ก์‹œ ์„ค์ •(Proxy setting)


Express.js์—์„œ๋Š” ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ(Reverse Proxy)๋ฅผ ์ด์šฉํ•  ๊ฒฝ์šฐ, proxy-addr ํŒจํ‚ค์ง€ ๊ธฐ๋ฐ˜์ธ trust proxy ์„ค์ •์„ ํ•ด์ฃผ์–ด์•ผ ์ •์ƒ ์ž‘๋™ํ•œ๋‹ค.

์ด๋ฅผ ์„ค์ •ํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด, ํด๋ผ์ด์–ธํŠธ์˜ IP ์ฃผ์†Œ ๋Œ€์‹ , ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์˜ IP ์ฃผ์†Œ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ์ฐฉ๊ฐํ•œ๋‹ค๋Š” ๋“ฏํ•˜๋‹ค.

X-Forwarded-For: <client>, <proxy1>, <proxy2>
X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178
//X-Forwarded-For ํ—ค๋”์˜ ์˜ˆ์‹œ

์ด๋•Œ, HTTP ํ—ค๋” ์ค‘ X-Forwarded-for ํ—ค๋”๋ฅผ ์ด์šฉํ•ด ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๋ฅผ ํŒ๋ช…ํ•˜๋ฉฐ, ๋ณดํ†ต ์ตœ์ขŒ์ธก์ด ํด๋ผ์ด์–ธํŠธ IP ์ฃผ์†Œ์ด๋‹ค.

app.set('trust proxy', true)

true : HTTP ๋ฉ”์‹œ์ง€์˜ X-Forwarded-For ํ—ค๋”์˜ ์ตœ์ขŒ์ธก์˜ IP ์ฃผ์†Œ๋ฅผ ํด๋ผ์ด์–ธํŠธ IP ์ฃผ์†Œ๋กœ ์„ค์ •

๐Ÿ”ต HTTP ๋ฉ”์‹œ์ง€์˜ X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto ํ—ค๋”๋ฅผ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๊ฐ€ ๋ฎ์–ด์“ฐ๊ฒŒ ์„ค์ • ํ•˜์ง€ ์•Š์œผ๋ฉด, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ฅผ ์ด์šฉํ•ด ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ์ธ ์ฒ™ ํ–‰์„ธํ•  ์ˆ˜ ์žˆ๋‹ค.

false: ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉฐ, req.socket.remoteAddress์— ์กด์žฌํ•˜๋Š” IP ์ฃผ์†Œ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ๊ฐ„์ฃผ, ๊ธฐ๋ณธ๊ฐ’

app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal', '123.123.123.123'])

๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์˜ IP ์ฃผ์†Œ๋ฅผ ๋ช…์‹œํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค. ์•„๋ž˜๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ ์„œ๋ธŒ๋„ท ๋ฌธ์ž์—ด ๋“ค์ด๋‹ค.

  • loopback - 127.0.0.1/8, ::1/128
  • linklocal - 169.254.0.0/16, fe80::/10
  • uniquelocal - 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7

์ด๋•Œ ๋ช…์‹œ๋œ IP ์ฃผ์†Œ๋‚˜ ์„œ๋ธŒ๋„ท์€ ํด๋ผ์ด์–ธํŠธ IP ์ฃผ์†Œ๊ฐ€ ์•„๋‹Œ ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ•˜๋ฉฐ, req.socket.remoteAddress์˜ ์ฃผ์†Œ๊ฐ€ ๋ช…์‹œ๋˜์–ด ์žˆ๋‹ค๋ฉด(trusted), ํ•ด๋‹น ๋ฉ”์‹œ์ง€์˜ X-Forwarded-For ํ—ค๋”์— ๋ช…์‹ ๋œ ์ฃผ์†Œ์—์„œ ์ตœ์šฐ์ธก๋ถ€ํ„ฐ ์ขŒ์ธก ์ˆœ์œผ๋กœ ํ™•์ธํ•˜๋ฉด์„œ ๊ฐ€์žฅ ์ฒซ๋ฒˆ์งธ๋กœ ๋ช…์‹œ๋˜์–ด ์žˆ์ง€ ์•Š์€(untrusted) ์ฃผ์†Œ๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๋กœ ๊ฒฐ์ •ํ•œ๋‹ค.

app.set('trust proxy', 2)

์ˆซ์ž๋ฅผ ๋ช…์‹œํ•ด์ค„ ๊ฒฝ์šฐ, ๋ช‡ ํ™‰์˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์ดํ›„์— ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๊ฐ€ ๋‚˜์˜ค๋Š”์ง€๋กœ ๊ฒฐ์ •ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, 0์„ ๋ช…์‹œํ•˜๋ฉด, ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๊ฐ€ ์กด์žฌํ•˜์ง€์•Š์œผ๋ฉฐ, req.socket,remoteAddress๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๋กœ ํŒ๋ช…๋˜๋ฉฐ, 1์„ ๋ช…์‹œํ•˜๋ฉด, X-Forwarded-For ํ—ค๋”์˜ ์ตœ์šฐ์ธก์—์„œ ๋‘๋ฒˆ์งธ๋ฅผ ํด๋ผ์ด์–ธํŠธ IP ์ฃผ์†Œ๋กœ, ๋‚˜๋จธ์ง€๋งŒ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์ฃผ์†Œ๋กœ ๊ฒฐ์ •ํ•œ๋‹ค.

app.set('trust proxy', function (ip) {
  if (ip === '127.0.0.1' || ip === '123.123.123.123') return true // trusted IPs
  else return false
})

๋˜๋Š”, ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ด์ฃผ์–ด, ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋ฅผ ํŒ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. true์ผ ๊ฒฝ์šฐ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์ฃผ์†Œ์ด๋ฉฐ, X-Forwarded-For ํ—ค๋”์˜ ๋‹ค์Œ ์ฃผ์†Œ๋ฅผ ํ•จ์ˆ˜์— ๋„ฃ์–ด๋ณด๊ฒŒ ๋˜๊ณ , false์ผ ๊ฒฝ์šฐ ํ•ด๋‹น IP ์ฃผ์†Œ๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ ์ฃผ์†Œ์ด๋‹ค.

trust proxy ์„ค์ • ์ดํ›„, req.hostname์˜ ๊ฐ’์€ X-Forwarded-Host ํ—ค๋”์—์„œ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜๋ฉฐ, X-Forwarded-Proto ํ—ค๋”๊ฐ€ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์— ์˜ํ•ด ๋ณ€๊ฒฝ๋˜์–ด ํ”„๋กœํ† ์ฝœ ๋“ฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฉฐ, req.ip, req.ips ๊ฐ’์ด ์„ค์ •๋˜๊ฒŒ ๋œ๋‹ค.

๋ฏธ๋“ค์›จ์–ด(Middleware)


๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋ž€?(About middleware function)


๋ฏธ๋“ค์›จ์–ด ํ•จ์ˆ˜๋Š” ์‘์šฉํ”„๋กœ๊ทธ๋žจ์˜ ์š”์ฒญ-์‘๋‹ต ์‚ฌ์ดํด์˜ ์š”์ฒญ ๊ฐ์ฒด(request object)์™€ ์‘๋‹ต ๊ฐ์ฒด(response object), ๊ทธ๋ฆฌ๊ณ  next() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

  • ์š”์ฒญ ๊ฐ์ฒด(request object) : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญํ•œ HTTP ์š”์ฒญ์˜ ์š”์†Œ(์ฟผ๋ฆฌ ๋ฌธ์ž์—ด, ์ธ์ž, ๋ฐ”๋””, ํ—ค๋” ๋“ฑ)๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ๊ฐ์ฒด
  • ์‘๋‹ต ๊ฐ์ฒด(response object) : ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋Œ๋ ค์ค„ HTTP ์‘๋‹ต์„ ์œ„ํ•œ ๊ฐ์ฒด, ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์‘๋‹ต ๋ฉ”์‹œ์ง€๋ฅผ ์กฐ์„ฑํ•˜๊ณ  ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค.
  • next() ํ•จ์ˆ˜ : ์‹คํ–‰์‹œ ๋‹ค์Œ ์ˆœ์„œ์˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ•จ์ˆ˜, ํ•ด๋‹น ๋ฏธ๋“ค์›จ์–ด์—์„œ ํ†ต์‹ ์„ ์ข…๋ฃŒํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜๊ธฐ๋ ค๋ฉด ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค.

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

์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ์ฆ, ์ธ๊ฐ€ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜, ํ•„ํ„ฐ๋ง, ์บ์‰ฌ ๊ตฌํ˜„ ๋“ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

var express = require('express')
var app = express()
var router1 = express.Router() // router-๋ ˆ๋ฒจ ๋ฏธ๋“ค์›จ์–ด ์ƒ์„ฑ์„ ์œ„ํ•œ ๋ผ์šฐํ„ฐ ์„ ์–ธ
var router2 = express.Router()

app.use(function(req,res, next){ // ์‘์šฉํ”„๋กœ๊ทธ๋žจ ๋ ˆ๋ฒจ ๋ฏธ๋“ค์›จ์–ด ์ƒ์„ฑ
    console.log('middleware 1')
    next()
})

router1.use(function (req, res, next) {
    console.log('middleware 2')
    next()
})

router1.use(function (req, res, next) {
    console.log('middleware 3')
    next()
})

router2.use(function (req, res, next) {
    console.log('middleware 4')
    next('router')  // ํ˜„์žฌ ๋ผ์šฐํ„ฐ ๋ ˆ๋ฒจ์˜ ๋ชจ๋“  ๋ฏธ๋“ค์›จ์–ด๋ฅผ skip
})

router2.use(function (req, res, next) {
    console.log('middleware 5') // ์ƒ์œ„ ๋ฏธ๋“ค์›จ์–ด์—์„œ ๋ผ์šฐํ„ฐ ๋ ˆ๋ฒจ ๋ฏธ๋“ค์›จ์–ด๋“ค์„ skipํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
    next()
})

app.use(function(req,res, next){
    console.log('middleware 6')
    next()
})

app.use('/', router1) // ๋ผ์šฐํ„ฐ ๋ฏธ๋“ค์›จ์–ด ์„ ์–ธ์€ ๋นจ๋ž์ง€๋งŒ, app์— ์ ์šฉ์ด ๋Š๋ฆฌ๋ฏ€๋กœ middleware 6๋ฒˆ๋ณด๋‹ค ๋’ค์— ์‹คํ–‰๋œ๋‹ค.
app.use('/', router2)

์œ„ ์ฝ”๋“œ์˜ ์‹คํ–‰๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

middleware 1
middleware 6
middleware 2
middleware 3
middleware 4

์œ ์šฉํ•œ ๋ฏธ๋“ค์›จ์–ด (Additional Middleware)


static

[[#์ •์  ํŒŒ์ผ(static file) ์„ค์ • ์•ž์„œ]] ์„ค๋ช…ํ–ˆ๋˜ Express.js ๋นŒํŠธ์ธ ๋ชจ๋“ˆ, ์ •์  ํŒŒ์ผ์„ ์ด์šฉํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค.
express.static(root, [options])

cors

npm install cors

CORS๋Š” Express ํŒ€์—์„œ ๋งŒ๋“  ์„œ๋“œ ํŒŒํ‹ฐ ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค.

CORS(Cross-Origin Resource Sharing, ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ) ์„ค์ •์„ ํ†ตํ•ด ์ ‘๊ทผ ๊ถŒํ•œ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: ['http://example.com', 'http://example2.com'], // '*'์„ ์ด์šฉํ•˜๋ฉด ๋ชจ๋“  ์š”์ฒญ CORS ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ.
  optionsSuccessStatus: 200, // ์˜ค๋ž˜๋œ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ฝ”๋“œ 204๋ฅผ ์“ฐ๋ฏ€๋กœ 200์œผ๋กœ ๊ฐ•์ œ
  credentials: true
  //'Access-Control-Allow-Credentials' CORS ํ—ค๋” ์„ค์ • ์—ฌ๋ถ€
}

//์ผ๋ถ€ route์—๋งŒ cors ์ ์šฉ ์˜ˆ์‹œ
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for only example.com.'})
})

// ๋ชจ๋“  route์— cors ์ ์šฉ ์˜ˆ์‹œ
app.use(cors())

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

express-session

npm install express-session

Session ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํ˜•์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” Express ํŒ€์—์„œ ๋งŒ๋“  ์„œ๋“œ ํŒŒํ‹ฐ ๋ฏธ๋“ค์›จ์–ด.

Session์„ ์ด์šฉํ•˜์—ฌ, ์œ ์ €์˜ ์ฟ ํ‚ค๋ฅผ ์ €์žฅํ•˜๊ณ , ์š”์ฒญ์„ ์œ ์ €๋ณ„๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ, ๋ณด์•ˆ๊ณผ ์œ ์ € ํŠนํ™” ์„œ๋น„์Šค ๋“ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

var app = express()
var sess = {
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: false }
}

if (app.get('env') === 'production') {
  app.set('trust proxy', 1) // trust first proxy
  sess.cookie.secure = true // serve secure cookies
}

app.use(session(sess))

helmet

npm install helmet

HTTP ํ—ค๋” ์„ค์ •์„ ํ†ตํ•ด ์–ดํ”Œ๋ ˆ์ด์ผ€์ด์…˜ ๋ณด์•ˆ ํ–ฅ์ƒ์„ ๋„์™€์ฃผ๋Š” ์„œ๋“œ ํŒŒํ‹ฐ ๋ฏธ๋“ค์›จ์–ด.

const express = require("express");
const helmet = require("helmet");

const app = express();
const helmet_setting = {
    referrerPolicy: { policy: "no-referrer" }, // ์„ธ๋ถ€ ๋ณด์•ˆ ์„ค์ •
   contentSecurityPolicy: false // ์‚ฌ์šฉ ์•ˆํ•จ ์„ค์ •
}
app.use(helmet(helmet_setting));

helmet ์€ 15๊ฐœ์˜ ๋ณด์•ˆ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ฐ์ž ์„ค์ • ๋ฐ ์‚ฌ์šฉ ์—ฌ๋ถ€๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.