1. 동기의 장점
1. 코드의 간결성과 가독성
- 동기 코드는 작성 및 읽기가 쉽습니다. 작업이 순차적으로 진행되며, 로직을 따라가기 쉬워 디버깅과 유지보수가 편리합니다.
- 특히, 비동기 코드에서는 flatMap 체인이나 Reactive Streams의 복잡한 흐름을 이해하기 어려울 수 있습니다.
2. 단순한 요청/응답 처리
- 애플리케이션의 트래픽이 크지 않거나 I/O 작업이 많지 않은 경우, 비동기의 이점은 크지 않습니다.
- 단순한 CRUD API 또는 내부 서비스 호출 등에서 동기 방식으로 구현하면 불필요한 복잡성을 줄일 수 있습니다.
3. 비동기의 필요성이 없는 경우
- CPU 바운드 작업: 작업이 대부분 CPU 연산(예: 이미지 처리, 데이터 암호화 등)인 경우, 비동기 코드로 변경해도 성능 이점이 없습니다. 오히려 비동기 컨텍스트 전환 오버헤드가 성능을 저하시킬 수 있습니다.
- 짧은 요청 시간: 작업이 매우 빠르게 끝나는 경우(예: 간단한 메모리 내 연산), 비동기를 사용할 필요가 없습니다.
4. 팀의 기술 스택과 이해도
- 비동기 프로그래밍은 동기 방식보다 복잡하며, 팀원이 모두 비동기 프로그래밍을 이해하고 있어야 유지보수가 용이합니다.
- 트러블슈팅: 비동기 코드에서는 에러의 흐름을 추적하기 어려울 수 있으며, 디버깅 도구 사용이 필요할 수 있습니다.
5. 트랜잭션 관리의 어려움
- Spring에서는 전통적으로 @Transactional과 같은 동기 트랜잭션 관리가 널리 사용됩니다.
- 비동기 방식에서는 트랜잭션 컨텍스트 관리가 까다롭습니다. Reactor에서 TransactionalOperator를 사용해야 하며, 이는 추가적인 학습과 구현 노력이 필요합니다.
6. 레거시 시스템과의 호환성
- 기존에 동기 코드로 작성된 시스템과 통합해야 할 경우, 동기 방식으로 유지하는 것이 더 간단합니다.
- DB 라이브러리나 서드파티 API가 동기 방식만 지원하는 경우에도 동기 코드가 더 적합합니다.
7. 비동기의 오버헤드
- 비동기는 컨텍스트 스위칭과 Reactive Streams 관리에서 오버헤드가 발생합니다. 트래픽이 낮거나 작업량이 적은 환경에서는 성능 이점을 얻지 못하고 오히려 성능 저하를 초래할 수 있습니다.
- 작은 프로젝트나 간단한 API에서는 동기 방식이 더 효율적일 수 있습니다.
2. 비동기의 장점
- I/O 작업(WebClient 요청, DB 조회 등) 중에는 스레드가 블록되지 않아 더 많은 요청을 동시에 처리할 수 있습니다.
- 트래픽이 높거나 I/O 바운드 작업이 많은 경우 비동기 방식을 선택할 수 있습니다.
3. 비동기 적용하기
1) 비동기 처리의 순서 유지 원리
- Mono와 Flux의 체이닝
- Reactor의 Mono와 Flux는 체이닝을 통해 데이터를 순차적으로 처리할 수 있습니다.
- 각 단계에서 데이터를 변환하거나 처리한 결과를 다음 단계로 전달합니다.
- FlatMap과 Map
- map: 데이터를 변환하며, 비동기 처리가 필요 없는 경우 사용합니다.
- flatMap: 비동기 작업을 수행하고, 그 결과를 다음 단계로 넘깁니다.
- Context 유지
- Reactor는 체인의 순서를 자동으로 보장합니다. 이전 단계가 완료된 후에만 다음 단계가 실행됩니다.
2) 비동기 코드로 순차적 로직 유지하기
1. 기존 동기 코드 로직
현재 동기 코드는 다음 순서로 진행됩니다
- contentService.getContent를 통해 Content 조회
- 조회한 데이터를 가공하여 originIndex 생성
- referenceFilesRepository에서 referenceFiles 조회 및 가공
- WebClient로 요청 전송
- 요청 결과를 반환
3) 주요 변경 사항 설명
- 순차적으로 데이터 가공 유지
- flatMap을 사용해 각 단계가 완료된 후에만 다음 단계로 넘어가도록 보장합니다.
- 데이터 흐름이 Mono 체인에서 순서대로 전달됩니다.
- 데이터 가공 후 WebClient 요청
- OriginIndex를 생성한 후에만 referenceFiles를 조회합니다.
- referenceFiles 가공이 완료된 후에만 WebClient 요청을 보냅니다.
- 에러 처리
- 각 단계에서 발생하는 에러는 체인에서 자동으로 전파되며, 필요시 doOnError를 사용해 로깅하거나 적절히 처리합니다.
4. 결론
현재 코드는 데이터베이스 조회 및 외부 API 호출 등 I/O 작업이 많은 전형적인 I/O 바운드 작업 흐름을 가지고 있습니다. 비동기 프로그래밍(WebFlux, Reactor)을 효과적으로 사용하면 현재 코드의 동시 처리 성능을 더욱 높일 수 있습니다.
특히, 데이터베이스와 같은 I/O 작업을 Reactive 방식으로 변환하면 성능 개선 효과를 기대할 수 있습니다.
비동기로 변환할 코드도 데이터 가공 및 요청 순서를 명확히 유지하며, 필요한 경우 체인을 끊거나 조합하여 세부적인 로직을 커스터마이즈할 수 있습니다. 현재 동기코드를 수정하여 비동기 로직으로도 원하는 대로 동작할 수 있습니다. 적절한 순차 처리와 비동기의 장점을 살려 코드를 수정합니다.
'오늘의 공부 & 기록' 카테고리의 다른 글
랭체인 공부 (0) | 2024.06.25 |
---|---|
[Kubernetes] 쿠버네티스와 마이크로 서비스(Microservice) (0) | 2024.04.14 |
[MQTT] 에러 해결 과정 정리 (0) | 2024.04.03 |
api 동시 요청 수 제한하는 방법 (0) | 2023.12.11 |
HTTP 상태코드 (0) | 2023.09.30 |