spring data프로젝트중 하나인 spring data redis를 사용해서 CRUD작업을 한다. (@RedisHash 어노테이션을 사용)
우선 일반적으로 관계DB에서 쓰는 형식으로 만들어보겠습니다.
item.java
package com.example.redis;
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import java.io.Serializable;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@RedisHash("item")
public class Item implements Serializable {
@Id
private Long id;// Id를 String으로 쓰면 UUID가 자동으로 배정된다.
private String name;
private String description;
private Integer price;
}
ItemRepository
package com.example.redis;
import org.springframework.data.repository.CrudRepository;
public interface ItemRepository extends CrudRepository<Item, Long> {
}
위 코드는 평소에 엔터티를 만들때 쓰는 기본적인 형식입니다.
package com.example.redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class RedisRepositoryTests {
@Autowired
private ItemRepository itemRepository;
@Test
public void createTest() {
Item item = Item.builder()
.id(1L)
.name("keyboard")
.description("Mechanical Keyboard Expensive 😢")
.price(100000)
.build();
itemRepository.save(item);
}
}
태스트를 통해서 데이터를 넣으면
item과 id를 조합하여 키를 만듭니다.

@Test
public void readOneTest() {
Item item = itemRepository.findById(1L)
.orElseThrow();
System.out.println(item.getDescription());
}
@Test
public void updateTest() {
Item item = itemRepository.findById(1L)
.orElseThrow();
item.setDescription("On Sale!!!");
itemRepository.save(item);
item = itemRepository.findById(1L)
.orElseThrow();
System.out.println(item.getDescription());
}
@Test
public void deleteTest() {
itemRepository.deleteById(1L);
}
Repository를 사용하는 것은 CRUD작업을 손쉽게 만들 수 있으며, 저희가 익숙한 Spring Data JPA와 유사하다는 장점을 가지고 있습니다. 그 외에 확장하는 방법 등도 동일합니다.
한편, Redis의 서로 다른 자료형, 그 자료형을 활용한 복잡한 기능을 만드는데는 한계가 있을것 같은 기분도 느낄 수 있습니다.
하지만 redis만의 데이터형을 못쓴다.
기본적인 CRUD는 Repository를 사용하지만 정교한 작업 String, Set, SortSet작업 등의 복잡한 자료형에 대한 사용법이 정의 되어있다.
java데이터의 형태로 직렬 역직렬화를 도움
package com.example.redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
@SpringBootTest
public class RedisTemplateTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
//RedisTemplate을 상속해서 만들어진 탬플릿
//자바에서 데이터를 어떤 타입으로 취급할건지를 나타냄
@Test
public void stringValueOpsTest() {
// 지금 RedisTemplate에 설정된 타입을 바탕으로 Redis 문자열 조작을 함
// ValueOperations는 redis에서 문자열 데이터를 조작하기 위해 필요한 명령어를 메서드의 형태로 보관하고 있다.
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
ops.set("simplekey", "simplevalue");
System.out.println(ops.get("simplekey"));
ops.set("greeting", "hello redis!");
System.out.println(ops.get("greeting"));
}
}
ValueOperations<String, String>를 보면 <String, String>으로 들어가 있고 ValueOperations를 들어가 보면
public interface ValueOperations<K, V>으로 되어 있다.
여기서 K는 키, V는 값이다. 즉 K, V는 어떤 자바타입으로 키와 값을 생성할건가를 물어보는 거다.
값 V는 String이 아니라 여러 클래스가 들어 갈 수 있다.
즉 StringRedisTemplate에 의해서 redis에 저장되는 타입이 결정되는게 아니라 ValueOperations<K, V>로 타입이 정해진다.
StringRedisTemplate은 데이터를 자바에서 어떤 타입으로 취급할지를 정하는거가 한마디로 StringRedisTemplate는 String 타입의 데이터를 읽고 저장할 수 있다는 말이다. 실제로 저장시 문자열만 넣고 있다.
@Test
public void stringSetOpsTest() {
SetOperations<String, String> setOps = stringRedisTemplate.opsForSet();
setOps.add("hobbies", "games");
setOps.add("hobbies", "coding");
setOps.add("hobbies", "alcohol");
setOps.add("hobbies", "games");
System.out.println(setOps.size("hobbies"));
}
package com.example.redis;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, ItemDto> itemRedisTemplate(
// RedisConnectionFactory : 레디스의 컨넥션을 관리해주는 클래스 yml정보를 바탕으로 연결
RedisConnectionFactory connectionFactory
) {
RedisTemplate<String, ItemDto> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);// 어떤 설정으로 연결을 할건지yml파일 정보 읽어옴
// 키는 어떻게 직렬화 역직렬화 할거냐/ 키가 어떤 타입인지 여기서는 String을 쓰고 있기때문에 string으로 설정
template.setKeySerializer(RedisSerializer.string());
// 값을 어떻게 직렬화 역직렬화 할거냐/ 값이 어떤 타입인지 Dto를 저장할거기 때문에 json으로 지정
template.setValueSerializer(RedisSerializer.json());
// 나중에 RedisSerializer를 직접 만들어 줄 수 있음 인터페이스 이여서 가능함
return template;
}
}
@Autowired
private RedisTemplate<String, ItemDto> itemRedisTemplate;// 빈 불러옴
@Test
public void itemRedisTemplateTest() {
ValueOperations<String, ItemDto> ops = itemRedisTemplate.opsForValue();
ops.set("my:keyboard", ItemDto.builder()
.name("Mechanical Keyboard")
.price(300000)
.description("Expensive 😢")
.build());
System.out.println(ops.get("my:keyboard"));
ops.set("my:mouse", ItemDto.builder()
.name("mouse mice")
.price(100000)
.description("Expensive 😢")
.build());
System.out.println(ops.get("my:mouse"));
}
테스트 코드에 추가해서 실행하면 데이터가 저장된 걸 볼 수 있다.
