본문 바로가기
Learning

document, Express.js

by zsgg 2020. 1. 21.

expressjs

Guide

Serving static files in Express

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

스태틱 경로 설정할 수 있음

Routing

METHOD

app.get('/', function (req, res) {
  res.send('hello world')
})

위 형태로 get post patch delete 를 구현할 수 있음. 또는 all을 사용해서 모든 메서드에 적용할 수도 있고. use를 이용해서..

use 와 all 차이를 모르겠다..

Path

Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }

경로에 파라미터를 포함하는 api를 만들 수 있다

next()

var cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

var cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()
}, function (req, res) {
  res.send('Hello from D!')
})

path에 매칭된느 api에서 callback function을 자유롭게 붙이고 뗏다 할 수 있게 되어있다.
next() 호출하지 않고 response end 되는 메서드들

  • res.download()
  • res.end()
  • res.json()
  • res.jsonp()
  • res.redirect()
  • res.render()
  • res.send()
  • res.sendFile()
  • res.sendStatus()
app.route('/book')
  .get(function (req, res) {
    res.send('Get a random book')
  })
  .post(function (req, res) {
    res.send('Add a book')
  })
  .put(function (req, res) {
    res.send('Update the book')
  })

체이닝 가능

express.Router

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

// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
  console.log('Time: ', Date.now())
  next()
})
// define the home page route
router.get('/', function (req, res) {
  res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
  res.send('About birds')
})

module.exports = router

// --
// Then, load the router module in the app:
// --

var birds = require('./birds')

// ...

app.use('/birds', birds)

api 별로 router로 분리하여 모듈화를 시킬 수 있다.

Writing middleware for use in Express apps

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

var requestTime = function (req, res, next) {
  req.requestTime = Date.now()
  next()
}

app.use(requestTime)

app.get('/', function (req, res) {
  var responseText = 'Hello World!<br>'
  responseText += '<small>Requested at: ' + req.requestTime + '</small>'
  res.send(responseText)
})

app.listen(3000)

// --------------------------------------------

module.exports = function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next()
  }
}
// The middleware can now be used as shown below.

var mw = require('./my-middleware.js')
app.use(mw({ option1: '1', option2: '2' }))

이렇게도 할 수 있음. cookie-session 이 위 방법으로 만들어진 라이브러리 임

Using middleware

rquest response callback을 이어가는걸 미들웨어라고 말한다.

Application-level middleware

app.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})

path가 생략된 use는 모든 path에 동작한다

app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // send a regular response
  res.send('regular')
})

// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
  res.send('special')
})

스택에 쌓여있는 콜백을 무시하고 다음 라우터로 이동하고자 할때 next('route')를 호출한다.

해봐야 알겠지?. 쌓여있다는게 어디를 말하는거야 정확하게 어디?

Router-level middleware

var app = express()
var router = express.Router()

// predicate the router with a check and bail out when needed
router.use(function (req, res, next) {
  if (!req.headers['x-auth']) return next('router')
  next()
})

router.get('/', function (req, res) {
  res.send('hello, user!')
})

// use the router and 401 anything falling through
app.use('/admin', router, function (req, res) {
  res.sendStatus(401)
})

라우터레벨의 미들웨어란 app.use 에서 사용하는 path 이하를 route에서 선언한 path와 합쳐서 api를 정의하는거다.

여기서도 next('route')를 볼 수 있는데 음 보니까 중간중간 callback처럼 묶은 건 쌓인 stack으로 치고 마지막에 use 나 method아니지 마지막에 선언한걸로 skip 하는거 같다.

Error-handling middleware

에러 미들웨어는 꼭 파라미터 네개(err, req, res, next)를 줘야한다 네개 안맞춰주면 에러 미들웨어라고 판단 못한다함.

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

생긴거 보니 네개 안주면 다른거랑 구분이 안되겠네;;

Built-in middleware

내부함수 정도로 이해하면 될 거 같다.

express.static
: serves static assets such as HTML files, images, and so on.

express.json
: parses incoming requests with JSON payloads. NOTE: Available with Express 4.16.0+

payloads란 response에 담긴 body에 담긴 실제 원하는 데이터를 의미함 그 나머지는 overhead라고 함

express.urlencoded
: parses incoming requests with URL-encoded payloads. NOTE: Available with Express 4.16.0+

Third-party middleware

편한걸 잘 찾아보자! 찾아보는게 재미있지 암

var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')

// load the cookie-parsing middleware
app.use(cookieParser())

third-party middleware functions that are commonly used with Express

Using template engines with Express

템플릿 엔진을 사용하면 간단히 정적인 페이지를 만들 수 있음! 별로 쓸 일은 없을거 같다.

See Template Engines (Express wiki) for a list of template engines you can use with Express. See also Comparing JavaScript Templating Engines: Jade, Mustache, Dust and More.

직접 만드는 방법도 있다! Developing template engines for Express 간단한 결과 페이지나 음 뭐 그런데 쓰면 좋을듯

Error Handling

기본적으로 에러 처리하는 미들웨어가 있다. 가장 중요한건 모든 에러에 대해 포착하도록 코드를 짜는게 중요.

next('any string without route')을 하면 에러 콜백(미들웨어)을 호출한다.

app.get('/', function (req, res, next) {
  setTimeout(function () {
    try {
      throw new Error('BROKEN')
    } catch (err) {
      next(err)
    }
  }, 100)
})

비동기로 코드를 짤때는 try catch를 해주어야 함. 비동기는 express의 프로세스가 아니므로 에러가 나도 생략하기때문

app.get('/', function (req, res, next) {
  Promise.resolve().then(function () {
    throw new Error('BROKEN')
  }).catch(next) // Errors will be passed to Express.
})

promise 사용시 알아서 잡아줌 try 안해도 아니지 위에 보니까 catch 하네 알아서가 아니고 promise 스팩안에서 해결됨

에러가 발생할때 스택추천을 해주는데 production 모드에서는 안한다함.

왜지? 필요한거 아닌가?
Set the environment variable NODE_ENV to production, to run the app in production mode.

var bodyParser = require('body-parser')
var methodOverride = require('method-override')

app.use(bodyParser.urlencoded({
  extended: true
}))
app.use(bodyParser.json())
app.use(methodOverride())
app.use(function (err, req, res, next) {
  // logic
})

에러처리 등록은 마지막 use에 해라.

function logErrors (err, req, res, next) {
  console.error(err.stack)
  next(err)
}

next('error message')를 하지 않으면 가비지 컬렉터에 포함되지 않음

Advanced topic

보안, 효율, 메니징, 템플릿엔진 주제가 있다. 지금 볼 내용은 아닌거 같고 필요하면 봐야지

5.x API

express 사용하면서 알게되는걸 적어보자ㅂ

Review

express로 하나 만들고 리뷰해보자

QnA

Node.js + Nginx - What now?

Related Library

왠지 멋인는 익스프레스 써드파티 라이브러리 모아보자

Connect is an extensible HTTP server framework for node using "plugins" known as middleware.

'Learning' 카테고리의 다른 글

인사이드 자바스크립트  (0) 2020.01.23
document, winston.js  (0) 2020.01.21
성공과 실패를 결정하는 1%의 네트워크 원리  (0) 2020.01.21
생각을 넓혀주는 독서법  (0) 2020.01.19
서평 쓰는 법  (0) 2020.01.19

댓글