Programming/Spring

[Spring Boot] Spring Boot + Redis CRUD 예제

kmindev 2023. 9. 24. 21:41

Spring Boot로 Redis 간단한 CRUD를 예제를 해보겠다.

1. Redis 설치

아래 링크에서 Redis를 설치하면 된다! 로컬환경에 설치를 진행했다.

https://github.com/microsoftarchive/redis/releases

 

Releases · microsoftarchive/redis

Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes - microsoftarchive/redis

github.com

 

 

2. Spring  Boot Redis

RedisTemplate 방식과 RedisRepository 인터페이스 두가지 방식으로 예제를 보여주겠다.

 

a. 공통 설정 부분


Spring Data Redis 의존성 추가 (공통)

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

application.yml(공통)

spring:
  redis:
    host: localhost
    port: 6379

 

RedisConfig(공통)

@Configuration
public class RedisConfig {

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

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

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }
}

Redis를 사용하기 위한 기본 Confiuration이다 application.yml에 설정한 host, port를 @Value 어노테이션으로 주입하고, redis 서버와 연결을 관리하기 위한 설정을 해준다.

 

PersonController(공통)

@RestController
@RequiredArgsConstructor
public class PersonController {
	private final PersonService personService;
	
	@PostMapping("/create")
	public void create(@RequestBody Person person) {
		System.out.println(person.getName());
		personService.create(person);
	}
	
	@GetMapping("/read")
	public Person read(String key) {
		return personService.read(key);
	}
	
	@DeleteMapping("/delete")
	public void delete(String key) {
		personService.delete(key);
	}
	
	@PutMapping("/update")
	public void update(@RequestBody Person person) {
		personService.update(person);
	}
}

엔드포인트 테스트 용도의 Controller이다.

 

 

b. RedisTemplate 방식


Person(RedisTemplate 방식)

@Getter
@NoArgsConstructor
@Data
public class Person {
    @Id
    private String id;
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

RedisTemplate과 맵핑하기 위한 Person 객체이다.

 

RedisConfig(RedisTemplate 방식)

@Configuration
public class RedisConfig {

    // ...생략
    
    @Bean
    public RedisTemplate<?, ?> redisTemplate() {
    	 RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
         redisTemplate.setConnectionFactory(redisConnectionFactory());
         
         // 기본 직렬화( JSON 형식) Object <=> JSON
         redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
         
         // Key 직렬화 (String 형식)
         redisTemplate.setKeySerializer(new StringRedisSerializer());
         
         // value 직렬화 (JSON 형식)
         redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
         
         // 해시 데이터 구조 직렬화 (JSON 형식)
         redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
         
         return redisTemplate;
    }
}

RedisTemplate을 사용하기 위해 LettuceConnectionFactory 주입 설정

redis에 저장 할 경우 <key, value> 형식으로 데이터를 저장하게 되는데, 이 과정에서 직렬화-역직렬화 방식을 지정해야 한다.

 

RedisTemplate에서 제공하는 자료구조 별 메서드

메서드 반환 타입 자료구조
opsForValue() ValueOperations String
opsForList() ListOperations List
opsForSet() SetOperations Set
opsForZSet() ZSetOperations Sorted Set
opsForHash() HashOperations Hash

 

PersonService(RedisTemplate 방식)

value 타입이 hash

@Service
@RequiredArgsConstructor
public class PersonService {
    private final RedisTemplate<String, Person> redisTemplate;

    public void create(Person person) {
        redisTemplate.opsForValue().set(person.getId(), person);
        redisTemplate.expire(person.getId(), 20, TimeUnit.SECONDS);
    }

    public Person read(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void update(Person person) {
        create(person);
    }

    public void delete(String key) {
        redisTemplate.delete(key);
    }
}

expire(key, time, 단위): redis에 저장할 시간 지정

 

 

PersonService(RedisTemplate 방식)

value 타입이 string

@Service
public class PersonService {

		private final RedisTemplate<String, Object> redisTemplate;
    private final HashOperations<String, String, Object> hashOperations;

    private static final String KEY_PATTERN = "person:";
    
    @Autowired
    public PersonService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.hashOperations = redisTemplate.opsForHash();
    }

    public void create(Person person) {
    	HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
        String hashKey = KEY_PATTERN + person.getId(); // 해시의 키를 지정합니다.
        hashOperations.put(hashKey, "id", person.getId());
        hashOperations.put(hashKey, "name", person.getName());
        hashOperations.put(hashKey, "age", person.getAge());
        // 필요한 모든 속성을 해시에 저장할 수 있습니다.
        
        // 만약 만료 시간을 설정하려면 아래와 같이 설정할 수 있습니다.
        redisTemplate.expire(hashKey, 20, TimeUnit.SECONDS);
    }

    public Person read(String key) {
        String hashKey = KEY_PATTERN + key;
        Map<String, Object> hashEntries = hashOperations.entries(hashKey);

        if (hashEntries.isEmpty()) {
            return null;
        }

        String id = (String) hashEntries.get("id");
        String name = (String) hashEntries.get("name");
        int age = (int) hashEntries.get("age");

        return new Person(id, name, age);
    }

    public void update(Person person) {
        create(person);
    }

    public void delete(String key) {
        String hashKey = KEY_PATTERN + key;
        redisTemplate.delete(hashKey);
    }
}

여기까지가 RedisTemplate 방식으로 진행한 예제이다.

 

 

 

c. RedisRepository 방식


Person(RedisRepository 방식)

@Getter
@NoArgsConstructor
@Data
@RedisHash(value = "person", timeToLive = 20)
public class Person {

    @Id
    private String id;
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

@RedisHash(valeu =””, timeToLive = sec)

  • value: key 패턴 지정 ⇒ person:id값
  • timeToLive: redis 저장 시간(20초)

 

RedisRepository(RedisRepository 방식)

public interface RedisRepository extends CrudRepository<Person, String>{

}

Spring Data Jpa와 비슷하다. CrudRepsotiory를 extends 해서 Repsository를 만든다.

 

PersonService(RedisRepository 방식)

@Service
@RequiredArgsConstructor
public class PersonService {
	private final RedisRepository redisRepository;
	
	public void create(Person person) {
		redisRepository.save(person);
	}

	public Person read(String key) {
		return redisRepository.findById(key).get();
	}

	public void update(Person person) {
		redisRepository.save(person);
	}

	public void delete(String key) {
		redisRepository.deleteById(key);
	}
}