📗 BOOK/스프링으로 시작하는 리액티브 프로그래밍

1장 리액티브 시스템과 리액티브 프로그래밍

미미누 2024. 11. 20. 22:40

리액티브 시스템(Reactive System)이란?

  • 어떤 이벤트나 상황이 발생했을 때, 반응을 해서 그에 따라 적절하게 행동하는 것을 의미한다.
  • 클라이언트의 요청에 즉각적으로 응답함으로써 지연 시간을 최소화한다.

리액티브 선언문

MEANS: 리액티브 시스템에서 주요 통신 수단으로 무엇을 사용할 것인지 표현한 것입니다.

비동기 메시지 기반의 통신을 통해서 구성요소들 간의 느슨한 결합, 격리성, 위치 투명성 보장

  • 위치 투명성: 사용자 및 응용 프로그램이 데이터가 어디에 저장되어 있는지에 대한 세부 정보를 숨긴다.

FORM: 메시지 기반 통신을 통해서 어떠한 형태를 지니는 시스템으로 형성되는지를 나타낸다. (탄력성, 회복성)

  • 탄력성(Elastic): 시스템의 작업량이 변화하더라도 일정한 응답을 유지하는 것을 의미한다.
  • 응답성을 유지하기 위해서 입력을 처리하기 위한 시스템 자원을 그때 그때 적절하게 추가하거나 감소시킨다.
  • 회복성(Resilient): 시스템에 장애가 발생하더라도 응답성을 유지하는 것을 의미한다.
  • 회복성을 확보하기 위해서 리액티브 시스템의 구성요소들은 비동기 메시지 기반 통신을 통해 느슨한 결합과 격리성을 보장한다.

→ 시스템 구성 요소들이 독립적으로 분리되기 때문에 장애가 발생 하더라도 시스템은 여전히 응답 가능하고 장애가 발생한 부분만 복구하면 된다는 의미

VALUE: 비동기 메시지 기반 통신을 바탕으로 한 회복성과 예측 가능한 규모 확장 알고리즘을 통해 시스템의 처리량을 자동으로 확장하고 축소하는 탄력성을 확보함으로써 즉각적으로 응답 가능한 시스템 구축 가능

<aside>

시스템 설계 원칙에 따라 대규모 분산 시스템 또는 멀티코어 기반의 클라우드 시스템, 모바일 시스템 등 빠른 응답성을 바탕으로 유지보수와 확장이 용이한 시스템 구축 가능

</aside>

1.3 리액티브 프로그래밍(Reactive Programming)이란?

  • 리액티브 프로그래밍은 리액티브 시스템을 구축하는 데 필요한 프로그래밍 모델이다.
  • 리액티브 시스템에서 비동기 메시지 통신은 Blocking I/O 방식이 아닌 Non-Blocking I/O 방식의 통신이다.

Blocking I/O 방식의 통신

  • 해당 스레드가 작업을 처리할 때까지 남아 있는 작업들은 해당 작업이 끝날때까지 차단되어 대기한다.

Non-Blocking I/O 방식의 통신

  • 스레드가 차단되지 않는다.

1.4.1 declarative Programming

  • 선언형 프로그래밍으로, C언어나 JAVA 같은 명령형 프로그래밍 방식과 달리 실행할 동작을 구체적으로 명시하지 않고 동작을 하겠다는 목표만 선언한다.

1.4.2 data streams와 the propagation of Change

  • data streams는 데이터 흐름, 데이터가 지속적으로 발생한다는 의미이고, the propagation of change는 데이터가 발생할 때마다 이것을 변화하는 이벤트로 보고, 이 이벤트를 발생시키면서 데이터를 계속해서 전달하는 것을 의미한다.

코드로 보는 명령형 프로그래밍 vs 선언형 프로그래밍

// 명령형 프로그래밍 코드 예제
public class Example P
	public static void main(String[] args) {
		List<Integer> numbers = Arrays.asList(1, 3, 21, 10, 8, 11);
		int sum = 0;
		for(int number : numbers) {
			if (number > 6 && (number % 2 != 0)) {
				sum += number;
			}
		}
		
		System.out.println("합계: " + sum);
	}
}
  1. 먼저 for문을 돌아서 numbers에서 각각의 숫자들에 접근하는 동작을 한다.
  2. 다음으로 if문을 사용해서 6보다 더 큰 숫자이면서, 나머지가 0이 아닌 즉 홀수인 숫자만 선택하기 위한 동작을 진행한다.
  3. 조건문으로 선택된 숫자들을 sum이라는 변수에 차례차례 더하는 동작을 진행한다.
// 선언형 프로그래밍 코드 예제
public class Example {
	public static void main(String[] args){
		List<Integer> numbers = Arrays.asList(1, 3, 21, 10, 8, 11);
		int sum = numbers.stream()
			.filter(number -> number > 6 && (number % 2 != 0))
			.mapToInt(number -> number)
			.sum();
		
		System.out.println("합계: " + sum);
	
	}
}
  1. numbers List에 포함된 각각의 숫자에 접근하는 동작을 하는 for문이 사라진 것이다. 구체적인 동작을 Java의 스트림이 내부에서 직접 해준다.
  2. sum이라는 메서드를 선언만 했지, 구체적인 숫자를 더하는 동작은 스트림 내부에서 대신 처리해준다.

선언형 프로그래밍의 특징

  1. 선언형 프로그래밍 방식에서는 동작을 구체적으로 명시하지 않고, 목표만 선언한다.
  2. 각 동작에 대해서 메서드 체인을 형성해서 한문장으로 된 코드를 구성한다.
  3. 선언형 프로그래밍 방식은 함수형 프로그래밍으로 구성된다.

리액티브 프로그래밍의 구성

Publisher

  • 발행인, 발행자 정도로 해석할 수 있다. 발행자, 게시자, 생산자 등 여러가지 용어를 사용하지만, 공통점은

입력으로 들어온 데이터를 제공하는 역할을 한다.

Subscriber

  • Publisher가 제공한 데이터를 전달받아서 사용하는 주체이다. 구독자라고 불리고, 데이터를 소비하는 관점에서 소비자라고 불린다.

Data Source

  • Publisher의 입력으로 들어온 데이터를 대표하는 용어이다. 리액티브 프로그래밍에서는 Data Stream이라고도 부른다.

Data Source vs Data Stream

Data Source는 원천 데이터로, 측 최초로 생성되는 데이터 그 자체이다. Data Stream은 Publisher의 입력으로 들어오는 데이터의 형태이다. Stream은 ‘연속적으로 흐른다’라는 의미가 있는데, 데이터가 연속적으로 끊임없이 입력으로 들어오는 것을 의미한다.

 

Operator

  • 애플리케이션의 요구사항에 맞게 Publisher와 Subscriber 사이에서 적절한 가공 처리가 이루어지는데, 가공 처리를 담당한다.
  • 데이터를 생성하는 Operator부터, 데이터 필터링, 데이터 변환 등 수많은 Operator가 존재한다.