WebFlux 는 Spring Reative Streams 에서 제공하는 비동기 처리 라이브러리로, Controller 부터 시작해서 데이터 엑세스계층까지 모두 비동기처리가 될 경우 가장 빠른 응답을 기대할 수 있습니다.
병렬 처리 시 스케줄링은 WebFlux 에서 자체적으로 제공하는 Scheduler 를 사용할 수도 있고, 직접 설정할 수도 있습니다.
WebFlux 도입으로 성능개선을 하고자 한다면, 비즈니스 로직과 더불어 서버의 cpu, memory 등 가용한 리소스에 따라 전략적으로 구현하는 것이 가장 중요하다고 판단하고 있습니다.
전략을 세우고, 기존 개발과 병행하여, 학습부터 적용까지 약 4주가 소요되었습니다.
그러한 전략을 공유하고, WebFlux 를 어떤 식으로 도입했는지와 함께 얼마나 성능개선의 효과가 있었는지 공유하려고 합니다.
WebFlux 를 도입한 이유는 다음과 같습니다.
- 비즈니스 요청사항 : 제가 다루는 코드는 대용량 분석 시스템입니다. 분석 데이터가 증가되었으면 좋겠다는 요청사항에 따라, 추가적인 성능개선을 고려하게 되었고, WebFlux 를 도입하기로 결정하였습니다.
- 많은 I/O 작업: 외부 API를 활용하는 I/O 작업이 많기 때문에, 비동기처리를 도입하는 것이 가장 적합하다고 느껴졌습니다.
- 부하 분산 전략: 외부 API 역시 저희가 관리하는 서버이기 때문에, 과부하를 방지하기 위해 리액티브 라이브러리에서 제공하는 스트림 api로 백프레셔 전략 적용, 부하 분산하는데 수월할 것으로 예상하였습니다.
- 메모리 사용량 절약: 대용량 데이터 분석이기 때문에 서버의 메모리를 최소화하여 사용하고자 했기 때문에, 이벤트 루프 기반의 WebFlux 가 우선적으로 고려되었습니다.
굳이 WebFlux 의 단점을 꼽자면, 학습 곡선이 다소 존재한다는 점(Mono, Flux 개념 등), 디버깅이 다소 어렵다는 점입니다. 따라서 구현에 앞서서 책 한권을 정독하였습니다.
기본적인 WebFlux 에 대한 설명은 다음 글에 있습니다.
실제 저희 시스템의 문제와 해결에 대해 서술하도록 하겠습니다.
1. 기존 문제점
배경
다음과 같은 순서에 따라서 분석이 진행됩니다.

데이터 하나씩 처리하면서 서버의 리소스를 효율적으로 사용하지 못하고, 처리에 시간이 오래 걸리는 상황입니다.
→ 비동기 처리 방식을 이용하여, 동시에 여러 데이터를 처리할 수 있도록 서버 성능 개선을 계획하게 되었습니다.

2. 해결 전략
- 아키텍처적 접근
- 알고리즘 서버 api 서버의 HPA 도입 및 조절
- cpu 사용량에 따라 pod 개수가 증가하도록 적절한 값을 도입하였습니다. 이를 위해 부하테스트를 진행했습니다.
- 부하테스트 시 고려한 점 : 분석 요청 client 수, k8s cpu/memory 사용량(k9s 활용), 분석 응답 시간(postman)
- 코드 최적화
- 초기 WebFlux 를 도입한 시점의 비동기 코드의 동작은 다음과 같았습니다.
- 데이터를 병렬 처리를 수행하기는 하지만, 각 단계가 동기적으로 구성되어있는 상황이었습니다. (각 함수에서 block() 호출) 각 데이터의 상태 관리를 위해서, 그리고 기존 코드의 구조를 유지하느라 다음과 같이 작성되었던 것으로 파악하였습니다.
- 초기 WebFlux 를 도입한 시점의 비동기 코드의 동작은 다음과 같았습니다.

2. 데이터를 파이프라인화 하여, 각 과정을 한 데이터마다 모두 비동기로 수행할 수 있도록 리팩토링을 수행했습니다.

3. 메모리 리소스 사용량을 줄이기 위한 전략을 도입하였습니다.
- 비동기를 도입함에 따라, 동기적으로 작동할 때 수행하는 작업들에 대해 메모리를 계속 유지하고 있는 문제가 해소되었습니다.
- 알고리즘 서버의 응답 파싱 단계에서 기존 응답을 GC 하도록 전략적으로 코드를 작성하였습니다. (null 초기화, Collection clear 메소드 사용)
3. 개선 효과
k9s, Azure Container service, Azure Application Insights, postman 을 활용하여 사용률과 응답시간을 측정한 결과는 다음과 같았습니다.
- 성능 개선
- 기존보다 처리할 수 있는 데이터량이 10배 증가하였습니다.
- 기존보다 분석 속도가 19.92% 감소하였습니다. (postman 응답시간 측정. )
- 메모리 사용량 개선
- 메모리 사용량이 38.27% 감소하였습니다. (Azure Container Monitoring 측정)
- 외부 api 의 과부하 개선
- 기존에는 알고리즘 서버에 과부하가 심하여 pod 개 최소 8개 이상 존재해야하는 문제점이 존재했는데, 이후에는 더 적은 개수로 유지해도 정상적으로 동작하는 것을 확인하였습니다.
- mongoDB 데이터베이스 서버에 발생하는 부하 감소한 것을 확인하였습니다. (Azure MongoDB 모니터링 측정)
- 분석 상태 추적
- 비동기로 동작하면서도 각 데이터의 상태를 관리할 수 있도록 Thread-Safe 자료구조를 활용하여, 동기적으로 처리될 때와 마찬가지로 데이터 분석 실패/성공 여부를 기록할 수 있도록 구현하였습니다. (AtomicInteger, ConcurrentHashMap 활용, onErrorMap, onError 등 Operator 사용)
4. 추가 개선 여부
- Azure KEDA 서비스와 Event Hub 를 도입
- 사용자가 대용량 데이터를 분석하려는 시점을 예측하여 (페이지 접근, 대용량 데이터 업로드 시 ), Event Hub 를 통해 메시지를 보내면, 그에 맞게 pod 개수를 미리 증가시키는 방식을 고려하고 있습니다.
- 데이터 엑세스 계층도 비동기 처리
- Non-Blocking NoSQL 모듈, R2DBC 등 데이터 엑세스 계층 적용도 non-blocking 으로 이루어진다면 커다란 성능 효과가 나타날 것으로 기대하고 있습니다.
- 학습 후 추후 적용기회가 생긴다면 도입할 예정입니다.
이번기회로 WebFlux 에 대해 더 자세히 알게 되고, 활용하여 유의미한 성과를 얻게 되어 의미가 큰 경험이었다고 생각합니다.
앞으로도 새로운 기술을 탐구하고 기술로 비즈니스 문제를 해결하는 개발자가 되도록 노력하려고 합니다.
지금까지 읽어주셔서 감사합니다.
'개발 > TIL' 카테고리의 다른 글
| WebFlux 란 (3) | 2025.07.27 |
|---|---|
| RestController 의 응답 객체가 직렬화되는 방법 (1) | 2025.07.21 |
| aop 를 활용한 로깅 시스템 구축/ 보안 적용/ transaction 이해하기 (0) | 2025.05.14 |
| [sql 튜닝] Chapter 5. 소트 튜닝 (2) | 2025.05.14 |
| [sql 튜닝] Chapter 4.3 해시 조인 4.4 서브쿼리 조인 (0) | 2025.05.08 |