MERN 스택을 사용하는 프로젝트를 조금 더 최적화하기 위해 redis를 사용하기로 하였다. 다행히 서버를 호스팅해주는 Heroku에서 redis 기능도 지원해서 쉽게(?) 추가할 수 있었다.
다음 3가지 레퍼런스를 참고하여 Heroku에 redis를 추가하고 Nodejs와 연결하였다. 각 레퍼런스에 방법이 자세히 나와있으니 참고하면 좋다.
1. hsik0225님의 github: [Heroku] Redis 사용하기
2. npm: node-redis
3. Heroku Dev Center: Connecting to Heroku Redis
팁이 있다면,
먼저 localhost에서 redis에 값이 잘 저장되는지, 에러가 나지는 않는지 테스트를 먼저 해본 후 heroku redis에 연결하는 것을 추천한다. Heroku로 업로드하는데도 은근 시간이 걸리고 에러가 localhost에서 돌릴 때처럼 직관적으로 콘솔에 찍히지 않기 때문에 개인적으로 좀 불편하다고 느꼈다.
또한, 아래와 같은 command로 Heroku의 Redis에 접근할 수 있어서 실제로 값이 잘 저장되고 있는지 확인할 수 있다.
$ heroku redis:cli -a <app_name>
끝으로, 혹시 도움이 될까 싶어 우리 프로젝트에서 Heroku redis와 관련된 코드를 첨부한다.
node의 index.js
// localhost에서 redis를 띄울 때 사용 (localhost:6379)
// const redis_client = redis.createClient();
// Heroku에서 redis를 띄울 때 사용
const redis_client = redis.createClient({url: process.env.REDIS_URL});
redis_client.on('error', (err) => console.log('Redis Client Error', err));
await redis_client.connect();
// test용: redis에 임의의 값 set
await redis_client.set('key', 'value');
const value = await redis_client.get('key');
console.log(value);
// 다른 파일에서도 redis_client를 사용하기 위해 export
export default redis_client;
node의 controller
import PostSelection from "../models/postSelection.js";
import redis_client from "../index.js";
// count값을 구하는 함수
export const getCount = async (req, res) => {
try {
// redis에 key가 count인 값이 있는지 확인
const data = await redis_client.get('count');
// 있다면 value를 response로 보내기
if (data != null) {
console.log("Get the count value in redis!");
res.status(200).json(parseInt(data) + 1);
} else { // 없다면 db에서 값 불러오기
try {
const count = await PostSelection.find().count();
// 200: OK
res.status(200).json(count);
console.log("GET count DONE! : ", count);
// redis에 count값 저장
await redis_client.set('count', count);
console.log("Save the count value in redis!");
} catch (error) {
// 404: Not Found
res.status(404).json({ message: error.message });
console.log(error.message);
}
}
} catch (error) {
// 404: Not Found
res.status(404).json({ message: error.message });
console.log(error.message);
}
}
// post를 db에 저장하는 함수
export const createPosts = async (req, res) => {
const post = req.body;
const newPost = new PostSelection(post);
try {
await newPost.save();
// 201: created
res.status(201).json(newPost);
console.log("POST DONE!");
// redis에 key가 count인 값이 있다면 count + 1로 업데이트 해준다 (본 함수는 post가 하나 추가되는 함수이기 때문)
try {
const count = await redis_client.get('count');
if (count != null) {
await redis_client.set('count', parseInt(count) + 1);
console.log("Update count in redis!", parseInt(count) + 1);
}
} catch (error) {
// 404: Not Found
res.status(404).json({ message: "Couldn't get the redis value when create the post. " + error.message });
console.log(error.message);
}
} catch (error) {
// 409: Conflict
res.status(409).json({ message: error.message });
console.log(error.message);
}
}