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

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

by 사바라다 2020. 8. 18.

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

안녕하세요. Redis 4번째 시간입니다. 오늘은 Spring Data Redis로 Redis에 접근하는 또 다른 접근법을 알아보고자 합니다. 우리는 이전 포스팅에서 RedisTemplate을 통해 Redis에 Strings, List, Set, Sorted Set, Hash에 접근하는 방법을 배웠습니다. 오늘 배우는 RedisRepository는 Spring Data JPA 처럼 객체를 기반으로 Redis에 적재하는 방법입니다.

개발환경부터 의존성, Redis 환경설정은 RedisTemplate편과 동일합니다.

개발 환경

  • 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 어노테션을 통해서 환경설정에 사용됩나다.

RedisRepository

Spring Data Redis에서 Redis Repository를 이용하면 쉽게 domain Objects를 Redis Hash 자료구조로 변환, secondary indexes를 적용, 그리고 TTL 등을 적용시 킬 수 있습니다. 오늘은 Person 객체를 이용하여 테스트를 진행해보면서 실제 어떻게 동작하는지 확인해보도록 하겠습니다.

오늘 Test에 이용할 Person과 Address 객체입니다. Person은 id를 Redis id로 가집니다. 또한 Address 객체를 내부 멤버변수로 가지고 있습니다. Redis Repository로 이용하기 위해서는 @Redishash 어노테이션을 이용해 key를 설정해 주어야합니다. 최종적으로 Redis에 들어가는 key는 @RedisHash의 value + @Id가 붙어있는 멤버변수입니다.

@Getter
@RedisHash("people")
public class Person {
    @Id
    String id;
    String firstname;
    String lastname;
    Address address;

    @Builder
    public Person(String id, String firstname, String lastname, Address address) {
        this.id = id;
        this.firstname = firstname;
        this.lastname = lastname;
        this.address = address;
    }
}

@Getter
public class Address {
    private String address;

    public Address(String address) {
        this.address = address;
    }
}

해당 Model을 기준으로 Repository를 생성하도록 하겠습니다. Repository는 JPA Repository와 크게 다른점은 없습니다. 아래와 같이 선언해주시면 됩니다. interface를 만드시고 해당 interface에 CrudRepository<Model, Id>를 상속받아주시면 됩니다.

public interface PersonRedisRepository extends CrudRepository<Person, String> {
}

테스트를 진행해보도록 하겠습니다.

@Autowired
private PersonRedisRepository redisRepository;

@Test
public void basicSave() {
    // given
    Address address = new Address("서울특별시 서울시청");
    Person person = new Person(null, "fisrt", "last", address);

    // when
    Person savedPerson = redisRepository.save(person);

    // then
    Optional<Person> findPerson = redisRepository.findById(savedPerson.getId());

    assertThat(findPerson.isPresent()).isEqualTo(Boolean.TRUE);
    assertThat(findPerson.get().getFirstname()).isEqualTo(person.getFirstname());
}

위 테스트는 Redis에 Person 객체를 저장하고 다시 찾아와 값을 비교하는 것입니다. 이는 정상적으로 실행되고 성공했습니다. 이제 실제 Redis에는 어떻게 저장되는지 한번 확인해보도록 하겠습니다.

Redis Repository에는 2개의 Key가 생성됨을 확인할 수 있었습니다. peoplepeople:bc268471-eeee-4892-b03a-cd4d5f1cb64c입니다. people은 people과 관련된 모든 key를 관리하며 people의 Id와 매핑된 정보는 people:bc268471-eeee-4892-b03a-cd4d5f1cb64c와 같이 people:{id}의 형태로 저장됩니다. 그리고 id를 null로 저장했기 때문에 id는 redis의 랜덤값으로 설정되었습니다.

peoplepeople:bc268471-eeee-4892-b03a-cd4d5f1cb64c의 type을 확인해보도록 하겠습니다. 먼저 people은 Set의 형태를 가지고 있습니다. Set은 해당 요소가 들어있는지 확인할 때 유용합니다. 그리고 실제 정보를 가지고 있는 people:bc268471-eeee-4892-b03a-cd4d5f1cb64c는 hash임을 확인할 수 있습니다.

people에는 어떤 내용이 들어있을지 smembers 명령어를 통해 확인해보도록 하겠습니다. 확인 결과 people에 속하는 id 값들이 들어있음을 알 수 있었습니다.

그렇다면 people:bc268471-eeee-4892-b03a-cd4d5f1cb64c의 안에는 어떤 값들이 들어있을까 확인해봤습니다. key와 value들을 각각 조회했습니다. 특이점은 key의 5번입니다. 기존에는 Person 객체에 포함되어있는 Address 객체였습니다. 내부 객체에 대해서는 해당 객체의 내부 변수가 .을 통해 들어가 있는 것을 확인할 수 있었습니다.

마무리

오늘은 이렇게 Spring Data Redis의 기본적인 사용방법과 실제 Redis에 들어가는 값에 대해서 알아보는 시간을 가져보았습니다. 추가적으로 Redis Repository에서도 TTL과 Secondary Indexes를 쉬운 방법으로 제공하고 있습니다. 이런 부분은 추후 다른 포스팅으로 찾아뵙도록 하겠습니다.

감사합니다.

참조

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

댓글