개발/Spring

[Spring] Spring WebFlux 예제

hojak99 2018. 4. 30. 15:51

Spring WebFlux 에 대한 간단한 예제 코드를 작성해보았다.


우선 이전에 WebFlux 에 대한 글을 작성했었지만, 다시 간단하게 WebFlux 가 무엇인지에 대해서 알아보고 가겠다.


Spring WebFlux 는 비동기-논블록킹 리엑티브 개발을 할 수 있으며 효율적으로 동작하는 고성능 웹 어플리케이션 개발을 할 수 있는 서비스 간 호출이 많은 마이크로서비스 아키텍처에 적합한 프레임워크이다.


(참고로 Spring WebFlux 는 기본적으로 tomcat이 아닌 netty 를 사용하고 있다.)



필자는 Spring Boot 2.0.1 버전을 사용하였다.


<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-webflux</artifactId>
	</dependency>
		
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>

	<dependency>
		<groupId>io.projectreactor</groupId>
		<artifactId>reactor-test</artifactId>
		<scope>test</scope>
	</dependency>
		
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>


위의 코드처럼 dependency를 추가해주면 된다.



아래의 코드를 보자. 원래 코드를 볼 땐 main 메소드부터 확인해야 한다는 것을 잊지말자.


monoRotuerFunction() 메소드는 이번에 새로 등장한 RouterFunction 이다. 기존에는 어노테이션 기반으로 메소드를 작성했지만, 새로운 방식은 RouterFunction 과 HandlerFunction 이 존재한다. 


아래의 RouterFunction 에서는 주석 그대로 URL 정의를 하는 메소드이다. 그리고 GET, POST 를 지정할 수 있고, 그 옆에 echoHandler::echo 코드는 메소드 레퍼런스를 이용한 코드이다.


ServerResponse 와 ServerRequest 에 대한 키워드는 필자가 전에 작성한 Spring WebFlux 소개 글을 보면 알 수 있으니 모르면 읽기 바란다.

@SpringBootApplication
public class SpringWebFluxApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringWebFluxApplication.class, args);
	}


	
	/**
	 * 새로운 방식의 routing 방법. 좀 더 functional 한 프로그래밍을 할 수 있다. 
	 * 쉽게 생각하면 URL을 명시하는 RouterFunction 과 URL과 로직을 연결하는 HandlerFunction 으로 나눌 수 있다.
	 * 
	 * @param echoHandler
	 * @return
	 */
	@Bean
	public RouterFunction<ServerResponse> monoRouterFunction(EchoHandler echoHandler) {
		return route(POST("/echo"), echoHandler::echo);
	}
}


다음은 RouterFunction() 메소드와 연결하고 로직을 처리하는 HandlerFunction() 메소드이다.

@Component
public class EchoHandler {
	
	public Mono<ServerResponse> echo(ServerRequest request) {
		return ServerResponse.ok().body(request.bodyToMono(String.class), String.class);
	}
}




다음은 기존의 어노테이션 방식을 이용한 Controller 클래스이다.

@RestController
public class ExampleController {
	
	/**
	 * 기존의 어노테이션을 사용한 컨트롤러 메소드
	 * 
	 * @return
	 */
	@PostMapping(path="/", consumes = {MediaType.APPLICATION_JSON_VALUE, "!application/xml"},
			produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo", params = "a!=alpha")
	public String example() {
		return "Hello World";
	}
}
@RestController
public class WelcomeController {
	
	/**
	 * 기존의 어노테이션을 이용한 컨트롤러 메소드
	 * 
	 * @return
	 */
	@GetMapping("/")
	public String welcome() {
		return "Hello World";
	}
}




이제 컨트롤러 메소드는 다 작성했다. 이제 한 번 테스트 코드를 작성하고 제대로 동작되는지 살펴보즈아~~~


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SpringWebFluxApplicationTests {

	@Autowired
	private WebTestClient webClient;

	
	@Test
	public void testWelcome() {
		this.webClient.get().uri("/").accept(MediaType.TEXT_PLAIN).exchange()
			.expectBody(String.class).isEqualTo("Hello World");
	}
	
	@Test
	public void testEcho() {
		this.webClient.post().uri("/echo").contentType(MediaType.TEXT_PLAIN)
			.accept(MediaType.TEXT_PLAIN)
			.body(Mono.just("Hello WebFlux!"), String.class).exchange()
			.expectBody(String.class).isEqualTo("Hello WebFlux!");
	}
	
	@Test
	public void testActuatorStatus() {
		this.webClient.get().uri("/actuator/health").accept(MediaType.APPLICATION_JSON)
			.exchange().expectStatus().isOk().expectBody()
			.json("{\"status\":\"UP\"}");
	}

}


통과~

반응형