[WebFlux] 비동기 개발
15 Apr 2024
비동기 개발과 주의점
기본 개념
- 리액티브 프로그래밍은 데이터의 흐름과 그에 따른 변화에 중점을 둔 프로그래밍 패러다임.
- 시스템 전체의 반응성 향상을 위해 비동기적 데이터 스트림 처리에 초점.
- 리액티브 스트림은 발행자와 구독자 간의 상호작용 기반.
- 발행자는 데이터 생성 및 구독자에게 전달. 구독자는 데이터 처리.
- 백프레셔는 구독자의 처리 능력에 맞게 데이터 전송 속도 조절, 리소스 과부하 방지.
- 리액티브 프로그래밍은 대규모 데이터 처리, 복잡한 데이터 스트림, 높은 동시성 요구 시스템에 적합.
백프레셔
- 리액티브 스트림에서 중요한 개념. 구독자가 처리할 수 있는 데이터량을 제어.
- 발행자와 구독자 사이의 데이터 전송 속도 차이로 인해 빠른 발행자가 느린 구독자를 침범할 위험 상황을 방지.
- 구독자는 받을 준비가 되면 발행자에게 알려, 그에 따라 데이터 전송.
- 빠른 발행자와 느린 구독자 간의 균형을 유지하며, 리소스 과부하와 메모리 누수 방지.
- 다양한 전략을 통해 구현 가능.
- 버퍼링: 데이터를 일시적으로 저장하여, 데이터의 묶음으로 구독자에게 전달하는 방법.
- 드롭: 느린 구독자가 데이터를 처리할 시간이 없는 경우, 일부 데이터를 삭제하는 방법.
- 에러 반환: 데이터의 처리가 불가능한 경우, 에러를 발생시키는 방법.
스케줄링과 병렬처리
- 리액티브 프로그래밍에서의 스케줄링은 작업을 어떤 스레드에서 실행할지 결정.
- 스케줄러를 사용하여 비동기 및 병렬 처리를 쉽게 구현.
- 병렬처리는 여러 작업을 동시에 처리하여 시스템의 전체적인 효율성 향상.
- 리액티브 스트림의 연산자를 활용해, 원하는 스레드에서 데이터 처리 지정.
- 병렬처리는 리소스 활용을 극대화하지만, 동기화와 스레드 안전성 문제 주의 필요.
연산자
- 리액티브 스트림에는 다양한 연산자가 제공, 데이터 스트림 처리의 핵심 요소.
- 연산자는 스트림의 데이터를 변환, 필터링, 병합 및 그룹화하는데 사용.
- 데이터 변환: map 연산자를 사용하여 스트림의 요소들을 가공하고 새로운 스트림을 생성하는 등, 각 요소의 데이터 변환 가능.
- 데이터 필터링: filter 연산자는 주어진 조건에 맞는 요소만을 포함하는 새로운 스트림을 생성하며, 이를 통해 불필요한 데이터를 제거하거나 원하는 데이터만을 선택 가능.
- 데이터 병합: merge 연산자는 여러 스트림을 하나의 스트림으로 합칠 때 사용되며, 이를 통해 여러 소스로부터 오는 데이터를 단일 스트림으로 처리 가능.
- 데이터 그룹화: groupBy 연산자를 사용하여 스트림의 요소를 그룹화하고 각 그룹에 대한 집계 작업을 수행하는 등, 데이터 통계 또는 분석 가능.
- 연산자를 연결하여 복잡한 데이터 플로우 및 처리 로직 구성.
- 올바른 연산자 선택과 조합은 효과적인 데이터 처리와 최적의 성능을 보장.
에러 핸들링
- 에러가 발생할 경우, 해당 스트림은 종료됨. 복구 전략이 필요.
- onErrorResume, onErrorReturn 등의 연산자를 활용하여 에러 상황에 적절히 대응.
- onErrorResume: 에러 발생 시, 백업 스트림으로 전환하여 계속 데이터 처리.
- onErrorReturn: 에러 발생 시, 에러 대신 특정한 값을 반환.
- 이 연산자들은 에러 발생 시 대체 값 제공하거나 다른 스트림으로 전환.
- 적절한 에러 핸들링 전략은 시스템의 안정성을 보장하고, 예기치 않은 문제로부터 시스템을 보호.
테스트
- Spring Boot의 WebTestClient와 같은 테스트 도구가 리액티브 애플리케이션 테스트 지원.
- 비동기적 특성으로 인해, 가상 시간을 사용한 테스트나 테스트 시간 조절 가능.
- StepVerifier를 활용하여 리액티브 시퀀스 검증.
- 반응성, 백프레셔 처리 등 리액티브의 특징을 고려한 테스트 전략이 필요.
API 디자인
- 리액티브 API 설계 시, 클라이언트의 리액티브 지원을 검토.
- 모든 API를 리액티브로 만들 필요 없음; 사용 케이스와 성능 요구사항에 따라 결정.
- 데이터의 연속성, 백프레셔 등을 고려하여 리액티브 API 디자인.
- 스트리밍이나 서버 푸시를 활용하여 향상된 사용자 경험 제공.
로깅과 모니터링
- 여러 스레드와 문맥 전환 때문에 ThreadLocal 기반 로깅이 제대로 동작하지 않을 수 있음.
- MDC 같은 로깅 방법은 리액티브 환경에서 문제 발생 가능성.
- 로깅 라이브러리 선택 시, 리액티브 지원 여부 확인이 중요.
- 백프레셔, 레이턴시 등 리액티브 이슈에 대한 모니터링 전략 필요.
성능 튜닝
- 리액티브 시스템의 성능은 설정, 연산자 선택, 데이터 처리 방식 등에 따라 변동.
- 성능 테스트 도구로 리액티브 애플리케이션의 부하와 특징을 모의 테스트.
- 스레드 풀 크기, 백프레셔 전략, 버퍼 크기 등을 조절하여 성능 튜닝.