일반적으로 express-session에서의 세션은 휘발성 인메모리 데이터베이스에 잠깐 저장되고 서버가 종료되면 사라지게 된다.
이때 redis db서버를 사용하여 세션관리를 하면 서버가 꺼져도 데이터가 유지되게 할수 있으며, 복수 서버 환경(클러스터링)에서도 세션을 공유할 수 있게 된다.
Connect-redis 설치 & 사용법
connect-redis는 멀티 프로세스 간 세션 공유를 위해 레디스와 익스프레스를 연결해주는 패키지이다.
기존에는 로그인할 때 express-session의 세션 아이디와 실제 사용자 정보가 서버 메모리에 저장된다.
싱글 서버를 사용할땐 문제가 없지만 pm2를 통해 노드 클러스터 서버 인프라를 구축했을때 세션 불일치 문제가 생긴다.
따라서 세션 불일치를 해결하기 위해 이 세션 데이터를 서버 메모리가 아닌 redis db에 저장하도록 코드를 구현해보자.
const express = require('express');
const cookieParser = require('cookie-parser');
const dotenv = require('dotenv');
const session = require('express-session');
const redis = require('redis');
const RedisStore = require('connect-redis')(session); // express-session 객체를 넣는다.
dotenv.config(); // env환경변수 파일 가져오기
const app = express();
//* Redis 연결
// redis[s]://[[username][:password]@][host][:port][/db-number]
const redisClient = redis.createClient({
url: `redis://${process.env.REDIS_USERNAME}:${process.env.REDIS_PASSWORD}@${process.env.REDIS_HOST}:${process.env.REDIS_PORT}/0`,
legacyMode: true, // 반드시 설정 !! 설정 안하면 connect-redis 동작 안함
});
redisClient.on('connect', () => {
console.info('Redis connected!');
});
redisClient.on('error', (err) => {
console.error('Redis Client Error', err);
});
redisClient.connect().then(); // redis v4 연결 (비동기)
const redisCli = redisClient.v4; // 기본 redisClient 객체는 콜백기반인데 v4버젼은 프로미스 기반이라 사용
//* 세션 쿠키 미들웨어
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
resave: false,
saveUninitialized: true,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
store: new RedisStore({ client: redisClient, prefix: 'session:' }), // 세션 데이터를 로컬 서버 메모리가 아닌 redis db에 저장하도록 등록
};
app.use(session(sessionOption));
Tip
createClient({ legacyMode: true })로 레거시 모드를 설정하지 않으면 connect-redis 모듈이 동작 안하니 주의
sessionOption.store는 세션을 어디에 저장할지 고르는 옵션 정보로, 기본값은 서버의 메모리 스토리지에 저장하는데, 이것을 RedisStore로 바꾸게 되면 세션 데이터를 Redis에 저장하게 된다.
즉, 재기동을 하여도 세션이 날라가는 문제가 발생하지 않도록 처리해줄 수 있다.
이제 서버를 실행해보고 개발자 도구의 Application 탭에 cookies 탭을 확인하면 다음과 같이 connect.sid 로 세션 쿠키가 서명되어 저장되어 있는 것을 볼 수 있다.
그리고 redis db를 확인해 보면 다음과 같이session:세션ID형태로 키가 저장 됨을 확인 할 수 있다.
값을 조회해 보면 세션 쿠키 객체가 문자열 형태로 들어있는 것을 확인 할 수 있다.
사진에서 session: 이 두개인 이유는 서로 다른 사용자가 사이트를 접속했기에 사용자 세션 두개가 redis에 저장된 것이다.
Tip
Node API 서버를 구축할때 사람들이 많이 들 쓰는 api 사용량을 제한하는 패키지 'express-rate-limit' 역시 사용량을 서버 메모리에 기록하므로 서버를 재시작하거나 다른 서버로 로드밸런싱 하면 사용량 기록이 초기화되게 된다. 따라서 이것도 redis에 기록하는 것이 좋다. express-rate-limit 패키지와 rate-limit-redis 패키지를 같이 사용하면 된다.