Skip to content

12. How to route based on RouterFunction

이진혁 edited this page Jun 1, 2021 · 4 revisions

웹플럭스에서는 어노테이션 기반 방식 말고 보다 더 Functional한 프로그래밍을 할 수 있도록
RouterFunction을 통한 라우팅 방식을 제공합니다.
오늘은 이 RouterFunction 라우팅 방식에 대해 알아보도록 하겠습니다.

다음은 RouterFunction 예제입니다.
``java @Configuration public class RouterFunctionTestRouter {

@Bean
public RouterFunction<?> route(RouterFunctionTestHandler testHandler) {
    return RouterFunctions.route()
            .POST(
                    "/test",
                    RequestPredicates.accept(MediaType.APPLICATION_JSON)
                            .and(RequestPredicates.contentType(MediaType.APPLICATION_JSON)),
                    testHandler::testHandler
            ).build();
}

}

`RouterFunction`은 웹플럭스에서 인터페이스로 제공하고 있으며,  
쉽게 구현할 수 있도록 `RouterFunctions`라는 정적 팩토리 클래스도 함께 제공합니다.  
따라서 직접 `RouterFunction`을 구현하는 것보다는`RouterFunctions` 클래스를 이용해서  
`RouterFunction`을 작성하는 것이 일반적입니다.  

`RouterFunction`은 기존 어노테이션 기반 라우팅에서는 찾아볼 수 없었던 개념이긴 한데,  
컨트롤러를 한 대 모아놓은 것이라고 생각하면 쉽습니다.  
여러 컨트롤러(라우터)들의 엔트리포인트를 `RouterFunction`에 모아두고  
이후에 나올 `RouterHandler`에게 실제 라우팅을 넘기는 것입니다.  

위 예제에서는 `HTTP Method`로 `POST`를 사용하였고,  
경로는 `/test`이며 오고 가는 `Request Body`는 `application/json`으로 구성하며  
실제 `/test`로 오는 요청은 `RouterFunctionTestHandler` 컴포넌트의  
`testhandler()` 메소드로 처리하겠다는 것을 알 수 있습니다.  

현재는 하나의 엔트리포인트밖에 없지만 여러 개 있을 경우  
`andRouter()` 메소드로 라우터를 추가할 수 있습니다.  

다음은 `RouterHandler`의 예제입니다.  
```java
@Component
@RequiredArgsConstructor
public class RouterFunctionTestHandler {

    private final RouterFunctionTestService testService;

    public Mono<ServerResponse> testHandler(ServerRequest request) {
        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(request.bodyToMono(RouterFunctionTestRequest.class).flatMap(req -> Mono.just(
                        new RouterFunctionTestResponse(
                                testService.combineName(req.getFirstName(), req.getLastName()),
                                req.getAge(),
                                testService.combineGradeClassNumber(req.getGrade(), req.getClassroom(), req.getNumber())
                        )
                )), RouterFunctionTestResponse.class);
    }
}