Spring Data Redis는 2가지 방식의 적용이 가능하다.
1. RedisTemplate
2. RedisRepository
오늘은 두번째로 소개한 redisRepository 방식을 사용할 것이다.
redisRepository는 Spring Data JPA와 같이 객체를 기반으로 redis에 적재되는 방식이다.
다른 블로그에도 많으니 기본셋팅만 적어본다.
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Session> getRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Session> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
오늘 예시에 사용할 Item 객체를 생성해준다.Item은 id를 redisKey로 가진다.
RedisRepository로 사용하기 위해 @RedisHash 어노테이션을 사용하여 Key설정을 해준다. prefix는 config를 커스텀하여 설정한다.
@Data
@RedisHash(timeToLive = 60L,value="SHOP:ITEM")
public class Item {
@Id
private Long id;
private String itemName;
private int price;
private int dcPrice;
@Builder
public Item(Long id, String itemName, int price, int dcPrice) {
this.id = id;
this.itemName = itemName;
this.price = price;
this.dcPrice = dcPrice;
}
}
이 도메인 객체를 기준으로 repository를 생성한다.
public interface ItemRepository extends extends CrudRepository<Item, String> {}
interface로 만들고 CrudRepository를 상속받으면 된다.
CrudRepository는 spring data commos 모듈에 선언된 인터페이스로 데이터베이스를 다루는데 필요한 메소드를 모아둔 인터페이스이다. 도메인 클래스 타입과 ID타입을 제네릭 인자로 전달하고 CrudRepository 인터페이스를 상속하면 데이터 조회와 갱신 기능을 편하게 사용할 수 있다. Spring Data Redis Repository 역시 인터페이스에 선언된 모든 메소드를 오버라이딩 하여 Redis Hash 데이터에 쉽게 접근 할 수 있다.
@Autowired
private RedisRepository redisRepository;
public void saveItem() {
redisRepository.save(
new Item.Builder()
.id(1L)
.itemName("상품명")
.price(2000)
.dcPrice(1000)
.build()
);
}
Item객체를 저장했으니, redis를 확인해보도록 한다. redis에는 2개의 key가 생성되었음을 확인 할 수 있다. SHOP:ITEM와 SHOP:ITEM:1 이다.
이 두가지를 자세히 알아보자.
1.SHOP:ITEM
2.SHOP:ITEM:1
위와 같은 로직으로 redisRepository를 사용하여 redis에 데이터를 저장하는 방식을 확인 할 수 있었다.
Time To Live (TTL)
@RedisHash(timeToLive = 60L) 어노테이션을 통해 데이터의 TTL을 설정한면 오류가 발생하기 시작한다.
TTL 시간이 지나면 저장된 데이터는 제거되지만, key목록을 관리하는 Set의 element는 제거되지 않기 때문에 데이터의 정합성이 깨지게 된다.
@EnableRedisRepositories(enableKeyspaceEvents = ON_STARTUP) 선언을 추가하는 것으로 redis로부터 expired이벤트를 수신할 수 있다. 이를 통해 set의 크기를 적당하게 유지할 수 있지만 변경필요하다.
이유1. CrudRepository인테페이스에 선언된 대부분의 기능을 사용하지 않고 있다.
이유2. 불필요한 오버헤드 동작이 내부적으로 존재한다.
이유3. 관리하지 않으면 무한정 쌓이는 set 데이터를 처리하기 귀찮다.
대부분의 로직에서 redis on/off를 처리하기 위해 redisTemplate을 커스텀하여 구성하고, 앞서 말한 이유와 상관없이 항상 redis를 통해 처리해야할 것들을 위해 redisRepository를 사용해 보았는데, set과 관련된 이슈로 인해 redisTempalte을 다시 커스텀하여 사용하는 방향으로 다시 생각해봐야겠다.