Redis와 Spring을 위한 객체 매핑, 그리고 그 이상
Redis OM Spring은 Spring 애플리케이션에서 도메인 모델을 설계하고 데이터를 Redis에 손쉽게 저장할 수 있도록 돕는 새로운 클라이언트 라이브러리입니다. 이 라이브러리는 오픈소스 Redis와 함께 작동하며, 특히 RedisJSON과 함께 사용할 때 강력한 인덱싱과 쿼리 기능을 추가로 제공합니다.
Redis는 다양한 모듈과 결합하면 세상에서 가장 빠른 데이터 플랫폼 중 하나가 됩니다. 하지만 그 뛰어난 성능을 실제 개발 환경에서 활용하는 일이 늘 쉬웠던 것은 아닙니다. Redis OM Spring은 개발자에게 탁월한 개발 경험을 제공하며, 이 글에서는 Redis OM Spring으로 무엇을 만들 수 있는지 소개합니다.
개발 배경과 동기
개발자 입장에서 강력하면서도 사용이 간편한 기술을 만나는 일은 드뭅니다. 오픈소스 Redis만으로도 엔터프라이즈 애플리케이션에 필요한 다양한 데이터 처리 작업과 메시징 작업을 수행할 수 있는 방대한 데이터 구조와 명령어를 활용할 수 있습니다.
엔터프라이즈 자바(Java) 개발 분야에서 Spring은 지난 18년여 동안 대규모 애플리케이션 개발의 복잡성을 획기적으로 낮춰 왔습니다. 이 과정에서 Redis는 저수준 API부터 고수준 추상화까지 폭넓은 지원을 제공하는 Spring Data Redis 덕분에 Spring 생태계에서 훌륭하게 지원받아 왔습니다.
다만 Spring Data Redis에는 한 가지 한계가 있었습니다. 바로 Redis 모듈을 지원하지 않는다는 점입니다. Redis 팀은 검색, JSON 인덱싱 및 쿼리, 그래프 데이터, 시계열 데이터, 그리고 서버 측 연산을 위한 완전한 프레임워크인 Redis Gears까지, Redis 핵심 데이터 구조를 확장하는 여러 혁신적인 모듈을 개발해 왔습니다. Redis OM Spring은 바로 이러한 모듈들의 강력함을 십분 활용하고 더욱 폭넓은 기능을 제공하기 위해 만들어졌습니다.
Redis OM Spring이란?
Redis OM 클라이언트 라이브러리 계열은 개발자가 선택한 언어와 플랫폼에 맞는 자연스러운 방식으로 고수준 추상화를 제공하는 것을 목표로 합니다. 현재 Node.js, Python, .NET, Spring 커뮤니티를 위한 버전이 출시되어 있습니다. Redis OM Spring을 사용하면 Spring Boot 애플리케이션에 Redis의 강력한 기능을 손쉽게 통합할 수 있습니다.
특히 Redis OM Spring은 검증된 Spring Data Redis(SDR) 프레임워크를 기반으로 견고한 리포지토리(repository)와 커스텀 객체 매핑 추상화를 제공합니다.
현재 프리뷰(preview) 릴리스는 Spring Data Redis의 모든 기능을 포함하며, 여기에 더해 다음과 같은 기능을 제공합니다.
- 자바(Java) 객체와 JSON 간 매핑
- 향상된 해시(Hash) 매핑
- 검색 인덱스 자동 생성
- RediSearch 기반의 Spring Data 리포지토리
Java to JSON 매핑
RedisJSON을 사용해 저장된 JSON 문서와 자바 객체를 매핑하려면 @Document 어노테이션을 활용하면 됩니다. 다른 Spring Data 엔티티 매핑 어노테이션과 마찬가지로 클래스 선언부에 이 어노테이션을 추가하면 됩니다. 예를 들어 Company 타입의 객체를 매핑하고 싶다면 아래와 같이 @Document를 추가하기만 하면 됩니다.
클래스 내부에는 여러 가지 어노테이션이 사용된 것을 확인할 수 있습니다. 먼저 @Id는 Spring Data에서 제공하는 어노테이션으로, id 속성이 JSON 문서를 저장할 Redis 키가 되도록 선언합니다.
Spring Data 계열 라이브러리에서 가장 사랑받는 기능은 단연 선언형 데이터 리포지토리입니다. 이어지는 두 어노테이션은 RediSearch를 통해 JSON 문서를 인덱싱할 수 있게 해 주며, 이는 RedisDocumentRepository 인터페이스를 통해 노출됩니다.
내용이 비어 있는 리포지토리 선언만으로도 POJO에 대한 기본적인 CRUD 기능과 페이지네이션, 정렬 기능을 바로 사용할 수 있습니다.
Redis OM Spring은 @Indexed 또는 @Searchable 어노테이션이 붙은 POJO 필드를 기반으로 인덱스 스키마를 생성합니다. 앞선 Company POJO에서 name 속성은 'searchable'로 선언되어 있어, 해당 필드에 대한 전체 텍스트 검색(full-text search)이 가능합니다. 이는 스키마 필드 정의 $.name AS name TEXT에 반영됩니다.
반면 tags 필드는 'indexable'로 선언되어 TAG 타입의 인덱스 필드가 생성됩니다. 이는 필드 값과 정확히 일치하는 조건으로 회사를 검색할 수 있다는 의미이며, 스키마 필드 정의 $.tags[*] AS tags TAG로 나타납니다.
간단한 동적 쿼리 만들기
Redis OM Spring의 가장 매력적인 기능은 리포지토리 인터페이스만 정의하면 런타임에 구현체를 자동으로 생성해 준다는 점입니다. 필요한 필드만 인덱싱되어 있다면, 아래와 같은 다양한 쿼리를 단 한 줄의 추가 코드 없이 모두 수행할 수 있습니다.
리포지토리 프록시는 메서드 이름으로부터 저장소에 맞는 쿼리를 도출하는 두 가지 방식을 지원합니다.
- 메서드 이름을 분석해 직접 쿼리를 생성하는 방식
@Query또는@Aggregation어노테이션으로 직접 정의한 쿼리를 사용하는 방식
그럼 리포지토리 인터페이스에 추가된 몇 가지 메서드 선언을 살펴보겠습니다.
findOneByName
Redis OM Spring은 메서드 이름과 파라미터 정보를 활용해 적절한 쿼리를 자동으로 생성하고, 메서드의 반환 타입을 기준으로 결과를 어떤 형태로 감싸서 반환할지 결정합니다.
findOneByName은 Optional<Company>를 반환합니다. findOne이라는 이름은 여러 건의 결과가 존재하더라도 단 하나의 결과만 반환한다는 의미를 담고 있습니다. 라이브러리는 메서드 이름을 파싱해 필요한 파라미터의 개수를 판단합니다. 예를 들어 메서드 이름의 ByName 부분은 name이라는 이름의 파라미터 하나를 필요로 한다고 알려 줍니다.
findByLocationNear
Redis OM Spring은 지리 공간(geospatial) 데이터를 저장하기 위해 GeoJSON 타입을 지원합니다. 쿼리 메서드에 near 키워드를 사용하면 Point(org.springframework.data.geo.Point)와 Distance(org.springframework.data.geo.Distance) 타입을 파라미터로 전달받도록 동작합니다.
리포지토리 사용하기
다른 Spring Data 리포지토리와 마찬가지로, 생성된 리포지토리는 다른 Spring 컴포넌트에 간단히 주입(injection)해서 사용할 수 있습니다.
마무리하며
지금까지 소개한 내용은 Redis OM Spring의 프리뷰 릴리스 기준입니다. 아직 만들어야 할 기능이 많지만, 그만큼 여러분의 참여가 절실합니다! 프로젝트 README에서 Spring 애플리케이션에 Redis OM Spring을 설치하는 방법을 자세히 확인할 수 있으며, 여러분의 피드백, PR, 이슈 등록을 환영합니다!