Spring

Spring Reactive Data Persistence - 리액트 데이터 퍼시스턴스

비뀨_ 2022. 4. 9. 05:02

Spring WebFlux를 이용해서 Reactive를 구현했지만, DB가 Reactive하지 않고 막혀버린다면 Reactive하다고 할 수 없다.

 

스프링 데이터 리액티브 

스프링 데이터는 몽고DB(MongoDB), 카산드라(Cassandra), 레디스(Redis), 카우치베이스(Couchbase)로 데이터를 저장할 때 Reactive 프로그래밍 모델을 지원한다.

RDBMS, JPA리액티브 Repository가 지원되지 않는데, JDBC 드라이버도 블로킹 되지 않아야 하는데 그게 안 되기 때문이다.

 

하지만! DB가 리액티브가 아니어도 데이터를 가져와 리액티브 타입으로 변환하는 식으로 사용할 수 있다.

1.

// 데이터를 가져와서 리액티브로 변환
List<Member> members = repo.findByGender("male");
FLux<Member> memberFlux = Flux.fromIterable(members);

// 리액티브를 받아서 데이터 조작
// cart는 장바구니 개념이라고 가정해 봄
Iterable<Cart> cart = cartFlux.toIterable(); 
// 위는 Flux<cart>를 Iterable로 변환. 변환하면서 block()을 함.

cartRepository.saveAll(cart) // 카트 내역을 저장시킴

위의 코드들은 리액티브하다고 할 수도 없고 아니라고 할 수도 없다.따라서 Mono또는 Flux는 자제해야 한다.

 

블로킹되는 연산을 조금이라도 피하려면 Mono나 Flux를 구독(Subscribe)하면서 발행되는 요소 각각에 대해 연산을 수행하면 된다.

 

2.

// cart는 장바구니 개념
cartFlux.subscribe(cart->{
	cartRepository.save(cart);
});

둘 다 여전히 블락을 하지만, 1의 saveAll처럼 일괄적으로 하는 처리보다는 2번의 구독 시점에서 처리하는게 바람직하다.

 

 

몽고DB 리액티브 레포지토리 작성

 

몽고DB는 유명한 NoSQL DB 중 하나이며 문서형 DB다.

도메인 타입을 문서 구조로 Mapping하는 어노테이션을 도메인 클래스에 지정하고, 레포지토리 인터페이스를 작성하면 된다.

 

순서대로 알아보자

 

1. 몽고DB 활성화

<!-- 일반 몽고DB를 사용할 때 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

<!-- 리액티브로 몽고DB를 사용할 때 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>

리액티브를 알아볼 것이기 때문에 data-mongodb-reactive의 의존성을 추가한다.

 

2. 몽고DB Properties 추가

spring:
  data: 
    mongodb:
      host: mongodb.서버호스트주소
      port: 27018 --기본 값
      username: db사용자이름
      password: db사용자비번

 

3. 도메인(domain) 타입을 매핑

  • @Id : 문서 ID로 지정
  • @Document : 몽고DB에 저장되는 문서로 선언
  • @Field : 필드 이름을 지정
@Data
@RequiredArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE,force=true)
@Document  
//@Document(collection="meeeember") 라고 쓰면 meeeember라는 이름으로 컬렉션이 만들어짐
public class Member {
    @Id
    private final String id;
    private final String pw;
}

4. 리액티브로 레포지토리 인터페이스 작성

@CrossOrigin(origins="*")
public interface ProductRepository 
         extends ReactiveMongoRepository<Product, String> {
	Flux<Product> jpa메소드이름();
}

Reactive Repository를 만들기 위해서

ReactiveCrudRepository 또는 ReactiveMongoRepository 중 하나를 선택할 수 있다.

  • ReactiveCrudRepository : 새로운 문서 or 기존 문서의 save에 의존
  • ReactiveMongoRepository : 새로운 문서의 저장에 최적화

쉽게 말해서 고정된 값이 많고 변동사항이 없다면 Crud를 사용하고,

변동 사항이 많다면 Mongo를 사용하도록 한다.