본 게시물은 이전에 운영하던 velog에서 작성됨 (2023년 4월 6일 작성)
유튜브를 둘러보다가 'Redis 야무지게 사용하기'라는 영상을 보게 되었다.
NHN FORWARD 2021 Redis 야무지게 사용하기
영상을 본지는 꽤 오래되었다. 영상 앞 부분에서 설명해주신 캐싱 읽기 전략을 직접 구현해보고 싶었는데, 이제서야 프로젝트에 적용하게 되었다.
💥 로직
전체적인 흐름은 다음과 같다.
- 프론트엔드에게 postId를 받음
- redis 인스턴스에서 postId에 해당하는 데이터를 가져옴
- 만약 redis 인스턴스에서 가져온 데이터가 없으면 mysql에서 postId에 해당하는 데이터를 가져옴
- 데이터를 redis 인스턴스에 저장하고 프론트엔드에게 리턴
- 만약 redis 인스턴스에서 가져온 데이터가 있다면 곧바로 해당 데이터를 프론트엔드에게 리턴
🔥 코드 작성
우선 postId에 해당하는 게시물을 리턴하는 getPost 서비스 메소드를 다음과 같이 작성했다.
getPost 메소드가 실행되자마자 redis에서 데이터를 가져온다. 가져온 데이터가 존재하면 곧바로 JSON 객체로 만들어 리턴한다.(redis에는 문자열로 저장되기 때문에 JSON 객체로 변환해야한다.)
redis에서 가져온 데이터가 null이라면 mysql에 데이터가 존재하는지 확인한다. 없으면 예외처리하고 데이터가 존재하면 게시물에 대한 조회수를 업데이트하고 리턴할 데이터를 mysql에서 가져온다.
그리고 다음 요청부터 해당 게시물이 캐시 히트 되기 위해 registerPostToCache 서비스 메소드를 호출하여 redis에 게시물 데이터를 삽입한다. 원래 이 메소드는 getPost 메소드에 있던 로직인데, 뭔가 하나의 메소드가 두 가지 일을 하는 것 같아 분리했다.
위는 getPost에서 호출한 레파지토리의 메소드이다. 별건 없지만 주목할만한 건 hash 자료형이 아니라 string 자료형을 사용하였다. 일일이 hset 해서 넣는 것보다 string으로 바꿔서 넣는게 훨씬 편한 것 같다.
😽 수행 시간 측정
솔직히 수행 시간을 측정하기 전까지는 캐싱 작업을 한다고 해서 얼마나 빨라지겠어라고 생각했었는데, 직접 확인해보니 캐시 히트될 때와 캐시 미스 났을 때의 차이가 어마어마했다.
간단하게 컨트롤러에서 게시물 조회하는 메소드에서 getPost를 호출하는 부분에 console.time과 console.timeEnd를 달아주었다.
우선 캐시 미스 됐을 때를 가정하고 10번의 요청을 보내 보았다.
수행 시간 측정: 38.951ms
수행 시간 측정: 42.792ms
수행 시간 측정: 44.325ms
수행 시간 측정: 61.44ms
수행 시간 측정: 37.389ms
수행 시간 측정: 39.262ms
수행 시간 측정: 50.231ms
수행 시간 측정: 48.111ms
수행 시간 측정: 44.361ms
수행 시간 측정: 55.983ms
정수 부분만 더해서 평균을 내면 45.8ms가 나온다.
이제 캐시 히트 됐을 때를 가정하고 10번의 요청을 보내 보았다.
수행 시간 측정: 4.288ms
수행 시간 측정: 5.167ms
수행 시간 측정: 4.047ms
수행 시간 측정: 4.455ms
수행 시간 측정: 4.404ms
수행 시간 측정: 4.319m
수행 시간 측정: 4.855ms
수행 시간 측정: 4.555ms
수행 시간 측정: 4.547ms
수행 시간 측정: 4.168ms
정수 부분만 더해서 평균을 내면 4.1ms가 나온다.
무려 11배 차이가 난다. 많이 놀라웠다.
데이터가 클수록 캐싱의 효율도 더 커질 것이다.
여유만 된다면 캐싱 안할 이유는 없는 것 같다.
'NestJS' 카테고리의 다른 글
[NestJS | Redis | Docker] 용도별로 Redis 인스턴스 만들기 (0) | 2023.07.30 |
---|---|
[NestJS] OAuth 인증 (+ 중복 로그인 방지) (0) | 2023.07.30 |
[NestJS | Redis] 세션 스토리지 만들기 (0) | 2023.07.30 |
[NestJS] DTO 만들 때에는 interface보다 class를 사용하자 (0) | 2023.07.30 |