Redis로 캐싱 구현하기
1. kakao api 데이터 불러오기
- 카카오 지도 api를 요청하여 쿼리스트링으로 검색된 키워드의 편의시설을 검색하여 찾고 응답을 보냄 (여기선 이마트)
const endpoint = `https://dapi.kakao.com/v2/local/search/keyword.json?query=${keyword}`; // API 엔드포인트 URL
const headers = {
Authorization: `KakaoAK ${process.env.KAKAO_APIKEY}`,
'Content-Type': 'application/json',
};
const response = await axios.get(endpoint, { headers });
res.status(200).json({ result: response.data });
2. Redis 접근 코드작성
전체코드로직
1. 쿼리스트링으로 검색하려는 키워드 입력받기
2. redis에서 데이터를 찾을때 찾으려는 key 있는지 확인
3. redis에 key에 해당하는 데이터가 존재
4. 데이터를 응답으로반환
5. redis에 key에 일치하는 데이터가 없을때 카카오 api서버에 접근해 쿼리스트링에 해당하는 데이터를 가져옴
6. 가져온 데이터를 key, 만료시간, value를 인자로 전달함 이때 만료시간은 60*60 =1시간
7. 다시 같은 키워드를 검색했을때 redis에 데이터가 있다면 카카오 api서버에 접근하지 않고 redis에서 바로 응답
router.get('/', async (req, res, next) => {
try {
//1.쿼리 스트링으로 키워드 입력받기
// keyword = 이마트
const { keyword } = req.query
//2. redis에 'kakaoMapInfoEmart' 라는 키를 찾음
redisClient.get('kakaoMapInfoEmart', async (err, Emart) => {
if (err) console.error(err)
//3. 이때 'kakaoMapInfoEmart'라는 데이터가 존재하면 redis에 있는 데이터를 그대로 get
if (Emart != null) {
console.log('Cashe Hit')
//4. 응답값으로 데이터 반환
return res.json(JSON.parse(Emart))
} else {
//5. redis에 일치하는 데이터가 없다면 카카오 api서버에 접근하여 데이터를 가져옴
console.log('Cashe Miss')
const endpoint = `https://dapi.kakao.com/v2/local/search/keyword.json?query=${keyword}`; // API 엔드포인트 URL
const headers = {
Authorization: `KakaoAK ${process.env.KAKAO_APIKEY} `, // 카카오 API 키를 인증 헤더에 포함
'Content-Type': 'application/json',
};
const response = await axios.get(endpoint, { headers });
//6. 가져온 데이터를 redis에 key , 만료시간, value 순서로 인자를 전달하고 redis에 저장
redisClient.SETEX('kakaoMapInfoEmart', DEFAULT_EXPIRATION, JSON.stringify(response.data))
res.status(200).json({ result: response.data.documents });
}
})
} catch (error) {
console.error(error)
res.status(500).json({ msg: "조회실패" })
}
});
3. 캐싱 전, 후 속도비교
캐싱전
- 108ms으로 0.1초 정도 걸림
캐싱후
- 6ms으로 0.006초 걸림
결론
- 자주 검색이 되거나 자주 조회되는 데이터에 대해서는 redis에 데이터를 저장하고 요청을 받았을때 DB까지 접근하지 않고 redis에서 빠르게 응답을 반환하여 응답시간을 줄임
추가적인 구현 기능
- cashe 미들웨어를 추가하여 파라미터나 쿼리스트링으로 전달받은 데이터가 존재하면 미들웨어에서 바로 결과값을 반환
// Cache middleware
function cache(req, res, next) {
const { username } = req.params;
client.get(username, (err, data) => {
if (err) throw err;
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
}
- 여기서 사용된 방식은 look Aside 방식으로 읽기에 특화된 방식이다, 추가적으로 프로젝트에서는 look Aside + write Around 방식을 적용할 예정이다