http 모듈로 웹 서버를 만들 때 코드가 보기 좋지 않고, 확장성도 떨어진다. 이런 불편 사항을 해결해주는 대표적인 웹 서버 프레임워크가 익스프레스이다
1. 익스프레스 프로젝트 시작하기
익스프레스 프로젝트 먼저 package.json을 제일 먼저 생성해야 한다.
package.json
{
"name": "learn-express",
"version": "0.0.1",
"description": "익스프레스를 배우자",
"main": "add.js",
"scripts": {
"start": "nodemon app"
},
"author": "newjeans",
"license": "MIT",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^2.0.22"
}
}
$ npm i express
$ npm i -D nodemon
nodemon app을 하면 app.js를 nodemon으로 실행한다는 뜻이다.
nodemon는 서버 코드에 수정 사항이 생길 때마다 매번 서버를 재시작 해주는 모듈이다. nodemon은 개발용으로 사용하기 좋은 모듈로, 배포 후에는 서버 코드가 빈번하게 변경될 일이 없으므로 사용하지 않아도 된다.
app.js
const express = require('express');
const app = express();
app.set('port', process.env.PORT || 3000);
app.get('/', (req, res) => {
res.send('Hello, Express');
/*
문자열 대신 HTML로 응답할 땐 sendFile메서드 사용
res.sendFile(path.join(__dirname, '/index.html'));
*/
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중');
});
Express 모듈을 실행해 app 변수에 할당한다.
app.set('port', 포트)로 서버가 실행될 포트를 설정한다. process.env객체에 PORT속성이 있따면 그 값을 사용하고, 없다면 기본값으로 3000번 포트를 이용한다.
app.set으로 데이터를 저장하고, app.get으로 데이터를 가져온다.
2. 자주사용하는 미들웨어
미들웨어(middelware) : 요청과 응답 중간에 위치하기 때문에 미들웨어라고 부른다. 요청과 응답을 조작해 기능을 추가하기도 하고, 나쁜 요청을 걸러내기도 한다.
미들웨어는 app.use와 함께 사용된다
app.js
const express = require('express');
const path = require('path')
const app = express();
app.set('port', process.env.PORT || 3000);
// 미들웨어는 next를 적어줘야 다음 라우터로 넘어간다
app.use((req, res, next) => {
console.log('모든 요청에 실행하고 싶어요');
next();
})
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.post('/', (req, res) => {
res.send('hello express');
});
app.get('/', (req, res) => {
res.send('hello express');
})
app.get('/category/Javascript1', (req, res) => {
res.send(`hello Javascript1`);
})
// 라우트 매개변수 사용해서 매개변수를 받아오는 방법으로 카테고리별로 불러올 수 있다
app.get('/category/:name', (req, res) => {
res.send(`hello wildcard`);
})
// 노드는 순서대로 실행이 되어서 자바스크립트2 라우터를 실행시키려면 자바스크립트1처럼 라우트매개변수 위에 위치시켜야한다
app.get('/category/Javascript2', (req, res) => {
res.send(`hello Javascript2`);
})
app.listen(3000, () => {
console.log('익스프레스 서버 실행');
});
app.use에 매개변수가 req, res, next인 함수를 넣으면 된다.
익스프레스는 기본적으로 위 > 아래로 실행하지만, 미들웨어는 next를 해줘야 다음으로 넘어간다.
라우터는 기본적으로 위에서 아래로 실행이 되기때문에 /:name을 이용해서 매개변수를 받아오는 방법을 사용하면 특정위치를 지정하고 싶을때 위치를 신경써야 한다.
위의 코드에서 Javascript1은 라우트매개변수 위에 위치해 있어서 실행이 된다
하지만 Javascipt2는 라우터매개변수 아래에 있기 때문에 모든 category/ 뒤에 오는 것들은 wildcard로 연결된다.
미들웨어가 실행되는 경우
app.use(미들웨어) | 모든 요청에서 미들웨어 실행 |
app.use('/abc', 미들웨어) | abc로 시작하는 요청에서 미들웨어 실행 |
app.post('/abc', 미들웨어) | abc로 시작하는 POST 요청에서 미들웨어 실행 |
실무에 자주 사용되는 패키지는 morgan, static, body-parser, cookie-parser, express-session, multer이다.
app.js를 아래와 같이 추가해보자.
app.js
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');
dotenv.config();
const app = express();
app.set('port', process.env.PORT || 3000);
app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
name: 'session-cookie',
}));
app.use((req,res,next) => {
console.log('모든 요청에 다 실행됩니다.');
next();
});
app.get('/', (req, res, next) => {
console.log('GET / 요청에서만 실행됩니다.');
next();
}, (req, res) => {
throw new Error('에러는 에러 처리 미들웨어로 갑니다.')
});
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send(err.message);
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중');
});
1) morgan
morgan 연결후 localhost:3000에 접속하면 추가적인 로그를 확인할 수 있다.
맨 마지막 줄의 GET / 500 9.277 ms - 50 ([HTTP메서드] [주소] [HTTP 상태 코드] [응답 속도] - [응답 바이트]) 로그가 morgan 미들웨어에서 나오는 것이다.
요청과 응답에 대한 정보를 콘솔에 기록한다.
사용법
// 요청과 응답을 나타냄 (dev는 개발시, combined는 배포시-좀더 자세하게 기록됨)
app.use(morgan('dev'));
2) static
static 미들웨어는 정적인 파일들을 제공하는 라우터 역할을 한다.
기본적으로 제공되기 때문에 따로 설치할 필요 없이 express 객체 안에서 사용하면 된다.
사용법
app.use('요청 경로', express.static('실제 경로'));
app.use('/', express.static(path.join(__dirname, 'public')));
함수의 인수로 정적 파일들이 담겨 있는 폴더를 지정하면 된다. 현재는 public을 지정해 놨다.
예를 들어 public/stylesheets/style.css 는 http://localhost:300/stylesheets/style.css로 접근할 수 있다.
app.use(
morgan('dev'),
// 정적파일이 빨리 검색될 수 있도록 morgan 다음 위치를 시킴
express.static('/', path.join(__dirname, 'public')),
express.json(),
express.urlencoded({ extended : false }),
cookieParser(process.env.COOKIE_SECRET),
);
static은 정적 파일을 알아서 제공해주므로 위의 코드에서 static 미들웨어에서 파일을 찾으면 next를 호출 하지 않으므로 json, urlencoded, cookieParser는 실행되지 않는다.
3) body-parser
요청의 본문에 있는 데이터를 해석해서 req.body 객체로 만들어주는 미들웨어이다.
보통 폼 데이터나 AJAX 요청의 데이터를 처리한다. 단, 멀티파트(이미지, 동영상, 파일)은 처리하지 못하므로 multer 모듈을 사용해야한다.
사용법
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
body-parser는 JSON과 URL-encoded형식 외에 Raw, Text형식의 데이터를 추가로 해석할 수 있다.
Raw는 요청의 본문이 버퍼 데이터일 때, Text는 텍스트 데이터일 때 해석하는 미들웨어이다. 버퍼나 텍스트 요청을 처리할 필요가 있다면 body-parser를 설치한후 추가 해야한다.
npm i body-parser 로 body-parser 설치
const bodyParser = require('body-parser');
app.use(bodyParser.raw());
app.use(bodyParser.text());
4) cookie-parser
cookie-parser는 요청 헤더의 쿠키를 해석해 req.cookies 객체로 만든다
사용법
app.use(cookieParser(비밀키));
해석된 쿠키들은 req.cookies 객체에 들어간다.
비밀키로 쿠키 뒤에 서명을 붙여 내 서버가 만든 쿠키임을 검증할 수 있다.
실제 쿠키 옵션들을 넣을 수 있다.
-> expires, domain, httpOnly, maxAge, path, secure, sameSite 등, 지울 때는 clearCookie로 (expires와 maxAge를 제외한 옵션들이 일치해야 한다)
5) express-session
세션 관리용 미들웨어이다.
로그인 등의 이유로 세션을 구현하거나 특정 사용자를 위한 데이터를 임시적으로 저장해둘 때 매우 유용하다.
세션은 사용자 별로 req.session 객체 안에 유지된다.
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
name: 'session-cookie',
}));
express-session은 인수로 세션에 대한 설정을 받는다.
resave : 요청이 올 때 세션에 수정 사항이 생기지 않더라도 세션을 다시 저장할지 설정
saveUninitialized : 세션에 저장할 내역이 없더라도 처음부터 세션을 생성할지 설정
6) 미들웨어의 특성 활용하기
app.use((req, res, next) => {
console.log('모든 요청에 다 실행됩니다.');
next();
});
미들웨어는 req, res, next를 매개변수로 갖는 함수로서 app.use나 app.get, app.post 등으로 장착한다. 특정한 주소의 요청에만 미들웨어가 실행되게 하려면 첫번째 인수로 주소를 넣으면 된다.
app.use(
morgan('dev'),
express.static('/', path.join(__dirname, 'public')),
express.json(),
express.urlencoded({ extended : false }),
cookieParser(process.env.COOKIE_SECRET),
);
위와 같이 동시에 여러개의 미들웨어를 장착할 수도 있으며, 다음으로 넘어가려면 next함수를 호출해야한다.
next함수를 호출하지 않는 미들웨어는 res.send나 res.sendFile 등의 메서드로 응답을 보내야한다.
express.static과 같은 미들웨어는 정적 파일을 제공할 때 next 대신 res.sendFile메서드로 응답을 보낸다. 미들웨어는 장착 순서에 따라 어떤 미들웨어는 실행 되지 않을 수 있다.
7) 미들웨어 확장법
app.use('/', (req, res, next) => {
if (req.session.id) {
express.static(__dirname, 'public')(req, res, next)
} else {
next();
}
});
미들웨어 안에 미들웨어를 넣으면 확장이 될 수 있다. (req, res, next)를 붙여서 확장할 수 있는데, 해당 방법은 cors같은 경우에도 이용이 되니까 잘 알아두자!
참고 : ⌜node.js 교과서⌟ 책을 공부하며 요약・정리한 내용입니다.
'💻 Web_Back end > node.js' 카테고리의 다른 글
[node.js] 라우터 (0) | 2023.06.22 |
---|---|
[node.js] 시퀄라이즈 (Sequelize) 사용하기 (0) | 2023.05.12 |
[node.js] npm (0) | 2023.05.11 |
[node.js] 쿠키와 세션 (0) | 2023.05.10 |
[node.js] http 모듈로 서버 만들기 (0) | 2023.05.10 |