ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Netflix의 BFF에서 GraphQL Federation으로 전환기
    📖 개발 공부 2024. 4. 14. 01:25

    ByteByteGo 에서 재밌게, 또 유익하게 본 아티클의 내용을 정리하려고 한다!

     

    Evolution of Java Usage at Netflix

     

    Evolution of Java Usage at Netflix

    Stop releasing bugs with fully automated end-to-end test coverage (Sponsored) Bugs sneak out when less than 80% of user flows are tested before shipping. But how do you get that kind of coverage? You either spend years scaling in-house QA — or you get th

    blog.bytebytego.com

     

     

     

    넷플릭스는 마이크로서비스 아키텍처로 많이 알려져있다!

     

    이번 글에서는 넷플릭스가 BFF 방식에서 새로운 아키텍처인 GraphQL로 넘어가는 과정을 살펴보도록 하자.

    The Groovy Era with BFFs

    넷플릭스를 키면, LOLOMO 화면이 보인다. (LOLOMO: List Of List Of Movies 약자)

    해당 화면에서는 여러 서비스에서 데이터를 가져온다.

    • 상위 10개 영화 목록을 반환하는 서비스
    • 영화별로 개인화된 이미지를 제공하는 Artwork 서비스
    • 영화 제목, 배우 및 설명을 반환하는 Metadata 서비스
    • 사용자 홈 페이지에 실제로 렌더링할 목록을 제공하는 LOLOMO 서비스

    디바이스에서 이렇게 많은 서비스를 호출하는 것은 비효율적이다. 이는 확장성이 떨어지고 사용자 경험을 해치운다.

     

    이 이슈를 해결 방식으로 넷플릭스는 다양한 API의 front door을 사용했다. 이는 디바이스가 front door에게 콜을 하고, front door가 다른 마이크로서비스에게 팬아웃(전파)을 수행한다. 이로써 성능 이슈를 해결할 수 있었다.

    front door는 API Gateway 역할을 하고, 넷플릭스는 이를 위해 Zuul을 사용했다.

     

    하지만 이는 또다른 해결해야하는 문제점이 있었다.

     

    사용자들이 넷플릭스에 접속하기 위해 사용할 수 있는 모든 다른 장치들은 미묘한 방식으로 서로 다른 요구사항들을 가지고 있다.

    넷플릭스가 모든 디바이스에서 UI와 UI의 동작에 대해 일관된 경험을 유지하려고 노력했지만, 메모리 또는 네트워크 대역폭에 있어서는 각 디바이스마다 서로 다른 제한이 있어서 조금씩 다른 방식으로 데이터를 로드한다.

     

    이렇게 다양한 기기에서 작동할 수 있는 REST API 하나를 만들기는 어렵다.

    • REST API 데이터를 너무 많이 가져오거나 너무 적게 가져온다.
    • 모든 데이터 요구를 처리하기 위해 REST API 하나를 만들더라도 많은 데이터를 낭비하게 된다. → overfetching

    이 문제를 해결하기 위해 넷플릭스는 BFF 패턴(Backend For Frontend)을 사용했다.

     

    BFF 패턴은 모든 프론트엔드 또는 UI는 그들만의 mini backend를 갖는다. 미니 백엔드는 팬아웃을 수행하고 그 특정 지점에서 UI가 필요로 하는 데이터를 가져오는 역할을 한다.

     

    BFF는 본질적으로 특정 디바이스의 특정 화면을 위한 Groovy 스크립트다. 특정 화면을 렌더링하는 데 필요한 정확한 데이터를 아는 UI 개발자가 해당 스크립트를 작성했다.

    스크립트가 작성되면, 해당 스크립트는 API 서버에 배포되고 Java 클라이언트 라이브러리를 호출함으로써 모든 다른 마이크로서비스에 팬아웃을 수행한다. (이러한 클라이언트 라이브러리는 gRPC 서비스 또는 REST 클라이언트를 감싼 래퍼이다)

     

     

    Groovy 스크립트는 fanout을 수행하는 것을 도왔지만, 몇몇 한계점이 있었다.

    • 엔드포인트별로 스크립트가 존재하여 유지 및 관리해야 할 스크립트가 많이 생성된다.
    • UI 개발자들은 모든 미니 백엔드를 만들어야 했고, RxJava와 함께 Groovy Java를 써야하는 것을 좋아하지 않았다. (주로 사용하는 언어가 아니었음)
    • Reactive programming은 일반적으로 어렵다.

    The Move to GraphQL Federation

    지난 몇 년간 넷플릭스는 완전히 새로운 아키텍처로 옮겨왔다. 이 새로운 아키텍처의 중심은 GraphQL Federation이다.

     

    GraphQL을 REST와 비교할 때 가장 큰 차이점은 GraphQL이 항상 스키마를 가지고 있다는 것이다.

    GraphQL을 사용하면 클라이언트가 필드 선택에 대해 명시적으로 설명해야 한다. 필드를 요청하지 않으면 필드를 얻지 못한다.

     

    REST의 경우 REST 서비스가 전송하기로 결정한 것은 무엇이든 받는다. (필요하지 않더라도)

    클라이언트가 쿼리를 GraphQL에서 지정해야하는 작업이 생겼지만, 실제로 필요한 것보다 훨씬 더 많은 데이터를 얻을 수 있는 overfetching 문제를 해결한다.

     

    GraphQL을 고도화하기 위해 넷플릭스는 더 나아가서 마이크로서비스 아키텍처에 맞는 GraphQL Federation을 사용했다.

     

    여기서 microservice들은 이제 DGS(Domain Graph Service)라고 불리운다. DGS는 넷플릭스가 GraphQL 서비스를 구축하기 위해 개발한 사내 프레임워크이다. DGS는 GraphQL 엔드포인트와 스키마를 가진 자바 마이크로서비스일 뿐이다.

     

    DGS는 여러 개 존재하지만 TV와 같은 디바이스의 관점에서는 큰 GraphQL 스키마는 하나뿐이다. 이 스키마는 렌더링할 수 있는 가능한 모든 데이터를 포함한다.

    디바이스는 스키마의 일부인 다양한 마이크로서비스에 대해 알 필요가 없어졌다.

     

    서로 다른 두 DGS는 서로에 대해 몰라도 된다. 그들이 해야 할 일은 그들의 스키마를 Federated Gateway에 올리는 것이다. Federated Gateway는 모든 GraphQL endpoint를 가지고 있기 때문에 DGS와 통신하는 것을 알고 있다.

     

    이는 다음과 같은 장점이 있다.

    • API 중복이 없다.
    • API로서의 GraphQL은 필드 선택 기능으로 인해 서로 다른 디바이스를 지원할 수 있을 정도로 유연하기 때문에 BFF가 필요하지 않다.
    • UI 엔지니어들이 서버 측에서 개발할 필요가 없다. 백엔드 개발자들과 UI 개발자들은 스키마에 대해 소통할 뿐이다.

    자바에서는 더 이상 어떤 클라이언트 라이브러리도 필요 없다. Federated Gateway는 특정 코드를 작성할 필요 없이 일반적인 GraphQL 서비스와 대화하는 방법을 알고 있기 때문이다.

     

    이 글에서는 넷플릭스의 기술적 전환, BFF 방식에서 GraphQL Federation으로 넘어가는 과정을 살펴보았다. 데이터에 접근하는 방식을 최적화하고 각 디바이스의 요구에 맞는 더 나은 사용자 경험을 제공하기 위해 노력했던 과정들을 볼 수 있었다! 👍🏻

    반응형

    댓글

Designed by Tistory.