Introduction
Spring-boot-starter-cache 라이브러리를 사용하던 중 Spring Application 을 재시작해도 캐시가 초기화 되지 않아 빈 DB를 조회해도 Cache 에서 데이터를 꺼내 반환하는 문제가 발생하였다. 심지어 Intellij 를 껏다 켜도 마찬가지였다. 컴퓨터를 재부팅 해야지만 캐시가 초기화 되었다.
상식적으로 Spring cache는 Spring Application 내부의 메모리를 사용하는 것일텐데 어떻게 App 이 종료되어도 캐시가 초기화되지 않는 것인가?
Code
Controller
@GetMapping("/{postId}")
public ResponseEntity<PostDto> getPost(@PathVariable long postId) {
return ResponseEntity.ok(postService.getPost(postId));
}
Service
@Cacheable(value = "post", key = "#postId")
public PostDto getPost(long postId) {
log.info("Get id: {}", postId);
Post post = postRepository.findById(postId)
.orElseThrow(EntityNotFoundException::new);
return modelMapper.map(post, PostDto.class);
}
Entity
@Entity
@Data
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column
private long views = 0;
}
실행 결과
select * from post
<< H2DB 에는 아무것도 들어있지 않으나
GET http://localhost:8080/1
<< 이전 앱 실행에서 저장된 캐싱 데이터가 튀어나온다.
분명히 현재 H2DB에는 데이터가 존재하지 않지만 1번 포스트에 대한 GET 요청을 할 시 데이터를 반환받는다. 해당 데이터는 이전 APP 실행에서 POST 요청을 통해 삽입된 데이터이다.
Solution
관련 문서를 찾아보던 중 해당 문서를 발견했다.
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-caching.html#boot-features-caching-provider-redis
Spring Cache는 추상화된 인터페이스로, 실제 캐시가 저장된 공간을 정의하지 않는다. 이는 CacheManager 또는 CacheResolver 에 의해 구체적으로 정의되며 해당 Bean 이 존재하지 않을 경우 해당 순서대로 캐시가 저장될 공간을 탐색한다.
1. Generic
2. JCache
3. EnCache 2.x
4. Hazelcast
5. Infinispan
6. Couchbase
7. Redis
8. Caffeine
9. Simple (In-memory)
여기서 9번 Simple 이 바로 Spring Application 의 In-memory 캐싱을 의미한다.
나의 경우는 현재 프로젝트 내에서 Redis 설정 Bean 과 Redis docker container 가 설정되어 있었기 때문에 7번 Redis 가 감지되었고 9번 In-memory 보다 우선순위가 높기 때문에 Caching 공간으로 채택된 것이다.
외부 저장공간을 캐싱 공간으로 사용하였기 때문에 당연히 Spring Application 을 재시작 해도 캐싱된 데이터가 남아있었던 것이다.
확인해 보니 정말로 캐싱된 데이터가 Redis에 들어있었다...
Redis 를 사용하는 동시에 Spring Cache 는 In-memory 를 사용하고 싶다면 application.yml 에 해당 설정을 추가해 주면 된다. 해당 설정을 통해 Spring Cache 저장공간을 디텍팅 하는 방식에서 강제로 고정시킬 수 있다. 만약 설정한 저장 공간이 설정되어 있지 않는다면 Spring 시작 시 예외가 발생한다.
spring:
cache:
type: simple
Reference
'개발 > Spring Boot' 카테고리의 다른 글
[Spring Boot] Spring cache 를 사용해 보자 (1) | 2024.02.07 |
---|---|
[ModelMapper] 필드 타입이 다른 두 객체간 매핑 커스텀하기 (0) | 2023.12.02 |
[SpringBoot] 발급받은 타행 SSL인증서를 SpringBoot에 적용시키기 (0) | 2022.12.10 |