🙋 @Cacheable 캐싱 안 먹는 이유? (Spring AOP)

Spring에서 @Cacheable 써서 캐싱할 때,

같은 클래스 안에서 메서드 부르면 AOP가 안 먹힌다. 그 이유는 Spring AOP는 프록시 객체로 동작하는데, 클래스 내부에서 자기 자신을 호출하면 프록시가 아니라 해당 메서드를 불러버리기 때문이다.

프록시는 외부에서 해당 메서드가 호출될 때만 동작한다.

 

  @Service
  public class userService {
  
      public testResponse test(Long id) {
      ...
      	  // user 정보 얻기
          User user = getUser(id);
      ...
      }

	  // 캐싱 적용
      @Cacheable(value = "userCache", key = "#root.args[0]")
      public User getUser(id){
        return userRepository.findById(id)
      }
 
 }

 

 

✏️ 해결방법 첫번째, 서비스 분리

캐싱할 메서드를 다른 서비스(UserCacheService)로 빼버린다.

 

@Service
public class UserCacheService {
    @Autowired
    private UserRepository userRepository;
    
    @Cacheable(value = "userCache", key = "#root.args[0]")
    public User getUser(Long id){
        return userRepository.findById(id);
    }
}

 

✏️ 해결방법 두번째, 자기 자신을 빈으로 주입

서비스 나누기 싫다면? 자기 자신을 @Autowired을 통해 Bean으로 주입한다.

그러면 자기 자신 호출할 때도 프록시를 거치니까 AOP 적용되고 캐싱도 잘 된다.

 

@Service
public class UserService {

    @Autowired
    private UserService self;  // 자기 자신을 주입

    public TestResponse test(Long id) {
        User user = self.getUser(id);  // 프록시를 거쳐서 호출
    }

    @Cacheable(value = "userCache", key = "#root.args[0]")
    public User getUser(Long id){
        return userRepository.findById(id);
    }
}

 

💡 Redis로 캐시 확인하는 방법

해당 프로젝트는 Redis를 캐시 저장소로 설정했다. (Redis는 Docker로 실행)

따라서 캐싱이 잘 적용됐는지 확인하기 위해 Redis CLI 사용.

Redis Docker 컨테이너 실행하고 Spring에서 Redis와 연동됐다는 가정하에,

 

1) Redis CLI 접속

Docker로 실행 중인 Redis에 접속하려면, 터미널에서 Redis CLI에 들어가서 명령어를 입력할 수 있다.

docker exec -it [redis 컨테이너 이름] redis-cli

 

2) 캐시된 키 확인

현재 Redis에 저장된 모든 캐시 키를 볼 수 있다.

keys *

 

 

+ Recent posts