Redis -> DynamoDB

RTUnu12·2025년 7월 24일
0

개요

Redis와 DynamoDB를 혼용한 NoSQL 체제를 2개월동안 유지하였다. 그리고 5월에 AWS Summit Seoul이라는 굉장히 좋은 기회가 생겼고 여기서 AWS 전문가 분들이랑 이야기를 나눌 수 있는 너무 좋은 기회를 얻게 되었다.
나는 아키텍처의 전체적인 완성도에 대해 질문을 하였고, 전문가 분은 나에게 2가지 답변을 주셨다.

  • EC2 + Auto Scaling + 고가용성 구조는 매우 짜임새있지만, 구식이다. 요즘은 컨테이너를 사용하는 EKS나 ECS를 쓰니 한번 마이그레이션 해보는 것도 좋은 선택이다. 이때 두 구조를 성능이나 비용 면에서 비교하는 것도 좋은 실험일 것 같다.
  • Redis + DynamoDB 구조는 데이터의 특성과 목적에 따라서 나누었다는 것 자체는 향후 미래에 좋은 방향성이나, 지금 Redis를 사용한 이유가 사실 DynamoDB 하나로 대체가 가능하다. 그렇기에 Redis를 DynamoDB로 대체하거나 일부 기능을 DynamoDB로 옮기는 것이 비용/운영 효율적이지 않겠는가?

실제로 해당 2번째 답변을 받고 달에 나온 요금을 살펴보았다.

ElastiCache for Redis는 프리티어 적용이 아니였다. 그렇기에 내지 않아도 될 7달러가 달에 청구되고 있었다. 당장 대체할 때였다.

Redis 무료 클라우드


Redis는 30MB 정도 무료로 클라우드 환경에서 Redis를 사용할 수 있게 해준다. 현재는 개발 단계이니, 30MB 정도면 상당히 괜찮다고 볼 수 있다.
물론 런칭을 하면 상당히 부족한 용량인 것은 맞으니... 임시로 쓴다는 느낌으로 써야겠다.

Redis로 사용하고 있는 기능


Redis는 현재 3가지 기능의 구현을 위해 사용하고 있다고 보면 된다.

  1. 알림
    누군가 자신의 회고에 댓글을 달았거나 좋아요를 눌렀을 때 발생하는 알림이다.
    alert:{userId}로 저장되며 List 형식이다. TTL이 적용되어있으며, 7일이다.
  2. 통계 연산을 위한 메모이제이션
    stats:retrospect:total:{날짜} 형식으로 저장된다.
    전체 달로 모든 유저가 얼마나 retrospect를 작성하였는지 등을 위한 변수는, 통계를 작성할 때마다 연산할 경우 상당히 속도가 느릴 것이다. 그렇기에 한번만 연산한 후, 이후엔 +-1만 하는 방식으로 연산하게 된다. TTL이 적용되지 않았다. 한 달로 TTL을 잡으면 될 것 같다. (한 달 뒤엔 갱신이 되질 않을 테니)
  3. 각 유저별 월별 회고 작성 통계
    stats:retrospect:user:{userId}:{날짜} 형식으로 저장된다.
    위와 마찬가지로 메모이제이션이다. 통계 호출할 때마다 계산하면 상당한 부담이 되니까, 미리 기록을 해둔다. 마찬가지로 TTL이 적용되어있지 않다.

위 기능 모두 임시로 저장하고 속도가 빠른 "캐시"에 더 가까우나, 전문가 분의 말대로 DynamoDB의 TTL 기능과 DAX 기능으로 대체가 가능한 상황이였다. 하나하나씩 해결해보자.

TTL 기능

앞서 말했듯이 Redis에서는 TTL을 설정해 일시적인 데이터를 관리하고 있었다. DynamoDB 역시 TTL(Time To Live) 기능을 지원하며, 이는 지정된 timestamp가 지나면 해당 항목을 자동으로 삭제하는 기능이다.

Redis에서 alert:{userId}로 저장했던 알림 기능은 리스트 구조였고, 7일의 TTL을 적용했었다. 이를 DynamoDB로 옮기면서 다음과 같은 방식으로 재설계했다.
테이블 구조는 userId, timestamp, type, content 등으로 설계했고, timestamp는 알림 생성 시각으로 넣되, 이 값에 +7일을 더한 값을 ttl 컬럼에 저장했다.
이 ttl 컬럼을 TTL로 설정해두면, DynamoDB가 주기적으로 확인하고 해당 시각이 지난 데이터를 자동으로 삭제해준다.

즉, 알림 데이터는 DynamoDB에 저장되지만, Redis처럼 7일 뒤에 사라지는 동작을 동일하게 유지할 수 있었다.

통계용 캐싱 데이터(stats:retrospect:total:{날짜}, stats:retrospect:user:{userId}:{날짜})는 Redis에서는 TTL 없이 영구적으로 남아있었는데, 사실 한 달만 지나면 쓸 일이 거의 없다. 그래서 이 또한 DynamoDB에 옮기면서 TTL을 한 달(30일)로 설정해 데이터를 자동 정리하도록 했다. 결과적으로 불필요한 데이터가 DB에 계속 쌓이지 않게 되어 운영 효율이 더 높아졌다.

DAX 기능

Redis를 쓰던 주된 이유 중 하나는 속도였다. 캐시 용도로 Redis를 두었고, DynamoDB는 궁극적인 영속 저장소였다. 그러나 DynamoDB는 기본적으로 디스크 기반 저장소이기 때문에, Redis처럼 메모리 기반의 빠른 응답을 기대하기 어려웠다.
이때 DynamoDB Accelerator(DAX)가 대안으로 떠올랐다.
DAX는 DynamoDB 전용 인메모리 캐시 서비스로, 기존 코드 변경 없이도 DynamoDB 호출 속도를 Redis 수준으로 끌어올릴 수 있는 기능이다. 사용 방법도 비교적 간단하다.

  • 기존의 DynamoDB 클라이언트를 DAX 클러스터 엔드포인트로 교체
  • IAM 권한 및 VPC 설정을 맞춰서 보안 문제 없이 통신 가능하도록 구성
  • 캐시 일관성 정책을 Eventually consistent로 설정하여 캐시 사용 비율 극대화

알림 및 통계 연산 쿼리는 대부분 read가 많고, 즉각적인 일관성보다는 속도와 비용 효율이 더 중요하기 때문에, 구조적으로는 DAX가 굉장히 잘 맞았다.

다만, DAX는 Redis와 마찬가지로 프리티어가 적용되지 않아 요금이 추가로 발생하는 구조였다. 개발 초기 단계에서는 이 비용이 부담이 될 수 있었기에, 도입은 보류하고 향후 런칭 이후나 성능 테스트 단계에서 Redis와의 성능·비용을 비교해보는 용도로 검토하기로 했다.

즉, 지금은 직접 적용하진 않았지만, 향후 확장성과 운영 효율을 고려할 때 충분히 유력한 후보로 자리 잡았다.

요금이 얼마나 줄었는가?

보라색이 ElastiCache For Redis이다. 6월에 교체 작업을 하고 나서 상당히 줄어든 모습이다. 7월은 아직 나오지 않았지만, 6월보다도 요금이 줄어들었다.

이제 교체 작업은 끝이 났으나, ECS 교체도 남아있고, 그 무엇보다 7월에 프리티어가 끝난다. 그렇기에 8월에 CloudFormation을 통한 마이그레이션 작업을 시작해야 할 것 같다.

profile
이제 나도 현실에 부딪힐 것이다.

0개의 댓글