3. spring boot에서 redis

위성구·2024년 8월 6일

Redis

목록 보기
3/7

Repository사용

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만의 데이터형을 못쓴다.

Redis Template

기본적인 CRUD는 Repository를 사용하지만 정교한 작업 String, Set, SortSet작업 등의 복잡한 자료형에 대한 사용법이 정의 되어있다.
java데이터의 형태로 직렬 역직렬화를 도움

String 타입

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 타입의 데이터를 읽고 저장할 수 있다는 말이다. 실제로 저장시 문자열만 넣고 있다.

Set타입

    @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;
    }
}
  • 기본 RedisSerializer는 비성호적인 부분이 있어서 직접 구현해서 상황에 맞게 만들어 줄 수 있다.

    @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"));
    }

테스트 코드에 추가해서 실행하면 데이터가 저장된 걸 볼 수 있다.

profile
안녕하세요.

0개의 댓글