Express에서의 Session 사용법
기초중의 기초이지만, 간혹 사용법이 헛갈릴때가 많아서 정리하였습니다.
요구사항
- ES6 문법을 기초로 이용
- Session을 이용한 로그인 관리
- Cluster를 이용가능 (pm2 등을 이용)
- login을 통해 얻어진 사용자 이름을 session에 저장.
- view는 모두 json을 이용
개발 환경 구성
yo generator
중에 generator-express
설치
npm install -g generator-express
특정 directory에서 yo express
실행하면 기본적인 express application이 구성됩니다. 구성된 폴더안에서 gulp default
를 실행하면 기본 port 3000번으로 application이 구동됩니다.
Application이 구동되지 않을때.
port 35729가 사용중일때 : gulp.liveload를 이용한 다른 application이 구동되고 있을 때, 발생되는 error. 두개의 application을 동시에 실행하고 싶은 경우에는
gulpfile.js
에서 liveload method에 port 번호를 명시.livereload.listen(60000);
config.root undefined가 될때.
config/config.js
가 정상적으로 로드되지 않은 경우.NODE_ENV
를development
,production
등으로 지정하지 않은 경우에 발생. 자신의NODE_ENV
를 확인후,NODE_ENV
에 맞게config.js
를 수정
추가 npm - express-session
, filestore
Session을 이용하기 위해서 express-session
설치합니다. 구 버젼을 기반으로한 책이나 blog에서는 이 과정이 나오지 않습니다. express의 middleware들은 대부분 npm module로 따로 분리가 되어 사용됩니다. express에 기본으로 들어가 있는 경우는 얼마 없습니다.
npm install express-session --save
babel-express-app@0.0.1 /home/ykyoon/dev/code/babel-express-app
└─┬ express-session@1.13.0
├── crc@3.4.0
└─┬ uid-safe@2.0.0
└── base64-url@1.2.1
npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.7
express.js
파일에 express-session
을 middleware로 등록합니다.
const session = require('express-session');
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
cookie: { secure: false }
}));
지정되는 parameter는 다음 의미를 갖습니다.
- secret: session의 암호화에 사용되는 key값입니다.
- resave: requrest가 요청되었을때, 기존의 session이 존재하는 경우 다시 저장할 필요가 있는지를 확인하는 option입니다.
express-session
에서 제공되는touch
를 구현하고 있는지를 확인해보면 됩니다. 기본적인MemoryStore
의 경우,touch
가 구현되어 있기 때문에 설정할 필요가 없습니다. - saveUninitialized: 설정하지 않는 경우, Session이 저장되지 않습니다. 일반적인 로그인을 구성할 때,
false
로 지정해줘야지 됩니다. 기본값은true
이며 모든 초기화되지 않은 session은 저장되게 됩니다. - cookie.secure:
https
로 호출되는 경우에만 session cookie를 생성하는 option입니다. 실 production에 유용한 option으로 테스트나 개인 공부를 할 때는false
로 지정해주시면 됩니다. - cookie.maxAge: cookie가 만료되는 시간을 설정합니다.
login url 구현
DB를 사용하지 않는 최소한의 application이기 때문에 사용자가 입력한 username을 그대로 session의 username으로 넣어주는 code를 구성합니다.
'use strict';
const express = require('express'),
router = express.Router();
router.get('/login', (req, res) => {
const session = req.session;
session.username = req.query.username;
return res.json(session);
});
module.exports = (app) => {
app.use('/user', router);
};
원래는 login의 경우, post로 구현해야지 되는 것이 원칙이지만, 테스트를 위한 application이고, browser에서 그대로 구현하기 위해서이니 그냥 get으로 구현하였습니다. 이제 저장된 username을 얻어내야지 됩니다. 이제 browser에서는 저장된 username이 계속 유지가 되어야지 됩니다.
router.get('/info', (req, res) => {
return res.json(req.session);
});
이제 url을 두개를 연달아 browser에서 실행하면 다음과 같은 결과를 볼 수 있습니다.
{
"cookie":{"originalMaxAge":null,"expires":null,"secure":false,"httpOnly":true,"path":"/"},
"username":"abcdef"
}
Session store의 변경
고성능, 고가용성을 구현하기 위해서는 기본적으로 nodejs는 cpu의 core 숫자와 동일한 process숫자로 실행되어야지 됩니다. 이 사실은 지금 application의 경우 심각한 문제를 가지고 있는 것을 의미합니다. process간의 memory 공유는 원칙적으로 되지 않는거니까요. (hacking이나 memory editor의 경우 다르겠지만, web application의 기본 기능과는 거리가 있는 상황이니.)
그래서, nodejs
application에서는 공용으로 사용되어야지 되는 정보는 file이나 redis, db와 같은 공용 IO에 저장해서 모든 process가 공유하는 형식으로 사용하게 됩니다. 또한, nodejs application은 application을 종료했다가 다시 올리는 경우가 왕왕 있습니다. express-session
의 기본값인 MemoryStore
는 기본적으로 production에 올릴수 없는 설정입니다.
성능은 안좋고, multiple instance에서는 절대로 사용할 수 없는 방법이지만, File에 session정보를 저장하기 위해서 FileStore를 이용해보도록 하겠습니다. FileStore와 Session간의 interface를 하는 session-file-store
를 설치하면 FileStore
가 같이 설치됩니다.
npm install session-file-store --save
babel-express-app@0.0.1 /home/ykyoon/dev/code/babel-express-app
├── filestore@0.1.3
└─┬ session-file-store@0.0.24
├── bagpipe@0.3.5
├─┬ fs-extra@0.26.5
│ ├── jsonfile@2.2.3
│ ├── klaw@1.1.3
│ └─┬ rimraf@2.5.2
│ └── glob@7.0.0
└── retry@0.8.0
FileStore를 Session에 설정합니다. 코드는 다음과 같습니다.
const session = require('express-session');
const FileStore = require('session-file-store')(session);
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
cookie: { secure: false },
store: new FileStore()
}));
설치후, folder를 보면 session
라는 folder가 생성되어 있는 것을 볼 수 있습니다. 이제 위에서 실행했던 URL을 다시 실행해보면 File이 하나 생성되어 있는 것을 볼 수 있습니다. 파일을 열어보면, session의 정보가 그대로 저장되어 있는 것을 볼 수 있습니다.
정리
express에서 session을 구성하는 방법에 대해서 간단히 알아봤습니다. 또한 MemoryStore
가 아닌 다른 Store를 이용하는 방법에 대해서도 간단히 알아 보았습니다. 실무에서는 대부분 redis를 이용하는 경우가 일반적이긴 하지만, 개발단에서 편하게 알아보기 위해서, File을 사용하는 경우도 꼭 나쁜 것은 아닙니다.