일반적으로 요청-응답 시 데이터베이스에 접근할 때 가장 많은 시간이 소요된다고 한다. 그리고 지금 내가 진행중인 프로젝트는 WEB-WAS-DB의 3티어 구조이다. 사용자가 많이 늘어나 DB에 무리가 갈 것을 사전에 방지 하고자 캐시를 활용해 서버 성능을 개선 시켜 보려고 한다.
- 캐시는 데이터나 값을 미리 복사해 놓는 임시 장소를 가리킨다.
- 캐시는 보통 메모리를 사용하기 때문에 속도가 상당히 빠르다.
- 캐시에 데이터를 미리 복사해 놓으면 계산이나 접근 시간 없이 더 빠른 속도로 데이터에 접근할 수 있다.
- 즉, 미리 결과를 저장하고 나중에 요청이 오면 그 요청에 대해서 DB에 접근하지 않고 Cache에 요청을 처리한다.
이렇게 유용하게 쓰이는 캐시에도 단점이 존재한다고 한다. 캐시 서버는 속도를 위해서 주로 메모리를 사용하기 때문에 서버에 장애가 생기면 메모리가 날라가서 데이터가 손실될 수 있다. 그래서 때로는 디스크를 사용하도록 구성하거나 무분별한 캐시 사용은 피해야 겠다.
- Redis(Remote Dictionary Server)는 "키-값" 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈소스 기반의 비관계형 데이터베이스 관리 시스템(DBMS)이다.
- 모든 데이터를 메모리로 불러와서 처리하는 메모리 기반 DBMS이다.
- Redis가 지원하는 데이터 구조
- String
- List
- Set
- Sorted
- Set
- Hashes
Redis는 Homebrew를 사용하여 Mac에 설치할 수 있다.
brew install redis
다음 명령어를 실행하여 Redis 서버를 로컬로 시작할 수 있다.
redis-server
Redis에 연결하기 위해 redis 의존성을 설치한다.
npm install redis
server.js
const express = require('express');
const redis = require('redis'); // Redis 모듈 불러오기
const axios = require('axios');
const bodyParser = require('body-parser');
const redisClient = redis.createClient();
// ...
createClient() 메서드는 새로운 RedisClient 객체를 생성하는데, redis 서버와 express 서버가 같은 호스트에서 돌아가고 있다면 createClient() 에 별도의 설정을 해 주지 않아도 된다. 만약 호스트가 다르다면 호스트 url, 포트 번호 등의 설정을 추가해주어야 한다.
//...
app.get('/photos', async(req, res) => {
const albumId = req.query.albumId
const {data} = await axios.get(
'https://jsonplaceholder.typicode.com/photos',
{params : {albumId}},
)
res.json(data)
})
//...
Json api를 테스트해볼 수 있는 사이트를 통해 데이터가 큰 "/photos"를 보내달라고 요청해봤다.
응답에 걸리는 시간은 0.4초. 자 그럼 동일한 요청이 들어올 경우 캐시를 반환 하도록 수정해보자.
//...
// 캐시 체크를 위한 미들웨어
checkCache = (req, res, next) => {
redisClient.get(req.url, (err, data) => {
if (err) {
console.log(err);
res.status(500).send(err);
}
// Redis에 저장된게 존재한다.
if (data != null) {
res.send(data);
} else {
// Redis에 저장된게 없기 때문에 다음 로직 실행
next();
}
});
};
app.get('/photos', checkCache, async (req, res) => {
try {
console.log(req.url)
const {data} = await axios.get('https://jsonplaceholder.typicode.com/photos');
await redisClient.setex(req.url, 1440, JSON.stringify(data));
return res.json(data);
} catch (error) {
console.error(error);
return res.status(500).json(error);
}
});
//...
수정이 됐다면 잊지말고 Redis 서버도 실행시킨 후 다시 요청을 보내보자.
동일한 요청을 반복해서 보내는 경우 응답 시간은 0.03초. 첫 번째 요청과 비교하면 매우 빨라진 것을 확인할 수 있었다.
이렇게 Redis를 통해 캐시를 활용해봤다. 잘 활용하면 애플리케이션의 속도와 성능을 크게 증가시키는 역할을 할 수 있겠다. 적절한 api에 적용 후 서버 부하 테스트를 다시 돌려서 향상된 성능을 직접 느껴봐야겠다.
https://redis.io/docs/about/
https://ko.wikipedia.org/wiki/%EC%BA%90%EC%8B%9C
https://sabarada.tistory.com/103
https://brunch.co.kr/@jehovah/20
https://charming-kyu.tistory.com/37