pile·
백엔드·카카오 스타일 (지그재그)카카오 스타일 (지그재그)·

GraphQL 이해하기: (4) 리졸버 인자 - 2. args

GraphQL.js 리졸버의 두 번째 인자인 args를 다룬 연재 글이다. 객체 속성에도 인자를 줄 수 있다는 특성과 null을 준 것과 아예 누락한 것이 구분된다는 점을 실행 결과로 보여준다. 후반부는 상위 필드의 인자를 하위 리졸버에서 써야 하는 목록 페이지네이션 상황을 다룬다.

핵심 포인트
  • GraphQL에서는 최상위 필드뿐 아니라 객체의 속성에도 인자를 줄 수 있어 서버에서 가공해 내려줄 수 있다.
  • nullable 인자에 null을 준 것과 인자를 아예 누락한 것은 서로 다르게 전달된다.
  • 리졸버는 어떤 경로로 온 객체인지 몰라도 동작하도록 짜는 것이 바람직하다.
  • 그런데 목록과 전체 개수를 함께 반환하는 API에서는 상위 인자가 필요해진다.
  • 상위 리졸버가 인자를 담은 객체를 반환하면 하위 리졸버가 source로 받아 쓸 수 있다.
  • 대안은 상위에서 둘 다 계산해 반환하는 것인데, 하나만 요청해도 나머지를 계산하는 비효율이 생긴다.
상세 정리
  • 기본 동작: 해당 필드에 인자가 주어지면 그 값이 두 번째 인자로 들어온다. Java 쪽에서는 환경 객체의 getArguments로 얻는다.
  • 예제 구성: 사용자 목록을 반환하는 쿼리에 검색어와 개수 인자를 두고, 사용자 타입의 이름 필드에도 길이 인자를 뒀다.
  • 예제 동작: 목록 리졸버는 검색어로 거른 뒤 개수만큼 잘라 반환하고, 이름 리졸버는 길이만큼 문자열을 자른다.
  • 세 가지 질의: 검색어와 개수를 모두 준 경우, 개수만 주고 이름에 길이를 준 경우, 두 인자에 명시적으로 null을 준 경우를 한 번에 실행한다.
  • 결과의 관전 포인트: 인자를 누락하면 빈 객체가 들어오지만 null을 명시하면 그 키가 null 값으로 들어온다.
  • 저자의 견해: 자바스크립트의 null과 undefined 구분은 혼란을 주지만 가끔 유용하다. 다만 GraphQL API는 모든 언어를 고려해야 해 실제로 이 차이를 활용한 적은 없다고 밝힌다.
  • Java 구현: DGS Framework로 같은 예제를 짜도 결과가 동일하며 arguments를 출력해보면 null과 누락이 구분되는 것을 확인할 수 있다.
  • 상위 인자 문제의 발단: 사용자 타입의 필드 리졸버는 그 객체가 어떤 경로를 거쳐 왔는지 알 수 없으므로 경로에 의존하지 않게 짜야 한다.
  • 그럼에도 필요한 경우: 목록 API에서 페이지네이션을 보여주려면 요청한 목록 외에 전체 개수도 필요하고, GraphQL이면 둘을 한 번에 요청할 수 있다.
  • 표준 스펙: 페이스북이 GraphQL을 내놓을 때 Relay와 함께 Connections 스펙을 제시했고, 전체 개수와 페이지 정보, edges와 cursor로 구성된다.
  • 카카오스타일의 선택: 그 스펙이 복잡하다고 보고 Connection과 Edge, Node 대신 List와 Item 개념을 쓴다. cursor를 위로 빼 Edge를 없애고 다음 페이지 여부는 next_cursor가 null인지로 대체했다.
  • 문제 상황: 목록 쿼리에 작성자와 기간, 제목 조건과 offset·limit 인자를 두면, 전체 개수와 목록 리졸버 모두가 그 인자들을 알아야 한다.
  • 나쁜 대안: 하위 필드에 같은 인자를 중복해 기술하는 것은 좋아 보이지 않는다.
  • 선택한 기법: 상위 리졸버가 인자를 특정 키에 담은 객체를 반환하면 하위 리졸버가 source에서 꺼내 쓴다. 원 리졸버의 args와 헷갈려 익숙해지는 데 시간이 걸리지만 동작한다.
  • 다른 대안: 상위에서 전체 개수와 목록을 모두 구해 반환하면 되지만, 둘 중 하나만 요청받아도 나머지를 계산하게 된다. 다음 편에서 다룰 info로 최적화할 수는 있다고 덧붙인다.
  • 사용 지침: 상위 인자 접근은 일반적으로 좋지 않은 패턴이므로 목록과 개수처럼 사실상 한 쌍으로 취급되는 경우에만 쓰기를 권한다.
  • Java의 대안: GraphQL Java에는 상위 필드가 반환한 값을 별도로 전달받는 localContext 개념이 있어 인자를 그쪽에 실어 보낼 수 있다.
왜 읽나목록과 전체 개수를 함께 내려주는 GraphQL API를 짜다 하위 리졸버가 검색 조건을 몰라 막혔다면 두 가지 우회와 각각의 대가가 정리돼 있다.
카카오 스타일 (지그재그)
카카오 스타일 (지그재그) 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·twilio-engTwilio Engineering·

    Programmable Messaging에서 Verify API로 마이그레이션하기

    Twilio의 Programmable Messaging API로 자체 OTP 솔루션을 운영하던 서비스가 Verify API로 전환하는 방법을 코드 예시와 함께 설명한다. Verify는 OTP 전송·검증을 위한 전용 API로, 전화번호 구매, 토큰 생성, DB 저장·만료 관리를 내부에서 처리해 개발자가 직접 구현할 코드를 크게 줄인다.

    요약 이어보기
    #authentication#twilio#sms+2
  2. 백엔드·포스타입포스타입·

    포스타입이 개인화 추천을 하는 방법 2부

    포스타입 백엔드 엔지니어가 벡터 기반 개인화 추천 시스템을 실제 운영하며 맞닥뜨린 성능 장애와 용량 문제를 해결한 과정을 담은 2부다. 수백만 개의 벡터 KNN 검색이 피크 시간대에 전체 Elasticsearch 검색 성능을 흔드는 문제부터 클러스터 OOM 사태까지, 쿼리 최적화와 인프라 분리 두 가지 경로로 근본 해결에 이른다.

    요약 이어보기
    #elasticsearch#vector-search#recommendation-system+2
  3. 백엔드·포스타입포스타입·

    포스타입이 개인화 추천을 하는 방법 1부

    포스타입이 태그 기반 추천의 한계를 극복하고 벡터 임베딩 기반 개인화 추천 시스템을 구축한 과정을 담은 1부다. 유사한 콘텐츠가 다른 용어를 쓰거나 동일한 태그가 전혀 다른 톤의 콘텐츠를 가리키는 문제를 임베딩 벡터로 해결하고, OpenSearch의 HNSW ANN 검색으로 수백만 벡터를 실시간 검색하는 시스템을 구축해 구매율 15% 향상을 달성했다.

    요약 이어보기
    #opensearch#vector-search#recommendation-system+2