[WebFlux] 💚 Webflux 그림으로 이해하기(Reactive프로그래밍)
아래의 개념정리는 유튜브 메타코딩의 spring boot weblflux강좌를 요약한 내용입니다.
webflux에 대한 개념이 1도 잡혀있지 않았는데 강의를 보고 진짜 금방 이해가 되었다. 정말 이해하기 쉽게 설명해주셨다.
Spring Webflux가 '왜' 나왔는가?
예를 들어, 아래와 같이 A가 몇시냐고 물어봤을때 그 대답을 얻기까지 과정은 아래의 프로세스에 따라서 진행이 된다.
하지만 이렇게 진행할 경우 두가지 문제점이 있다.
- 멍때리는 시간이 존재한다. 그 시간에 다른일을 못함
- 알고싶은 정보를 알기 위해선 항상 물어봐야한다.
그래서 이 문제점을 해결할 수 있는게 Reactive programing (반응형 프로그래밍)
Reactive programing (반응형 프로그래밍)이란, "요청이 있을때 멍때리지 않고 응답하는 방식"이다.
Reactive programing의 배경
Reactive programing (반응형 프로그래밍)을 이해하기에 앞서 그렇지 않은 방식일때의 문제점을 조금더 살펴보면 이렇다.
이렇게 client, server, db라고 생각하고 흐름을 이해해보자.
만약 db에서 10초가 걸린다고 했을때 server가 그걸 기다리면서 멍때린다면 무슨 문제가 발생할 것인가?
a의 요청을 해결하기 위해 계속 멍때리기 때문에 다른 클라이언트의 요청을 받지 못한다.
그래서 기존에는 이러한 문제를 해결하기 위해 스레드(thread) 방식을 사용했다.
Time slicing (타임슬라이싱) 방법으로 해야할 일을 쪼개서 진행했다.
하지만 이 경우 context switching 문제가 생긴다.
context switching은 붓을 바꾸는 행위라고 이해할 수 있다. (이해 쏙쏙비유 최고..)
아래 왼쪽 그림에선 빨/노/초를 색깔별로 한번에 색칠해서 순차적인 처리를 한다고 하면,
빨 쭉~그리고, 노 쭉~그리고, 초 쭉~그리면 붓을 3번만 바꾸면 된다.
하지만 오른쪽 그림처럼 빨한번, 노한번, 초한번 이렇게 하나하나씩 칠한다고 하면 그만큼 붓을 바꾸는 행위가 많아질 것이다.
그래서 context switching행위가 많이 생겨서 스레드를 생성하는 방법은 느려지게 된다.
스레드 방식으로 처리해도 느리다면 도대체 어떻게 처리해야하는가? '비동기처리'
이벤트 루프, 비동기처리로 멍때리지 않게!
서버가 db한테 요청을 보냈을때 db는 10초 걸릴것 같다고 바로 응답을 준다. 그리고 서버도 바로 클라이언트한테 응답을 준다.
그럼 이제 서버는 할일이 없어지기 때문에 다른 요청을 받을 수 있다. 즉 비동기처리가 가능해진다.
대신 a가 요청한 이벤트를 기억하고 있어야하는데, 이걸 이벤트 루프라고 부른다.
그리고 서버가 계속 요청을 받다가 잠깐 쉴 때 개발자가 이 이벤트 루프를 확인하게 한다.
근데 이전에 기억하고 있었던 a가 요청한 이벤트가 10초만 기다리면 된다고 했는데 지금 13초가 지나서 끝난 상황이다?
그러면 이제 서버는 이 내용을 a한테 응답 해준다.
결국 이렇게 이벤트 루프 덕분에 서버는 멍때리지 않고 여러가지 요청을 동시에 받고 기억할 수 있어서 비동기처리가 가능해진다.
Stream, 계속 물어보지 않게 응답유지!
HTTP 프로토콜 방식은 stateless이기 때문에 client가 요청을 보내고, server가 응답을 한번 보내면 그 선이 끊킨다.
근데 이러면 이벤트루프에서 기억하고 있었던 응답을 다시 보내줄수가 없게 된다.
그래서 응답을 안끊고 계속 유지시킨다.
즉 응답을 stream으로 만들어서 끊키지 않게 계속 유지시키는 것인데, 이걸 SEE 프로토콜 방식이라고 한다.
사실 웹소켓방식도 응답을 유지시키는 방법이다.
아래의 왼쪽처럼 요청이 있고 계속 응답을 유지하는게 웹소켓방식.
오른쪽처럼 요청은 필요없어서 요청을 끊고 응답만 계속 유지시키는게 SSE(Server Send Event)프로토콜 방식이다.
결국 이렇게 stream같은 SSE프로토콜방식 덕분에 클라이언트가 계속 물어보지 않아도 응답을 게속 유지시킬 수 있다.
Webflux의 탄생
이벤트 루프와 stream같은 SSE프로토콜방식으로 Reactive programing (반응형 프로그래밍)을 할 수 있다.
그래서 이걸 spring에 적용한게 Webflux다. (flux는 stream과 동의어로 '흐름'을 뜻한다)
webflux는 구독과 출판의 개념을 가지고 있다.
- 구독(subscribe) : response가 유지되고 있다
- 출판(publish) : 유지되고 있는 선으로 게속적으로 데이터를 응답해준다.
다른사람이 어떤 이벤트를 요청해서 데이터의 변경이 일어나면,
서버가 그 데이터를 바라보고있는 상대들한테 즉각적으로 push해줄수 있다.
일반적으로 RDBMS는 지원하지 않고, reactive를 지원하는 DB (mongodb,redis) 를 사용해야한다
최근에는 r2dbc라이브러리로 MySQL과 비동기방식으로 연결이 가능해졌다.
spring 5에서는 non-blocking(논블로킹)런타임이 추가되었다.
지금까지 Spring MVC는 서블릿 컨테이너에 Servlet API를 기반으로 한 프레임워크이었지만,
Spring WebFlux는 Servlet API를 사용하지 않고 Reactive Streams와 그 구현체인 Reactor를 기반으로 한 새로운 HTTP API이다.
그러니까, spring5가 되면서 reactive 라이브러리가 추가되었고, 그게 라이브러리가 Reactive Stream이며, 그 구현체가 Reactor이다.
그리고 Reactor의 객체는 mono와 flux 이다. 하나의 결과를 모아서 줄때는 mono를, 여러개의 값을 처리할때는 flux로 처리한다.
- mono는 한번 응답하고 끊나는 방식으로. 0~1개의 데이터 요청에 대해 응답할때 사용
- flux는 지속적으로 응답하는 방식으로, 1개 이상의 데이터요청에 대해 응답할때 사용