다음과 같이 특정 응답을 캐시하는 코드를 작성했다. 초기화 콜백에서 의존성이 주입된 리포지토리를 통해 조회하고 있다.
@Component
@RequiredArgsConstructor
public class GenreCached {
private final GenreRepository repository;
@Getter
private static Map<Long, Genre> genres;
**@PostConstruct**
public void init(){
Map<Long, Genre> genresMap = new HashMap<>();
**List<Genre> genreList = repository.findAll();**
for (Genre genre : genreList) {
genresMap.put(genre.getId(), genre);
}
genres = Collections.unmodifiableMap(genresMap);
}
절대 변경이 일어나지 않는 엔티티라 캐시해도 되겠다는 생각을 했다. 그래도 불안한지라 수정 불가능하도록 UnmodifiableMap을 사용했다. 다만 컬렉션의 수정을 막을 뿐 요소에 접근하면 변경이 가능했기 때문에 세터를 모두 제거하고 DTO로 변경한 뒤 응답을 내보내어 여태 문제가 없었다.
문제는 테스트 코드에서 GenreCached가 사용하는 GenreRepository Mock 객체가 findAll() 실행할 때 빈 배열을 리턴하여 발생했다. Mock 객체가 빈 컬렉션을 반환한다는 것은 스터빙이 안 되었다는 뜻이다.
문제를 해결하기 이전 우선 빈 라이프사이클에 대해 알아보았다.
빈 생명주기는 다음과 같다.
스프링 컨테이너 생성 -> 스프링 빈 생성 -> **의존관계 주입 -> 초기화 콜백 -> 사용** -> 소멸 전 콜백 -> 스프링 종료