@Cacheable 어노테이션이 적용된 메서드는 메서드가 호출될 때 캐시에서 데이터를 찾고, 데이터가 존재할 경우 메서드의 본문은 실행되지 않는다. 대신 캐시에서 찾은 데이터가 바로 반환된다.
이 동작은 캐시 히트가 발생했을 때 적용되며, 캐시에 저장된 데이터가 캐시의 키와 일치하는 경우에 해당된다. 만약 캐시에 저장된 데이터가 없거나 캐시 키와 일치하지 않는 경우에는 메서드의 본문이 실행되어 데이터를 생성하고, 이후에는 캐시에 저장된다.
즉, 해당 메서드가 실행되어도 캐시에 저장되지 않는다. 메서드가 호출되어도 반환값이 없으므로 캐싱할 필요가 없다고 간주하기 때문이다.
@Cacheable 어노테이션에선 캐시의 이름과 키 를 설정할 수 있다.
@Cacheable(cacheNames = ["tickets"],
key="#createTicketRequest.eventId + '_' " +
"+ #createTicketRequest.date + '_' " +
"+ #createTicketRequest.grade + '_' " +
"+ #createTicketRequest.seatNo"
)
key 속성은 SpEL(Spring Expression Language)을 사용하여 정의된다.
Spring Expression Language(SpEL)은 스프링 프레임워크에서 사용되는 표현 언어로, 문자열 템플릿을 사용하여 다양한 기능을 제공하며, 주로 애노테이션, XML 설정 파일 등에서 사용된다.
'#' 기호를 사용하여 빈의 속성이나 메서드에 접근할 수 있다. 예를 들어, #user.name은 user 빈의 name 속성에 접근한다.
'${}' 기호를 사용하여 프로퍼티 값을 참조할 수 있다. 예를 들어, ${java.version}은 자바의 버전을 나타낸다.
이렇게 SpEL을 사용하여 동적으로 값을 지정하거나 조건에 따라 동작을 결정할 수 있기 때문에 코드의 유연성과 재사용성을 높일 수 있다.
한 서비스 내의 메서드에서 @Cacheable이 적용된 다른 메서드를 호출하는 것은 권장되지 않는다. 이것은 "self-invocation"이라고도 불리며, Spring AOP에서 캐싱을 처리하는 데 문제가 발생할 수 있다고 한다.
@Cacheable이 적용된 메서드는 메서드 호출 시 AOP 프록시에 의해 런타임에 캐싱 로직이 적용되는데, 같은 빈 내에서 이러한 메서드를 호출하면 AOP 프록시를 우회하고 캐싱이 적용되지 않을 수 있다. 이는 예기치 않은 동작을 초래할 수 있으며, 캐시 무효화, 캐시 누수 및 동시성 문제 등을 초래할 수 있다.
대신, 같은 서비스 내에서 캐시가 필요한 로직은 메서드 밖에서 별도의 서비스나 컴포넌트로 분리하여 호출하는 것이 좋다. 이를 통해 캐시 로직이 제대로 동작하고 코드의 의도가 명확해지며, 예기치 않은 문제가 발생할 가능성을 줄일 수 있다.
예를 들어
createTicket() 에서 @Cacheable 어노테이션이 붙은 chkTicket() 메서드를 호출하면 어노테이션을 통해 값을 가져오는 대신 직접 본문을 실행하고 결과를 가져온다.
뭔 내용인지 1도 모르겠습니다... -프론트엔드