다음과 같이 특정 응답을 캐시하는 코드를 작성했다. 초기화 콜백에서 의존성이 주입된 리포지토리를 통해 조회하고 있다.

@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 객체가 빈 컬렉션을 반환한다는 것은 스터빙이 안 되었다는 뜻이다.

문제를 해결하기 이전 우선 빈 라이프사이클에 대해 알아보았다.

빈 라이프사이클


빈 생명주기는 다음과 같다.

스프링 컨테이너 생성 -> 스프링 빈 생성 -> **의존관계 주입 -> 초기화 콜백 -> 사용** -> 소멸 전 콜백 -> 스프링 종료