on Backend, Redis, Cache, Spring, Kotlin-serialization, Jackson, Gson
Spring Data Redis에는 Object를 Json으로 변환할 수 있는 Serializer를 제공한다. Redis를 캐시 저장소로 사용할 때에도 이 Serializer를 이용하는데, 이 Serializer를 이용해 List 타입을 반환하는 메소드에 캐시를 적용하면 예외가 발생한다.
# [Spring] Redis를 DB Cache로 사용할 때 리스트 저장하기 * toc {:toc} 예전에 토이 프로젝트를 진행할 때 `EhCache`로 `Database Cache`를 구현한 적이 있었다. 당시에는 서버를 이중화하여 사용할 일이 없어서 `Redis`를 캐시 저장소로 사용하지 않았지만, 최근에 Redis를 이용해 Database Cache를 구현 할 일이 생겼다. 문제는 EhCache를 이용할 때에는 이상 없이 동작하던 것이 Redis를 사용할 때에는 오류가 발생했다. 이번 포스트에서 이 문제의 원인이 무엇인지 어떻게 해결하였는지를 써보려고 한다. 참고로 이번 포스트는 Kotlin으로 테스트했다. ### Srping 설정 우선 테스트를 위해 `build.gradle.kts`에 라이브러리 의존성을 다음과 같이 설정했다. 유닛 테스트를 이용할 예정이라 `spring-boot-starter-web`은 추가하지 않았다. ```kotlin // build.gradle.kts dependencies { implementation("org.springframework.boot:spring-boot-starter-cache") implementation("org.springframework.boot:spring-boot-starter-data-redis") // Jackson implementation("com.fasterxml.jackson.module:jackson-module-kotlin") // Gson implementation("com.google.code.gson:gson:2.9.0") // Kotlin Serialization implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") testImplementation("org.springframework.boot:spring-boot-starter-test") } ``` 그리고 Redis에 연결할 수 있도록 RedisConnectionFactory를 만든다. ```kotlin // RedisConfig.kt @Configuration class RedisConfig { @Value("\${spring.redis.port}") var port = 0 @Value("\${spring.redis.host}") var host: String? = null @Bean fun redisConnectionFactory(): RedisConnectionFactory { val redisStandaloneConfiguration = RedisStandaloneConfiguration() redisStandaloneConfiguration.hostName = host!! redisStandaloneConfiguration.port = port return LettuceConnectionFactory(redisStandaloneConfiguration) } } ``` SampleDto를 만든다. ```kotlin // SampleDto.kt data class SampleDto ( val name: String = "", val number: Int = 0, ) ``` 마지막으로 캐상울 적용할 Service를 만든다. ```kotlin // TestService.kt @Service class TestService { val logger: Logger get() = LoggerFactory.getLogger(this.javaCl다ass) @Cacheable(key = "#id", value = ["one"]) fun getOne(id: Int): TestData { logger.info("호출") return TestData( str = "$id", number = id ) } @Cacheable(value = ["multiple"]) fun getMultiple(): List { logger.info("호출") return (1..10).map { TestData( str = "$it", number = it, ) } } } ``` ## Redis가 기본적으로 제공하는 Serializer 사용해보기