Javascript

Node.js - Express로 서버 만들기

Express 프레임워크를 써서 서버를 만들어 보자.

 

어플리케이션

  • 익스프레스 인스턴스를 어플리케이션이라 한다
  • 서버에 필요한 기능인 미들웨어를 어플리케이션에 추가한다
  • 라우팅 설정을 할 수 있다
  • 서버를 요청 대기 상태로 만들수 있다

 

익스프레스 인스턴스(= 어플리케이션 = 익스프레스 객체 = 서버 객체) 만들기

const express = require('express');

const app = express();

app.listen(3000, function(){
  console.log('Server is running');
})

 

미들웨어

  • 미들웨어는 함수들의 연속이다
  • 미들웨어로 어플리케이션에 기능을 추가할 수 있다

logger: log를 찍는 미들웨어

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

// 미들웨어는 인터페이스가 정해져 있다
// req, res, next 인자를 받는다
// 미들웨어는 자신의 할 일을 다하고 next 함수를 호출해야 한다.
// next를 호출하고 다음 로직을 수행한다.
// logger는 log를 찍는 미들웨어
function logger(req, res, next){
  console.log('I am logger');
  next();
}

function logger2(req, res, next){

}

app.use(logger);
app.use(logger2);

app.listen(3000, function(){
  console.log('Server is running');
})

 

use() 함수란?

http://expressjs.com/ko/api.html#app.use

미들웨어를 어플리케이션에 적용하는 함수

 

use()와 get()의 차이?

http://daplus.net/node-js-express-js에서-app-use와-app-get의-차이점/

 

미들웨어의 실행 순서

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

function logger(req, res, next){
  console.log('I am logger');
  next();
}

function logger2(req, res, next){
  console.log('I am logger2');
  next();
}

app.use(logger);
app.use(logger2);

app.listen(3000, function(){
  console.log('Server is running');
})

// 콘솔 출력
// Server is running
// I am logger
// I am logger2

만약 next()를 호출하지 않으면? 다음 차례의 미들웨어를 수행하지 않는다.

 

써드파티 미들웨어 사용하기

 

morgan - 로그를 남겨주는 유명한 미들웨어

npm i morgan

https://expressjs.com/en/resources/middleware/morgan.html

 

Express morgan middleware

morgan HTTP request logger middleware for node.js Named after Dexter, a show you should not watch until completion. Installation This is a Node.js module available through the npm registry. Installation is done using the npm install command: $ npm install

expressjs.com

const morgan = require('morgan')

app.use(morgan('tiny'))

morgan 함수는 format string을 인자로 받는데, 이미 정의된 포맷을 선택하여 입맛에 맞게 로그 포맷을 바꿔줄 수 있다. combined, dev, short, common, tiny 등이 있다.

 

const express = require('express');
const logger3 = require('morgan');
const app = express();

function logger(req, res, next){
  console.log('I am logger');
  next();
}

function logger2(req, res, next){
  console.log('I am logger2');
  next();
}

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

app.listen(3000, function(){
  console.log('Server is running');
})

// 콘솔 출력
// Server is running
// I am logger
// I am logger2
// GET /users 404 5.817 ms - 144

morgan을 logger3에 할당하여 실행해보니 순서대로 잘 동작하는 것을 확인할 수 있었다.

 

일반 미들웨어 vs 에러 미들웨어

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

function commonmw(req, res, next){
  console.log('common');
  next(new Error('error!!'));
}

function errormw(err, req, res, next){
  console.log(err.message);
  // 에러 미들웨어는 에러를 처리하거나
  // 에러를 next의 인자로 넣어 다음 미들웨어로 전달해 준다.
  next();
}

app.use(commonmw);
app.use(errormw);

app.listen(3000, function(){
  console.log('Server is running');
})

에러 미들웨어는 4개의 인자를 갖는다.

 

오류 처리 미들웨어는 다른 app.use() 및 라우트 호출을 정의한 후에 마지막으로 정의해야 한다.

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

app.use(bodyParser());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

출처: https://expressjs.com/ko/guide/error-handling.html

 

목적에 따라 여러 개의 에러 핸들 미들웨어를 만들어서 각자의 로직을 수행하고

다음 미들웨어로 에러를 넘겨주는 방식으로 구성하기도 하는듯?

 

라우팅

  • 요청 url에 대해 적절한 핸들러 함수로 연결해 주는 기능을 라우팅이라고 부른다.
  • 어플리케이션의 get(), post() 메서드로 구현할 수 있다.
  • 라우팅을 위한 전용 Router 클래스를 사용할 수도 있다.

 

http 모듈로 구현한 라우팅을 상기해보자.

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  console.log(req.url);
  if (req.url === '/'){
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
  } else {
    res.statusCode = 404;
    res.end('Not Found\n');
  }
});

console.log(typeof server)

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

여러 조건문으로 장황해진 코드를 익스프레스를 활용하여 깔끔하게 개선할 수 있다.

 

다음의 라우트 경로는 요청을 루트 라우트 /에 일치시킨다.

app.get('/', function (req, res) {
  res.send('root');
});

 

다음의 라우트 경로는 요청을 /about에 일치시킨다.

app.get('/about', function (req, res) {
  res.send('about');
});

 

다음의 라우트 경로는 요청을 /random.text에 일치시킨다.

app.get('/random.text', function (req, res) {
  res.send('random.text');
});

 

요청객체와 응답객체

 

요청객체

  • 클라이언트의 요청 정보를 담은 객체를 요청(requeset) 객체라 한다
  • http 모듈의 request 객체를 래핑
  • 편리한 메서드를 제공해주는 것이 장점
  • req.prams(), req.query(), req.body() 메서드를 주로 사용

 

응답객체

  • 클라이언트 응답 정보를 담은 객체를 응답(response) 객체라 한다
  • http 모듈의 response 객체를 래핑
  • res.send(), res.status(), res.json() 메서드를 주로 사용

 

Hello Express

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

app.get('/', function (req, res) {
  res.send('Hello Express!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

 

'Javascript' 카테고리의 다른 글

이벤트 복습하기  (0) 2022.01.09
map()과 forEach()차이  (0) 2022.01.07
Node.js - http모듈로 서버 만들기  (0) 2021.12.14
Node.js - 모듈/동기/비동기  (0) 2021.12.14
코어 자바스크립트 - 클래스  (0) 2021.11.18