Published on

ApolloClient OnError 에 대해서

Authors
  • avatar
    Name
    길재훈
    Twitter

ApolloClient Error Link

newWork 단계에서 error 를 검증하고 handling 하는 API 모음이다.

Error Link 는 onError 라고 하는 Custom Logic 이 존재한다.

onError 는 GraphQL 또는 network error 가 발생할때 작동한다.

onError 는 Callback 함수를 하나 받는데, 만약 작업도중 많게는 하나 혹은 여러개의 error 를 반환한다면 이 함수가 실행된다.

onError 의 Callback 함수는 다음처럼 생겼다.

import { onError } from '@apollo/client/link/error'

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.forEach(({ message, locations, path }) =>
      console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`)
    )
  if (networkError) console.log(`[Network error]: ${networkError}`)
})

onError 를 가져오기 위해서는 @apollo/client 에서 /link/error 에 존재한다.

그리고 structuring assignment(구조분해할당) 을 통해 해당 onError 를 가져온다. 가져온 Callback 에서 다음과 같은 인자를 받는다.

Name/TypeDescription
opreation: Operation오류를 발생한 GraphQL 의 세부정보
response: ExecutionReulstserver 를 통한 GraphQL 결과이다.
Docs 에서는 chain 을 통해 다음 link 로 타고 내려가 terminating link 에 더 가까운 link 에 의해 전달된다고 되어있다.
해당 내용은 지식이 더 필요할듯 싶다.
response 는 수정이 가능하다고 명시되어 있다!
graphQLErrors: ReadonlyArray < graphQLErrors >만약 에러가 존재한다면, 실행중에 발생한 에러를 Array 객체로 내보낸다.
networkError: Error | serverError | ServerParseError만약 에러가 존재한다면, 작업 실행중 network error 가 발생된것이다.
forward: function이 function 은 연결되어진 chain 을 타고 내려가 다음 link 를 호출한다.
onError 의 콜백에서 return forward(operation) 를 호출하면,
구독할 upstream link 에 대한 새로운 observable이 반환된다.

지금 이 내용상에서 보면, chain 에 대해서 설명하고 있는것이 눈에 띈다. onError 를 정확히 인지하고 사용하기 위해서는 다음의 몇가지 키워드를 바로 잡아야 한다.

  1. chain
  2. link
  3. operation
  4. forward
  5. observable

Apollo Link 라이브러리는 GrapyQL server 와 Apollo Client 사이의 data 흐름을 custom 하게 도와주는 도구이다.

Apollo Link 를 통해 client network 동작을 순서대로 실행되는 link 가 서로 이어져 있는데 이렇게 이어져 있는 구조를 chain 이라 한다.

아폴로 링크는 다음과 같은 구조로 되어 있다.




ApolloLink




각각의 Link 들은 각 역할을 수행하도록 이어져 있으며, 이전 Link 의 operation 을 다음 Link 에 전달한다.

이러한 구조라면, 전송될 data 를 각 역할마다 따로 로직을 구성하여 통합할 수 있어 좋은 구조라는 생각이 든다.

각 Link 는 사용자가 직접 지정하여 만들수도 있으며, ApolloClient 에서 제공해주는 Link 를 사용하여 만들 수 있다.

이때 가장 마지막에 있는 Link 를 terminating Link 라고 부르며, GraphQL Server 에 Request 하는 역할을 하며, Link 의 Chain 은 종료된다.

Request 가 아닌 Server 로 부터 Response 할때는 위의 다이어그램의 역순으로 Link 가 이어진다.

ApolloClient 가 GraphQL Server 에 보낼때 용어를 Down Chain 이라고 부르며,
GraphQl Server 가 ApolloCient 에 보낼때는 Up Chain 이라고 한다.

Docs 를 보면서 이 용어가 꽤나 자주나온다..

Link 에 대한 자세한 내용은 1페이지 를 할애할 정도로 양이 많은 상황이라, 이부분은 추가적으로 내용을 정리해야 할것 같다.

여기서 중요한 부분은 Apollo Client 에서 GrapyQL Server 사이의 Network 흐름을 처리하기 위해 Link libary 를 사용하며, Link library 는 각 Link(수행할 역할) 을 Chain 형식으로 연결지어 두었는것이다.

operation 과 forward

위의 Link 에 대해 대략적으로 살펴보았다. Link 는 Network 조작을 위해 존재한다고 했으며, onError 는 Network 상 어떠한 Error 가 발생했을때, Catch 하여 알려준다.

즉, onError는 Apollo Client 에서 제공해주는 Link 이다. Link 는 호출내부에 callback 함수를 받는데, 이를 request handler 라고 부른다.

먼저 code 를 살펴보도록 하자.


import { onError } from '@apollo/client/link/error'

  const errorLink = onError(({ graphQLErrors, networkError, operation, foword}) => { ... })

위 코드를 보면 callback 함수의 인자 중 operation 과 forward 가 보일것이다.

request handler 는 다음의 인자를 기본적으로 제공한다.

  1. operation
  2. forward

물론, onError 의 callback 은 다른 인자를 갖기도 하지만 Link 이기에, request handler 이기에 위 인자를 사용할 수 있다.

Docs 에서는 위 인자는 다음의 property 를 제공한다.

operation

operation

NameDescription
query발생하는 작업을 설명하는 DocumentNode
variables작업과 함께 전송하는 GraphQL variables 의 map
operationName만약 이름이 있다면 query 의 이름, 아니면 null
extentionsserver 로 보낼 확장 data 가 저장된 map
getContext요청의 context 를 리턴하는 함수
이 context 는 수행작업을 정하기 위해 links 에서 사용할 수 있다.
setContext새로운 context 객체 또는 함수를 가지는 함수, 함수일때 이전 context 를 인자로 가질수 있고 새로운 context 를 return 할 수 있다.

forword

link 의 request handler가 done 일때 forward를 반환한다.

만약 link 가 terminating link 라면 제외

return forward(operation) 은 link chain 에서 다음의 link에 전달된다.

만약 customLink 가 return forward(operation) 을 반환하지 않으면, 다음 링크가 실행되지 않고 terminating link 로 인식하여 종료된다. 그러므로 연결된 다른 link 가 실행되지 않을 수 있으니 주의하자

observable

우리가 사용하고 있는 forward 의 return 타입은 observable 타입이다. 여기서 observable 타입이 무엇인지 알 필요가 있다.

observable 는 데이터를 비동기로 처리해 변화에 유연함을 주는 프로그래밍 패러다임이라고 한다.

이러한 observable 은 reactive programing 을 하는데 사용되는 pattern 중에 하나이다.

reactive programing 이란, 어떠한 데이터가 변화되었을때, 즉각적으로 반응하여 처리하는 프로그램 패러다임을 뜻한다.

reactive programing 이란 무엇인지 조금더 개념을 살펴보아야 겠다.

Reactive Programing 개념

observable 은 RP(reactive programing) 에서 producer 라고 부르며, observable 의 상태를 관찰하고 반응하는 observer 는 consumer 라고 부른다.

이렇게 prodcuer 와 consumer 가 구분되어 처리되는것을 통해 각 상태의 분리가 가능하며, 불변성역시 보장된다 .

producer 가 데이터를 받아 consumer 로 보내는데, 이렇게 보내는 흐름을 stream 이라고 표현한다.

이러한 스트림은 pipe line 을 통해 이어지는데, 여기서 pipe 는 producer 로 부터 받은 원본데이터를 순차적으로 가공하여 consumer 로 보내주는 역할을 한다. 그리고 그 받은 데이터를 consumer 가 소비(데이터를 사용)한다.

즉, producer 는 마치 consumer 가 수신할 알림을 보내는 역할을 한다. consumer 는 producer 로 부터 받은 모든 이벤트에 대해 비동기로 반응하기에, single thead 인 nodejs 에서 동기적으로 멈출일이 없다.

이는 비동기 프로그래밍 에서의 이점을 살리며 처리하는 방식이다.

이러한 비동기 로 인해 RP 는 data fetching 에 이상적으로 작동 가능하다. 이는 대규모 이벤트 처리 가 일어나더라도, 멈추는 일 없이 처리 가능하다는 것이다.

RP 에서의 중요한 부분은, comsumer 가 subscription 하지 않으면 동작하지 않는다는 것이다.

subscription 된 consumer 가 존재한다면, subscription 된 모든 consumer 들이 공통적인 pipe 를 통해 동일한 처리가 이루어진다.

tc39/proposal-observable 에서 javascript 의 observable 이 어떻게 만들어지고 작동하는지 설명해준다.

observable 에 대한 부분을 알기 위해서는 더 많은 공부가 필요할것 같다. 추푸 RxJS 를 추가적으로 공부할 계획이다.

다시 onError 로 돌아와서..

forward: function 에서의 문구를 다시 보자

function 은 연결되어진 chain 을 타고 내려가 다음 link 를 호출한다.
onError 의 콜백에서 return forward(operation) 를 호출하면,
구독할 upstream link 에 대한 새로운 observable이 반환된다.

이 문구상에서 chain 은 Link 객체가 연결되어진 것을 뜻하며, onError 의 forward 를 통해 다음 Link 에 전달된다.

이때 중요한 것은 OnError는 서버로부터 받은 상태값이기에, Downstream 이 아닌 Upstream 이라는 것이다,

이렇게 반환된 결과값은 forword 에 의해 observable 타입으로 반환되는것을 알수 있게 되었다.