개발/flutter

Flutter - GraphQL 세팅 및 쿼리 하는방법

덤벨로퍼 2020. 9. 29. 16:19

Flutter와 GraphQL을 같이 사용하기 위해 처음 해야 할 것은 역시 세팅이다.

graphql 플러그인을 넣어주고 (pub.dev/packages/graphql) 세팅을 시작해보자

 

최신으로다가

처음 graphql 세팅하려면 GrapqlClient 가 필요하다.

나중에 이 GrapqlClient을 통해 api를 호출할것이다.

 

GrapqlClient를 만들기 전에 우선 graphql_client.dart 파일을 생성했다.

여기서 GrapqlClient을 만들 작업을 할 것이다.

GrapqlClient를 생성하기 위해서 AuthLink와 HttpLink가 필요하다.

final _httpLink = HttpLink(
  uri: '$SERVER_URL',
  headers: <String, String>{'os': os, 'uuid': uuid}
);

HttpLink 에다가 graphql의 엔드포인트 uri를 설정해주고 httplink 헤더 안에 유저의 os, uuid를 넣어줬다.

헤더는 필수적인 것은 아니라 생략 가능하다.

final AuthLink _authLink = AuthLink(getToken: ()  {
  return userToken;
});

AuthLink 에는 로그인한 유저의 인증 토큰이 들어갈 것이다.

만약 유저 인증 토큰이 필요 없는 api 호출이라면 null을 리턴해도 상관없다.

 

이제 이 두 링크를 사용해  GrapqlClient을 생성한다.

final Link _link = _authLink.concat(_httpLink); //아까만든 두 링크합침


GraphQLClient _client; //전역변수 선언
GraphQLClient getGraphQLClient() { 
  _client ??= GraphQLClient( //_client 전역변수 없으면 넣어줌,
    link: _link,
  );
  return _client;
}

 

이렇게 GraphQLClient를 생성했고 이제 클라이언트에서 필요한 api 호출을 할 때

getGraphQLClient()를 사용하면 된다.

가장 단순한 유형의 쿼리를 사용해 실제로 데이터를 받아오는 부분을 구현해보자

 String readInquiryChannel() => '''
  {
    inquiryChannel
  }
  ''';

해당 api는 필요한 url를 리턴해주는 단순한 쿼리이다.

클라이언트에서 필요한 것은 저 String 타입인 url 한 개뿐이다.

 

api통신을 통해 원하는 데이터를 받아오는 함수를 구현해보자.

Future<String> getInquiryChannel() {
  return getGraphQLClient().query(_queryOptions()).then(_toInquiryChannel);
}

아까 만든 getGraphQLClient() 함수를 실행해 GraphQLClient를 리턴 받는다.

GraphQLClient.query()는 내가 만든 쿼리를 실행해 결괏값을 리턴해주며

에러를 받으면 에러를 리턴해준다.

 

query() 함수 안에는 인자 값으로 QueryOptions이 들어간다.

QueryOptions 은 api 통신에 대한 규칙과 방식이 담겨있으며 쿼리도 이안에 들어간다.

 

 QueryOptions _queryOptions() {
    final query = readInquiryChannel(); //아까만든 쿼리

    return QueryOptions(
      fetchPolicy: FetchPolicy.networkOnly, //networkOnly를 사용하지 않으면 내부 캐싱을 사용
      documentNode: gql(query), 
    );
  }

 

문의 채널 url 이 자주 바뀌거나 하지는 않으니 사실 내부 캐시 데이터를 사용해도 무방하다.

그 외 다른 옵션들이 있으나 필수적인 것은 저 두 개가 있고 다른 건 사용해본 적은 없다.

 

다시 api 호출 함수를 보자

Future<String> getInquiryChannel() {
  return getGraphQLClient().query(_queryOptions()).then(_toInquiryChannel);
}

query(_queryOptions()) 가 실행되면서 쿼리를 실행했고

따라서 데이터가 리턴되었거나 에러가 발생했다면 에러가 리턴되었을 것이다.

그 결괏값을 _toInquiryChannel 함수에 받아왔다.

 

String _toInquiryChannel(QueryResult queryResult) {
    if (queryResult.hasException) {
      getLogger(this).w(queryResult.exception);
      throw queryResult.exception;
    }
    final String channel = queryResult.data['inquiryChannel']
    return channel;
  }

 

그 결괏값은 queryResult에 담겨있다.

queryResult에는 에러가 발생했다면 queryResult.exception 을통해 에러를 받아 올 수 있고

그 에러를 가지고 어떻게 에러를 처리할 건지 작업이 필요할 것이다.

 

그리고 데이터를 리턴 받았다면 queryResult.data를 통해 데이터를 받아 올 수 있다.

받아오는 데이터 구조가 복잡하다면 여기에서 모델링을 해야 할 것이다.

 

 

 

 

 

 

Future<String> getInquiryChannel() {
  return getGraphQLClient().query(_queryOptions()).then(_toInquiryChannel);
}

QueryOptions _queryOptions() {
    final query = readInquiryChannel();

    return QueryOptions(
      fetchPolicy: FetchPolicy.networkOnly, 
      documentNode: gql(query), 
    );
  }

String _toInquiryChannel(QueryResult queryResult) {
    if (queryResult.hasException) {
      getLogger(this).w(queryResult.exception);
      throw queryResult.exception;
    }
    final String channel = queryResult.data['inquiryChannel']
    return channel;
}
  
String readInquiryChannel() => '''
  {
    inquiryChannel
  }
''';

추후 포스팅 예정

인자값 넣어서 mutation 하기

데이터 모델링 하기

에러 핸들링하기

페이지 네이션 하기