TIL

7. 함수형 엔드포인트

두 개의 함수

RouterFunction (요청 → 핸들러 라우팅)              ≒ @RequestMapping
    │
    ├────── RequestPredicate (매칭 조건 — 메서드·경로·미디어 타입)
    └────── HandlerFunction (요청 처리)            ≒ 핸들러 메서드 본문
RouterFunction<ServerResponse> route = route()  // RouterFunctions.route() 빌더
    .GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
    .GET("/person", accept(APPLICATION_JSON), handler::listPeople)
    .POST("/person", handler::createPerson)
    .build();

ServerRequest와 ServerResponse

ServerRequest

메서드 반환
bodyToMono(Person.class) Mono<Person> — 단건 역직렬화
bodyToFlux(Person.class) Flux<Person> — 스트림 역직렬화
formData() Mono<MultiValueMap<String, String>> — 폼 데이터
multipartData() Mono<MultiValueMap<String, Part>> — 멀티파트

ServerResponse

핸들러 클래스

public class PersonHandler {
    private final PersonRepository repository;

    public Mono<ServerResponse> getPerson(ServerRequest request) {
        int id = Integer.parseInt(request.pathVariable("id"));    // 인자 추출도 직접
        return repository.getPerson(id)
                .flatMap(p -> ok().contentType(APPLICATION_JSON).bodyValue(p))
                .switchIfEmpty(ServerResponse.notFound().build()); // 값이 없으면 404
    }

    public Mono<ServerResponse> createPerson(ServerRequest request) {
        Mono<Person> person = request.bodyToMono(Person.class);
        return ok().build(repository.savePerson(person));          // 저장(Mono<Void>) 완료 시 200
    }
}

라우트 평가 순서와 조합

중첩 라우트 — path / nest

RouterFunction<ServerResponse> route = route()
    .path("/person", b1 -> b1                        // 공통 경로 프리픽스 공유
        .nest(accept(APPLICATION_JSON), b2 -> b2     // 경로 외 공통 조건도 중첩 가능
            .GET("/{id}", handler::getPerson)
            .GET(handler::listPeople))
        .POST(handler::createPerson))
    .build();

필터 — before / after / filter

서버에서 실행

RouterFunctionMapping은 order -1RequestMappingHandlerMapping(order 0)보다 먼저 검사된다

애노테이션 모델과 비교

  애노테이션 컨트롤러 함수형 엔드포인트
매핑 선언 @RequestMapping 스캔 코드(RouterFunction 빈)로 명시
라우트 선택 가장 구체적 매핑 자동 선언 순서 첫 매치
핸들러 인자 리졸버가 자동 바인딩 ServerRequest에서 직접 추출
검증 @Valid 자동 Validator 수동 적용
스타일 관례 중심, 간결 명시적, 전 과정 제어