Flutter - GraphQL 세팅 및 쿼리 하는방법
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 하기
데이터 모델링 하기
에러 핸들링하기
페이지 네이션 하기