HTTP 요청에 대하여 라우팅 및 미들웨어 기능을 제공하는 웹 프레임워크(서버 구축을 위한 프레임워크)
npm install express --save
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 app.js
하지만 이런 경우 코드를 수정할때마다 서버를 내렸다 올렸다를 반복해야 되는데, 번거로운 과정을 생략할 수 있는 좋은 패키지가 하나 있다! 바로 nodemon이다.
// nodemon 설치 명령어
npm i -g nodemon
nodemon을 설치한 후 실행하면 소스코드가 바뀔때마다 자동으로 서버가 재시작되어 매우 편리하다.
핵심 서버 역할. 주로 미들웨어가 위치한다.
var app = express(); // express 패키지를 호출하여 app 변수 객체 생성
app.set() 메서드: 익스프레스 앱 설정
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use() 메서드: 미들웨어 연결
/* 주요 미들웨어 */
app.use(logger('dev')); // morgan: 요청 정보를 콘솔에 기록
app.use(express.json()); // 요청 들어온 본문을 JSON으로 해석
app.use(express.urlencoded({ extended: false })); // 요청 들어온 본문을 querystring을 사용하여 해석
app.use(cookieParser()); // cookie-parser: 요청에 동봉된 쿠키 해석
app.use(express.static(path.join(__dirname, 'public'))); // 정적 파일이 담긴 폴더 설정
/* 라우팅 미들웨어 */
app.use('/', indexRouter);
app.use('/users', usersRouter);
/* 404(Not Found) 처리 미들웨어 */
app.use(function(req, res, next) {
next(createError(404));
});
/* 에러 처리 미들웨어 */
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
// bin/www 파일에서 사용하기 위한 app 객체 모듈화
module.exports = app;
http 모듈에 express 모듈 연결 및 접속 포트 지정
var app = require('../app');
var debug = require('debug')('learn-express:server'); // 콘솔에 로그를 남기는 모듈
var http = require('http');
// process.env(환경변수) 객체에 PORT 속성이 있다면 이것을, 없으면 3000번 포트 사용
var port = normalizePort(process.env.PORT || '3000');
// 서버가 실행될 포트 설정
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('error', onError); // 이벤트 등록
server.on('listening', onListening);
// ...
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
/* 커스텀 미들웨어 적용 */
app.use(function (req, res, next) {
console.log(req.url, '안녕요?ㅎ');
next();
});
/* morgan 미들웨어: 요청 정보를 콘솔에 기록 */
app.use(logger('dev'));
// ...
가독성이 좋지 않게 되지만 하나의 use에 여러 개의 미들웨어를 장착할 수 있음.
app.use('/', function (req, res, next) {
console.log('첫 번째 미들웨어');
next();
}, function (req, res, next) {
console.log('두 번째 미들웨어');
next();
}, function (req, res, next) {
console.log('세 번째 미들웨어');
next();
});
/*** app.js ***/
// ...
var logger = require('morgan');
// ...
app.use(logger('dev')); // 주요 인자: dev, short, common, combined 등
// ...
/*** app.js ***/
var express = require('express');
/* Express 4.16.0 버전 이후 내장된 body-parser 부분 */
app.use(express.json());
// app.use(bodyParser.raw()); // 본문이 버퍼 데이터일때 해석
// app.use(bodyParser.text()); // 본문이 텍스트 데이터일때 해석
app.use(express.urlencoded({ extended: false })); // false: querystring 모듈 사용, true: qs 모듈(querystring을 확장한 모듈) 사용
/* 위의 코드 작동 예시 */
// JSON 형식으로 { name: 'pengsu', study: 'nodejs' }를 본문으로 보낸다면 req.body 객체에 그대로 들어감
// URL-encoded 형식으로 name=pengsu&study=nodejs를 보낸다면 req.body 객체에 { name: 'ing-yeo', study: 'nodejs' }가 들어감
/*** app.js ***/
// 정적 파일을 제공하는 폴더를 public 폴더로 지정 (/public/abc.png -> abc.png)
app.use(express.static(path.join(__dirname, 'public')));
// public 폴더 경로를 img로 지정 (/public/abc.png => /img/abc.png)
app.use('/img', express.static(path.join(__dirname, 'public')));
라우팅 미들웨어는 첫 번째 인자로 주소를 받아서 특정 주소에 해당하는 요청이 왔을 때만 동작
app.use('/', function (req, res, next) {
console.log('/ 주소의 요청일 때 실행됩니다. HTTP 메서드는 상관 없습니다.');
next();
});
app.use('/', function (req, res, next) {
console.log('/ 주소의 요청일 때 실행됩니다. HTTP 메서드는 상관 없습니다.');
next();
});
app.get('/', function (req, res, next) {
console.log('GET 메서드 / 주소의 요청일 때만 실행됩니다.');
next();
});
app.post('/data', function (req, res, next) {
console.log('POST 메서드 /data 주소의 요청일 때만 실행됩니다.');
next();
});
router 객체를 만든 후 app.js 파일에서 이들을 미들웨어로 사용하여 라우팅
/*** app.js ***/
// ...
// routes 폴더에 있는 js 파일(router 객체)을 require
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
// ...
// ...
// 주소가 /로 시작하면 routes/index.js를 호출
app.use('/', indexRouter);
// 주소가 /users로 시작하면 routes/users.js를 호출
app.use('/users', usersRouter);
// ...
/*** routes/index.js ***/
var express = require('express');
var router = express.Router(); // router 객체 생성
// '/' 주소로 GET 요청 시 살행
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router; // 라우터 모듈화
/*** routes/users.js ***/
var express = require('express');
var router = express.Router();
// '/users' 주소로 GET 요청 시 실행
router.get('/', function (req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
router 하나에 여러 개의 미들웨어를 여러 개 장착할 수 있음
router.get('/', middleWare1, middleWare2, middleWare3);
라우터에 연결된 나머지 미들웨어들을 건너뛸 때: next('route') 메서드 사용
router.get('/', function(req, res, next) {
next('route'); // 연결된 미들웨어들을 건너뜀
}, function(req, res, next) {
console.log('실행되지 않습니다.');
next();
}, function(req, res, next) {
console.log('실행되지 않습니다.');
next();
});