Dev/Java

[Reactive Programming] 리액티브 시스템과 리액티브 프로그래밍

김세진 2024. 6. 25. 14:26
반응형

 

 

 

리액티브 시스템(Reactive System)

 

리액티브란 사전적 의미로 어떤 이벤트나 상황이 발생했을 때, 적절하게 행동하는 것을 의미한다.

 

따라서 리액티브 시스템이란 반응을 잘 하는 시스템이라고 정의할 수 있고, 이는 클라이언트의 요청에 즉각적으로 응답함으로써 지연 시간을 최소화하는 시스템이라고 할 수 있다.

 

 


리액티브 선언문(The Reactive Manifesto)

 

리액티브 선언문이란 리액티브 시스템 구축을 위한 일종의 설계 원칙이자 리액티브 시스템의 특징이다. 이는 아래 그림 하나로 명확하게 설명할 수 있다.

 

방법(Means)

주요 통신 수단으로 무엇을 사용할 것인지 표현한 것으로, 위 그림처럼 비동기 메시지 기반(Message Driven)의 통신을 사용할 것임을 뜻한다. 이는 구성요소들 간의 느슨한 결합, 격리성, 위치 투명성을 보장한다.

 

형태(Form)

메시지 기반 통신을 통해 탄력성과 회복성을 가지는 시스템이어야 함을 의미한다.

 

탄력성(Elastic): 시스템의 작업량이 변화하더라도 일정한 응답을 유지하는 것

회복성(Resilient): 시스템에 장애가 발생하더라도 응답성을 유지하는 것. 메시지 기반 통신을 통해 느슨한 결합과 격리성이 보장되기 때문에 가능

 

값(Value)

리액티브 시스템의 핵심 가치로, Means와 Form을 바탕으로 즉각적으로 응답 가능한 시스템을 구축할 수 있음을 의미한다.

 

 

이같은 특징들을 통해 빠른 응답성을 바탕으로 유지보수와 확장이 용이한 시스템을 구축할 수 있다.

 


리액티브 프로그래밍(Reactive Programming)

 

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

 

Blocking I/O: 해당 스레드가 작업을 처리할 때까지 다른 작업들은 처리되지 않고 대기하는 방식. 동시 처리를 위해서는 별도로 추가 스레드를 할당해야 한다.

Non-Blocking I/O: I/O 작업이 즉시 반환되며, 호출한 스레드가 작업이 완료되기를 기다리지 않고 다른 작업을 수행할 수 있는 방식

 

즉, 리액티브 프로그래밍은 Non-Blocking 통신을 위한 프로그래밍 모델이다.

 

특징

1. 선언형 프로그래밍(Declarative Programming): 구체적인 동작 대신 목표만 선언하는 프로그래밍 방식

2. 데이터 흐름(Data Streams): 연속적으로 발생하는 데이터 이벤트의 흐름

3. 변화의 전파(The Propagation of Change): 데이터의 변경이 다른 부분으로 전달되는 특징

 

 


명령형 프로그래밍 vs 선언형 프로그래밍

 

명령형 프로그래밍

public class Example1_1 {
	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문을 돌며 각 number에 접근한다.

2. if문을 사용하여 6보다 더 큰 숫자이면서 홀수인 경우를 찾는다.

3. 조건에 해당하는 숫자를 결과값인 sum에 더한다.

 

선언형 프로그래밍

public class Example1_2 {
	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);
	}
}

 

위는 자바의 stream을 활용한 선언현 프로그래밍의 예시이다. 가장 큰 차이점으로 for문이 사라진 것을 볼 수 있다. 직접 numbers의 원소에 접근하는 것이 아닌 체이닝 메서드를 통해 물 흐르듯 변형된 데이터를 전달하고, 전달받은 데이터가 각 부분에서 어떻게 처리되어야 하는지 목표를 선언한다.

 

1. 선언형 프로그래밍에선 동작을 구체적으로 명시하지 않고 목표를 선언

2. 각 동작에 대해 메서드 체인을 형성하는 함수형 프로그래밍 방식으로 구성

 

 


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

 

Publisher

데이터를 제공하는 역할. 발행인, 게시자 등과 같은 용어로 사용하기도 함

 

Subscriber

Publisher가 제공한 데이터를 전달받아서 사용하는 주체. 구독자 혹은 소비자라고도 함

 

Data Source

Publisher의 입력으로 들어오는 데이터를 의미. 엄밀히 따지면 다르지만, Data Stream이라고도 표현함

- Data Source는 원천 데이터 그 자체, Data Stream은 Publisher의 입력으로 들어오는 데이터의 형태

 

Operator

Publisher와 Subscriber 사이에서 데이터를 가공하는 역할

 

 

 

 

 

 

 

 

반응형