← Back to list

Netflix DGS를 직접 구현하며 이해한 GraphQL Federation

들어가며

Twoweeks · 2026-07-06 05:28 · 0 claps · 6.1 min read
#graphql #gds #graphql-federation #architecture #netflix
Open on Medium ↗
Wiki topics: 🎬 · Film & Television 🏛️ · Architecture

Netflix DGS를 직접 구현하며 이해한 GraphQL Federation

들어가며

기술을 공부할 때마다 항상 먼저 드는 질문이 있습니다.

“이 기술은 어떤 문제를 해결하기 위해 등장했을까?”

최근 Netflix Engineering의 Java 관련 발표를 보다가 Netflix DGSGraphQL Federation을 접하게 되었습니다.

How Netflix Uses Java — 2026 Edition

How Netflix Uses Java — 2026 Edition

GraphQL은 이미 널리 사용되는 기술입니다.

Q1. 그런데 Netflix는 왜 DGS라는 프레임워크를 만들었을까요? Q2. 그리고 GraphQL만으로는 부족해 왜 Federation이라는 구조가 필요했을까요?

궁금증을 해결하기 위해 간단한 프로젝트를 직접 만들어보며 GraphQL Federation이 어떻게 동작하는지 살펴봤습니다.

GraphQL만으로는 해결되지 않는 문제

MSA에서는 하나의 화면을 만들기 위해 여러 서비스의 데이터를 함께 조회해야 하는 경우가 많습니다.

예를 들어 OTT 서비스의 홈 화면이라면

  • 콘텐츠 정보
  • 추천 목록
  • 사용자 정보

처럼 여러 서비스의 데이터를 조합해야 합니다.

REST에서는 API Gateway가 각 서비스를 호출해 응답을 합쳐줄 수 있습니다.

하지만 서비스가 늘어날수록 Gateway에는 화면별 API가 계속 추가되고, 관리해야 할 조합도 점점 복잡해집니다.

GraphQL은 필요한 데이터만 조회할 수 있다는 장점이 있지만, MSA에서는 또 다른 문제가 생깁니다.

서비스마다 GraphQL 서버를 따로 운영한다면 클라이언트는 결국 여러 GraphQL Endpoint를 알아야 하고, 화면에서 필요한 데이터를 직접 조합해야 합니다.

그래서 GraphQL Federation이 등장했다

Federation은 여러 GraphQL 서버를 하나의 GraphQL API처럼 사용할 수 있도록 만들어주는 구조입니다.

클라이언트는 하나의 Gateway만 호출하면 되고,

뒤에서는 Gateway가 필요한 서브그래프(Subgraph)들을 호출하여 하나의 응답으로 합쳐줍니다.

Client
    │
Spring Cloud Gateway (zuul) -> 인증, 인가, 로깅, Rate Limit과 같은 공통 기능을 담당
    │
Apollo Router -> GraphQL Query를 각 Subgraph로 분산하는 역할
 ├── Content Service
 ├── Lolomo Service
 └── User Service

각 서비스는 자신의 도메인만 책임지고, 클라이언트는 서비스가 어떻게 분리되어 있는지 알 필요가 없습니다.

직접 구현해봤다

개념만으로는 잘 와닿지 않아 Netflix 홈 화면(lolomo)을 간단하게 구현해봤습니다.

프로젝트는 두 개의 서브그래프로 분리했습니다.

  • Content : 영화와 시리즈 정보
  • Lolomo : 홈 화면의 Shelf 구성

그리고 그 위에 Apollo Router를 올려 하나의 GraphQL API처럼 동작하도록 구성했습니다.

github link

github link

가장 중요한 개념은 Entity

Federation에서는 하나의 타입을 여러 서비스가 함께 사용할 수 있습니다.

이를 Entity라고 부르며, @key로 식별합니다.

type Content @key(fields: "id") {
    id: String!
    title: String!
}

Content를 소유하지 않는 서비스는 모든 필드를 알 필요가 없습니다.

type Content @key(fields: "id") @extends {
    id: String! @external
}

