본문 바로가기

Study Information Technology

Spring Boot와 WebFlux를 활용한 리액티브 애플리케이션 개발

728x90
반응형

Spring Boot와 WebFlux를 활용한 리액티브 애플리케이션 개발

Overview

Spring Boot와 WebFlux는 현대 웹 애플리케이션 개발에서 주목받고 있는 조합으로, 비동기 및 논블로킹 방식으로 많은 동시 연결을 효율적으로 처리할 수 있는 리액티브 애플리케이션을 쉽게 만들 수 있도록 도와줍니다. 이번 글에서는 Spring Boot와 WebFlux의 기본 개념, 구성 요소, 그리고 실제 애플리케이션 예제를 통해 어떻게 리액티브 프로그래밍을 구현하는지 자세히 살펴보겠습니다.

1. 리액티브 프로그래밍이란?

리액티브 프로그래밍은 데이터 스트림과 변화 전파를 중심으로 한 프로그래밍 패러다임입니다. 전통적인 동기 프로그래밍에서는 요청이 들어오면 그 요청이 처리되는 동안 해당 스레드가 대기 상태가 되지만, 리액티브 프로그래밍은 요청을 비동기적으로 처리하여 스레드가 블로킹되지 않도록 합니다.

예시: 웹 애플리케이션에서 대량의 데이터베이스 요청을 처리할 때, 동기 방식에서는 요청이 완료될 때까지 클라이언트가 대기하게 됩니다. 반면, 리액티브 방식에서는 요청을 비동기적으로 처리하여 다른 작업을 계속할 수 있습니다.

2. Spring Boot와 WebFlux

Spring Boot는 스프링 기반 애플리케이션을 쉽게 만들 수 있도록 돕는 프레임워크입니다. WebFlux는 스프링 5에서 도입된 모듈로, 리액티브 프로그래밍을 지원합니다. 이를 통해 개발자는 비동기 및 논블로킹 애플리케이션을 간편하게 구축할 수 있습니다.

2.1 주요 특징

  • 논블로킹 I/O: 요청 처리 시 블로킹이 없으므로 서버 리소스를 효율적으로 사용할 수 있습니다.
  • 스케일러빌리티: 더 많은 동시 연결을 지원할 수 있어 대규모 트래픽을 처리하는 데 유리합니다.
  • 리액티브 스트림: 데이터 스트림을 처리하기 위한 표준 인터페이스를 제공합니다.

3. WebFlux의 주요 구성 요소

WebFlux는 리액티브 애플리케이션을 구축하기 위한 여러 구성 요소를 제공합니다:

  • Router: HTTP 요청을 처리할 경로를 정의합니다.
  • Handler: 각 요청에 대한 비즈니스 로직을 수행합니다.
  • Mono와 Flux: 리액티브 프로그래밍의 기본 단위로, 각각 단일 값 또는 다수의 값을 비동기적으로 처리합니다.

4. 예제: 간단한 리액티브 애플리케이션

이제 Spring Boot와 WebFlux를 이용해 간단한 리액티브 애플리케이션을 만들어 보겠습니다. 이 예제에서는 사용자 정보를 관리하는 API를 구축합니다.

4.1 프로젝트 설정

Maven 또는 Gradle을 사용하여 Spring Boot와 WebFlux 의존성을 추가합니다. 여기서는 Maven을 기준으로 설명하겠습니다.

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

4.2 도메인 모델

사용자 정보를 나타내는 도메인 모델을 생성합니다.

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class User {
@Id
private String id;
private String name;
private String email;

// 생성자, Getter, Setter 생략
}

4.3 레포지토리 인터페이스

MongoDB와 통신하기 위한 리액티브 레포지토리를 생성합니다.

import org.springframework.data.mongodb.repository.ReactiveMongoRepository;

public interface UserRepository extends ReactiveMongoRepository<User, String> {
}

4.4 서비스 클래스

비즈니스 로직을 처리하는 서비스를 작성합니다.

import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class UserService {
private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

public Mono<User> createUser(User user) {
return userRepository.save(user);
}

public Flux<User> getAllUsers() {
return userRepository.findAll();
}

public Mono<User> getUserById(String id) {
return userRepository.findById(id);
}

public Mono<Void> deleteUser(String id) {
return userRepository.deleteById(id);
}
}

4.5 컨트롤러

HTTP 요청을 처리하는 컨트롤러를 작성합니다.

import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;

public UserController(UserService userService) {
this.userService = userService;
}

@PostMapping
public Mono<User> createUser(@RequestBody User user) {
return userService.createUser(user);
}

@GetMapping
public Flux<User> getAllUsers() {
return userService.getAllUsers();
}

@GetMapping("/{id}")
public Mono<User> getUserById(@PathVariable String id) {
return userService.getUserById(id);
}

@DeleteMapping("/{id}")
public Mono<Void> deleteUser(@PathVariable String id) {
return userService.deleteUser(id);
}
}

5. 애플리케이션 실행 및 테스트

애플리케이션을 실행하고 Postman 또는 curl을 사용하여 API를 테스트할 수 있습니다. 예를 들어, 사용자 추가 요청은 다음과 같습니다.

curl -X POST http://localhost:8080/users -H "Content-Type: application/json" -d '{"name":"John Doe", "email":"john@example.com"}'

이 요청은 새로운 사용자를 데이터베이스에 추가합니다.

6. 오류 처리

비동기 처리에서는 다양한 오류가 발생할 수 있습니다. 예를 들어, 사용자를 찾을 수 없는 경우 Mono가 비어 있을 수 있습니다. 이를 처리하기 위해 다음과 같은 방식을 사용할 수 있습니다.

public Mono<User> getUserById(String id) {
return userRepository.findById(id)
.switchIfEmpty(Mono.error(new RuntimeException("User not found")));
}

이 코드는 사용자가 존재하지 않을 경우 RuntimeException을 발생시킵니다. 클라이언트는 적절한 오류 메시지를 받을 수 있습니다.

7. 결론

Spring Boot와 WebFlux를 활용한 리액티브 애플리케이션 개발은 비동기 및 논블로킹 방식으로 높은 성능과 확장성을 제공하는 효과적인 방법입니다. 위의 예제를 통해 기본적인 리액티브 애플리케이션을 이해하고, 실제 프로젝트에서 어떻게 적용할 수 있는지를 살펴보았습니다.

참고문서

728x90
반응형