Continuous Challenge

[항해플러스 7기 백엔드] 7주차 회고 - Redis를 활용한 성능 개선 (캐시 및 메모리 활용) 본문

Study/항해플러스 7기

[항해플러스 7기 백엔드] 7주차 회고 - Redis를 활용한 성능 개선 (캐시 및 메모리 활용)

응굥 2025. 2. 10. 19:09

이번 주차에는 기존 로직을 Redis 의 캐시와 메모리를 이용하여 성능을 개선해보는 시간을 가졌습니다.

 

그 전에 캐시와 캐시전략에 대한 정리를 하였고, 캐시 스탬피드 현상에 대해서도 알아보았습니다.(github)

 

hhplus-ecommerce/docs/cache.md at main · o3ozzvb/hhplus-ecommerce

Contribute to o3ozzvb/hhplus-ecommerce development by creating an account on GitHub.

github.com

 


캐시란?

캐시는 캐시 저장소에 한 번 구성된 응답 데이터를 저장해두었다가 동일한 요청이 오면 캐시 저장소에 저장되어있는 데이터를 반환하는 것이다. 캐시는 DB에 비해 실시간성은 떨어질 수 있지만, 성능 측면에서는 확실한 이점을 가져갈 수 있는 도구이다.

 

이커머스 서비스 로직 개선

1. 캐시 사용

 - 동일한 조건의 조회가 빈번하게 발생하고 데이터에 대한 변경이 거의 없는 응답 데이터는 캐시를 사용하는 것이 성능 측면에서 이점을 갖기 때문에 캐시를 사용하여 개선할 수 있도록 하였습니다.

  • 인기상품 목록 조회
    - 인기상품 목록 조회의 경우에는 조회 조건(일간, 주간, 월간)에 따라 스케줄러를 활용하여 배치가 도는 시점에 해당 데이터를 조회하여 Redis 에 캐시가 적재될 수 있도록 개선하였습니다. 
  • 상품 목록 조회
     - 상품 목록 조회의 경우에는 조회 조건(상품명, 가격범위, 카테고리 등)에 따라 응답 데이터가 달라지기 때문에 검색조건을 키값에 포함하여 캐시가 적재될 수 있도록 개선하였습니다.

2. Redis 메모리 활용

 - 동시에 대량의 요청이 발생할 수 있는 기능일 경우, 기능 내 조회 로직이 있다면 해당 조회 데이터를 Redis 에 적재하여 DB에 접근하지 않고 메모리에서 읽어 성능을 개선할 수 있습니다.

  • 선착순 쿠폰 발급 요청
    - 발급 요청 : Redis 의 Sorted Set 자료구조를 활용하여 요청 시각을 가중치로 두어 선착순으로 발급 요청 에 대한 처리를 비동기적으로 수행할 수 있도록 개선하였습니다.
  • 쿠폰 발급에 대한 검증
    - 중복 발급 방지 : Redis 의 Set 자료구조를 활용하여 발급 요청 시 쿠폰 ID 를 key 값으로 갖는 set 에 value 로 사용자 ID 값을 넣어 이미 발급 요청을 한 사용자인지 검증할 수 있도록 하였습니다.
    - 잔여 수량 체크 : Redis 의 Hash 자료구조를 활용하여 쿠폰의 잔여 수량을 적재하고 쿠폰 발급 요청이 호출되면 Redis 에서 쿠폰의 잔여수량을 조회하여 쿠폰에 대한 발급을 요청한 사용자 ID가 있는 set의 크기와 비교하여 잔여 수량에 대한 검증이 이뤄지도록 하였습니다.

선착순 쿠폰 발급 기능 외에도 주문 요청에 대한 로직이나 재고 수량 검증에 대한 로직 또한 Redis 를 활용하여 개선할 수 있을 것입니다.


Redis 를 활용하여 Cache 를 구현하다보면 데이터의 직렬화/역직렬화 문제를 마주하게 됩니다. 

RedisTemplate 의 Bean 생성 시에 사용하는 직렬화 구현체에 대해 알아보겠습니다.

직렬화/역직렬화

  • 스프링 서버와 외부에서 실행 중인 레디스 서버는 다른 어플리케이션이기 때문에 데이터에 대한 작업을 위해서는 직렬화/역직렬화 과정이 필요합니다.

