express Redis 연동
express와 Redis를 연동하는 방법
요약
Key-Value형식의 NoSQL의 장점을 활용하여 데이터 검색이 빈번한 SessionID를 저장하는 db를 구현하다.
Mac Redis 설치, 운용
설치하기
1. 설치
brew install redis
sudo apt-get install redis-server
2. 버전확인
redis-server --version
3. 비밀번호 설정
apt-get설치 :/etc/redis/redis.conf 경로 Homebrew를 통해 설치:/opt/homebrew/etc/redis.conf
require your_redis_password 부분 주석제거하고 설정
4. ACL설정
Redis 6.0 이후 버전에서 ACL(Access Control Lists) 기능이 도입
# 기본 사용자 비활성화
user default off
# 읽기 전용 사용자
user readOnlyUser on >password1 ~* +@read
# 읽기/쓰기 사용자
user readWriteUser on >password2 ~* +@all
실행하기
3. Redis 백그라운드 실행(launchd이용)
brew services start redis
sudo service redis-server start
3-1. 일반적인 포그라운드 실행은
redis-server
클라언트 접속하기
redis-cli
운용하기
1. 재실행
brew services restart redis
sudo service redis-server restart
2. 중지
brew services stop redis
3. 삭제
brew uninstall redis
4. 데이터 저장
set KEY VALUE
5. 데이터 조회
get KEY
6. 키 조회
keys PATTERN
7. 데이터 삭제
del KEY
express에서 redis 사용하기
패키지 설치
npm install connect-redis redis
서버 설정
- app.js
const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');
const { v4: uuidv4 } = require('uuid');
const app = express();
const port = 3000;
// Redis 클라이언트 설정
const redisClient = redis.createClient({
host: 'localhost',
port: 6379
});
redisClient.on('error', (err) => {
console.error('Redis error: ', err);
});
// 세션 설정
app.use(session({
genid: (req) => {
return uuidv4(); // 세션 ID로 UUID 생성
},
store: new RedisStore({ client: redisClient }),
secret: 'your-secret-key', // 강력한 비밀 키 사용
resave: false,
saveUninitialized: false,
cookie: { secure: false } // HTTPS를 사용할 경우 true로 설정
}));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
- 사용방법
// 라우트 설정
app.get('/', (req, res) => {
res.send('Welcome to the Node.js Redis session example');
});
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 간단한 인증 로직 (예: 사용자 이름이 "admin"이고 비밀번호가 "password"인 경우 인증 성공)
if (username === 'admin' && password === 'password') {
req.session.user = { username }; // 세션에 사용자 정보 저장
res.send('Login successful');
} else {
res.status(401).send('Invalid credentials');
}
});
app.get('/protected', (req, res) => {
if (req.session.user) {
res.send(`Hello ${req.session.user.username}, you are authenticated`);
} else {
res.status(401).send('You are not authenticated');
}
});
app.post('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.status(500).send('Could not log out.');
} else {
res.send('Logout successful');
}
});
});
- ACL 적용
// 읽기/쓰기 Redis 클라이언트 설정
const readWriteClient = redis.createClient({
host: 'localhost',
port: 6379,
username: 'readWriteUser', // 설정한 사용자 이름
password: 'password2' // 설정한 비밀번호
});
readWriteClient.on('error', (err) => {
console.error('Redis error (read-write): ', err);
});
// 세션 설정
app.use(session({
genid: (req) => {
return uuidv4(); // 세션 ID로 UUID 생성
},
store: new RedisStore({ client: readWriteClient }), // 세션 저장은 읽기/쓰기 클라이언트 사용
secret: 'your-secret-key', // 강력한 비밀 키 사용
resave: false,
saveUninitialized: false,
cookie: { secure: false } // HTTPS를 사용할 경우 true로 설정
}));
추가: 오류 해결
redis ver6.X부터 새로운 마이그레이션이 등장하여 오류가 발생했다.
제일 큰 변경사항은 아래의 1번과 2번입니다.
더이상 redis client의 lagacy 모드를 지원하지 않습니다. 타입스크립트 코드 기반으로 재작성되어 더이상 기존 @types/connect-redis를 사용하지 않습니다. 빌드는 이제 CJS와 ESM을 모두 지원합니다. 노드 14에 대한 지원이 제거되었습니다.
그러므로 RedisStore 초기화는 더 이상 express-session을 사용하지 않는다. 별도의 RedisStore 초기화 과정없이 바로 import된 RedisStore를 사용하면 된다.
// 기존
const RedisStore = require("connect-redis")(sessions);
// 현재
const RedisStore = require("connect-redis").default;
접근방법: redis-cli -h localhost -p 6379 -a “Tunnel325?” -u Decide4Me
redis-cli auth Decide4Me Tunnel325?
주의 현재(2024.06.14) nodejs에는 Redis ACL의 client name을 지원하는 모듈이 없다. 그러므로 디폴트 유저로만 접근 가능하다. 디폴트 유저에 비밀번호 설정되는것에 만족하자 참조: https://stackoverflow.com/questions/63432302/connecting-to-managed-redis-with-auth-username-password-nodejs
express-session은 connect.sid라는 이름의 쿠키를 사용