저고데

[Spring Boot]7. 스프링 부트에서 리액티브란? 본문

Spring Boot

[Spring Boot]7. 스프링 부트에서 리액티브란?

진철 2023. 12. 29. 14:13
728x90
반응형

스프링은 리액티브 프로그래밍을 어떻게 사용할까?
구체적인 사용법을 예로 들자면, 스프링 부트와 프로젝트 리액터를 기반으로 SQL, NoSQL DB와의 엑세스를 구동하는 방식이 있다.

 

리액티브 프로그래밍이란

리액티브 프로그래밍이란 대규모 트래픽을 처리하는 데 있어서 효과적이다.

그말은 즉, 동시적인 작업이 수행하다라고도 할 수 있겠다.

일반적인 서비스는 처리할 요청(트래픽)이 발생하면 각 스레드가 생성되는데, 각 스레드는 자원을 사용하기 때문에 한 어플리케이션이 생성할 스레드는 제한이 있다.

리액티브 프로그래밍은 다음과 같은 확장성 문제를 해결하는 데 사용된다.

응답성, 회복력, 탄력석, 메시지 기반이 큰 특징이며, 최소한의 자원으로 작업의 효율을 높인다.

또한 서비스는 하나의 어플리케이션으로만 이루어지지 않고 여러 어플리케이션의 통신을 하면서 사용이 되는데, 대부분의 문제는 이러한 통신으로부터 발생한다고 해도 과언이 아니다.

 

리액티브 스트림

따라서 통신 문제를 해결하기 위해서 리액티브 스트림이 개발되었으며 비동기식 통신과 처리를 기반으로 구축되었다.

비동기식 통신이란 비유를 하자면, 식당 차례를 기다릴 때, 번호표를 뽑고 가게 앞에서 기다리는 것이 아니라, 다른 곳에서 쇼핑을 하다가 알람이 울리면 차례에 들어가는 것이다. (동기식은 이와 반대로, 번호표를 뽑고 가게 앞에서 기다리는 것이다. 즉, 대기하는 동안 다른 일을 하지 못한다.)

이는 서비스 간의 상호작용을 위해 API, 사양, 구현 예제, 기술 호환성 키트(TCK : 호환성 수준과 결함을 검사하고 입증, 넷 중에서 가장 중요하다.)에 초점을 둔다.

또한 논블로킹 백프레셔를 추가하여 통신 간의 흐름 제어와 견고성을 부여하였다.

논블로킹 백프레셔는 서비스 간의 감당 가능한 자원 양을 전달하는 일종의 방파제 역할을 한다.

응답 처리 능력을 다른 서비스에게 전달하는 셈이다.

백프레셔가 없다면 서비스 간의 응답하는 엄청난 양을 보호할 수단이 없는 상태로 정보를 요청하기 때문에 어플리케이션의 리소스가 정보의 폭주할 것이다.

따라서 리액티브 스트림에서 백프레셔는 서비스에 들어오는 응답 속도를 관리하고 설정, 조정한다.

 

프로젝트 리액터

JVM에서 가장 많이 사용되는 리액티브 스트림 구현체는 프로젝트 리액터이다.

스택의 맨 윗단부터 아랫단까지 종단간 end to end의 리액티브 파이프라인을 제공하기 때문에 완벽한 솔루션이다.(아직 사용해보진 않았지만 책에서 극찬을 아끼지 않았다 ㅎㅎ)

end to end에 파이프라인을 제공한다는 것은 모든 스택이 리액티브 서비스의 이점을 얻을 수 있다를 의미한다.

이전에 ArrayList에서 자주 사용한 Iterable과 달리 Mono(0 or 1), Flux(0 or n개)의 퍼블리셔를 정의한다.

또한 리액터는 스프링의 방향성과도 매우 자연스럽게 일치하기 때문에 블로킹 코드를 논블로킹 코드로 변환하려면 간단하게 의존성과 메서드 반환값만 변경하면 된다.

 

Tomcat and Netty

얼핏보면 동물농장 같지만 이는 자바 웹 개발에서 중요한 요소이다.

Tomcat, Netty는 기본 서블릿 엔진이다.

서블릿(Servlet)은 자바 언어로 작성된 웹 애플리케이션의 구성 요소 중 하나로, 웹 서버에서 동작하는 자바 클래스이다.

클라이언트의 요청을 처리하고 동적인 웹 페이지를 생성하는 역할을 하며, 기본적으로 서블릿은 웹 서버에서 동작하며, 클라이언트의 요청에 응답하기 위해 사용된다.

이러한 서블릿을 실행시키기 위한 소프트웨어나 라이브러를 서블릿 엔진이라고 한다.

Tomcat은 스프링 MVC로부터 요청을 수신하고 서비스를 도와주는 반면, Netty는 스프링 리액티브인 스프링 웹플럭스로부터 요청을 수신하여 서비스를 하는 네트워크 엔진이다.

Tomcat도 최근 들어서 비동기식 엔진을 지원하지만 Netty가 성능이 입증된 비동기식 엔진이라고 할 수 있다.

 

리액티브 데이터 엑세스, R2DBC

아마 서비스에서 가장 많은 처리량이 이루어지는 것은 데이터일 것이다.

따라서 효율적인 리액티브 시스템을 구현하기 위해서는 어떻게 DB를 접근할 것이냐로부터 결정된다.

가장 이상적인 방법은 요청하는 어플리케이션과 정교한 흐름 제어, 백프레셔 메커니즘을 블로킹하지 않고 작업을 수행하는 것이다.

이전에는 JPA, H2 DB를 이용하여 코드를 짰었는데, 이는 명령형 사양을 기반으로 구축된 블로킹 방법이다.

따라서 논블로킹 리액티브 방식을 사용하기 위해서 R2DBC가 개발되었다.

JPA와 달리 R2DBC는 프로젝트 리액터의 리액티브 스트림 구현을 기반으로 하며 완전히 리액티브하고 논블로킹이다.

 

리액티브 프로세스 통신, RSocket

소켓은 시스템 프로그래밍에서도 나오고, 앞서 웹소켓도 나오고 프로세스 간 통신에서 빠질 수 없는 친구이다.

그중에서 RSocket은 리액티브 스트림을 사용한 프로세스 간의 통신이다.

초고속 이진 프로토콜로 속도가 매우 빠르다.

요청-응답, 요청-스트림, 실행 후 무시, 요청 채널(양방향)과 같은 네 가지 비동기 상호작용 모델을 지원한다.

서비스 간의 연결이 이루어지면, 클라이언트와 서버 간의 구분이 사라지는 것이 특징이다.

무엇보다 탄력적이기 때문에 끊어진 연결을 다시 설정하고 중단된 지점에서 자동으로 통신을 재개할 수 있다. (스프링 부트는 '자동'이라는 특징이 대부분인 것 같다.)

RSocket은 HTTP 주소/엔드포인트처럼 루트 경로를 기반으로 구축하지 않기 때문에 '/'로 매핑하지 않는다.

엔드포인트와 서비스 메서드가 정의된 후에는 RSocket이 연결 요청을 수신할 포트를 application.properties에서 지정해야한다.

 

728x90
반응형