Web/Spring

Spring WebFlux 세팅과 구현 방식 Reactive Programming in Spring Framework

TLdkt 2022. 10. 18. 15:27
728x90
반응형

🚀들어가며

Reactive Programming을 학습하다 보니, 늘 서비스의 확장 가능성을 고민해야 하는 입장으로서 지금 당장 쓰지는 않더라도 확실하게 내용을 정리해야겠다는 생각이 들었다.

이전에 포스팅했던 넷플릭스의 Zuul 2 도입기에서 기존 블로킹 코드와의 충돌 부분을 흥미롭게 읽었는데,

Webflux에서도 JPA의 트랜잭션이 블로킹이 적용된 코드이므로 연동을 지원하지 않는다는 내용을 보고 왠지 뿌듯했다! 

그럼 바로 본론 시작~

 

 


참고로 아래 작성한 프로젝트는 회원이 커피를 주문하고, 스탬프를 적립받는 시스템의 일부다.

커피를 주문하면 스탬프를 찍어주는 기능이 있다보니 회원정보에 스탬프 필드가 들어가 있다.

그 외에 기본적인 CRUD는 보편적인 방식으로 구현했으나, 궁금한 점이 있으시면 댓글 달아주시길!

 

 

1️⃣Webflux 사용을 위한 사전 설정

build.gradle

 

application.yml

DB.Schema

Spring application. class 설정

 

 

2️⃣Controller구현과 특징

  • @RequestBody 를 Mono 래핑
    • 바로 오퍼레이터 체인 적용 가능
    • reactor의 mono.오퍼레이터() X requestbody.오퍼레이터()O
  • 모든 데이터 객체를 Mono, Flux로 래핑
    • 응답객체는 보통 하나이므로 mono를 자주 쓴다
  • PageRequest객체를 컨트롤러에서 미리 생성
    • 시퀀스 내부에서 재사용되어야 하므로!
  • 리턴되는 데이터가 없는 경우 Mono<void>

 

3️⃣Entity 구현과 특징

  • Spring Data family 프로젝트의 최소 설정만 포함해야 함
    • 기본 지원 Auditing 기능 활용 가능
    • @CreatedDate, @LastModifiedDate
  • @Id
    • 외래키 갖는 엔티티 클래스는 직접 해당 클래스에 추가해줘야 함
  • R2DBC는 애너테이션, 컬렉션을 이용한 연관관계 매핑 지원하지 않음
    • 내부적으로 블로킹 요소가 포함될 가능성이 있기 때문→라이브러리 사용시에도 주의!

 

4️⃣Service 구현과 특징

 

의존성 주입, createMember()

 
  • R2DBC의 데이터 접근방식
    • Repository방식
    • R2DBC가 지원하는 SQL 쿼리 빌드 메서드 방식
  • 모든 데이터 객체가 mono, flux 타입이므로 바로 오퍼레이터 체인 연결
  • then() 오퍼레이터
    • 이전에 동작하던 시퀀스를 종료(verify~ 시퀀스인듯)
    • 새로운 시퀀스 시작
  • 자동 인식을 지원하지 않으므로 직접 repository나 쿼리 코드 짜야 함
    • ex: R2dbcEntityTemplate. insert()
  • 반드시 코드 마지막에 subscribe() 호출해야 함

 

 

updateMember()

 
  • switchIfEmpty(퍼블리셔) 오퍼레이터
    • emit되는 데이터가 없다면 파라미터가 대체 동작 수행
  • BeanUtils.copyNonNullProperties(member, findMember)
    • 첫 파라미터에 들어온 데이터 중 null이 아닌 값만
    • 두번째 파라미터(db조회한 값)에 반영

 

 

findMember(), findMembers()

 
  • collectList() 오퍼레이터
    • 리스트로 변환해 emit
  • 호출한 오퍼레이터.zipWith(파라미터 Mono)
    • 호출한 오퍼레이터의 Mono와
    • 파라미터 Mono를
    • Tuple2 객체로 결합해서 전달
  • new PageImpl<>(데이터1, 페이지리퀘스트, 데이터2)

 

 

 

 

deleteMember()

 
  • R2dbcEntityTemplate.delete(SQL쿼리빌드메서드체인 )
  • 외래키로 관계를 맺는 테이블의 경우
    • 외래키가 있는 쪽에서 외래키 먼저 삭제
    • 이후 기본키 쪽 삭제

 

 

 

5️⃣Repository 구현과 특징

  • R2dbcRepository
    • CRUD,페이지네이션, 정렬기능 모두 포함함

 

 

 

👏나가며

기존에 익숙하게 사용하던 JPA에서 지원하던 기능들이 사라지면서 확실히 기초가 탄탄해야 함을 느꼈다. 특히 템플릿 부분이 잘 기억이 안 나서 복습이 필수라고 체감했다... 

 

또, 넷플릭스에서 Zuul2를 도입하면서 기존의 블록킹 코드를 찾아내고, 변경하느라 애를 먹었다는 내용이 끊임없이 강조되는 걸 보면서(ㅋㅋㅋㅋ) 어떤 기술을 사용할 때 장점만을 기대하며 도입해서는 안 되겠다는 교훈을 얻게 되었다. 넷플릭스 오픈소스인 Zuul2의 코드는 어떻게 구현되어 있을지 분석하는 포스팅도 작성해보고 싶다.

 

728x90
반응형