최근에 Redis를 공부하면서, Redis가 가지는 장점인 "접근 속도가 빠르다"를 활용하여 데이터베이스의 캐시를 만들어보려 한다.
사실 많이 사용할 것 같지는 않지만, 그래도 WebFlux와 Redis에 대해 더 잘 이해할 수 있을 거 같아서 한 번 시도해보고 정리하려 한다.
implementation("io.lettuce:lettuce-core:6.5.0.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive")
implementation("org.springframework.boot:spring-boot-starter-data-redis-reactive")
implementation("org.springframework.boot:spring-boot-starter-webflux")
우선 위의 의존성들을 추가 해 준 후
사용한 Entity와 Repository는 다음과 같이 작성했다.
Entity
@Document("user")
data class User(
@Id
var id: ObjectId? = null,
var email: String,
var name: String,
@CreatedDate
var createdAt: LocalDateTime? = null,
@LastModifiedDate
var updatedAt: LocalDateTime? = null,
)
Repository
interface UserRepository: ReactiveMongoRepository<User, ObjectId> {
}
간단하게 userId를 검색하면 이메일이 나오는 서버를 만들어 보았다.
@GetMapping("/users/{id}")
fun getUserEmail(@PathVariable id: String): Mono<String> {
return Mono.just("result")
}
이렇게 /users/{id}의 주소로 요청하면 값이 반환되도록 작성했다.
우선 가장 처음으로 만든 코드는
return redisTemplate.opsForValue().get("users:$id")
.map{
it
}.switchIfEmpty {
userRepository.findById(ObjectId(id)).map{
it.email
}
}
이렇게 작성했다.
redis를 먼저 살펴 본 후에 있으면 그 값을, 없으면 다시 데이터베이스에 접근하여 값을 가져온다.
일단 테스트를 해보면
Redis에 데이터가 있는 경우는

이렇게 Redis에서, Redis의 값을 지우면

이렇게 Mongodb에서 값을 가져오게 된다.
근데 여기서 든 생각은, 비동기를 사용하기 때문에 동시에 접근해서 먼저 온 값을 넣는 방법은 없을까? 였다.
이렇게 사용하는 방법은 만약 cache miss가 일어난다면, 바로 데이터베이스에 접근하는 것보다 못하기 때문이다.
그래서 Mono.firstWithSignal을 사용했다.
firstWithSignal은 먼저 값이 나오는 Mono를 사용하는 메서드이다.
최종으로는 이렇게 수정했다.
@GetMapping("/users/{id}")
fun getUserEmail(@PathVariable id: String): Mono<String> {
val cacheMono = redisTemplate.opsForValue().get("users:$id")
.mapNotNull {
it
}
val dbMono = userRepository.findById(ObjectId(id)).map{
it.email
}
return Mono.firstWithSignal(cacheMono,dbMono)
}
이번에도 테스트를 해보면
Redis에 값이 있으면

이렇게 Redis에서 값을 가져오고
Redis에 값이 없다면

이렇게 Mongodb에서 값을 가져오는 것을 볼 수 있다.
'토이 프로젝트' 카테고리의 다른 글
| Redis Sentinel 설정 (0) | 2024.11.09 |
|---|---|
| Redis의 pub-sub을 사용한 SSE notification 서버 만들기 (1) | 2024.11.09 |
| Ubuntu에 Jenkins 설치하기 (0) | 2024.11.06 |
| Spring cloud gateway 적용하기 (0) | 2024.11.04 |
| Spring WebFlux + AOP로 사용자 로그 남기기 (3) | 2024.10.26 |