My Library Docs

Multi-root Sidebar

flex-layout

  • Getting Started

  • Guides

  • Reference

typed-rx-http

  • Getting Started

  • Guides

  • Reference

global-rx-state

  • Getting Started

  • Guides

  • Reference

webflux-fe-dev-assistant

reactive-mongo-dsl


v0.0.11Drag to reorder

Overview

백엔드와 프론트를 함께 개발하면서 같은 API 계약과 타입을 두 번 작성하던 병목을 없애고, 라우터·handler·MongoDB field 문자열까지 반복되는 개발 작업을 source 기반 생성으로 바꾼 배경과 원칙을 설명합니다.


Origin story

저는 백엔드와 프론트를 함께 작업합니다. 한 기능을 만들 때 Java WebFlux에서 endpoint와 request/response DTO를 작성하고, 다시 프론트에서 같은 URL과 TypeScript type을 작성해야 했습니다. Swagger 문서까지 직접 맞추려면 이미 백엔드에 존재하는 정보를 다른 형식으로 한 번 더 옮기는 일이 반복됐습니다.

가장 큰 병목은 백엔드에서 만든 API 계약을 프론트가 사용할 수 있는 형태로 다시 작성하는 과정이었습니다. URL, HTTP method, path/query parameter와 request/response 구조 중 하나라도 양쪽에서 다르게 수정되면 컴파일보다 늦게 문제를 발견했습니다. 단순히 귀찮은 일을 넘어, 같은 내용을 사람이 두 번 관리하면서 생기는 불일치가 더 큰 문제였습니다.

RouterFunction과 handler를 새로 만들 때의 반복도 줄이고 싶었습니다. 라우터에 ApiAccountHandler::search 같은 참조를 추가했다면, 존재하지 않는 handler class와 method 골격 정도는 자동으로 만들어져도 된다고 생각했습니다. MongoDB query를 작성할 때 entity field 이름을 "username"처럼 문자열로 반복하는 것 역시 번거롭고 오타가 나기 쉬웠기 때문에, entity source를 읽어 Java enum으로 생성하는 기능도 같은 도구 안에 넣었습니다.

그렇게 Swagger/OpenAPI 생성, handler 골격 생성과 Mongo entity field enum 생성이 먼저 만들어졌고, 이후 RSocket을 사용하면서 AsyncAPI 생성도 추가했습니다. 각각 별개의 아이디어처럼 보이지만 출발점은 같습니다. 백엔드 소스에 이미 적어 둔 사실을 사람이 다시 작성하지 않고, 기계가 읽을 수 있는 부분은 개발 도구가 대신 만들도록 하는 것입니다.

개발 철학

백엔드 소스를 기준으로 삼습니다

RouterFunction, handler, DTO와 entity에 이미 있는 정보를 API 문서와 생성 코드의 원본으로 사용합니다. 같은 계약을 별도 파일에서 다시 관리하지 않는 것이 핵심입니다.

런타임 마법보다 개발 시점 자동화를 선택합니다

production 요청을 가로채는 framework가 아니라 local 개발 환경에서 source를 분석하고 실제 파일을 생성합니다. 결과물을 눈으로 확인하고 버전 관리할 수 있습니다.

프로젝트 관례를 예측 가능하게 따릅니다

모든 Java 코드를 이해하는 범용 compiler를 목표로 하지 않습니다. 제가 실제로 사용하는 WebFlux functional endpoint 구조를 명확한 규칙으로 분석하는 쪽을 우선합니다.

반복되는 연결 구간을 없앱니다

백엔드 endpoint에서 Swagger를 만들고, 프론트 생성기가 그 문서를 읽어 service와 type을 만드는 흐름까지 하나의 자동화 체인으로 연결합니다.

백엔드에서 무엇을 읽는가

RouterFunction source

HTTP method, nested path, handler method reference와 predicate를 읽습니다.

Handler source

request body, query/path 값과 response publisher type을 읽습니다.

Request / Response DTO

백엔드에 이미 작성한 Java type을 OpenAPI schema로 연결합니다.

Mongo entity source

Java field와 @Field의 storage raw name, @Document collection을 읽습니다.

RSocket controller

@MessageMapping route와 request/response payload type을 읽습니다.

반복 작성 대신 무엇을 만드는가

swagger.json

REST endpoint를 프론트 service와 TypeScript type 생성기가 사용할 수 있는 API 계약으로 만듭니다.

asyncapi-rsocket.json

RSocket route와 payload를 프론트 RSocket client 생성기가 읽을 수 있는 계약으로 만듭니다.

Handler source

RouterFunction에 먼저 적은 handler reference를 기준으로 class와 method 골격을 생성·보정합니다.

{Entity}Fields enum

문자열 field 이름을 반복하지 않도록 entity의 Java field와 storage raw name을 enum으로 만듭니다.

CollectionNames enum

@Document에 선언된 collection 이름을 문자열 대신 사용할 수 있도록 생성합니다.

현재 프로젝트에서의 자동화 흐름

백엔드에서 RouterFunction, handler와 Java request/response DTO를 작성합니다.

local profile의 watcher가 source 변경을 감지해 swagger.json 또는 asyncapi-rsocket.json을 갱신합니다.

프론트의 @byeolnaerim/typed-rx-http 생성 스크립트가 문서를 읽어 service 함수와 TypeScript type을 생성합니다.

화면 코드에서는 URL과 response type을 다시 작성하지 않고 생성된 함수를 import해서 사용합니다.

entity가 변경되면 query에 사용하는 field enum과 collection enum도 함께 갱신합니다.

© 2026 Byeolnaerim. All rights reserved.소개개인정보처리방침