자바 객체를 JSON으로 매핑
저자: Brian Sam-Bodden
Redis 개발자 옹호자
소개
JSON 형식은 데이터 교환 및 저장 형식으로 널리 사용되고 있으며, 많은 전통적인 관계형 데이터베이스에서도 JSON을 네이티브 형식으로 지원하고 있습니다. CouchDB와 MongoDB 같은 여러 문서 지향 데이터베이스도 인기를 얻고 있습니다. JSON은 관계형 데이터베이스 스키마의 경직성을 제거하고 애플리케이션이 자연스럽게 진화할 수 있도록 합니다.
하지만 Redis가 JSON을 네이티브로 지원하는 완전한 문서 데이터베이스라는 것을 알고 계셨나요? Redis Stack은 JSON을 ReJSON-RL이라는 네이티브 Redis 데이터 유형으로 추가하고, 이는 Redis의 검색 및 쿼리 엔진과 원활하게 통합됩니다. 이 튜토리얼에서는 Redis OM Spring을 사용하여 간단한 문서 애플리케이션을 구축해 보겠습니다.
구축할 내용
회사의 POJO(Plain Old Java Objects)를 Redis에 JSON 문서로 저장하는 애플리케이션을 구축할 것입니다.
필요한 준비물
- 약 15분
- 좋아하는 텍스트 에디터 또는 IDE
- JDK 11 이상
- Gradle 4+ 또는 Maven 3.2+
- Docker / Docker Compose
Spring Initializr로 시작하기
Spring Initializr를 사용하여 기본 Spring Boot 애플리케이션을 생성합니다. 이 미리 초기화된 프로젝트를 사용하여 ZIP 파일을 다운로드하십시오. 이 프로젝트는 튜토리얼의 예제에 맞게 구성되어 있습니다.
- https://start.spring.io로 이동합니다. 이 서비스는 애플리케이션에 필요한 모든 종속성을 가져오고 대부분의 설정을 수행합니다.
- Gradle 또는 Maven과 사용하려는 언어를 선택합니다. 이 가이드에서는 Java를 선택했다고 가정합니다.
- 웹, Lombok, Spring Boot DevTools를 선택합니다.
- Generate를 클릭하여 ZIP 파일(roms-documents.zip)을 다운로드합니다. 이 파일은 선택한 구성으로 웹 애플리케이션을 포함한 아카이브입니다.
Redis OM Spring 추가하기
Maven을 사용하는 경우, pom.xml
파일에 다음 종속성을 추가합니다:
<dependency>
<groupId>com.redis.om</groupId>
<artifactId>redis-om-spring</artifactId>
<version>0.5.2-SNAPSHOT</version>
</dependency>
Gradle을 사용하는 경우, build.gradle
파일에 다음 종속성을 추가합니다:
dependencies {
implementation 'com.redis.om.spring:redis-om-spring:0.1.0-SNAPSHOT'
}
Redis 문서 리포지토리 활성화하기
생성된 애플리케이션에는 단일 파일, @SpringBootApplication
으로 주석이 달린 메인 애플리케이션이 포함되어 있습니다:
package com.redis.om;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.redis.om.spring.annotations.EnableRedisDocumentRepositories;
@SpringBootApplication
@EnableRedisDocumentRepositories(basePackages = "com.redis.om.documents.*")
public class RomsDocumentsApplication {
public static void main(String[] args) {
SpringApplication.run(RomsDocumentsApplication.class, args);
}
}
Redis 시작하기
Redis OM Spring은 Redis Stack의 강력함에 의존합니다. 아래의 Docker Compose YAML 파일을 사용하여 빠르게 시작할 수 있습니다. 이 파일을 프로젝트의 루트 폴더에 docker-compose.yml
로 저장하십시오:
version: '3.9'
services:
redis:
image: 'redis/redis-stack:latest'
ports:
- '6379:6379'
volumes:
- ./data:/data
environment:
- REDIS_ARGS: --save 20 1
deploy:
replicas: 1
restart_policy:
condition: on-failure
Docker Compose 애플리케이션을 시작하려면 명령줄에서 다음 명령을 실행합니다:
docker compose up
또한 Redis CLI 인스턴스를 시작하여 ROMS의 작업을 모니터링할 수 있습니다:
redis-cli MONITOR
도메인 엔티티
애플리케이션에는 Company
클래스가 포함됩니다. Lombok을 사용하여 게터와 세터를 생성할 필요가 없습니다. Lombok 주석 @Data
, @RequiredArgsConstructor
및 @AllArgsConstructor
를 사용합니다. 마지막으로, 클래스가 JSON 문서임을 나타내기 위해 @Document
주석을 사용합니다:
package com.redis.om.documents.domain;
import java.util.HashSet;
import java.util.Set;
import org.springframework.data.annotation.Id;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.index.Indexed;
import com.redis.om.spring.annotations.Document;
import com.redis.om.spring.annotations.Searchable;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@Data
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Document
public class Company {
@Id
private String id;
@NonNull
@Searchable
private String name;
@Indexed
private Set<String> tags = new HashSet<String>();
@NonNull
private String url;
@NonNull
@Indexed
private Point location;
@NonNull
@Indexed
private Integer numberOfEmployees;
@NonNull
@Indexed
private Integer yearFounded;
private boolean publiclyListed;
}
Redis OM Spring 문서 리포지토리
Redis OM Spring 문서 리포지토리를 사용하면 도메인 객체를 Redis JSON 키에 매핑하여 저장하고, 사용자 정의 매핑 전략을 적용하며, Redis가 유지 관리하는 보조 인덱스를 사용할 수 있습니다. 저장 및 검색을 담당하는 구성 요소를 만들기 위해 리포지토리 인터페이스를 정의해야 합니다. RedisDocumentRepository
는 Spring Data 리포지토리의 핵심 패키지에서 제공하는 PagingAndSortingRepository
를 확장합니다.
CompanyRepository
를 다음과 같이 생성합니다:
package com.redis.om.documents.repositories;
import com.redis.om.documents.domain.Company;
import com.redis.om.spring.repository.RedisDocumentRepository;
public interface CompanyRepository extends RedisDocumentRepository<Company, String> {
}
기본 CRUD 기능, 페이징 및 정렬 기능을 얻으려면 빈 리포지토리 선언만으로 충분합니다. CompanyRepository
는 RedisDocumentRepository
인터페이스를 확장합니다. 이는 CRUD 기능을 자동으로 구현합니다.
데이터베이스 미리 채우기
두 개의 Company
POJO를 Redis에 추가하여 데이터를 미리 채워보겠습니다. RomsDocumentsApplication
클래스에 CompanyRepository
를 추가하고, CommandLineRunner
를 사용하여 두 개의 Company
POJO를 생성하고 데이터베이스에 저장합니다:
package com.redis.om.documents;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.geo.Point;
import com.redis.om.documents.domain.Company;
import com.redis.om.documents.repositories.CompanyRepository;
import com.redis.om.spring.annotations.EnableRedisDocumentRepositories;
@SpringBootApplication
@Configuration
@EnableRedisDocumentRepositories(basePackages = "com.redis.om.documents.*")
public class RomsDocumentsApplication {
@Autowired
CompanyRepository companyRepo;
@Bean
CommandLineRunner loadTestData() {
return args -> {
companyRepo.deleteAll();
Company redis = Company.of("Redis", "https://redis.com", new Point(-122.066540, 37.377690), 526, 2011);
redis.setTags(Set.of("fast", "scalable", "reliable"));
Company microsoft = Company.of("Microsoft", "https://microsoft.com", new Point(-122.124500, 47.640160), 182268, 1975);
microsoft.setTags(Set.of("innovative", "reliable"));
companyRepo.save(redis);
companyRepo.save(microsoft);
};
}
public static void main(String[] args) {
SpringApplication.run(RomsDocumentsApplication.class, args);
}
}
애플리케이션이 실행 중이라면 재시작되었을 것입니다. 그렇지 않다면 mvn
명령을 사용하여 애플리케이션을 시작합니다:
./mvnw spring-boot:run
Redis CLI에서 키를 확인할 수 있습니다:
redis-cli
127.0.0.1:6379> SCAN 0 MATCH com.redis.om.documents.domain.Company*
간단한 동적 쿼리 생성
CompanyRepository
에 간단한 메서드를 추가하여 회사 이름으로 회사를 찾습니다:
package com.redis.om.documents.repositories;
import java.util.Optional;
public interface CompanyRepository extends RedisDocumentRepository<Company, String> {
Optional<Company> findOneByName(String name);
}
테스트 컨
트롤러
REST 컨트롤러를 생성하여 findOneByName
메서드를 테스트합니다:
package com.redis.om.documents.controllers;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.redis.om.documents.domain.Company;
import com.redis.om.documents.repositories.CompanyRepository;
@RestController
@RequestMapping("/api/companies")
public class CompanyController {
@Autowired
CompanyRepository repository;
@GetMapping("name/{name}")
Optional<Company> byName(@PathVariable("name") String name) {
return repository.findOneByName(name);
}
}
CURL을 사용하여 엔드포인트를 테스트합니다:
curl --location --request GET 'http://localhost:8080/api/companies/name/Redis'
지리 공간 데이터 저장 및 쿼리
CompanyRepository
에 지리 공간 쿼리 메서드를 추가합니다:
Iterable<Company> findByLocationNear(Point point, Distance distance);
컨트롤러에 지리 쿼리 메서드를 추가합니다:
@GetMapping("near")
Iterable<Company> byLocationNear(//
@RequestParam("lat") double lat, //
@RequestParam("lon") double lon, //
@RequestParam("d") double distance) {
return repository.findByLocationNear(new Point(lon, lat), new Distance(distance, Metrics.MILES));
}
CURL을 사용하여 테스트합니다:
curl --location --request GET 'http://localhost:8080/api/companies/near?lat=37.384&lon=-122.064&d=30'
네이티브 Redis Stack 검색 및 쿼리
@Query
및 @Aggregation
주석을 사용하여 네이티브 쿼리 API를 노출합니다:
@Query("@tags:{$tags}")
Iterable<Company> findByTags(@Param("tags") Set<String> tags);
CURL을 사용하여 테스트합니다:
curl --location --request GET 'http://localhost:8080/api/companies/tags?tags=reliable'
숫자 쿼리
숫자 속성을 사용한 다양한 쿼리 예제:
Iterable<Company> findByNumberOfEmployees(int noe);
Iterable<Company> findByNumberOfEmployeesBetween(int noeGT, int noeLT);
Iterable<Company> findByNameStartingWith(String prefix);
이 튜토리얼을 통해 Redis OM Spring의 기본 개념과 주요 기능을 이해하고, Spring Boot 애플리케이션에 Redis를 통합하는 방법을 배울 수 있습니다.