[ GraphQL ] 공식문서로 공부하기, '모범사례'

minidoo·2023년 3월 27일
0

GraphQL

목록 보기
1/4
post-thumbnail

공식문서 - GraphQL 모범 사례


GraphQL 명세는 **1) 네트워크, 인증, 페이지네이션 처리와 같은 API가 직면하는 몇 가지 중요한 문제**에 대해 의도적으로 다루지 않습니다. GraphQL을 사용할 때 이러한 문제에 대한 해결책이 없다는 것은 아닙니다. 단지 이 문제들은 GraphQL 이 *무엇* 인지에 대한 것과 직접적인 관련이 없으며 이것은 일반적이기 때문입니다.

1) API의 단일 진입점인 API 게이트웨이는 해커의 타겟 대상이 될 수 있다. HTTP 메서드를 사용하여 엑세스할 수 있다는 점이 보안성이 관해서는 단점이 된다.

이 섹션에 글은 전적으로 받아 들여서는 안되며, 특정한 경우에는 이 접근방법이 올바르지 않을 수도 있습니다. 이 문서에서는 GraphQL 서비스의 설계 및 배포와 관련된 Facebook에서 개발된 철학을 소개하고, HTTP를 통한 서빙 및 인증과 같은 일반적인 문제를 해결하기 위한 방법을 제안합니다.

다음에서는 GraphQL 서비스의 가장 일반적인 모범 사례와 좋은 방법에 대해 간략히 설명합니다. 그리고, 이 섹션의 각 문서에서는 이 주제들에 대해 더 자세히 설명합니다.

HTTP

1) GraphQL은 일반적으로 서비스의 모든 기능을 하나의 엔드포인트 HTTP를 통해 제공됩니다. 이는 2) 각각 하나의 리소스를 여러 URL로 노출하는 REST API와는 대조적입니다. GraphQL은 이 리소스 URL들과 함께 사용할 수도 있지만, 3) GraphiQL과 같은 도구를 사용하기가 어려울 수 있습니다.

Serving over HTTP 에서 더 자세히 알아보세요.

1) 단일 endpoint (일반적으로 /graphql)로 작동한다.

2) Over-Fetching, Under-Fetching의 문제가 있다.

3) 웹 브라우저에서 GraphiQL 편집기를 사용하여 API를 테스트할 수 있다. ex) Playground

JSON (with GZIP)

GraphQL 서비스는 일반적으로 JSON으로 응답하지만 GraphQL 명세에서는 필수는 아닙니다. JSON은 더 좋은 네트워크 성능을 보장하는 API 레이어를 위해서는 1) 이상한 선택처럼 보일 수 있지만 대부분 텍스트이기 때문에 2) GZIP으로 매우 잘 압축됩니다.

모든 프로덕션 GraphQL 서비스는 GZIP을 활성화하고 클라이언트가 다음 헤더를 보내는것을 권장합니다.

Accept-Encoding: gzip

JSON은 클라이언트 및 API 개발자들에게도 친숙하며, 읽고 디버깅하기 쉽습니다. 실제로 GraphQL 문법은 JSON 문법에 부분적으로 영향을 받았습니다.

1) 보통 Rest에서 응답은 JSON 형태로 한다. 그렇지만 응답은 string, binary 등 다양한 타입이 가능하다. 만약, 이미지를 응답한다고 했을 때 JSON 형태보다 binary(buffer)로 응답하는 것이 더 편할텐데 왜 JSON으로 하는 것일까? 이는 GZIP으로 압축이 잘 되기 때문이다.

2) GZIP은 단일 파일을 .gz로 압축하는 명령어이며, 큰 파일을 무손실 압축할 수 있다. 다른 압축 알고리즘으로 deflate가 있다. 여러 압축 알고리즘을 함께 사용할 수 있으며, 요청 헤더로 Accept-Encoding에 가중치를 줄 수 있다.

버저닝

GraphQL 서비스가 다른 1) REST API와 마찬가지로 버전이 변경되는 것을 막을 수는 없지만, GraphQL 스키마의 지속적인 업데이트를 위한 도구를 제공하여 버전 관리를 피하는 것에 대해서 강한 의견을 가지고 있습니다.

왜 대부분의 API는 버전관리를 해야할까요? API 엔드포인트에서 리턴된 데이터에 대한 변경이 있을 때 모든 변경은 큰 변화를 일으킬 수 있으며, 큰 변경사항에는 새 버전이 필요합니다. API에 새로운 기능을 추가하는데 새로운 버전이 필요한 경우 API를 이해하기 쉽고 유지 보수할 수 있는 버전을 자주 출시하고 업데이트된 버전을 사용하는 것이 좋습니다.

반대로 GraphQL은 명시적으로 요청된 데이터만 반환하므로 새로운 타입과 필드를 통해 새로운 기능을 추가할 수 있습니다. 이는 항상 변경사항을 피하고 버전없는 API를 제공하는 방법으로 이어집니다.

