본문 바로가기
프로그래밍/redis

[Java + Redis] Spring Data Redis로 Redis와 연동하기 - RedisTemplate 편

by 사바라다 2020. 8. 12.

[Redis] 캐시(Cache)와 Redis
[Redis] Redis의 기본 명령어
[Java + Redis] Spring Data Redis로 Redis와 연동하기 - RedisTemplate 편
[Java + Redis] Spring Data Redis로 Redis와 연동하기 - RedisRepository 편

안녕하세요. 오늘은 Redis에 관련된 이야기 3번째입니다. 저번시간까지 우리는 캐시(Cache)에 대한 간단한 이론, 그리고 Redis의 기본 명령어에 대해서 알아보는 시간을 가졌습니다. 이번 포스팅에서는 Java에서 Spring Data Redis를 이용하여 Redis와 통신하는 방법에 대해서 알아보도록 하겠습니다.

Redis에 접근하기 위해서 Spring Data Redis 라이브러리를 이용합니다. Spring Data Redis는 Redis를 2가지 방식으로 접근할 수 있도록 제공합니다. Redis 통신 framework로 잘 알려진 Lettuce와 Jedis입니다. Lettuce는 별도의 설정없이 사용할 수 있으며 Jedis를 사용하고자 하시면 별도의 의존성을 필요로 합니다.

또한 Spring Data Redis는 Redis에 2가지 접근 방식을 제공합니다. 첫번째는 RedisTemplate을 이용한 방식이며, 두번째는 Redis Repository를 이용한 방식입니다. 오늘은 RedisTemplate을 이용하는 방식에 대해서 알아보며 다음시간에 RedisRepository를 이용한 방식을 알아보도록 하겠습니다.

개발 환경

  • macOS mojave 10.14.5
  • Spring Boot 2.3.1.RELEASE
  • JAVA 11

의존성 (Dependency)

compile 'org.springframework.boot:spring-boot-starter-data-redis:2.3.1.RELEASE'

Redis Source-Code 설정

Redis 접근 Library는 Spring Data Redis에 내장되어있는 Lettuce를 사용하도록 하겠습니다. 환경설정은 아래와 같이 잡아주시면 됩니다.

@Configuration
@EnableRedisRepositories
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(redisHost, redisPort);
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate() {
        RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }

}

application.yml 설정

application.yml 파일에는 사용할 redis의 host(url)와 port를 설정해 주도록 합시다. 이렇게 설정한 정보는 위의 RedisConfig의 @Value 어노테션을 통해서 환경설정에 사용됩나다.

yml setting

RedisTemplate, StringRedisTemplate

이제 본격적으로 RedisTemplate을 사용해 보도록 하겠습니다. RedisTemplate을 그냥 사용할 수 도 있지만 저희는 RedisTemplate의 Serialize, Deserialize로 String을 사용하는 StringRedisTemplate을 사용하도록 하겠습니다.

Redis는 여러 자료 구조를 가지고 있습니다. 이런 여러 종류의 자료구조를 대응하기 위해 Spring Data Redis는 opsFor[X](ex. opsForValue, opsForSet, opsForZSet 등)라는 메서드를 제공합니다. 해당 메서드를 사용하면 각 자료구조에 대해서 쉽게 Serialize 및 Deserialize 할 수 있습니다. 각 메서드에 대한 설명은 아래와 같습니다.

메서드 설명
opsForValue Strings를 쉽게 Serialize / Deserialize 해주는 Interface
opsForList List를 쉽게 Serialize / Deserialize 해주는 Interface
opsForSet Set를 쉽게 Serialize / Deserialize 해주는 Interface
opsForZSet ZSet를 쉽게 Serialize / Deserialize 해주는 Interface
opsForHash Hash를 쉽게 Serialize / Deserialize 해주는 Interface

Strings

Redis의 Strings 자료구조는 opsForValue 메서드를 사용합니다. 사용한 테스트 코드와 결과입니다.

@Autowired
StringRedisTemplate redisTemplate;

@Test
public void testStrings() {
    final String key = "sabarada";

    final ValueOperations<String, String> stringStringValueOperations = redisTemplate.opsForValue();

    stringStringValueOperations.set(key, "1"); // redis set 명령어
    final String result_1 = stringStringValueOperations.get(key); // redis get 명령어

    System.out.println("result_1 = " + result_1);

    stringStringValueOperations.increment(key); // redis incr 명령어
    final String result_2 = stringStringValueOperations.get(key);

    System.out.println("result_2 = " + result_2);
}
result_1 = 1
result_2 = 2