처음에는 왜 id만 가지고 있는지 이해되지 않았습니다.

실제로 실행해보니 이유를 알 수 있었습니다.

Lolomo 서비스는 Content의 id만 반환하고,

실제 title이나 rating은 Apollo Router가 Content 서비스에 다시 요청해서 채워주기 때문입니다.

Query Plan을 보니 동작 원리가 이해됐다

Apollo Router에는 Query Plan을 확인하는 기능이 있습니다.

Sandbox UI

Sandbox UI

직접 확인해보니 요청은 다음과 같은 순서로 실행되었습니다.

Client Query
↓
Lolomo Service 호출
↓
Content ID 수집
↓
Content Service 호출
↓
응답 병합

Query Plan을 확인해보니 Apollo Router는 하나의 GraphQL Query를 그대로 전달하는 것이 아니었습니다.

먼저 Lolomo 서비스에서 Content의 id만 조회한 뒤, 그 id를 이용해 Content 서비스에 필요한 필드만 다시 요청했습니다.

마지막으로 두 결과를 병합하여 하나의 응답으로 반환했습니다.

구현하면서 가장 흥미로웠던 점

서비스를 분리한 뒤 기존 코드 하나가 동작하지 않았습니다.

contents.sortedByDescending { it.rating }

예전에는 가능했습니다.

하지만 rating은 이제 Content 서비스의 소유 필드입니다.

Lolomo 서비스에서는 더 이상 접근할 수 없었습니다.

결국 랭킹 데이터를 별도로 관리하거나, 추천 서비스에서 미리 계산된 결과를 받아오는 방식으로 설계를 변경해야 했습니다.

Federation은 API를 연결해주는 기술이 아니라, 서비스의 소유권(Bounded Context)을 코드 레벨에서 강제하는 기술이라는 점이 인상적이었습니다.

Netflix DGS는 무엇일까?

Netflix DGS는 Spring Boot에서 GraphQL과 Federation을 쉽게 개발할 수 있도록 만든 프레임워크입니다.

Federation을 구현하기 위한 Entity Resolver, Schema 구성 등을 Spring Boot 방식으로 쉽게 개발할 수 있도록 지원합니다.

이번 프로젝트 역시 DGS를 사용해 별도의 Federation 구현 없이 Entity Resolver만 작성하면 Apollo Router와 자연스럽게 연동되는 것을 확인할 수 있었습니다.

마치며

이번 실습을 통해 가장 크게 느낀 점은 GraphQL보다 Federation이 더 흥미로운 기술이었다는 것입니다.

GraphQL은 데이터를 조회하는 방법을 바꾸는 기술이라면,

GraphQL Federation은 분리된 서비스를 하나의 API처럼 제공하는 아키텍처에 가깝습니다.

특히 Query Plan을 직접 확인하면서 Federation의 내부 동작을 이해할 수 있었고, 서비스를 분리하는 순간 필드의 소유권이 어떻게 달라지는지도 체감할 수 있었습니다.

앞으로도 새로운 기술을 공부할 때는 사용법보다 왜 이 기술이 등장했고, 어떤 문제를 해결하기 위해 만들어졌는지를 먼저 이해하는 개발자가 되고 싶습니다.

참고


메타데이터
post_id
97b98bcce7e8
slug
netflix-dgs를-직접-구현하며-이해한-graphql-federation-97b98bcce7e8
url
https://medium.com/@twoweeks315/netflix-dgs%EB%A5%BC-%EC%A7%81%EC%A0%91-%EA%B5%AC%ED%98%84%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-graphql-federation-97b98bcce7e8
canonical_url
https://medium.com/@twoweeks315/netflix-dgs%EB%A5%BC-%EC%A7%81%EC%A0%91-%EA%B5%AC%ED%98%84%ED%95%98%EB%A9%B0-%EC%9D%B4%ED%95%B4%ED%95%9C-graphql-federation-97b98bcce7e8
author_url
https://medium.com/@twoweeks315
status
ok
fetched_at
2026-07-20 21:08:49