본문 바로가기

스터디/Spring Boot

BFF패턴과 MVC패턴의 차이점

BFF는 프론트엔드(UI/UX)의 요구사항에 최적화된 '전용 백엔드 비서' 서버를 의미한다.

💡 핵심 개념 및 등장 배경

  • 정의: Backend for Frontend의 약자로, 프론트엔드를 위한 전용 백엔드 서버이다.
  • 해결 과제 및 등장 배경: 프론트엔드의 백엔드 종속성을 최소화를 실현하고, 기기별 커스텀 데이터 처리를 통해 리소스 낭비를 막고자 설계된 패턴이다.
  • 핵심 가치: 접근하는 디바이스마다 UI가 다르게 보여지는 분기 처리를 지원하는 것이다.
  • 특징: '1개 클라이언트 = 1개 BFF' 구조. 각 화면을 위한 전용 비서가 존재하는 셈이며, MSA 아키텍처에서 특히 유용하다.

🔄 MVC 패턴 vs BFF 패턴 비교 (Spring/JPA 환경)

Spring Framework와 JPA, QueryDsl을 사용하는 환경이라고 가정

[기존 MVC 패턴의 흐름]

  1. 사용자가 리스트 조회 URL 접근
  2. Controller 매핑 및 HTML 호출(렌더링)
  3. JS 파일 초기화와 동시에 리스트 조회 API 호출
  4. RestController가 요청을 받아 reqDto에 담음
  5. Service 영역의 함수 호출
  6. Repository에서 Query 실행 (JPA/QueryDsl)
  7. 응답 값을 resDto에 담아 Service로 전달
  8. Service에서 가공 후 RestController에 전달
  9. JS 후속 로직을 통해 화면에 리스트 렌더링

기존 구조의 한계: > 모든 동작이 DB 조회 → Service 가공 → Controller 렌더링 순으로 이어져 백엔드(DB) 영역에 대한 의존성이 매우 강함. 테이블 간 연관 관계가 복잡해질수록 가독성이 떨어지고 오류 수정 비용이 큼.

[BFF 패턴 적용 시의 이점]

  • 직관적 구현: 세부 정보의 연관 관계만 명시하고 실제 DB 연관 관계를 맺지 않더라도, Service 영역에서 쿼리를 여러 번 분할 실행하여 직관적으로 구현 가능.
  • UI 유연성: 1개 화면에 1개 서비스가 전용 데이터를 제공함으로써 디바이스별로 UI를 다르게 구성하고 최적화된 데이터만 제공 가능.
  • 프론트 비중 강화: 백엔드 의존성을 줄이고 화면 구성에 이점을 살림.
  • 데이터 분할 제공: 데이터를 한 번에 거대한 JSON으로 보내지 않고, Service 영역에서 분할하여 화면에서 필요한 데이터를 쉽게 갈아끼울 수 있도록 한다.

⚠️ 주의사항

  • 각 디바이스별로 전용 API를 만들어야 하므로 코드 중복 및 재작성에 따른 개발 공수가 증가할 수 있음.

글로만 보면 이해가 잘 되지 않으니 마지막으로 코드를 통해 차이점을 확인해보자

1️⃣ 기존 MVC 패턴 (도메인/DB 중심)

전형적인 3계층 구조로, 서비스 레이어에서 DB 연관 관계에 따라 데이터를 통째로 가져오는 방식이다.

// Controller: 데이터를 그대로 반환함
@GetMapping("/users")
public List<UserResponseDto> getUsers() {
    return userService.findAllUsers(); // 서비스가 주는 대로 받음
}

// Service: DB 엔티티와 강하게 결합됨
@Transactional(readOnly = true)
public List<UserResponseDto> findAllUsers() {
    return queryFactory
        .selectFrom(user)
        .leftJoin(user.orders, order).fetchJoin() // 복잡한 연관 관계 조인
        .fetch()
        .stream().map(UserResponseDto::from).toList();
}
  • 특징: 화면이 필요로 하는 것보다 많은 정보(orders 등)를 한 번에 가져와야 함.
  • 문제: 화면 요구사항이 바뀌면 서비스 로직과 쿼리 자체를 건드려야 함.

2️⃣ BFF 패턴 (화면/UI 중심)

BFF 서버에서는 여러 마이크로서비스나 기능을 호출하여 프론트엔드에 최적화된 형태로 조립한다.

// BFF Controller: 특정 화면(예: 모바일 리스트) 전용 API
@GetMapping("/mobile/user-list")
public MobileUserListDto getMobileUserList() {
    // 1. 핵심 유저 정보 조회
    List<UserBasicInfo> users = userService.getBasicInfo();
    
    // 2. 화면에 필요한 부가 정보(예: 안 읽은 알림 수)만 별도 호출
    // 복잡한 JOIN 없이 필요한 것만 '조립(Aggregation)'함
    return users.stream().map(user -> {
        int noticeCount = noticeService.getUnreadCount(user.getId());
        return new MobileUserListDto(user, noticeCount);
    }).collect(Collectors.toList());
}
  • 특징: 서비스 로직이 가벼워지고, 화면에 딱 필요한 정보만 담은 DTO를 만듦.
  • 장점: 복잡한 테이블 연관 관계에 얽매이지 않고, 비즈니스 로직을 기능별로 분할해서 호출하므로 가독성이 높음.

'스터디 > Spring Boot' 카테고리의 다른 글

트랜잭션  (1) 2025.07.26
RDBMS, NoSQL이란  (0) 2024.08.16
모놀리식 아키텍처  (0) 2024.08.15
[Spring Boot] JPA란  (0) 2024.05.19
[Spring Boot] 스프링 부트란?  (0) 2024.05.19