List

Redis의 List 자료구조는 opsForList 메서드를 통해서 쉽게 컨트롤할 수 있습니다.

@Autowired
StringRedisTemplate redisTemplate;

@Test
public void testList() {
    final String key = "sabarada";

    final ListOperations<String, String> stringStringListOperations = redisTemplate.opsForList();

    stringStringListOperations.rightPush(key, "H");
    stringStringListOperations.rightPush(key, "e");
    stringStringListOperations.rightPush(key, "l");
    stringStringListOperations.rightPush(key, "l");
    stringStringListOperations.rightPush(key, "o");

    stringStringListOperations.rightPushAll(key, " ", "s", "a", "b", "a");

    final String character_1 = stringStringListOperations.index(key, 1);

    System.out.println("character_1 = " + character_1);

    final Long size = stringStringListOperations.size(key);

    System.out.println("size = " + size);

    final List<String> ResultRange = stringStringListOperations.range(key, 0, 9);

    System.out.println("ResultRange = " + Arrays.toString(ResultRange.toArray()));
}
character_1 = e
size = 10
ResultRange = [H, e, l, l, o,  , s, a, b, a]

Set

@Test
public void testSet() {
    String key = "sabarada";
    SetOperations<String, String> stringStringSetOperations = redisTemplate.opsForSet();

    stringStringSetOperations.add(key, "H");
    stringStringSetOperations.add(key, "e");
    stringStringSetOperations.add(key, "l");
    stringStringSetOperations.add(key, "l");
    stringStringSetOperations.add(key, "o");

    Set<String> sabarada = stringStringSetOperations.members(key);

    System.out.println("members = " + Arrays.toString(sabarada.toArray()));

    Long size = stringStringSetOperations.size(key);

    System.out.println("size = " + size);

    Cursor<String> cursor = stringStringSetOperations.scan(key, ScanOptions.scanOptions().match("*").count(3).build());

    while(cursor.hasNext()) {
        System.out.println("cursor = " + cursor.next());
    }
}
members = [l, e, o, H]
size = 4
cursor = l
cursor = e
cursor = o
cursor = H

Sorted Set

@Test
public void testSortedSet() {
    String key = "sabarada";

    ZSetOperations<String, String> stringStringZSetOperations = redisTemplate.opsForZSet();

    stringStringZSetOperations.add(key, "H", 1);
    stringStringZSetOperations.add(key, "e", 5);
    stringStringZSetOperations.add(key, "l", 10);
    stringStringZSetOperations.add(key, "l", 15);
    stringStringZSetOperations.add(key, "o", 20);

    Set<String> range = stringStringZSetOperations.range(key, 0, 5);

    System.out.println("range = " + Arrays.toString(range.toArray()));

    Long size = stringStringZSetOperations.size(key);

    System.out.println("size = " + size);

    Set<String> scoreRange = stringStringZSetOperations.rangeByScore(key, 0, 13);

    System.out.println("scoreRange = " + Arrays.toString(scoreRange.toArray()));
}
range = [H, e, l, o]
size = 4
scoreRange = [H, e]

Hash

@Test
public void testHash() {
    String key = "sabarada";

    HashOperations<String, Object, Object> stringObjectObjectHashOperations = redisTemplate.opsForHash();

    stringObjectObjectHashOperations.put(key, "Hello", "sabarada");
    stringObjectObjectHashOperations.put(key, "Hello2", "sabarada2");
    stringObjectObjectHashOperations.put(key, "Hello3", "sabarada3");

    Object hello = stringObjectObjectHashOperations.get(key, "Hello");

    System.out.println("hello = " + hello);

    Map<Object, Object> entries = stringObjectObjectHashOperations.entries(key);s

    System.out.println("entries = " + entries.get("Hello2"));

    Long size = stringObjectObjectHashOperations.size(key);

    System.out.println("size = " + size);
}
hello = sabarada
entries = sabarada2
size = 3

마무리

오늘은 이렇게 Java에서 Spring Data Redis를 이용해보았습니다.해당 모듈의 RedisTemplate를 사용하여 Redis와 통신까지 확인했습니다. RedisTemplate을 통하지 않고 RedisRepository를 통해서도 Redis와의 통신이 가능합니다. 다음시간에는 이 RedisRepository에 대해서 알아보는 시간을 가져보도록 하겠습니다.

감사합니다.

참조

https://docs.spring.io/spring-data/redis/docs/2.3.2.RELEASE/reference/html/#reference

댓글