codedbyjst
codedby.jst
codedbyjst
전체 방문자
오늘
어제
  • 분류 전체보기 (13)
    • 돈복사닷컴 (3)
      • 개발일지 (3)
    • 리세마라 매크로 (3)
      • 개발일지 (3)
    • naver-sens (1)
    • 개발팁 (6)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • rdbms
  • 우마무스메
  • 돈복사닷컴
  • FastAPI
  • django에서 react로
  • codedbyjst
  • 파라미터
  • PostgreSQL
  • MySQL
  • sqlalchemy
  • 개같이부활
  • 백엔드
  • query
  • 매크로
  • PATH
  • pymysql
  • 리세마라

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
codedbyjst

codedby.jst

Spring Boot + Redis Cache 사용법 정리
개발팁

Spring Boot + Redis Cache 사용법 정리

2023. 8. 11. 11:34

정합성이 크리티컬하지 않고, 로직 처리에 시간이 오래 소요되는 경우 캐싱을 이용해 처리시간 문제를 해결할 수 있습니다

(물론 SQL/DB레벨 최적화가 최우선입니다!)

그런데 다른 블로그 글들을 따라하니 Cannot construct instance of... 오류가 많이 발생해서, 동료 개발자들에게 도움이 되도록 해결한 내용을 정리했습니다.

 

기본 참조 자료 :

https://kim-oriental.tistory.com/28

1단계 : 의존성 추가

build.gradle :

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

2단계 : Redis 서버 Host, Port 정보 입력

application.properties :

spring.cache.type=redis
spring.redis.host=${REDIS_HOST}
spring.redis.port=${REDIS_PORT}

3단계 : 세부 설정 입력

패키지 내의 어느 한 곳에 설정용 클래스 추가!

(아래 예시의 경우 ohmycarset/src/main/java/com.softeer2nd.ohmycarset/config/RedisConfig에 저장됨)

RedisConfig 예시 :

명시적으로 Lettuce 이용 :

@EnableCaching
@Configuration
@PropertySource("classpath:application.properties")
public class RedisConfig {

    @Value("${spring.redis.host}") // application.properties 에서 불러옴
    private String host;

    @Value("${spring.redis.port}") // application.properties 에서 불러옴
    private int port;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory());
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                .entryTtl(Duration.ofHours(12)); // TTL 12시간으로 지정
        builder.cacheDefaults(configuration);

        return builder.build();
    }
}

주입받는 경우 :

@EnableCaching
@Configuration
public class RedisConfig {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory);
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                .entryTtl(Duration.ofHours(12)); // TTL 12시간으로 지정
        builder.cacheDefaults(configuration);

        return builder.build();
    }
}

4단계 : 원하는 메서드에 적용!

Controller Methods

...
@GetMapping(value = "/tag/system")
@Cacheable(value = "purchaseTagSystemOption")
public List<SelectiveOptionTagDto> getPurchaseTagSystemOption() {
    return tagService.getPurchaseTagSystemOption();
}
...

주의! GenericJackson2JsonRedisSerializer

역직렬화를 위해 생성자와 매핑 정보가 필요

관련 정보 : https://stackoverflow.com/questions/53191468/no-creators-like-default-construct-exist-cannot-deserialize-from-object-valu

2가지 방법이 존재한다.

1. NoArgsConstructor(인자 없는 생성자) : 가장 간단한다. 다만, 이 경우 인스턴스 변수들이 final이 될 수 없으므로 immutable하지 못하다.

public SelectiveOptionTagDto() {
    super();
}

2.  AllArgsConstructor(모든 인자 생성자) + @JsonCreator 또는 @ConstructorProperties : 인스턴스 변수들이 final이여도 된다! 다만, 추가적으로 어노테이션(둘 중 택일)을 작성해줘야 한다.

@JsonCreator
public SelectiveOptionTagDto(
        @JsonProperty("optionId") Long optionId,
        @JsonProperty("optionName") String optionName,
        @JsonProperty("tagName") String tagName,
        @JsonProperty("percentage") Double percentage) {
    this.optionId = optionId;
    this.optionName = optionName;
    this.tagName = tagName;
    this.percentage = percentage;
}
@ConstructorProperties({"optionId", "optionName", "tagName", "percentage"})
public SelectiveOptionTagDto(Long optionId, String optionName, String tagName, Double percentage) {
    this.optionId = optionId;
    this.optionName = optionName;
    this.tagName = tagName;
    this.percentage = percentage;
}

효과

캐시 전(1.24초)
캐시 후(0.005초)

 

추가설명 링크

@JsonCreator : https://findmypiece.tistory.com/241

@ConstructorProperties : https://kdohyeon.tistory.com/97

'개발팁' 카테고리의 다른 글

Nginx와 Docker Compose로 무중단 배포하기  (0) 2023.08.20
Certbot HTTPS용 SSL 인증서 발급 / Nginx로 적용하기  (2) 2023.08.15
스프링 부트 CORS 설정법 정리  (0) 2023.08.12
[Fastapi]파라미터 올바르게 다루기  (0) 2023.03.03
[Fastapi]sqlalchemy말고, pymysql로 데이터베이스(Mysql)와 통신하기  (4) 2023.02.23
    '개발팁' 카테고리의 다른 글
    • Certbot HTTPS용 SSL 인증서 발급 / Nginx로 적용하기
    • 스프링 부트 CORS 설정법 정리
    • [Fastapi]파라미터 올바르게 다루기
    • [Fastapi]sqlalchemy말고, pymysql로 데이터베이스(Mysql)와 통신하기
    codedbyjst
    codedbyjst

    티스토리툴바