헬창 개발자
express 미들웨어 본문
미들웨어란?
미들웨어는 주춧돌처럼 중간 작업을 해주는 역할이다. 즉, 요청과 응답 사이에 express 자체에 있는 기능 외에 추가적인 기능을 넣어줄 수 있다. express 자체 미들웨어를 사용해도 되고 다른 사람이 만들어 놓은 미들웨어 npm을 통해 다운받아 사용해도 된다.
미들웨어 사용 메서드는 app.use(), app.set()이 있다.
둘의 차이점은 전자는 지역 후자는 전역으로 사용된다는 점이다.
코드를 보면서 이해해 보자
- app.use() 미들웨어 메소드
const express = require('express');
const app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
const myLogger = function (req, res) {
console.log('LOGGED');
};
app.use(myLogger);
app.listen(8080);
위 코드는 서버가 요청을 받을 때마다 ‘LOGGED’라는 메시지를 출력하는 것이다.
myLogger라는 미들웨어를 만들어 주었고 app.use()를 사용해 미들웨어를 붙어주었다. 이렇게 되면 요청이 들어올 때마다 myLogger를 반드시 거치게 된다.
여기서 요청은 ‘/’ 주소를 get했을때, 즉 localhost:8080/에 접속했을 때를 말한다.
하지만 접속하는 횟수만큼 콘솔 화면에 출력이 되지않는다 그 이유는 아래코드를 살펴보자
- app.set() 미들웨어 메소드
const express = require('express');
const app = express();
app.get('/', function (req, res, next) {
res.send('Hello World!');
next();
});
const myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};
app.use(myLogger);
app.listen(8080);
위 코드와 다른점은 next()함수를 추가했다는 점이다.
이번에는 접속 요청이 들어때마다 콘솔에 ‘LOGGED’을 출력한다.
미들웨어는 위에서 아래로 실행되기 때문에 순서가 중요하다.
먼저 app.get(’/’)이 수행되고 res.send()가 끝나고 응답을 종료해버리기 때문에 myLogger까지 도달하지 않았다.
next()는 다음 미들웨어로 넘어가는 역할을 하기 때문에 순서를 잘 배치를 해주고 next()를 통해 흐름을 잘 제어해줘야 한다.
- 오류 처리를 위한 미들웨어 함수
const express = require('express');
const app = express();
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(3000);
이번에는 오류 처리를 위한 미들웨어 함수를 알아볼것이다. 이 함수는 총 4개의 파라미터 erro, req, res, next를 갖는다. 오류는 오류 처리 미들웨어에서 따로 다뤄야한다. 보통 express로 서버를 만들 때 다음과 같은 순서로 구조를 짜게 된다.
- express를 불러온다.
- 포트를 설정해준다.
- 공통적으로 사용하는 미들웨어를 장착해준다.
- 라우터를 구성한다.
- 404 처리 미들웨어를 구성한다.
- 오류 처리 미들웨어를 구성한다.
- 생성된 서버가 포트를 리스닝한다.
자주 사용하는 미들웨어
express.static
서버의 응답을 할 때 html 파일만 필요한 것은 아니다. js, css, img 등 다양한 종류의 파일이 필요할것이다. 예를 들어 이미지 파일을 html 내에 띄우고 싶어서 html. 파일에 이미지를 삽입하면 어떻게 될까?
실제 브라우저에서는 이미자가 보이지가 않는다. 그 이유는 html파일은 이미지 파일이 어디있는지 모르기 때문이다. 아무리 이미지 파일의 경로를 쓴다 하더라도 Node.js 자체를 서버에 올리기 때문에 서버에 맞게 설정을 해줘야한다.
- static 미들웨어 사용
const express = require('express');
const app = express();
app.set('port', process.env.PORT || 8080);
app.use(express.static(__dirname + '/public'));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index2.html');
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 서버 실행 중 ..')
});
static은 express 안에 기본적으로 포함되어있기 때문에 별도의 설치 없이 꺼내서 사용하면 된다. static() 안에 폴더로 지정해 줄 파일의 경로를 입력하자 필자는 public 이라는 폴더를 생성해서 지정해 주었다.
static 폴더를 따로 지정해주면 지정한 파일이 바로 클라이언트로 가는 것이 아닌 static 미들웨어를 거친 후 도착하게 된다.
웹 페이지에 띄우고 싶은 이미지 파일을 public 폴더에 저장한 후 index2.html에 이미지를 추가한다.
<!-- index2.html -->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>express로 웹 만들기</title>
</head>
<body>
<h2>express로 웹 만들기</h2>
<p>메인 페이지 입니다.</p>
<img src="./sample.png" />
</body>
</html>
그러면 이렇게 html 파일 내에 public/ 이라는 경로를 따로 명시해주지 않아도 자동으로 서버에서 static 폴더에서 해당 파일을 찾은 후 띄워주게 된다.
또한 경로를 다 볼 수 없으니 보안에도 도움이 된다.
route
클라이언트로부터 요청이 왔을 때 서버에서 어떤 응답을 보내주어야 할지 결정해준다. route는 localhost:8080/요청 이 들어오면 index.html을 보내라는 역할을 담당한다. express에서 router는 app.get, app.post, app.use등 모듈을 담은 변수 뒤에 http 메서드가 붙은 것인데 이를 이용해 요청이 들어오는 경로와 응답을 만들 수 있다.
- http 요청 메서드의 종류와 내용
GET | /join | join.html 파일을 송신합니다. |
POST | /user | 사용자를 등록합니다. |
PUT | /user/user_id | user_id를 가진 사용자의 정보를 수정합니다. |
DELETE | /user/user_id | user_id를 가진 사용자의 정보를 삭제합니다. |
- 사용 예시
app.get("/user/:id", function (req, res){
res.send("user id: " + req.params.id);
});
get 메서드로 /user/1 이라는 URL 요청이 들어왔다고 생각해보자 이 요청에 대한 응답으로 req.params.id에 접근하여 얻은 고객의 아이디를 문자열로 보내게 된다.
morgan
const logger = require('morgan');
app.use(logger('combine'));
//:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
morgan은 request와 response를 깔끔하게 포매팅해주어 콘솔로 로그를 찍는 역할을 한다. 호출된 route가 어떤 상태이고 어떤 결과 값인지를 보여준다.
express.json, express.urlencoded
app.use(express.json());
app.use(express.urlencoded({ extended: true}));
클라이언트에서 post, put 요청 시 들어온 정보를 가진 req.body에 접근하기 위해 필요한 미들웨어이다.
요청 정보가 url에 들어온 것이 아니라 request.body에 들어있는데 이값을 읽을 수 있는 구문으로 파싱하고 req.body로 옮겨주는 역할을 한다.
cookie-parser
cookie-parser를 알아보기 전에 쿠키cookie와 세션session에 대해 알아 보자
클라이언트가 요청을 보낼 때마다 키-쌍으로 이우어진 쿠키를 보내고 서버에서는 클라이언트가 보낸 쿠키를 읽어 사용자가 누구인지를 식별하게 된다.
우리가 보안이 필요한건 문에 들어갈 때 출입증이 있어야만 게이트를 통과할 수 있는 것 처럼 쿠키는 그 출입증 같은 역할을 하는 존재이다.
- 쿠키 전달
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, { 'Set-cookie': 'name=roadbook' });
console.log(req.headers.cookie);
res.end('Cookie --> Header');
})
.listen(8080, () => {
console.log('8080포트에서 서버 연결 중 ..');
});
처음에 한 번만 서버에서 res.writeHead() 메서드를 통해 ‘Set-cookie’에 값을 넣어준다. 그러면 브라우저에 키-쌍으로 이루어진 쿠키가 헤더에 저장됩니다. 이렇게 한번 설정되고 난 후에는 브라우저에서 자동으로 쿠키를 매번 요청할 때마다 서버에게 보내게된다.
크롬 브라우저를 통해 Response Headers를 확인하면 해당 쿠키가 잘 전달된것을 확인할 수 있다.
해당 쿠키는 브라우저를 끄기 전까지 요청을 보낼 때마다 해당 쿠키 값도 같이 보내주게 된다.
브라우저를 끄기 전까지만 쿠기가 살아있는 이유는 쿠키의 expire를 지정해주지 않았기 때문에 기본 값으로 브라우저를 끄게 되면 쿠기값이 없어지는 것이다.
클라이언트가 쿠기와 함께 요청을 보내면 req.headers.cookie를 통해 쿠기 값에 접근을 할 수 있게 되는데 이때 req.headers.cookie에 저장된 값은 문자열인데 이를 자바스크립트에서 사용하기 위해서는 객체로 파싱하는 과정이 필요하다.
Cookie-paser를 사용하면 express의 req객체에 cookies 속성이 부여되므로 res.cookies.쿠키명을 통해 쿠키 값에 접근이 가능하다.
express-session
쿠키만 사용하게 되면 브라우저에서 쿠키 값을 확인할 수도 있고 값을 변경할 수도 있게 된다.
따라서 실제 정보는 서버에만 저장해두고 브라우저에는 암호화된 키 값만 보내고 그 키 값으로 실제 값에 접근할 수 있도록 하는 것을 세션이라고 한다.
- 세션을 통한 키 값 생성
const http = require('http');
const session = {};
const sessKey = new Date();
session[sessKey] = { name: 'roadbook' };
http.createServer((req, res) => {
res.writeHead(200, { 'Set-cookie': `session=${sessKey}` });
res.end('Session-Cookie --> Header');
})
.listen(8080, () => {
console.log('8080포트에서 서버 연결 중 ..');
});
세션 저장용 객체 하나를 session이라는 변수에 생성하고 키 값을 sessKey라는 변수에 생성한다.
session 객체에 sessKey라는 키 값을 지정해주고 값을 { name: 'roadbook' }으로 할당해준다.
그리고 앞서와 같이 쿠키 값을 바로 보내는것이 아닌 세션 값으로 생성한 키 값을 넣어준다.
브라우저를 통해 확인해 보면 쿠키 값이 바로 뜨는 것이 아니라 세션 값이 보여지게 된다.
이러한 세션을 다루기 위해서는 express-session을 사용해 req 객체에 session 속성이 부여되어 req.session을 통해 접근할 수 있다.
'공부방' 카테고리의 다른 글
Node.js를 이용한 웹파싱 (0) | 2022.09.01 |
---|---|
API???????? (3) | 2022.08.21 |
express 모듈을 사용해 서버 만들기 (1) | 2022.08.18 |
npm 명령어와 node.js 모듈의 관하여 (0) | 2022.08.17 |
자바스크립트 동기/비동기 부셔버리기 (0) | 2022.08.12 |