1) API 버전화 방법이는 URL 경로, 쿼리 매개변수, 사용자 지정 헤더, mime type(Accept Headers)을 통한 버전 지정이 있다. 하위 호환성을 고려하여 버전관리를 해야한다.

Nullability

null 을 판단하는 대부분의 타입 시스템은, 일반 타입과 해당 타입의 nullable 버전을 제공하며, 명시적으로 선언하지 않는한, 기본 타입은 null을 포함하지 않습니다. 하지만 GraphQL 타입 시스템에서는 모든 필드가 기본적으로 nullable 입니다. 이는 데이터베이스 및 기타 백엔드의 네트워크 서비스에서 많은 일이 발생할 수 있기 때문입니다. 데이터베이스가 다운되거나 비동기 작업이 실패할 수 있으며, 예외가 발생할 수도 있습니다. 단순한 시스템 실패 이외에도 요청 내의 각 필드가 서로 다른 인증 규칙을 가져서, 권한이 세분화될 수 있습니다.

이러한 이유로 인해 기본적으로 모든 필드를 nullable 로 설정하면 요청이 완전히 실패하지 않고 해당 필드가 null 로 반환될 수 있습니다. 대신, GraphQL은 1) non-null 타입을 제공하여, 요청시 필드가 절대 null 을 반환하지 않도록 보장할 수 있습니다. 대신에, 만약 오류가 발생하면, 이전 상위 필드가 대신 null 이 됩니다.

GraphQL 스키마를 설계할 때, 잘못될 수 있는 모든 문제와 실패한 필드에 대해 null 이 적절한 값임을 명심하는 것이 중요합니다. 일반적으로 그렇지만 때로는 그렇지 않는 경우도 있습니다. 이러한 경우, null 이 아님을 보장하는 non-null 타입을 사용하십시오.

1) 느낌표(!)는 필드가 non-nullable 임을 의미한다. ex) String!

1. GraphQL의 스칼라 타입은 쿼리의 끝을 나타낸다 (Int, Float, String, Boolean, ID)
2. 자바스크립트의 타입
 - 원시타입 : Boolean, Null, Undefined, Number, BigInt, String, Symbol
 - 객체타입 : Object

페이지네이션

GraphQL 타입 시스템은 일부 필드가 값의 리스트를 반환하지만 API 설계자는 긴 리스트에 대한 페이지네이션을 제공할 수 있습니다. 페이지네이션을 위한 다양한 API 디자인이 있으며, 각각 장단점이 있습니다.

일반적으로 긴 리스트을 반환할 수 있는 필드는 first나 after 인수를 사용하여, 목록의 특정 구간을 지정할 수 있습니다. 여기서 after 는 리스트의 각 값에 대한 고유 식별자(unique identifier)입니다.

기능이 다양한 페이지네이션을 사용하여 궁극적으로 API를 디자인하면 Connections 라는 모범 사례 패턴이 생깁니다. 1) Relay와 같은 GraphQL의 몇몇 클라이언트 도구는 2) Connections 패턴을 구현하며, GraphQL API가 이 패턴을 사용할 때 클라이언트 측 페이지네이션을 자동으로 지원합니다.

페이지네이션 문서에서 자세히 읽어보세요.

1) Relay는 GraphQL 기반의 데이터 중심 React 애플리케이션을 구축하기 위한 자바스크립트 프레임워크이다. 미리 정의된 데이터 구조에서 쿼리를 통해 필요한 데이터만 탐색할 수 있게 해준다.

2) Connection 패턴은 Cursor를 기반으로한 페이지네이션 디자인 패턴이다. 이 패턴에서 페이지는 엣지로 연결된 노드들의 집합이다. 다른 패턴으로는 Offset/Limit이 있다. (https://betterdev.tistory.com/17)

서버사이드 배치 & 캐시

GraphQL은 서버에 깔끔한 코드를 작성할 수 있는 방식으로 설계되었습니다. 모든 타입의 각 필드에는 해당 값을 확인하는데 초점을 맞춘 단일목적(single-purpose) 함수가 있습니다. 하지만 이러한 추가적인 고려없이, 간단한 GraphQL 서비스는 매우 반복적으로 데이터를 데이터베이스에서 로드할 수도 있습니다.

이은 일반적으로 백엔드의 데이터에 대한 다중 요청이 단기간에 발생할 때, 단일 요청에서 데이터베이스나 마이크로서비스로 전송되는 일괄 처리 기법인 Facebook의 1) DataLoader와 같은 도구를 사용하여 해결할 수 있습니다.

1) GraphQL의 N+1 문제를 해결할 수 있다. DataLoader은 특정 데이터를 가져오기 위한 각각의 요청을 batch(모아서) 한번의 요청으로 보내주며, 요청으로 받은 결과 값들을 각각의 요청에 맞게 보내준다. 또한 모든 요청을 caching 하는 것이 아닌 사용자의 단일 요청별로 생성된다. 즉, 성능최적화를 위한 도구이다.

GraphQL은 캐시를 고려하여 설계되었다!

0개의 댓글