Define the problem first
GraphQL의 경우에는 over-fetching을 방지하고, under-fetching에 이점이 있음api를 요청하는 쪽에서 필요한 데이터를 정의하고 조회할 수 있음DB 뿐만 아니라 저장 환경을 가리지 않고 사용할 수 있음query - 데이터 조회(read)mutation - 데이터 조작(create, update, delete)subscription - websocket 등 소켓 연결해서 변경사항 구독scalar(like primitive type)과 object가 있음fragment 사용 -> relay 구현에 중요한 개념union type - 리스트에 여러 타입을 받을 수 있게 함.fragment를 사용하거나 in-line fragment 로 사용할 수도 있음.interface - 여러개의 타입을 반환하게 함.introspection - api 세부사항에 대한 쿼리 작성 가능하게 해줌.간단한 GraphQL syntax
query 쿼리명 {
필드명 {
…
}
}
fragment 이름 on 필드 {
…
}
GraphQL은 사실 문서 처음에 1+N 문제를 언급해줘야한다고 생각함. 1+N 문제가 뭔지 생각해보자.
query 사업자조회 {
id,
name,
사업장 {
id,
name
}
}
같은 쿼리를 날린다고 하자. 그럼 보통의 Graphql resolver에서는 어떻게 동작하냐고 하면,
select * from 사업자
의 결과로 N개의 사업자를 얻었을 때, N개의 사업자의 사업장 정보를 얻기 위해서
select * from 사업장 where 사업장.ID = 앞쿼리의결과.사업장ID
같은 쿼리가 N번 날아간다. 이상하다.
만약에 이걸 rest api로 구현했으면 endpoint에서 DB 조회를
select *
from 사업자
join 사업장 ON 사업장.ID = 사업자.사업장ID
의 결과로 쿼리 1회로 끝날텐데 말이다.
이건 데이터가 많아지면 심각한 문제인데, 이를 해결하기 위해 batching을 이용하여 javascript로 구현한 Dataloader가 있고, clojure 생태계에서는 superlifter가 있는데 이들이 1+N문제를 어떻게 해결하고 있는지 살펴보자.
batching과 caching을 통해 데이터베이스나 웹 서비스 같은 원격 데이터 소스에 단순하고 일반된 API를 제공하기 위해 만들어진 것임Node.js 서비스용을 위한 javascript로 구현된 간단한 버전임graphql-js 서비스 구현에 좋음개념은 nodejs나 javascript에만 고유한 것이 아니라 다른 언어에서도 사용할 수 있는 메커니즘임Dataloader의 Haskell 구현체인 Haxl에 영감을 받아 구현lacinia에서 어떻게 사용하는지 살펴보자enqueue - fetcher를 큐에 넣는 과정. queue 이름이 없으면 default 세팅값으로update-trigger - trigger 내용을 업데이트하는 내용.{:triggers {:queue-size {:threshold 10}}} - 정해진 queue size{:triggers {:elastic {:threshold 0}}} - 탄력적으로 정의한 만큼의 queue size를 가지도록 하고 그 이후에는 다시 0으로 돌아감{:triggers {:interval {:interval 100}}} - 100ms 간격으로 쿼리threshold에 맞은 상태가 되면 queue에 데이터의 query를 한번에 함1:N 관계에서 def-superfetcher를 잘 정의하고 사용하면 됨Discuss this post here.
Published: 2022-01-20
Tagged: GraphQL