22년의 평화로운 어느날.. 😂 회사에서 상품 조회가 안된다는 이슈 알람이 지속적으로 발생했다.
CloudWatch로 로그를 확인해보니 특정 페이지에서 graphql 응답이 data: null로 오고 있었다. 이런 경우는 처음이어서 여러가지 가설을 세워보았다.
1. graphql federation 할때 문제가 생겼을 것이다.
2. 데이터가 너무 많아서 타임아웃이 발생했을 것이다.
3. 쿼리가 잘못된 것이다.
일단 2, 3번은 가능성이 낮다. 타임아웃이 발생했다면 다른 오류 메시지가 발생했을것이고, 쿼리가 잘못된것이었다면 다른 page의 상품을 불러오는것도 똑같이 문제가 됐어야 한다. federation 문제를 제일 유력한 용의자로 생각하고 가설증명을 시작하였다.
GraphQL Federation이란?
Federation이란 말 그대로 연합이라는 의미로 여러개의 마이크로 서비스에 있는 스키마들을 마치 하나의 스키마처럼 연합하는 방식이다.
클라이언트 입장에선 마치 하나의 연합된 스키마처럼 보인다.(apollo 공식문서에서는 Supergraph라고 한다.)
이 글에선 마이크로 서비스를 서브 그래프, 연합된 그래프를 슈퍼그래프라고 서술하겠다.
문제가 발생한 쿼리도 마이크로 서비스인 상품, 리뷰, 콘텐츠(이미지), 카테고리 서브 그래프들을 연합한 슈퍼 그래프에서 상품 정보를 가져오고 있었다.
Apollo 공식 문서를 보다보면 Apollo Federation subgraph specification에서 이런 내용을 확인할 수 있다.
This field must take a representations argument of type [_Any!]!
(a non-nullable list of non-nullable _Any scalars).
Its return type must be [_Entity]! (a non-nullable list of nullable objects that belong to the _Entity union).
출처: https://www.apollographql.com/docs/federation/subgraph-spec/
클라이언트가 슈퍼 그래프로 쿼리를 요청하면, 그 쿼리를 파싱해서 각자의 서브 그래프로 요청을 보내게 되는데 그 서브 그래프에서 리턴할때 반드시 non-nullable한 값을 보내줘야한다는것이다.
만약 요청한 쿼리가 아래와 같을때 content는 content subgraph를, review는 review의 subgraph, category는 category의 subgraph, 나머지 상품 정보는 product subgraph에서 가져와서 federation 할 것이고 이 4개의 subgraph 중에 하나가 null을 리턴한 것이다.
query GetProductList($page: Int, $size: Int, $filter: ProductFilterInput) {
product {
products(
page:$page,
size: $size,
filter: $filter
) {
totalCount
pageInfo{
hasNextPage
}
edges{
node{
id
status
title
content { # content subgraph
id
uri
}
reviewInfo{ # review subgraph
count
rating
}
category { # category subgraph
id
title
}
}
}
}
}
}
(회사코드이기 때문에 예제로 수정하였다)
실제로 content subgraph에서 잘못된 id를 참조해 null을 리턴하고 있었고, DB에서 값을 직접 수정해 해결할 수 있었다.
간단하게 해결할 수 있었던 이슈였지만 GraphQL Federation에 대해 제대로 모르고 사용하여 이슈를 해결하는데 조금 시간이 걸렸었던 것 같다.
결론
GraphQL의 Federation은 INNER JOIN과 비슷하게 동작하므로 subgraph에서 null을 리턴하지 않도록 주의해서 사용해야한다.
'기타' 카테고리의 다른 글
Lambda@Edge + Typscript로 이미지 리사이징 적용하기 (2) | 2024.06.05 |
---|---|
계층형 모델 테이블 설계(인접 모델, MPTT) (0) | 2024.04.27 |
SQLD 합격 후기 (0) | 2023.12.21 |
Serverless 배포할때 serverless update_rollback_failed state and can not be updated 에러가 나는 경우 (1) | 2023.10.09 |
블로그 시작 (0) | 2019.12.02 |