6.1 Express-generator로 빠르게 설치하기

$ npm i -g express-generator
$ express learn-express --view=pug
$ cd learn-express
$ npm install
$ npm start

npx 를 사용하여 글로벌 설치없이 코드 수정사항 즉시 반영하기

$ npx express learn-express --view=pug
$ cd learn-express
$ npm install
$ npx nodemon ./bin/www
  • 수정된 코드를 반영하기 위해서는 재시작이 필요하나 nodemon 사용을 통해 재시작 없이 코드를 자동 반영 할수 있음
  • 템플릿 엔진 미설정시 jade(pug의 이전이름)로 기본 설정됨

6.2 익스프레스 구조 이해하기

  1. 먼저 app, debug, http 모듈들을 가져옵니다. app 모듈은 나중에 살펴봅니다. debug 모듈은 콘솔에 로그를 남기는 모듈입니다.

    var app = require('../app');
    var debug = require('debug')('learn-express:server');
    var http = require('http');
  2. app.set('port', port)로 서버가 포트를 설정합니다. process.env 객체에 PORT 속성이 있다면 그 값을 사용하고, 없다면 기본값으로 3000번 포트를 이용하도록 되어 있습니다. 이렇게 app.set(키, 값)을 사용해서 데이터를 저장할 수 있습니다. 나중에 데이터를 app.get(키) 로 가져올 수 있습니다.

    var port = normalizePort(process.env.PORT || '3000');
    app.set('port', port);
  3. http.createServer에 불러온 app 모듈을 넣어줍니다. app 모듈이 createServer 메서드의 콜백 함수 역할을 합니다.

    var server = http.createServer(app);
  4. listen을 하는 부분은 http 웹 서버와 동일합니다. 4장에서 서버를 구동했던 것과 동일하게 포트를 연결하고 서버를 실행합니다. 익스프레스는 그저 콜백 함수 부분을 조금 다르게 만든 것입니다.

    server.listen(port);
    server.on('error', onError);
    server.on('listening', onListening);

6.3 미들웨어

요청과 응답의 중간에 위치하여 공통된 처리를 담당하는 로직.
app.use를 통해 사용.

6.3.1 커스텀 미들웨어 만들기

app.use(function(req, res, next) {
    console.log(req.url, '저도 미들웨어입니다.');
    next();
})
const customizedMiddleware = (req, res, next) => {
    console.log('req.url', '저도 미들웨어입니다.');
    next();
}

app.use(customizedMiddleware());

app.use에 여러개의 미들웨어 입력 가능(가독성이 좋지 않아 비추천!)

const customizedMiddleware1 = (req, res, next) => {
    console.log('첫 번째 미들웨어');
    next();
}

const customizedMiddleware2 = (req, res, next) => {
    console.log('두 번째 미들웨어');
    next();
}

const customizedMiddleware3 = (req, res, next) => {
    console.log('세 번째 미들웨어');
    next();
}

app.use(customizedMiddleware1(), customizedMiddleware2(), customizedMiddleware3());

6.3.2 morgan

const logger = require('morgan');

app.use(logger('dev'));

사용시 인자로 dev 이외에 short, common, combined 입력 가능.
각 인자마다 콘솔에 표시되는 로그내용이 다름.
개발시에는 dev, short를 배포시에는 common, combined를 많이 사용.

6.3.3 body-parser

const bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
  • express 4.16 버전 이후부터 express에 body-parser 기능이 일부 내장되어서 설치 하지 않고도 body 내용 확인 가능
  • JSON, URL-encoded 형식외에 Raw(Buffer), Text 형식의 본문을 추가로 해석 할때 사용
const cookieParser = require('cookie-parser');

app.use(cookieParser());

req.cookie 에 클라이언트에서 전송된 쿠키를 확인 가능함.

6.3.5 static

정적 파일(public 폴더)을 제공.
자체적으로 정적 파일 라우터 기능을 수행하므로 최대한 위쪽에 배치를 권장.

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

6.3.6 express-session

세션 관리용 미들웨어.

const session = require('exprsss-session');

app.use(session({
    resave: false,
    saveUninitialized: false,
    secret: 'secret code',
    cookie: {
        httpOnly: true,
        secure: false,
    },
}));

6.3.7 connect-flash

일회성 메세지 작성

6.4 Router 객체로 라우팅 분리하기

  • routes/learn.js
const express = require('express');
const router = express.Router();

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

module.exports = router;
  • app.js
const learnRouter = require('./routes/learn');

app.use('/learn', learnRouter);

http://localhost:3000/learn/express 로 요청 가능

  • route 활용
router.route('/express')
  .get(function(req, res, next) {})
  .put(function(req, res, next) {})
  .post(function(req, res, next) {})
  .delete(function(req, res, next) {})
  • req.params
router.get('/express/:name', function(req, res, next) {
    console.log(req.params);
});

http://localhost:3000/learn/choiseolbeom 로 요청시

console.log(req.params); // choiseolbeom
  • req.query
router.get('/', function(req, res, next) {
    console.log(req.query);
})

http://localhost:3000/learn?limit=5&skip=10 로 요청시

console.log(req.query); // {limit: '5', skip: '10'}

query에 한글포함시
querystring을 사용하여 stringify후 query 활용

const qs = require('querystring');

const query = {
    limit: '다섯개',
    skip: '열개',
};

const stringifiedQuery = qs.stringify(query);
console.log(stringifiedQuery) // 'limit=%EB%8B%A4%EC%84%AF%EA%B0%9C&skip=%EC%97%B4%EA%B0%9C'

const parsedQuery = qs.parse(query);
console.log(parsedQuery); // {limit: '다섯개', skip: '열개'}
  • 응답 메서드
  1. res.send() : 다양한 유형의 응답을 전송
  2. res.json() : json 데이터를 전송
  3. res.sendStatus() : httpStatus 코드 전송(데이터 전송 불가)
  4. res.status() : httpStatus 코드와 함께 데이터 전송가능
  5. res.end() : 응답 프로세스를 종료

한 개의 요청에 한개의 응답만 가능

6.5 템플릿 엔진 사용하기

6.5.1 Pug(Jade)

jade로 알려진 pug는 문법이 간단하여 코드의 양이 줄어드는 장점이 있어 인기가 많음.
html 과는 문법이 많이 달라 호불호가 갈림.

doctype html
html
    head
        title= title
        link(rel='stylesheet', href='/stylesheets/style.css')

6.5.2 EJS

ejs는 html문법을 그대로 사용하고 자바스크립트 문법을 사용 가능

<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<button class="<%= title%>" type="submit">전송</button>
<input placeholder="<%= title + '연습' %>">/>

6.5.3 에러 처리 미들웨어