-
[Spring Boot] RedisJSON 연동Spring Boot/기타 2023. 7. 17. 22:16반응형
RedisJSON 모듈은 Redis에 대한 JSON 지원을 제공하며, 다른 Redis 데이터 유형과 마찬가지로 Redis 데이터베이스에서 JSON 값을 저장, 업데이트 및 검색할 수 있습니다.
RedisJSON : https://redis.io/docs/stack/json/
1. Docker를 사용하여 Redis 설치
Docker를 사용하여 Redis를 로컬에 설치하세요.
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
포트 6379는 Redis 연결, 포트 8001는 RedisInsight에 사용됩니다.
Docker Hub : https://hub.docker.com/r/redis/redis-stack
RedisInsight
RedisInsight : https://redis.com/redis-enterprise/redis-insight/
2. 의존성 추가
Redis Json 명령어를 사용하기 위해 'Jedis'를 추가하세요.
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.2.2' id 'io.spring.dependency-management' version '1.1.4' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } repositories { mavenCentral() } dependencies { // SpringBoot implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' // Redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' // Jedis implementation 'redis.clients:jedis:5.1.0' // Lombok compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } test { exclude '**/*' }
Maven Repository : https://mvnrepository.com/artifact/redis.clients/jedis/5.1.0
3. RedisConfig 설정
Redis 클라이언트 라이브러리인 Jedis를 사용하여 Redis 서버와의 연결을 설정하세요.
RedisConfig.javapackage com.example.jedissample.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.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import redis.clients.jedis.JedisPooled; @Configuration public class RedisConfig { @Value("${redis.stand-alone.host}") private String standAloneHost; @Value("${redis.stand-alone.port}") private String standAlonePort; /** * RedisConnectionFactory 빈을 생성 * * @return RedisConnectionFactory 빈 */ @Bean public RedisConnectionFactory redisConnectionFactory() { return new JedisConnectionFactory( new RedisStandaloneConfiguration(standAloneHost, Integer.parseInt(standAlonePort))); } /** * RedisConnectionFactory를 사용하여 JedisPooled 빈을 생성 * * @param redisConnectionFactory RedisConnectionFactory * @return JedisPooled 빈 */ @Bean public JedisPooled jedisPooled(RedisConnectionFactory redisConnectionFactory) { JedisConnectionFactory jedisConnectionFactory = (JedisConnectionFactory) redisConnectionFactory; return new JedisPooled( jedisConnectionFactory.getPoolConfig(), jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort()); } }
4. RedisComponent 설정
Redis에 데이터 조회 및 저장을 위해 JedisCluster 객체를 사용하여 메서드를 구현하세요.
RedisComponent.javapackage com.example.jedissample.component; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.json.Path; @Slf4j @RequiredArgsConstructor @Component public class RedisComponent { private final JedisPooled jedisPooled; /** * Redis에 객체를 JSON 형식으로 저장 * * @param key Redis 키 * @param t 저장할 데이터 객체 * @param seconds 만료 시간(초) * @param <T> 데이터 객체의 유형 */ public <T> void setJson(String key, T t, long seconds) { jedisPooled.jsonSetLegacy(key, t); jedisPooled.expire(key, seconds); } /** * Redis에서 키를 사용하여 저장된 객체를 조회 * * @param key Redis 키 * @param clazz 검색할 데이터 객체의 클래스 유형 * @param <T> 검색할 데이터 객체의 유형 * @return Redis에서 검색한 데이터 객체 */ public <T> T getJson(String key, Class<T> clazz) { return jedisPooled.jsonGet(key, clazz); } /** * 키와 경로를 사용하여 Redis에서 저장된 객체를 조회 * * @param key Redis 키 * @param path 가져올 데이터 객체의 경로 * @return Redis에서 검색한 데이터 객체 */ public Object getJson(String key, Path path) { return jedisPooled.jsonGet(key, path); } /** * Redis에서 저장된 JSON 배열을 조회 * * @param key Redis에서의 키 * @param clazz 검색할 데이터 객체의 클래스 유형 * @param path JSON 배열의 경로 * @param <T> 검색할 데이터 객체의 유형 * @return 검색된 데이터 객체의 목록 * @throws IOException JSON을 파싱하는 동안 발생할 수 있는 예외 */ public <T> List<T> getJsonArray(String key, Class<T> clazz, String path) throws IOException { List<T> list = new ArrayList<>(); Object object = jedisPooled.jsonGet(key, new Path(path)); if (!ObjectUtils.isEmpty(object)) { ObjectMapper objectMapper = new ObjectMapper(); String jsonString = objectMapper.writeValueAsString(object); list = objectMapper.readValue( jsonString, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); } return list; } }
5. EmployeeService 추가
EmployeeService.java
package com.example.jedissample.service; import com.example.jedissample.component.RedisComponent; import com.example.jedissample.dto.EmployeeDto; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * * EmployeeDto 객체를 Redis에 저장 및 조회 * * <p> * Storing and Querying JSON documents using Redis Stack * https://developer.redis.com/howtos/redisjson/getting-started * </p> */ @Slf4j @RequiredArgsConstructor @Service public class EmployeeService { private final RedisComponent redisComponent; /** * EmployeeDto.Info를 Redis에 JSON 형식으로 저장 * * @param key Redis 키 * @param employeeInfo EmployeeDto.Info * @return EmployeeDto.Info */ public EmployeeDto.Info saveEmployeeInfo(String key, EmployeeDto.Info employeeInfo) { redisComponent.setJson(key, employeeInfo, 60 * 5); return redisComponent.getJson(key, EmployeeDto.Info.class); } /** * EmployeeDto를 Redis에 JSON 형식으로 저장 * * @param key Redis 키 * @param employee EmployeeDto * @return EmployeeDto */ public EmployeeDto saveEmployee(String key, EmployeeDto employee) { redisComponent.setJson(key, employee, 60 * 5); return redisComponent.getJson(key, EmployeeDto.class); } /** * 키(key)를 사용하여 Redis에 저장된 객체를 조회 * * @param key Redis 키 * @return EmployeeDto */ public EmployeeDto findEmployee(String key) { return redisComponent.getJson(key, EmployeeDto.class); } /** * 키(key)와 경로(path)를 사용하여 Redis에 저장된 객체를 조회 * * @param key Redis 키 * @param path 경로 * @return List<EmployeeDto.Info< */ public List<EmployeeDto.Info> findEmployee(String key, String path) throws Exception { return redisComponent.getJsonArray(key, EmployeeDto.Info.class, path); } }
6. EmployeeDto 추가
EmployeeDto.java
package com.example.redisjson.dto; import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @Builder public class EmployeeDto { List<Info> employees; @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public static class Info { private String name; private String email; private int age; } }
7. 저장 및 조회 확인
EmployeeServiceTest.java
package com.example.jedissample.service; import static org.junit.jupiter.api.Assertions.assertFalse; import com.example.jedissample.dto.EmployeeDto; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.util.ObjectUtils; @Slf4j @SpringBootTest class EmployeeServiceTest { @Autowired private EmployeeService employeeService; @Autowired private ObjectMapper objectMapper; @DisplayName("saveEmployeeInfo_EmployeeDto.Info를 Redis에 JSON 형식으로 저장") @Test void testSaveEmployeeInfo() throws Exception { // Given String key = "employee_profile"; EmployeeDto.Info employeeInfo = EmployeeDto.Info.builder() .name("Paul John") .email("paul.john@example.com") .age(42) .build(); // When EmployeeDto.Info responseEmployeeInfo = employeeService.saveEmployeeInfo(key, employeeInfo); // Then log.debug("responseEmployeeInfo: {}", objectMapper.writeValueAsString(responseEmployeeInfo)); assertFalse(ObjectUtils.isEmpty(responseEmployeeInfo)); } @DisplayName("saveEmployee_EmployeeDto를 Redis에 JSON 형식으로 저장") @Test void testSaveEmployee() throws Exception { // Given String key = "employee_info"; List<EmployeeDto.Info> employees = new ArrayList<>(); employees.add(EmployeeDto.Info.builder() .name("Alpha") .email("alpha@gmail.com") .age(23) .build()); employees.add(EmployeeDto.Info.builder() .name("Beta") .email("beta@gmail.com") .age(28) .build()); employees.add(EmployeeDto.Info.builder() .name("Gamma") .email("gamma@gmail.com") .age(33) .build()); employees.add(EmployeeDto.Info.builder() .name("Theta") .email("theta@gmail.com") .age(41) .build()); EmployeeDto employee = EmployeeDto.builder() .employees(employees) .build(); // When EmployeeDto responseEmployee = employeeService.saveEmployee(key, employee); // Then log.debug("responseEmployee: {}", objectMapper.writeValueAsString(responseEmployee)); assertFalse(ObjectUtils.isEmpty(responseEmployee)); } @DisplayName("findEmployee_키(key)를 사용하여 Redis에 저장된 객체를 조회") @Test void testFindEmployee() throws Exception { // Given String key = "employee_info"; // When EmployeeDto responseEmployee = employeeService.findEmployee(key); // Then log.debug("responseEmployee: {}", objectMapper.writeValueAsString(responseEmployee)); assertFalse(ObjectUtils.isEmpty(responseEmployee)); } @DisplayName("findEmployee_키(key)와 경로(path)를 사용하여 Redis에 저장된 객체를 조회") @Test void testFindEmployeePath() throws Exception { // Given String key = "employee_info"; String path = "$.employees[?(@.age>20&&@.age<40)]"; // When List<EmployeeDto.Info> responseEmployee = employeeService.findEmployee(key, path); // Then log.debug("responseEmployee: {}", objectMapper.writeValueAsString(responseEmployee)); assertFalse(ObjectUtils.isEmpty(responseEmployee)); } }
8. 콘솔 확인
9. RedisInsight 확인
redisdeveloper : https://developer.redis.com/
반응형'Spring Boot > 기타' 카테고리의 다른 글
[Spring Boot] Spring Cloud Config 연동 (0) 2024.03.07 [Spring Boot] Spring Boot 2.x에서 Spring Boot 3.x으로 버전 변경 (1) 2023.09.06 [Spring Boot] RedisTemplate을 이용한 Redis Data Type 확인 (0) 2023.07.02 [Spring Boot] ActiveMQ Queue, Topic 연동 (0) 2023.07.02 [Spring Boot] STOMP 사용 시 Interceptor 및 errorHandling 적용 (0) 2023.06.24