R2DBC (Reactive Relational Database Connectivity)
- 관계형 데이터베이스에 리액티브 프로그래밍 API를 제공하기 위한 개방형 사양(Specification)
- 드라이버 벤더가 구현하고 클라이언트가 사용하기 위한 SPI(Service Provider Interface)
- R2DBC의 등장으로 관계형 데이터베이스를 사용하더라도 클라이언트의 요청부터 데이터베이스 접근까지 완전한 non-blocking 애플리케이션을 구현하는 것이 가능해짐
1. R2DBC를 지원하는 드라이버 목록
- ClilckHouse R2DBC Driver
- Google Cloud Spanner
- Jasync-sql MySQL
- Oracle R2DBC Driver
- R2DBC H2
- R2DBC MariaDB
- R2DBC MySQL
- R2DBC PostgreSQL
- R2DBC Proxy
- R2DBC SQL Server
참고 문헌: https://r2dbc.io/
Spring Data R2DBC
- R2DBC 기반 Repository를 좀 더 쉽게 구현하게 해주는 Spring Data Family 프로젝트의 일부
- Spring이 추구하는 추상화 기법이 적용되어 Spring Data JDBC나 Spring Data JPA 같은 Spring Data Family 계열의 기술을 사용해 보았다면 Spring Data R2DBC의 API 사용법 역시 친숙하게 느껴짐
- JPA 같은 ORM 프레임워크에서 제공하는 caching, lazy loading, 기타 ORM 프레임워크에서 가지고 있는 특징들이 제거되어 단순한 방법으로 사용 가능
- 여타 Spring Data Family 프로젝트와 마찬가지로 Spring Data R2DBC를 통해 데이터 액세스 계층의 보일러플레이트 코드의 양을 대폭 줄임
1. Spring Data R2DBC 설정 (h2 기준)
1.1 pom.xml 설정
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-r2dbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
<version>3.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.r2dbc/r2dbc-h2 -->
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-h2</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
1.2 schema.sql, data.sql 및 application.yml 설정
- Spring Data R2DBC는 Spring Data JPA처럼 엔티티에 정의된 매핑 정보로 테이블을 자동으로 생성해주는 기능이 없기 때문에 테이블 스크립트를 직접 작성해서 테이블을 생성해야 함
- 따라서 resource 폴더 하위에 schema.sql과 함께 초기 데이터 필요시 data.sql 파일 생성 후 application.yml에서 프로젝트 기동 시 파일 내용을 DB 내용에 반영하도록 설정 필요
1.3 R2DBC Repository와 Auditing 기능 활성화
- R2DBC용 Repository와 Auditing 기능 활성화를 위해 @EnableR2dbcRepositories와 @EnableR2dbcAuditing 추가 필요
2. 도메인 엔티티 클래스 매핑
- Spring Data JPA의 Entity와 비슷하지만 아쉽게도 @XToX와 같은 어노테이션을 지원하지 않아 외래키 설정 불가
- Spring Data R2DBC에서 제공하는 매핑 어노테이션
- @Id: 데이터베이스 테이블의 Primary Key로 지정
- @Table: 클래스를 특정 데이터베이스 테이블과 매핑
- @Transient: 해당 어노테이션이 붙은 필드는 데이터베이스에 저장되지 않으며 데이터베이스와의 매핑에서 제외시킴
- @PersistenceCreator: R2DBC에서 엔티티 생성자를 지정할 때 사용하며 여러 생성자 중 엔티티를 영속성 컨텍스트에 로드할 때 사용할 생성자 명시
- @Value: 기본 값으로 설정하거나 속성 주입 방식으로 사용할 때 사용
- @Column: 클래스의 필드를 데이터베이스 테이블의 특정 열에 매핑
- @Version: Optimistic Locking을 구현할 때 사용
- @CreatedDate: 생성 일시 자동으로 테이블에 반영
- @LastModifiedDate: 수정 일시 자동으로 테이블에 반영
참고 문헌: https://docs.spring.io/spring-data/relational/reference/r2dbc/mapping.html
3. ReactiveCrudRepository
- Spring Data R2DBC에서 제공하는 리액티브 프로그래밍 모델을 지원하는 인터페이스로 비동기적이고 non-blocking 방식으로 데이터베이스와 상호작용할 수 있도록 지원
- Mono와 Flux 같은 리액티브 타입을 반환하며 데이터베이스에서의 작업이 완료될 때 비동기적으로 결과를 처리
3.1 ReactiveCrudRepository vs JpaRepository
항목 | ReactiveCrudRepository | JpaRepository |
프로그래밍 모델 | non-blocking, 비동기 | 동기적 blocking 방식 |
반환 타입 | Mono<T>, Flux<T> | Optional<T>, List<T> |
ORM 지원 여부 | X | JPA 기반의 ORM 제공 |
트랜잭션 관리 | 수동으로 관리 필요 트랜잭션 지원이 제한적 |
자동 트랜잭션 관리 지원 |
대상 DB | R2DBC 지원하는 데이터베이스 | JPA를 지원하는 전통적인 RDB |
4. R2dbcEntityTemplate
- 템플릿/콜백 패턴이 적용된 JdbcTemplate처럼 R2dbcEntityTemplate 역시 템플릿을 사용
- JdbcTemplate은 SQL 쿼리를 직접적으로 템플릿에 전달
- R2dbcEntityTemplate은 JPA 기술에 사용되는 QueryDSL과 유사한 방식의 쿼리 생성 메서드의 조합과 Entity 객체를 템플릿에 전달하여 데이터베이스와 상호 작용
- R2dbcEntityTemplate은 SQL 쿼리문의 시작 구문인 SELECT, INSERT, UDATE, DELETE 등에 해당하는 select(), insert(), update(), delete() 메서드인 Entrypoint Method를 지원
- all(), count(), one() 등의 메서드처럼 SQL 문을 생성하고 최종적으로 SQL 문을 실행하는 메서드인 Terminating Method를 지원
- 또한, R2dbcEntityTemplate은 SQL 연산자에 해당하는 다양한 Criteria Method를 지원
4.1 Terminating Method
메서드 | 설명 |
first() | 조건에 일치하는 result row 중에서 first row를 얻고자 할 경우 사용 만약 조건에 일치하는 row가 없다면 Mono<Void>를 반환 |
one() | 조건에 일치하는 result row가 단 하나일 경우 사용 만약 조건에 일치하는 row가 없다면 Mono<Void>를 반환 result row가 한 건보다 많을 경우 Exception 발생 |
all() | 조건에 일치하는 모든 result row를 얻고자 할 경우 사용 |
count() | 조건에 일치하는 데이터의 건수만 조회할 경우 사용 반환 타입은 Mono<Long> |
exists() | 조건에 일치하는 result row가 존재하는지 여부를 확인하고자 할 경우 사용 반환 타입은 Mono<Boolean> |
4.2 Criteria Method
메서드 | 설명 |
and(String column) | SQL 쿼리문에서 and 연산자에 해당 파라미터로 주어지는 컬럼명에 해당하는 Criteria를 추가한 새로운 Criteria 반환 |
or(String column) | SQL 쿼리문에서 or 연산자에 해당 파라미터로 주어지는 컬럼명에 해당하는 Criteria를 추가한 새로운 Criteria 반환 |
greaterThan(Object o) | SQL 쿼리문에서 '>; 연산자에 해당 'greater-than' Criteria를 추가한 새로운 Criteria 반환 |
greaterThanOrEquals(Object o) | SQL 쿼리문에서 '>=' 연산자에 해당 'greater-than or equal to' Criteria를 추가한 새로운 Criteria 반환 |
in(Object... o) in(Collection<?> collection) |
SQL 쿼리문에서 'IN' 연산자에 해당하는 Criteria를 추가한 새로운 Criteria 반환 |
is(Object o) | SQL 쿼리문에서 '=' 연산자에 해당하는 Criteria를 추가한 새로운 Criteria 반환 |
isNull() | SQL 쿼리문에서 'IS NULL' 연산자에 해당되는 Criteria를 추가한 새로운 Criteria 반환 |
isNotNull() | SQL 쿼리문에서 'IS NOT NULL' 연산자에 해당되는 Criteria를 추가한 새로운 Criteria 반환 |
lessThan(Object o) | SQL 쿼리문에서 '<' 연산자에 해당되며, 'less-than' Criteria를 추가한 새로운 Criteria 반환 |
lessThanOrEquals(Object o) | SQL 쿼리문에서 '<=' 연산자에 해당되며, 'less-than or equal to' Criteria를 추가한 새로운 Criteria 반환 |
like(Object o) | SQL 쿼리문에서 'LIKE' 연산자에 해당되는 Criteria를 추가한 새로운 Criteria 반환 |
not(Object o) | SQL 쿼리문에서 '!=' 또는 'NOT' 연산자에 해당되는 Criteria를 추가한 새로운 Criteria 반환 |
notIn(Object... o) notIn(Collection<?> collection) |
SQL 쿼리문에서 'NOT IN' 연산자에 해당되는 Criteria를 추가한 새로운 Criteria 반환 |
5. Spring Data R2DBC Pagination
- 다른 Spring Data 패밀리 프로젝트에서의 페이지네이션 처리와 유사
- Spring Data 패밀리 프로젝트에서 사용하는 Pageable을 이용해서 페이지네이션을 적용하는 방법은 동일하지만 반환 타입이 List<T>가 아니라 Flux<T>라는 차이점 존재
참고
- 스프링으로 시작하는 리액티브 프로그래밍 (황정식 저자)
반응형
'Spring > 스프링으로 시작하는 리액티브 프로그래밍' 카테고리의 다른 글
[Spring WebFlux] WebClient (0) | 2024.10.07 |
---|---|
[Spring WebFlux] 예외 처리 (0) | 2024.09.16 |
[Spring WebFlux] 함수형 엔드포인트(Functional Endpoint) (0) | 2024.09.06 |
[Spring WebFlux] 애너테이션 기반 컨트롤러 (0) | 2024.08.20 |
[Reactor] 자주 사용되는 Operator (0) | 2024.08.11 |