ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Flutter - GraphQL 세팅 및 쿼리 하는방법
    개발/flutter 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 하기

    데이터 모델링 하기

    에러 핸들링하기

    페이지 네이션 하기

    댓글

Designed by Tistory.