(Spring Cache) @Cacheable key값 정하기

|

Spring Cache는 @Cacheable어노테이션만 붙이면 알아서 인자값을 종류에 맞게 캐쉬된 데이터를 사용합니다.

@Cacheable
public List<String> getList(int page, String query){ ... }

위와 같은 경우 두 인자값이 모두 같아야 같은 캐쉬값을 내보내는데 리턴값에 영향을 미치는 요소가 page 인자값만 영향을 미친다면 아래와 같이 캐쉬 키값을 별도로 설정 할 수 있습니다.

@Cacheable(key = "#page")
public List<String> getList(int page, String query){ ... }

#인자값이름으로 특정 인자를 지정할 수 있는데 위와 같이 하면 같은 page값일 경우 query인자값은 어떤 값이 들어오더라도 같은 캐쉬값을 반환합니다. 그런데 아래와 같은 경우 캐쉬가 정상적으로 동작하지 않습니다.

class Person
{
  private String name;

  public String getName(){ return name; }
}

@Cacheable(key = "#kim")
public List<String getList(Person kim){ ... }

이유는 Spring 4.0 이전 버전에서 사용하는 기본 KeyGenerator인 DefaultKeyGenerator가 아래와 같은 방식으로 키를 생성하기 때문입니다.

Spring Cache Abstraction Default Key Generation - 원문보기 Spring Cache Abstraction Default Key Generation

객체의 native값을 이용하거나 Object일 경우 hashCode()만을 사용하여 키 값을 생성하는데 Object의 hachCode는 객체에서 재정의 하지 않은 이상 무조건 다른 값이 들어가게 되기 때문입니다. Spring 4.0 이후 버전에서의 기본 KeyGenerator는 SimpleKeyGenerator를 사용하며 hashCode만이 아닌 복합키를 사용한다고 합니다.

인자값이 Object 객체인 경우 객체내 값을 이용하여 키 값을 쓸 수 있습니다.(물론 이 때 내부 값도 native값이거나 String같은 heap내 주소가 유일한 경우에만 가능합니다.)

@Cacheable(key = "#kim.name")
public List<String getList(Person kim){ ... }

인자값이 null일 경우를 체크하려면 아래와 같이 사용할 수 있습니다.

@Cacheable(key = "#kim?.name")
public List<String getList(Person kim){ ... }

위 식은 if-then-else 구문에서 else만 빠진것으로 전부 표시하면 아래 같이도 사용 가능합니다.

@Cacheable(key = "#kim?.name:'Unknown'")
public List<String getList(Person kim){ ... }

특정 메소드를 사용하고 싶다면 아래와 같이 사용할 수도 있습니다.

@Cacheable(key = "#kim.getName()")
public List<String getList(Person kim){ ... }

List나 Map값은 객체들은 hachCode값을 이미 내부 객체의 hashCode값들을 이용하여 정해진 규칙대로 만들기 때문에 아래의 경우에는 별도의 처리 없이 사용가능합니다. 하지만 내부에 포함된 데이터가 native타입이 아닐 경우엔 List, Map도 문제가 생깁니다.

@Cacheable(key = "#strList")
public List<String getListByList(List<String> strList){ ... }

@Cacheable(key = "#map")
public List<String getListByMap(Map<Long, String> map){ ... }

마지막으로 인자값이 여러개 있을 경우에 표시하는 예제는 아래와 같습니다.

@Cacheable(key = "'KeyIs' + #kim?.getName():'Unknown' + #page + #list")
public List<String getList(Person kim, int page, List<String> list){ ... }

key값에 사용되는 문법은 sqEL 표현식으로 아래 링크에서 자세한 내용은 확인 가능합니다.

  • (Spring Expression Language (SpEL))[https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html]

Comments