파란하늘의 지식창고
article thumbnail
반응형

Spring Boot 기반에서 Redis를 사용하는 방법

Spring Boot 2.5.0 기준으로 작성함

dependency 설정

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

redis는 connectionFactory로 Lettuce와 Jedis 두 가지를 제공한다.
default로 Lettuce를 제공하고 만약 Jedis를 사용하고 싶은 경우 아래처럼 설정하면 된다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

Bean 설정

Spring Boot의 RedisAutoConfiguration은 RedisTemplate과 StringRedisTemplate 두 가지 bean을 자동으로 생성하여 제공하고 있다.

따라서 만약 개별 설정을 하고자 하는 경우 그냥 해당 bean을 별도 생성하면 된다.
아래는 redisTemplate을 개별 설정하는 경우에 대한 예시이다.

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setDefaultSerializer(RedisSerializer.json());
    template.setKeySerializer(RedisSerializer.string());
    template.setHashKeySerializer(RedisSerializer.string());
    template.setConnectionFactory(redisConnectionFactory);
    return template;
}

RedisTemplate의 defaultSerializer는 JdkSerializationRedisSerializer이고 StringRedisTemplate의 defaultSerializer는 StringRedisSerializer이다.

stringRedisTemplate bean은 일반적인 String 값을 key, value로 사용하는 경우 사용하면 된다.
redisTemplate bean은 java Object를 redis에 저장하는 경우 사용하면 된다.

위의 개별 설정은 key의 값이 java Object가 아닌 경우로 가정하여 key serializer를 StringRedisSerializer로 한 경우이다.
(redisTemplate을 default Serializer로 사용 시 key가 일반 String 형태가 아니어서 cli에서 호출이 불편하여 key를 단순 String 형태로 만들어 쓰기 위해 StringRedisSerializer로 key , hashKey Serializer를 선언하였다.)

RestTemplate은 개별 설정을 위한 RestTemplateCustomizer 기능을 제공하지만 Redis는 RedisTemplate에 대한 customizer를 제공하지 않고 있다.

Properties 설정

사용할 redis 관련 환경 정보를 설정한다.
(port는 생략하면 6379가 default로 설정됨)

spring.redis.host=111.222.333.444
spring.redis.port=6379

좀 더 자세한 properties 설정은 Spring Boot의 RedisProperties를 참고하면 되고 해당 properties의 설정을 각각 lettuce, jedis connectionConfiguration에서 사용하여 적절하게 connectionFactory를 생성하게 된다.

Java에서 사용

redisTemplate 사용하기

기본적으로 redis를 사용하는 방법은 RedisTemplate StringRedisTemplate (reactive의 경우 ReactiveRedisTemplate, ReactiveStringRedisTemplate)을 호출하여 사용하는 것이다.

public class Example {

  @Autowired
  private StringRedisTemplate redisTemplate;

  public void addLink(String userId, URL url) {
    redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
  }
}

redisTemplate에는 redis가 제공하는 list, set, sortedSet, hash... 와 같은 다양한 command를 지원하기 위한 opsFor* method가 있다.
사용하고자 하는 redis command에 대응되는 method를 호출하여 사용하면 된다.
해당 method를 호출하면 각 redis command에 대응된 operation 객체가 반환된다.

redisTemplate opsFor* method operations
opsForValue() ValueOperations
opsForHash() HashOperations
opsForList() ListOperations
opsForSet() SetOperations
opsForZSet() ZSetOperations
opsForStream() StreamOperations
opsForGeo() GeoOperations
opsForHyperLogLog() HyperLogLogOperations
opsForCluster() ClusterOperations

operation을 바로 inject 하여 사용하기

이런 operation은 호출해서 쓰기 쉽도록 PropertyEditor 설정이 제공되어 있어 위 호출한 예제의 경우 다음과 같이 사용이 가능하다.

public class Example {

  // inject the template as ListOperations
  @Resource(name="redisTemplate")
  private ListOperations<String, String> listOps;

  public void addLink(String userId, URL url) {
    listOps.leftPush(userId, url.toExternalForm());
  }
}

이렇게 직접 inject 할 수 있게 지원되는 operation은 다음과 같다.

  • GeoOperations
  • HashOperations
  • ListOperations
  • SetOperations
  • ValueOperations
  • ZSetOperations

Bound*Operations 사용하기

사용하다 보면 key가 변하지 않고 value만 반복적으로 처리하는 경우가 있다.

이 경우 매번 반복으로 사용하는 key를 상수값으로 method에 넘기지 않고 아예 operation 자체가 들고 있게 하여 key를 제외한 값만 method로 호출하여 사용하도록 간소화할 수 있도록 Bound*Operation을 제공한다.

이런 경우 위의 예제는 다음과 같이 사용이 될 수 있다.

public class Example {

  private BoundListOperations<String, String> BoundListOperations listOps;

  public Example(@Qualifier("stringRedisTemplate") RedisTemplate redisTemplate) {
	listOps = redisTemplate.boundListOps("userId");
  }
  
  public void addLink(URL url) {
    listOps.leftPush(url.toExternalForm());
  }
}

key가 고정이란 전제하에 boudListOperation을 사용하여 method호출의 매개변수가 간소화되었다.

이렇게 key를 bound 하여 사용할 수 있게 지원되는 operation은 다음과 같다.

redisTemplate bound*Ops method bound operations
boundGeoOps(K key) BoundGeoOperations
boundHashOps(K key) BoundHashOperations
boundListOps(K key) BoundListOperations
boundSetOps(K key) BoundSetOperations
boundStreamOps(K key) BoundStreamOperations
boundValueOps(K key) BoundValueOperations
boundZSetOps(K key) BoundZSetOperations

Redis Repositories 사용하기

Redis의 Hash는 java Object에 대응하는 형태로 구성하기 적절하다.
Redis Repositories를 사용하면 Redis Hash에서 domain object를 원활하게 변환 및 저장하고 custom mapping 전략을 사용하고 secondary index를 사용할 수 있다.

만약 이렇게 java object <-> redis hash command 간 처리를 redis repositories를 사용하지 않고 redisTemplate만 활용하는 경우 properties에 다음과 같이 비활성화 처리를 하면 된다.

spring.data.redis.repositories.enabled=false

만약 사용한다면 대략 다음과 같이 domain을 생성하고

@RedisHash("people")
public class Person {

  @Id String id;
  String firstname;
  String lastname;
  Address address;
}

관련 repository를 생성한 후

public interface PersonRepository extends CrudRepository<Person, String> {

}

configuration에서 @EnableRedisRepositories을 선언하여 적절하게 domain package, repository package의 scan 위치를 지정하고

@Configuration
@EnableRedisRepositories(/** 관련 설정 진행 **/)
public class ApplicationConfig {

}

해당 repository를 가져다 사용하면 된다.

@Autowired PersonRepository repo;

public void basicCrudOperations() {

  Person rand = new Person("rand", "al'thor");
  rand.setAddress(new Address("emond's field", "andor"));

  repo.save(rand);                                         

  repo.findOne(rand.getId());                              

  repo.count();                                            

  repo.delete(rand);                                       
}

 

반응형
profile

파란하늘의 지식창고

@Bluesky_

내용이 유익했다면 광고 배너를 클릭 해주세요