티스토리 뷰

반응형

spring cache 기본 사용법: https://dolgogae.tistory.com/85

Overview

앞선 글에서 spring caching에 기본적인 사용법에 대해서 설명을 했다. 결과 값이 자주 업데이트 되지 않는 함수에 대해서 적용하면 in-memory에서 별도 연산없이 바로 결과를 가져오기 때문에 성능적인 이득을 볼 수 있었다. caching을 만드는 과정에서 각 cache를 구분하는 key를 생성하는 keyGenerator에 관한 내용을 이번 장에서 다뤄보고자 한다.

SimpleKeyGenerator

SimpleKeyGenerator는 keyGenerator의 디폴트 설정값이다. 캐싱을 하는 메서드에서 인자값을 기반으로 key를 생성한다.

@Cacheable(value = "products")
public Product getProduct(Long id, String category) {
    return new Product(id, category);
}

위 함수에서 key는 SimpleKey(id, category)로 생성된다. 그리고 SimpleKey 생성자를 살펴보면 아래처럼 값을 구분하여 저장한다.

public SimpleKey(Object... elements) {
    Assert.notNull(elements, "Elements must not be null");
    this.params = (Object[])elements.clone();
    this.hashCode = Arrays.deepHashCode(this.params);
}

위처럼 deepHashCode를 사용해서 자신만의 해시 값을 가지게 되고, 그 해시 값을 기반으로 유니크한 값인지 비교를 한다.

여기서 deepHashCode에 대해서 이해할 필요가 있고,

deepHashCode가 어떤 경우에 단점을 가지는지 알면 우리가 언제 커스텀 key generator를 만들어야 할지 알 수 있다.

DeepHashCode

우선 그 전에 deepHashCode가 일반적인 해시코드와 무엇이 다른지 살펴보자.

  • hashCode: 중첩 배열을 참조값으로 처리하고, Object[] 배열 자체의 해시 코드만 계산.
  • deepHashCode: 중첩 배열까지 해시 코드를 재귀적으로 계산.

위에서 볼 수 있듯 일반 hashCode는 참조값을 기반으로 해시를 만들기 때문에

배열안에 들어가 있는 값이 같더라도 배열의 주소가 다르면 다른 해시 값을 생성하게 된다. 

따라서 캐싱에서는 주소값이 다르더라도 같은 값인게 중요하기 때문에 deepHashCode가 쓰였음을 확인할 수 있다.

성능 저하

앞서 설명한 것처럼 재귀적으로 호출하기 때문에 hash 값을 만드는데 성능적인 측면이 문제가 될 수 있다.

하지만 key를 생성하는 데이터 자체가 크지 않다면 성능은 크게 문제가 되지 않는다.

따라서 대규모 데이터를 통해서 key를 만들어야 하는 상황이라면 그 값 중 유니크한 값 몇 개를 추출하여 

customKeyGenerator를 만드는게 효과적이라고 할 수 있다.

충돌

사실 이 경우는 잘 발생하지 않지만 deepHashCode는 32비트 정수를 기반으로 생성된다.

물론 32비트 정수라도 어마어마하게 큰 수라서 중복될 가능성이 현저히 낮지만

보안적으로 더 좋은 알고리즘이나 충돌이 전혀 일어나지 않을 알고리즘을 선택하는 것도 방법이다.

CustomKeyGenerator

위에서 deepHashCode의 단점으로 keyGenerator를 만들때 방법이다.

KeyGenerator를 상속받아 클래스를 만들고 spring bean으로 등록해야 한다.

@Component("customKeyGenerator")
public class CustomKeyGenerator implements KeyGenerator {
    @Override
    public Object generate(Object target, Method method, Object... params) {
        String key = target.getClass().getSimpleName() + "_" + method.getName() + "_" + Arrays.toString(params);
        return key;
    }
}

generate() 함수를 오버라이드 받고 거기에 원하는 해싱 알고리즘을 만들면 된다.

커스텀으로 key를 만들어야 한다면 위처럼 자신만의 알고리즘을 만들어서 사용하면 된다.

 

728x90
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함
250x250