@Cacheable self-invocation (in effect, a method within the target object calling another method of the target object). The cache annotation will be ignored at runtime
@Cacheable 어노테이션을 사용해서 메서드 결과를 캐싱하려고 할 때, 같은 클래스 내의 다른 메서드를 호출하면 캐싱이 적용되지 않는 문제가 발생합니다. 저 역시 처음 이 문제를 겪고는 “왜 캐싱이 안 되지?”라는 의문을 가졌어요. 🤔
예를 들어, 아래처럼 getList 메서드에서 getTypeAList 메서드를 호출할 때 @Cacheable을 설정했는데도 캐시가 적용되지 않더라고요
public SiteListResponse getList(String type) throws Exception {
return getTypeAList(type);
}
@Cacheable(value = "getTypeA", cacheManager = "comdolliManager")
public List<String> getTypeAList(String type) throws Exception {
// Some logic to retrieve data
return result;
}
왜일까요? 이유는 @Cacheable 어노테이션이 프록시 방식을 사용해 캐싱을 처리하기 때문입니다. Spring에서 @Cacheable은 기본적으로 AOP 프록시 패턴을 통해 메서드를 가로채고 캐시 처리를 수행해요. 이 프록시는 클래스 외부에서 호출될 때만 적용됩니다. 즉 self-invocation이라 불리는 클래스 내부 메서드 간 호출은 프록시를 거치지 않기 때문에 @Cacheable이 무시돼요! 🤓
그러므로 캐시를 적용하려는 메서드를 같은 클래스가 아닌 다른 빈(Bean)에서 호출하도록 설계해야합니다. 가장 일반적인 방법은 인터페이스를 만들어 getTypeAList 메서드를 호출할 때 Spring이 프록시를 적용할 수 있도록 하는 것이에요.
아래처럼 getTypeAList 메서드를 별도의 서비스 클래스로 분리하면 문제 없이 캐시가 적용됩니다.
// testService.java
@Service
public class TestService {
@Cacheable(value = "getTypeA", cacheManager = "comdolliManager")
public List<String> getTypeAList(String type) throws Exception {
// Some logic to retrieve data
return result;
}
}
// MainService.java
@Service
public class MainService {
private final TestService testService;
public MainService(TestService testService) {
this.testService = testService;
}
public SiteListResponse getList(String type) throws Exception {
return testService.getTypeAList(type);
}
}
이제 getList 메서드가 TestService를 통해 getTypeAList를 호출하게 되었기 때문에, @Cacheable이 정상적으로 작동돼요. 이처럼 Spring의 프록시 메커니즘을 이해하고 설계하는 것이 중요합니다. 자칫 잘못된 방식으로 설계하게 되면 캐싱이 적용되지 않을 뿐 아니라, 코드의 유지보수성에도 영향을 미칠 수 있습니다 🤔
'Framework > Spring' 카테고리의 다른 글
[Spring] @Caching을 활용한 유연한 캐시 관리 - 컴도리돌이 (3) | 2024.11.04 |
---|---|
[Spring] Elasticsearch에서 Query String을 활용해서 검색하기 (feat. Java) - 컴도리돌이 (2) | 2024.11.01 |
[Spring] Elasticsearch에서 스크립팅 언어로 조건 필터링 구현하기(feat. Java) - 컴도리돌이 (4) | 2024.10.31 |
[Spring] Elasticsearch에서의 MultiMatch: 다중 필드에 대한 매칭(feat. Java)- 컴도리돌이 (6) | 2024.10.30 |
[Spring] Elasticsearch에서 다중 정렬하기 (feat. java, query DSL) - 컴도리돌이 (0) | 2024.10.29 |