백엔드/Spring

[Spring] Reactive MongoDB Stream의 Flux, Mono 조회 방법 비교

작은소행성 2024. 11. 22. 13:30

 

Reactive MongoDB 를 사용할 때 Flux, Mono 는 데이터를 처리하는 중요한 두가지 방식이다. 

 

 

buffer 와 next 를 사용한 스트리밍 방식

Flux<ResultResponse> dataStream = mongoTemplate.aggregate(aggregation, "result_data", ResultResponse.class);

return dataStream
        .buffer(pageSize) // 요청한 사이즈만큼 버퍼링
        .next()           // 첫 번째 페이지만 가져오기
        .defaultIfEmpty(Collections.emptyList()) // 데이터가 없을 경우 빈 리스트 반환
        .map(res -> {
            String newLastSeenId = res.isEmpty() ? null : res.get(res.size() - 1).getId();
            PagedResponse<ResultResponse> pagedData = new PagedResponse<>(
                    res,
                    pageRequestDTO.getPage(),
                    pageRequestDTO.getPageSize(),
                    totalCount,
                    (int) Math.ceil((double) totalCount / pageRequestDTO.getPageSize()),
                    res.isEmpty() || res.size() < pageRequestDTO.getPageSize(),
                    newLastSeenId
            );
            return pagedData;
        });

 

 

 

limitRequest, collectList를 사용한 전체 데이터 처리 

Mono<Object> pageMono =
    mongoTemplate.aggregate(aggregation, "result_data", ResultResponse.class)
        .limitRequest(pageSize) // 한 번에 요청할 데이터 수 제한
        .collectList()          // 전체 데이터를 List로 수집
        .map(res -> {
            String newLastSeenId = res.isEmpty() ? null : res.get(res.size() - 1).getId();
            PageImpl<ResultResponse> pageResponse = new PageImpl<>(res, pageRequestDTO.toPageRequest(), totalCount);
            PagedResponse<ResultResponse> pagedData = new PagedResponse<>(
                    pageResponse.getContent(),
                    pageResponse.getNumber(),
                    pageResponse.getSize(),
                    pageResponse.getTotalElements(),
                    pageResponse.getTotalPages(),
                    pageResponse.isLast(),
                    newLastSeenId
            );
            return pagedData;
        });

 

요약

  첫 번째 코드 두 번째 코드
메모리 사용 메모리 효율적 (pageSize만큼만 메모리에 로드) 메모리 사용량 큼 (전체 데이터를 메모리에 로드)
성능 빠름 (필요한 데이터만 점진적으로 소비) 느림 (전체 데이터를 수집한 후 처리)
Reactive Streams 친화성 높음 (스트리밍 처리 방식에 충실) 낮음 (스트리밍 특성을 충분히 활용하지 않음)
적합한 데이터 크기 대규모 데이터 처리에 적합 소규모 데이터 처리에 적합
복잡성 약간 높음 (Reactive Streams의 동작을 이해해야 함) 낮음 (단순한 처리)

 

대규모 데이터 및 Reactive Streams 방식을 사용하려면은 첫번째 코드가 적합하다. 

반응형