- NoSQL 데이터베이스 중 하나이며 오픈소스 소프트웨어입니다. 주요한 특징은 ‘키-값(Key-Value)’ 형태로 데이터를 저장하고 이 데이터를 ‘인-메모리 데이터 저장소’에 저장합니다.
- ‘키-값(Key-Value)’ 형태로 데이터를 저장을 하며 ‘다양한 종류의 값’을 지정 가능합니다. 값으로는 문자열, 리스트, 셋, 정렬된 셋, 해시 등을 지원합니다. - ‘인 메모리 데이터 저장소’를 사용하기에 서버의 메인 메모리에 모든 데이터를 저장하므로, 디스크 I/O를 거치는 다른 데이터베이스 시스템보다 훨씬 빠른 성능을 보여줍니다. - 메모리에 저장되는 데이터 베이스는 디스크에 저장하여 휘발성으로 사용되는 데이터를 영구적으로 저장하는 기능을 제공하여 서버가 다운되더라도 데이터를 복구할 수 있습니다. - 주로 데이터베이스, 캐시, 메시지 브로커 등 다양한 용도로 사용될 수 있습니다.
- ‘Not Only SQL’ 또는 ‘Non-Relational SQL’이라는 의미를 가지며 관계형 데이터베이스 관리 시스템(RDBMS)이 아닌 다른 형태의 데이터 저장소를 의미하며 스키마가 없거나 유연한 스키마를 가지고 있어 데이터 구조가 고정되어 있지 않습니다. 이로 인해 다양한 형태의 데이터를 저장하고 관리할 수 있습니다. - NoSQL은 대용량 분산 데이터 처리를 위해 개발되었으며 데이터의 구조적 유연성과 확장성을 제공합니다.
💡 Redis 서버를 내리고 다시 서버를 올리면 데이터가 모두 사라질까?
- Redis는 기본적으로 인-메모리 데이터 구조 저장소이기 때문에, 서버가 종료되면 메모리에 저장된 데이터는 사라집니다. - 그러나 Redis는 디스크에 데이터를 저장하는 영구 저장 기능을 제공합니다. 이 기능을 사용하면, 서버가 종료되어도 데이터를 복구할 수 있습니다. - 이 영구 저장 방식은 RDB (Redis DataBase)와 AOF (Append Only File) 두 가지 방법이 있습니다.
- Spring Data Redis를 쉽게 사용할 수 있도록 도와주는 라이브러리이며, 내장 Lettuce Client를 사용하여서 Redis의 데이터를 키-값 형태의 저장소로 이용이 가능합니다. - 이를 통해 Redis 데이터베이스에 접근하고 데이터를 저장, 조회하는 등의 작업을 수행할 수 있습니다.
- spring-boot-starter-data-redis 라이브러리 내에 내장되어 있으며 Java 환경에서 Redis를 이용하기 위한 Redis 클라이언트입니다. - 이를 사용하면 여러 Redis 명령을 비동기적으로 실행할 수 있습니다. 또한, Netty 네트워크 프레임워크를 사용하여 구현되어서 고가용성 및 확장성을 제공하며 다중 스레드 환경을 지원합니다.
특징
설명
비동기 지원
Lettuce는 비동기적으로 Redis 명령을 실행할 수 있습니다.
고가용성 및 확장성
Lettuce는 Netty 네트워크 프레임워크를 사용하여 구현되어 있어 고가용성과 확장성을 제공합니다.
- Spring Data Redis에서 제공하는 템플릿 클래스로 데이터 조작을 추상화하고 자동화해 주는 역할을 수행하여 코드의 중복을 줄여주는 클래스입니다. - 기본적으로 데이터를 읽고 쓰는데 필요한 모든 작업을 처리해 줍니다. 이 클래스를 활용하여 String, List, Set, Sorted Set, Hash 등 다양한 Redis 데이터 구조를 쉽게 다룰 수 있습니다. - 연결 관리, 직렬화/역직렬화, 예외 처리 등을 처리해 주며, 기본적인 Redis 데이터 액세스 코드를 간결하게 만들어줍니다
💡 RedisConfig - 주요 Redis를 구성하기 위한 환경설정을 위한 Configuration 클래스입니다. - 해당 클래스에서는 application.properties로부터 받아온 host, port 정보를 기반으로 Redis 클라이언트를 구성합니다. 이를 통해서 추후 Redis와의 통신에 사용됩니다.
1. RedisConnectionFactory
- Redis와의 연결을 위한 'Connection'을 생성하고 관리하는 메서드입니다. - 해당 여기서는 LettuceConnectionFactory를 사용하여 host와 port 정보를 기반으로 연결을 생성합니다.
2. RedisTemplate<String, Object>
- Redis 데이터 처리를 위한 템플릿을 구성하는 메서드입니다. 이 메서드에서는 Redis와의 데이터 통신을 처리하기 위한 직렬화를 수행합니다.
항목
설명
RedisConnectionFactory
- Spring Data Redis에서 제공하는 인터페이스. Redis 커넥션을 생성하고 관리함.
LettuceConnectionFactory
- 해당 클래스는 RedisConnectionFactory 인터페이스를 구현한 클래스입니다. - 내장 되어 있는 Lettuce 라이브러리를 사용하여 Redis 커넥션을 생성하고 관리하는데 사용됩니다. 이를 통해 Redis 서버와 비동기식 통신을 수행할 수 있습니다.
RedisTemplate
- Spring Data Redis에서 제공하는 클래스. Redis 데이터베이스에 접근하고 데이터를 처리하는 데 사용됩니다. 타입 안전성을 제공하고, 직렬화 및 역직렬화를 처리하며, Redis의 기본적인 데이터 구조를 지원합니다.
package com.adjh.springbootredis.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis 환경 설정
*
* @author : jonghoon
* @fileName : RedisConfig
* @since : 11/2/24
*/
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String host;
@Value("${spring.data.redis.port}")
private int port;
/**
* Redis 연결을 위한 'Connection' 생성합니다.
*
* @return RedisConnectionFactory
*/
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
/**
* Redis 데이터 처리를 위한 템플릿을 구성합니다.
* 해당 구성된 RedisTemplate을 통해서 데이터 통신으로 처리되는 대한 직렬화를 수행합니다.
*
* @return RedisTemplate<String, Object>
*/
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// Redis를 연결합니다.
redisTemplate.setConnectionFactory(redisConnectionFactory());
// Key-Value 형태로 직렬화를 수행합니다.
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
// Hash Key-Value 형태로 직렬화를 수행합니다.
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
// 기본적으로 직렬화를 수행합니다.
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
return redisTemplate;
}
/**
* 리스트에 접근하여 다양한 연산을 수행합니다.
*
* @return ListOperations<String, Object>
*/
public ListOperations<String, Object> getListOperations() {
return this.redisTemplate().opsForList();
}
/**
* 단일 데이터에 접근하여 다양한 연산을 수행합니다.
*
* @return ValueOperations<String, Object>
*/
public ValueOperations<String, Object> getValueOperations() {
return this.redisTemplate().opsForValue();
}
/**
* Redis 작업중 등록, 수정, 삭제에 대해서 처리 및 예외처리를 수행합니다.
*
* @param operation
* @return
*/
public int executeOperation(Runnable operation) {
try {
operation.run();
return 1;
} catch (Exception e) {
System.out.println("Redis 작업 오류 발생 :: " + e.getMessage());
return 0;
}
}
}
5. RedisHandler : class component
💡 RedisHandler : class component
- RedisConfig로부터 Redis 설정정보를 받아서 구현하려는 데이터 타입에 따른 객체를 구성하거나 혹은 작업 내용에 따르는 예외처리를 하는 공통 컴포넌트입니다. 1. getListOperations()
- Redis의 리스트 타입 데이터에 접근하여 다양한 연산을 수행할 수 있는 ListOperations 객체를 반환합니다.
2. getValueOperations()
- Redis의 단일 값 데이터에 접근하여 다양한 연산을 수행할 수 있는 ValueOperations 객체를 반환합니다.
3. executeOperation(Runnable operation)
- Redis 작업 중 등록, 수정, 삭제에 대해 처리 및 예외처리를 수행합니다. 작업이 성공적으로 완료되면 1을 반환하고 오류가 발생하면 오류 메시지를 출력하고 0을 반환합니다.
package com.adjh.springbootredis.handler;
import com.adjh.springbootredis.config.RedisConfig;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class RedisHandler {
private final RedisConfig redisConfig;
/**
* 리스트에 접근하여 다양한 연산을 수행합니다.
*
* @return ListOperations<String, Object>
*/
public ListOperations<String, Object> getListOperations() {
return redisConfig.redisTemplate().opsForList();
}
/**
* 단일 데이터에 접근하여 다양한 연산을 수행합니다.
*
* @return ValueOperations<String, Object>
*/
public ValueOperations<String, Object> getValueOperations() {
return redisConfig.redisTemplate().opsForValue();
}
/**
* Redis 작업중 등록, 수정, 삭제에 대해서 처리 및 예외처리를 수행합니다.
*
* @param operation
* @return
*/
public int executeOperation(Runnable operation) {
try {
operation.run();
return 1;
} catch (Exception e) {
System.out.println("Redis 작업 오류 발생 :: " + e.getMessage());
return 0;
}
}
}
Redis 단일 데이터 값을 등록/수정합니다. duration 값이 존재하면 메모리 상 유효시간을 지정합니다.
getSingleData(String key)
String
Redis 키를 기반으로 단일 데이터의 값을 조회합니다.
deleteSingleData(String key)
int
Redis 키를 기반으로 단일 데이터의 값을 삭제합니다.
package com.adjh.springbootredis.service;
import org.springframework.stereotype.Service;
import java.time.Duration;
/**
* Redis 단일 데이터를 처리하는 비즈니스 로직 인터페이스입니다.
*/
@Service
public interface RedisSingleDataService {
int setSingleData(String key, Object value); // Redis 단일 데이터 값을 등록/수정합니다.
int setSingleData(String key, Object value, Duration duration); // Redis 단일 데이터 값을 등록/수정합니다.(duration 값이 존재하면 메모리 상 유효시간을 지정합니다.)
String getSingleData(String key); // Redis 키를 기반으로 단일 데이터의 값을 조회합니다.
int deleteSingleData(String key); // Redis 키를 기반으로 단일 데이터의 값을 삭제합니다.
}
7. RedisSingleDataServiceImpl : interface 구현체
메서드 명
매개변수
리턴 값
설명
setSingleData
String key, Object value
int
Redis 단일 데이터 값을 등록/수정합니다. 성공 시 1, 실패 시 0을 반환합니다.
setSingleData
String key, Object value, Duration duration
int
Redis 단일 데이터 값을 등록/수정하고, 메모리 상 유효시간을 지정합니다. 성공 시 1, 실패 시 0을 반환합니다.
getSingleData
String key
String
Redis 키를 기반으로 단일 데이터의 값을 조회합니다. 값이 없으면 빈 문자열을 반환합니다.
deleteSingleData
String key
int
Redis 키를 기반으로 단일 데이터의 값을 삭제합니다. 성공 시 1, 실패 시 0을 반환합니다.
package com.adjh.springbootredis.service.impl;
import com.adjh.springbootredis.config.RedisConfig;
import com.adjh.springbootredis.handler.RedisHandler;
import com.adjh.springbootredis.service.RedisSingleDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.Duration;
/**
* Redis 단일 데이터를 처리하는 비즈니스 로직 구현체입니다.
*/
@Service
@RequiredArgsConstructor
public class RedisSingleDataServiceImpl implements RedisSingleDataService {
private final RedisHandler redisHandler;
private final RedisConfig redisConfig;
/**
* Redis 단일 데이터 값을 등록/수정합니다.
*
* @param key : redis key
* @param value : redis value
* @return {int} 성공(1), 실패(0)
*/
@Override
public int setSingleData(String key, Object value) {
return redisHandler.executeOperation(() -> redisHandler.getValueOperations().set(key, value));
}
/**
* Redis 단일 데이터 값을 등록/수정합니다.(duration 값이 존재하면 메모리 상 유효시간을 지정합니다.)
*
* @param key : redis key
* @param value: : redis value
* @param duration : redis 값 메모리 상의 유효시간.
* @return {int} 성공(1), 실패(0)
*/
@Override
public int setSingleData(String key, Object value, Duration duration) {
return redisHandler.executeOperation(() -> redisHandler.getValueOperations().set(key, value, duration));
}
/**
* Redis 키를 기반으로 단일 데이터의 값을 조회합니다.
*
* @param key : redis key
* @return {String} redis value 값 반환 or 미 존재시 null 반환
*/
@Override
public String getSingleData(String key) {
if (redisHandler.getValueOperations().get(key) == null) return "";
return String.valueOf(redisHandler.getValueOperations().get(key));
}
/**
* Redis 키를 기반으로 단일 데이터의 값을 삭제합니다.
*
* @param key : redis key
* @return {int} 성공(1), 실패(0)
*/
@Override
public int deleteSingleData(String key) {
return redisHandler.executeOperation(() -> redisConfig.redisTemplate().delete(key));
}
}
[ 더 알아보기 ] 💡Redis에서 등록/수정/삭제를 수행하는 경우 @Transactional 어노테이션이 필요할까?
- 일반적으로 RDBMS에서 사용되는 @Transactional 어노테이션입니다. Redis의 경우 각 명령은 원자적으로 실행하기에 @Transaction 어노테이션이 필요로 하지 않습니다. 그러나 만약 여러 개의 Redis 연산을 한 트랜잭션으로 묶어야 하는 경우 @Transactional을 사용할 수 있습니다.
8. RedisSingleDataController: controller
엔드포인트
HTTP Method
메서드 명
설명
/api/v1/redis/singleData/getValue
POST
getValue
Redis 키를 기반으로 단일 데이터의 값을 조회합니다.
/api/v1/redis/singleData/setValue
POST
setValue
Redis 단일 데이터 값을 등록/수정합니다. duration 값이 존재하면 메모리 상 유효시간을 지정합니다.
/api/v1/redis/singleData/delete
DELETE
deleteRow
Redis 키를 기반으로 단일 데이터의 값을 삭제합니다.
package com.adjh.springbootredis.controller;
import com.adjh.springbootredis.dto.RedisDto;
import com.adjh.springbootredis.service.RedisSingleDataService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* Redis 단일 데이터를 조회, 등록, 삭제하는 로직입니다.
*
* @author : jonghoon
* @fileName : RedisSingleDataController
* @since : 11/5/24
*/
@RestController
@RequestMapping("/api/v1/redis/singleData")
public class RedisSingleDataController {
private final RedisSingleDataService redisSingleDataService;
public RedisSingleDataController(RedisSingleDataService redisSingleDataService) {
this.redisSingleDataService = redisSingleDataService;
}
/**
* Redis 키를 기반으로 단일 데이터의 값을 조회합니다.
*
* @param redisDto
* @return
*/
@PostMapping("/getValue")
public ResponseEntity<Object> getValue(@RequestBody RedisDto redisDto) {
String result = redisSingleDataService.getSingleData(redisDto.getKey());
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* Redis 단일 데이터 값을 등록/수정합니다.(duration 값이 존재하면 메모리 상 유효시간을 지정합니다.)
*
* @param redisDto
* @return
*/
@PostMapping("/setValue")
public ResponseEntity<Object> setValue(@RequestBody RedisDto redisDto) {
int result = 0;
if (redisDto.getDuration() == null) {
result = redisSingleDataService.setSingleData(redisDto.getKey(), redisDto.getValue());
} else {
result = redisSingleDataService.setSingleData(redisDto.getKey(), redisDto.getValue(), redisDto.getDuration());
}
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* Redis 키를 기반으로 단일 데이터의 값을 삭제합니다.
*
* @param redisDto
* @return
*/
@DeleteMapping("/delete")
public ResponseEntity<Object> deleteRow(@RequestBody RedisDto redisDto) {
int result = redisSingleDataService.deleteSingleData(redisDto.getKey());
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
4) 결과확인: Postman & redis-cli
엔드포인트
HTTP Method
메서드 명
설명
/api/v1/redis/singleData/getValue
POST
getValue
Redis 키를 기반으로 단일 데이터의 값을 조회합니다.
/api/v1/redis/singleData/setValue
POST
setValue
Redis 단일 데이터 값을 등록/수정합니다. duration 값이 존재하면 메모리 상 유효시간을 지정합니다.
/api/v1/redis/singleData/delete
DELETE
deleteRow
Redis 키를 기반으로 단일 데이터의 값을 삭제합니다.
💡 [참고] redis-cli 명령어에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.