BindProject

[Backend] bff 구현하기 2편. DTO 관리 전략과 API 계약 모듈 도입

dding-shark 2025. 6. 26. 16:00
728x90

DTO 관리 전략과 API 계약 모듈 도입

도입 동기

서비스가 많아지면서 API마다 각기 다른 Request/Response DTO가 수십 종으로 증가했습니다.
BFF 레이어에서 뷰모델을 위해 동일한 DTO를 중복 정의하거나, 혹은 모든 필드를 그대로 내려보내는 방식은 유지보수 비용과 보안 리스크를 키웠습니다.
이를 해결하기 위해 API 계약(contract) 모듈과 BFF 전용 뷰모델(view-model) 매핑 전략을 결합했습니다.

설계 목표

  • DTO 중복 제거: 서비스와 BFF 간 하나의 계약 모듈로 Request/Response 타입 공유
  • 응답 스펙 최적화: 클라이언트가 실제 사용하는 필드만 담은 뷰모델 제공
  • 유지보수 효율화: 계약 변경 시 한 곳만 수정하면 전체 동기화
  • 타입 안정성 확보: 컴파일 타임에 스펙 불일치 감지

고려한 패턴 비교

패턴 장점 단점
공통 API 계약 모듈 DTO 중복 제거, 서비스·BFF 동기화 서비스↔BFF 결합도 증가, 불필요 필드 포함 가능
BFF 뷰모델 + MapStruct 매핑 뷰모델에 필요한 필드만 제공, 스펙 최적화 매핑 인터페이스 작성 부담, 뷰모델 수정 시 매퍼도 변경 필요
OpenAPI Generator 기반 코드 생성 스펙 변경 시 자동 코드 재생성, 일관성 보장 빌드 파이프라인 복잡도 증가
GraphQL 스키마 통합 하나의 엔드포인트로 다양한 필드·파라미터 조합 가능 GraphQL 런타임 학습, 캐싱·보안·모니터링 추가 설정 필요

공통 API 계약 모듈 구현

  1. common/api-contract 모듈 생성
    • java-library 플러그인 적용
    • 서비스별 DTO를 com.yourorg.contract.{service} 패키지에 정의
    • Jackson 애노테이션으로 JSON 직렬화/역직렬화 설정
  2. Gradle 멀티 프로젝트 설정
    • settings.gradleinclude ':common:api-contract', ':service:auth', ':application:bff' 등 추가
    • build.gradle 에 모든 하위 모듈 공통 의존성 관리
  3. 서비스 모듈
    • implementation project(':common:api-contract')
    • 컨트롤러 입출력 DTO로 계약 모듈 타입 사용
  4. BFF 모듈
    • implementation project(':common:api-contract')
    • WebClient bodyToMono(CommonResponseDto.class) 로 직접 바인딩

회고

이런 느낌으로 구현해보려고 한다.

728x90