Spring Reactive Programming
먼저 읽어보면 좋은 글
https://kimyhcj.tistory.com/343
함께 읽어보면 좋은 글
https://kimyhcj.tistory.com/346
언제 리액티브를 사용하는 것이 좋을지는 "먼저 읽어보면 좋은 글" 과 "함께 읽어보면 좋은 글" 에서 확인할 수 있다.
이벤트 스트림을 blocking 하지 않고 비동기로 처리하는 것이 최신 멀티코어 CPU의 사용률을 극대화 할 수 있는 방법이다. Spring 5 이전에는 동시성이란 것은 많은 Thread 였고 Thread 별로 다른 일을 하도록 하면 Thread 갯수만큼 동시에 여러일을 처리할 수 있는 것으로 이해했다.
그런데 시스템이 점점 분산되고(MSA), 많은 API 호출, 데이터 Access 등의 이유로 I/O 시간이 늘어나면서 Thread 점유가 길어짐에 따라 다양한 문제가 발생하게 된다.
- CPU, Memory 가 충분해도 Thread가 부족해서 처리율이 떨어지는 문제
- Thread를 늘릴수록 CPU, Memory 부하로 이어져 성능 저하 발생
- Thread 간 전환을 위한 Context Switching 으로 인한 부하
즉 Thread를 늘린다고 문제를 해결할 수 있는것이 아니라는 것이다.
리액티브 Framework 과 라이브러리는 Thread를 Future, Actor, Callback을 발생시키는 이벤트 루프등과 공유하고
처리할 Event를 변환하고 관리하기 때문에 Thread 보다 가볍다.
1초의 시간이 걸리는 API 를 2번 호출한다고 가정해 보자.
1. Sync / Blocking 방식
- API 두번 호출 시 총 2초 소요
2. 비동기 + 동시 요청
- 각각의 Thread 에서 동시 호출, 1초 소요
- Thread 2개 사용
3. 비동기 + 순서 보장
- 순서보장을 위해 비동기 호출에 대한 콜백을 이용, 2초 소요
- 호출해야 할 API 가 많을 경우 콜백지옥 발생
4. Async / Await + Blocking
- 코드만 보면 Thread 모델처럼 보이며 비동기로 처리됨
- 콜백지옥을 컴파일러가 해결
5. RestTemplate (Blocking) 이 아닌 Non-Blocking 방식을 사용 (ex. Webflux)
- 1초 소요
- Thread 1개 사용
리소스의 효율적인 사용을 위해서는
- Thread, CPU, Mmeory, Network 등을 최대한 효율적으로 활용해야 하며
- 그로인해 새로운 프로그래밍 모델이 필요하고 비동기 로직 구성과 Non-Blocking IO 가 필요하다는 것을 위의 예제를 통해 확인했다.
Java 의 Flow (Java 9 이상) class 는 리액티브 프로그래밍에 필요한 interface 를 규격화 해 두었고
RxJava 와 같은 라이브러리가 이를 잘 구현해 두었기 때문에 사용하면 된다.
무조건 Spring Reactive 를 사용해야 할까?
- Spring 개발자가 아니라면, Spring MVC로 별 문제 없다면, Blocking I/O 작업(ex. JPA, JDBC, MyBatis 등)이 있다면
API 호출이 전혀 없고 NoSQL 이나 Messaging Service 등을 사용하지 않는다면
그리고 개발팀이 커서 새롭고 도전적인 기술 학습과 시행 착오에 대한 부담이 있다면 사용할 필요가 없다.
- 그럼에도 요즘 기술 생태계가 리액티브를 좋아하고 적극 지원하고 있으며 Thread 모델의 Annotation 기반 Spring
이 아닌 새로운 프로그래밍에 도전하고 싶다면 공부해 보고 활용해 보는것이 중요하다.
참고:
- 토비 Youtube (https://youtu.be/8fenTR3KOJo)
- 우아한 형제들 기술 블로그 (https://techblog.woowahan.com/2619/)