reactive 리팩토리..
모든 비지니스 로직이 하나의 흐름에 들어가야 하는 것이 맞는건가??
결과는 같지만 정확한 이해를 위해서 다시 한번 곱씹어 봤다.
반년전에 작성했던 코드를 다시 보니.. @.@
1. 적절한 리액티브 연산자를 사용자.
Reactive는 흐름을 만들어서 데이터의 조작한다.
기본적으로 flatMap( .. )으로 흐름을 이어주는 즉, 만들어주는 친구다.
예를 들어 보자.
return existsById(user.getId())
.flatMap(isOk -> ServiceUtil.getRedisService().delOpsForValue(Constants.REDIS_USER + user.getId()))
.flatMap(isOk -> userRepository.updatePassword(user.getPassword(), user.getId()))
.flatMap(just -> getUser(user.getId()));
1. 사용자가 있는지 체크하고
2. 레디스 정보 지우고
3. 사용자 업데이트 하고
4. 사용자 다시 조회 한다.
::
여러개의 flatMap을 하나의 flatMap으로 진행해도 무방하지만 코드의 가독성을 위해서... 어떤코드가 더 좋은지는..?..
어쨌거 최종 전달하는 데이터는 사용자다. 중간중간 무의미한 코드가 보인다.
아래와 같이... and()로 조지고 then()으로 고고싱한다.
return existsById(user.getId())
.and(ServiceUtil.getRedisService().delOpsForValue(Constants.REDIS_USER + user.getId()))
.and(userRepository.updatePassword(user.getPassword(), user.getId()))
.then(getUser(user.getId()));
2. Join이 맞는건지... 두번의 쿼리가 맞는건지..
public Mono<UserGrpc.User> getSimpleUser(String userID){
return ServiceUtil.getUserRoleService().searchUserRoles(userID)
.collectList()
.flatMap(userRoles ->
userRepository.findById(userID)
.switchIfEmpty(Mono.defer(()->Mono.error(new DefinedException("user info is null"))))
.flatMap(user -> {
UserGrpc.User userWithRole = user.toProtoWithRoles(userRoles);
return ServiceUtil.getRedisService().setOpsForValue(Constants.REDIS_USER + userID, ObjectUtil.getObjectToJsonByGson(userWithRole))
.then(Mono.just(userWithRole));
})
);
}
1. 사용자의 Role을 불러와서 List로 만들고
2. 사용자를 불러와서 Role를 적재하고
3. 레디스 저장하구 리턴S
:: 가만히 보면 Role을 포함한 한방 쿼리를 통해서 사용자를 조회 할 수도 있다.
물론 R2DBC가 JPA처럼 성숙한 친구가 아닌것이 일차적인 문제이긴 하지만 @Query( .. )를 지원해 주니.. 테스트 해 볼만한 가치가 있다고 생각한다. 한방 쿼리가 된다면 로직이 심플해 질 수 있다.
정답은 없다... 정답인척하는 근거만 찾자잉.. 물론 그 근거가 뒤집힌다고 해서.. 좌절한것도 없다..
3. 따로따로 해도 되는건지...
모든 비지니스 로직이 하나의 흐름으로 처리 해야 하는건지?
아니다.!!
1. 데이터를 발행하고
2. 데이터를 가공하고
3. 구독에서 처리하규
:: 이것이 하나의 Set이다.
public void update(UserGrpc.User request, StreamObserver<UserGrpc.User> responseObserver) {
ServiceUtil.getUserRoleService().delete(request.getId()).subscribe(); // 기존 삭제 로직
request.getRolesList().forEach(role ->
ServiceUtil.getUserRoleService().create(UserRole.builder().userId(request.getId()).roleName(role.getRoleName()).build())
.subscribe()
);
subscribe(ServiceUtil.getUserService().update(toDto(request)), responseObserver);
}
1. 기존의 Role 삭제하고
2. 새로운 Role 등록하고
3. 사용자 업데이트 하구
각 비지니스 역할마다 데이터 발행/가공 -> 구독처리를 하는 것이다.
즉,, 각각의 로직에서 흐름만 가주가면 될듯 하다.