전통적인 반응형 프로그래밍 케이스는 보통 유저 이벤트.
버튼 클릭, io 작업 등...
그렇다면 서버에서의 백엔드에선 어떤 일이 일어나고 있나?
순차적으로 작업이 일어난다. 그렇다면 왜 유저 이벤트같은 일이 일어나지 않는 서버사이드에서도 Reactive programming이 중요할까?
현대 애플리케이션의 3가지 중요한 점
많은 데이터와 사용자, 또한 클라우드를 이용한 서버를 다룬다.
Unnecessarily sequential, 불필요하게 순차적일 수 있다.
@GetMapping("/user/{userId}")
public User getUserDetails(String userId) {
User user = userService.getUser(userId);
UserPreferences prefs = userPreferencesService.getPreferences(userId);
user.setUserPreferences(prefs);
return user;
}
위의 코드에서 무슨 문제점이 있는가?
userService와 userPreferencesService에서 userId를 이용하여 데이터를 받아오고 있다. 하지만 둘은 아무련 연관관계가 없다.
userService가 끝날때까지 userPreferencesService는 기다려야된다. 순차적으로 처리가 일어나기 때문에 연관관계가 없는 일이지만 우리는 그 일이 끝나야만 다음 작업을 할 수 있다.
이는 단일 유저의 요청에의해 응답하는 싱글 애플리케이션이라면 문제가 없을 것이다. 하지만 우리는 Web Application이고, 많은 유저들이 이용하고 있다고 생각해보자.
Web Server는 request가 들어올때 그 유저가 쓰레드를 점유하고 자원을 사용하게된다. 문제는 위와같은 요청에서 요청이 오래걸리게 된다면? 그 시간동안 Thread 점유가 일어나게 되고, 결국 웹 서버의 쓰레드풀의 쓰레드가 전부 이용중이라면 유저들은 접속이 되지 않을 것이다.
Spring boot , Spring mvc 같은 프레임워크를 이용하고 있다면 Java backend developer 들은 Concurrency에대해 생각하지 않고 개발한다.
단일 요청을 처리하는 것과 같이 생각하고 개발을 해도 Spring 이라는 프레임워크가 알아서 다 추상화해서 처리해주기때문에 이런 부분에 대해 생각을 할 필요가 없음.
다만, 우리는 순차적인 차단 작업과, idling threads로 비용을 지불한다.
우리는 이 비용을 최소화 하고 싶다고 생각하고, 이를 해결하기 위해 병렬적인 방식을 이용하고 싶다. 이때 이용할 수 있는 방법이 Reactive Programming.
Java API로 제공되는 비동기적인 작업을 위한 CompletableFuture라는 기능이 있지만 너무 사용하기 복잡하고 한계점이 많기에 거의 사용되지 않는다고 한다.
- 개발자가 처리해야되는 일이 너무 많다.
- 에러가 발생했을시 핸들링 해줘야된다.
- 코드가 너무 복잡해진다.
- 문제는 그럼에도 불구하고 여전히 마지막엔 동기화가 이루어져야 한다.
Reactive Programming의 장점
Reactive Programming은 서비스가 매우 작다면 필요가 없을 것이다. reactive programming을 하기위해선 좀 더 많은 노력과, 학습 커브가 필요하다. 다만 이는 애플리케이션이 확장되고 사용자 규모가 커짐에 따라 어떤 전환점을 넘게된다면 매우 큰 효과를 가져 올 것이다. 다만 그 이전에는 어떤 큰 이점이 없이 오버헤드를 감수하게 될 것이다.
Reactive Programming은 친숙하지만 다르다.