JdkSerializationRedisSerializer

  • Default 로 적용되는 Serializer로 기본 자바 직렬화 방식을 사용.
  • 자바에서는 Serializable 인터페이스만 구현하면 별도의 작업 없이 사용 가능. 
  • SerialVersionUID 설정을 하지 않으면 클래스의 기본 해시값을 SerialVersionUID 로 사용한다. 따라서 클래스 구조가 조금이라도 변경시 SerialVersionUID 가 달라서 역직렬화에 실패할 수 있다.
  • 만약 개발자가 주의를 가지고 SerialVersionUID 를 설정한다고 하여도, 클래스 내부 필드 타입이 변경되면 역시 역직렬화가 실패할 수 있다.
  • 기본적으로 타입에 대한 정보 등 클래스 메타 정보들을 가지고 있기 때문에 직렬화시 용량이 비대해질 수 있다.
  • 따라서, 클래스의 변경이 잦은 경우에는 JdkSerializationRedisSerializer 를 사용하는 것은 지양해야 한다.

GenericJackson2JsonRedisSerializer

  • Class Type 을 지정할 필요 없이 자동으로 객체를 Json 형식으로 직렬화해준다. 
  • 직렬화된 데이터가 Class Type 을 포함한다.
  • 직렬화 시 @class 필드에는 해당 class 의 패키지까지 함께 저장된다. 따라서, 어떤 Application 이던 해당 데이터를 꺼내오기 위해서는 해당 루트, 경로에 같은 이름으로 해당 DTO Class 를 생성해야만 사용이 가능하다.
  • 만약 MSA 구조를 가지는 여러 Application 이 상호작용하며 동일한 Domain을 가진다면 MSA API 가 Class Type 에 묶인다는 문제가 발생한다.

Jackson2JsonRedisSerializer

  • @class 필드를 포함하지 않고 Json 으로 저장해준다.
  • 항상 Class Type 정보를 Serializer 에 함께 지정해주어야합니다.
    (GenericJackson2JsonRedisSerializer와 반대의 특징을 가진다.)
  • RedisTemplate 객체를 저장하는 DTO 타입 별로 생성해서 각각의 Serializer의 Class Type 을 지정해주어야 한다.
  • 만약 사용하는 Class Type 종류가 많아진다면 큰 단점으로 작용할 수 있다.
@Bean
public RedisTemplate<?,?> redisTemplate() {

    RedisTemplate<?,?> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory());
    redisTemplate.setEnableTranscationSupport(true);
    // class Type 지정
    redisTemplate.setKeySerializer(new Jackson2JsonRedisSerializer(String.class));
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(DTO.class));
    
    return redisTemplate;
}

StringRedisSerializer

  • StringRedisSerialier 를 직렬화 구현체로 선택하는 것이 가장 단점을 최소화할 수 있는 방법이다.
  • StringRedisSerializer 는 String 값을 그대로 저장하는 Serializer 이다.
    그렇기에 Json 타입으로 별도로 변환하는 과정이 필요하지만 앞서 살펴본 직렬화 구현체들의 단점을 보완할 수 있다.
  • Class Type 을 별도 지정하지 않아도 된다.
  • Package 정보를 포함할 필요없다.
  • 용량을 최소화하여 저장한다.

참고 

 

[Cache] Redis 직렬화 방법에 대해서

안녕하세요 오늘은 Redis 직렬화 방식에 대해 살펴보겠습니다 💪우리는 앞서 Spring Data Redis 의존성과 함께 다양한 방법으로 Spring 서버에서 Redis 를 사용해보았습니다. Redis에 대해 알아봅시다(응

velog.io

 


이번 주차에서는 Redis 를 도입하여 Redis 를 활용한 서비스의 성능 개선을 경험해볼 수 있었습니다.

도구를 도입하기 전 도구에 대한 학습을 진행하고, 서비스 내에 도구를 적용할 수 있는 기능을 비교하고 분석하였습니다.

실제로 Redis 를 활용하는 기업이 늘어가고 있는 추세인만큼 Redis 의 무궁무진한 활용 가능성을 느낄 수 있었습니다.

어떻게 하면 이렇게 굉장한 Redis를 서비스에 잘 활용할 수 있을지 활용 사례들을 좀 더 탐색하고 탐구하는 시간을 가져야겠습니다!

 

 

728x90
728x90
Comments