---
title: Flutter GraphQL 프로젝트 설정 및 데이터 활용 가이드
slug: docs-kr/flutter/graphql/flutter-graphql-project-with-source-code-download
description: Flutter 앱에 GraphQL API 연결하여 데이터 가져오고 활용하는 방법을 배우세요.
image: https://www.back4app.com/images/logo-social.png
createdAt: 2024-03-18T18:07:29.171Z
---

# 소스 코드가 포함된 Flutter GraphQL 프로젝트 다운로드 및 Back4App 사용 시작하기



## 소개

이 튜토리얼에서는 GraphQL을 통해 Back4App 백엔드에서 데이터를 파싱하는 애플리케이션을 구축할 것입니다. 아시다시피, GraphQL은 API를 위한 오픈 소스 데이터 쿼리 및 조작 언어이며, 기존 데이터를 사용하여 쿼리를 수행하는 런타임입니다. Back4App은 개발자가 확장 가능하고 확장 가능한 모바일 및 웹 애플리케이션을 빠른 속도로 구축할 수 있도록 돕는 저코드 백엔드 서비스(오픈 소스 Parse 플랫폼 기반)입니다.

## 목표

주요 목표는 프로그래밍 언어 목록과 해당 저장 형식을 보여주는 간단한 앱을 만드는 것입니다.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/_-4cKpBMuxZgozn0f7GK8_image.png" size="50" width="249" height="441" position="center" showCaption="false"}

이 기사 끝에서 여러분은 다음을 할 수 있을 것으로 기대합니다:

- **GraphQL을 사용하여 Back4App에서 API 호출하기;**
- **GraphQL API에서 데이터 가져오기;**
- **Flutter 앱에서 데이터 가져오기.**

### 전제 조건

:::hint{type="info"}
**이 튜토리얼을 완료하려면 다음이 필요합니다:**

- Android Studio 또는 Flutter와 같은 Flutter 코드를 작성할 수 있는 IDE. 그러나 이 튜토리얼에서는 Android Studio를 사용할 것입니다.
- 여기에서 생성할 수 있는 Back4App 계정: [Back4App](https://www.back4app.com/)
- [GraphQL\_flutter](https://pub.dev/packages/graphql_flutter)
:::

## 1 - Github에서 Android Studio로 프로젝트 복제하기

다음으로 가세요 [Github 저장소](https://github.com/templates-back4app/Flutter-GraphQL), ZIP 파일을 다운로드하고, 압축을 풀고, Flutter IDE에서 엽니다.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/pWqIPMznW1Jcd-AyBCc3C_image.png)

이 단계를 완료하려면, zip 파일 안의 폴더를 바탕 화면으로 드래그하고 Android Studio를 열고 '기존 Android Studio 프로젝트 열기'를 클릭하세요. 프로젝트 디렉토리는 보통 '*C:\Users\Username\Desktop\back4App\_GraphQL-starting\_code*’입니다.

하지만 이는 사용자마다 다를 수 있습니다.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/NPwmVfaQbmfUk6XN_XTkq_image.png)

프로젝트를 열고 <font color="#2166ae">`lib\main.dart`</font> 파일로 가세요. 거기에는 많은 오류가 보일 것입니다. 걱정하지 마세요, '*Get dependencies*'를 모두 눌러주세요. 그러면 모든 오류가 사라질 것입니다. 만약 그렇지 않다면 '*Upgrade dependencies*'를 눌러주세요.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/Zot364iTdLBDGfAi7pihY_image.png)

당신의 <font color="#2166ae">`main.dart`</font> 코드가 이렇게 보여야 합니다.

```dart
1   import 'package:flutter/material.dart';
2   import 'package:graphql_flutter/graphql_flutter.dart';
3   import 'consonents.dart';
4
5   void main() {
6     runApp(MyApp());
7   }
8
9   class MyApp extends StatelessWidget {
10    @override
11    Widget build(BuildContext context) {
12      return MaterialApp(
13        home: MyHomePage(),
14        ),
15      );
16    }
17  }
18  class MyHomePage extends StatefulWidget {
19    @override
20    _MyHomePageState createState() => _MyHomePageState();
21  }
22
23  class _MyHomePageState extends State<MyHomePage> {
24  
25    @override
26    Widget build(BuildContext context) {
27      return SafeArea(
28        child: Scaffold(
29          appBar: AppBar(
30            title: Text('Parsing data using GraphQL',
31            ),
32          ),
33          body: Container(),
34      ),);
35    }
36  }
```

앱을 실행하면 에뮬레이터/장치에서 빈 화면만 보이게 되며, 제목이 *‘데이터 파싱하기 GraphQL’*&#xC778; AppBar만 표시됩니다.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/gvYh8hgqNlREnr-l-q-KR_image.png" size="50" width="247" height="442" position="center" showCaption="false"}

우리는 <font color="#2166ae">`main.dart`</font> 파일에서 작업할 것이며, 우리의 중요한 값은 <font color="#2166ae">`consonents.dart`</font>에 저장되어 있으며, 우리는 거기에서 직접 사용할 수 있습니다. 우리는 앱에서 graphQL을 사용하기 위해 <font color="#2166ae">`graphql_flutter`</font> 의존성이 필요합니다.

:::hint{type="info"}
&#x20;<font color="#2166ae">`graphql_flutter`</font>는 flutter를 위한 가장 인기 있는 GraphQL 클라이언트입니다. 이는 우리 코드에서 직접 *GraphQL* 쿼리를 사용할 수 있도록 도와줍니다. 이는 우리에게 <font color="#2166ae">`GraphQLClient`</font>, <font color="#2166ae">`GraphQLProvider`</font> 및 데이터베이스에서 데이터를 직접 파싱하는 데 도움이 되는 많은 유용한 위젯을 제공합니다. <font color="#2166ae">`StreamBuilder`</font>조차 사용하지 않고도 말이죠. 이 패키지는 다음과 같은 많은 기능을 제공합니다:

- 구독
- 메모리 캐시
- 오프라인 캐시 동기화
- 낙관적인 결과
- GraphQl 파일 업로드
:::

다음 코드를 <font color="#2166ae">`pubspec.yaml`</font> 파일에 작성하여 가져올 수 있습니다:

:::BlockQuote
dependencies:
&#x20; graphql\_flutter: **^**&#x33;.1.0
:::

:::hint{type="info"}
자세한 내용은 <font color="#2166ae">`graphql_flutter`</font>에서 확인하세요 [GraphQL Flutter 문서](https://pub.dev/packages/graphql_flutter)
:::

모든 종속성이 이미 사전 설치되어 있으며 이제 다음 단계로 진행할 수 있습니다.

## 2 - Back4App에서 백엔드 생성하기

Back4App 웹사이트에 가입한 후, 다음 단계로 진행하여 새 앱을 생성할 수 있습니다. [Back4App](https://www.back4app.com/)를 클릭하세요. *‘새 앱 만들기’*&#xB97C; 클릭합니다. 여기서 프로젝트 이름과 동일한 이름을 부여하세요. 즉, *‘back4app\_Graphql’*&#xC785;니다.

이제 왼쪽에서 *서버 설정*으로 스크롤하여 *설정* 관리 파서 서버 카드를 선택한 다음, 목록에서 *‘3.10.0 - Parse Server 3.10.0’* 옵션을 선택합니다. 이제 아래의 저장 버튼을 눌러 저장될 때까지 기다리세요.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/IvwhiBtWYUgBFYASsT2z-_image.png)

이제 *코어*로 돌아가서 (왼쪽), *API 콘솔*을 선택하고 그 안에서 *GraphQL 콘솔*을 선택하세요.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/h900ERbA5Rem8OAJb9c8q_image.png)

이곳은 GraphQL 쿼리/변경 코드 작성 및 테스트를 할 수 있는 창입니다. 다음 단계로 진행합시다.

## 3 - GraphQL을 통한 데이터 생성 및 가져오기

이제 GraphQL API 콘솔을 사용하여 Back4App에서 GraphQL API를 테스트해 보겠습니다. 먼저, 왼쪽 코드 상자에 다음 쿼리를 붙여넣으세요:

```graphql
1       mutation CreateClass {
2   		    createClass(input:{
3   	    name: "Language"
4    	    schemaFields: {
5   	      addStrings: [{name: "name"}{name: "saveFormat"}]
6   	    }
7   	  }){
8   	    class{
9   	      schemaFields{
10  		name
11   		__typename
12  	      }
13  	    }
14  	  }
15  	}
16
```

위 코드는 “Language”라는 이름의 클래스를 생성합니다. 이 새로운 클래스를 몇 개의 행으로 채워봅시다:

```graphql
1       mutation CreateObject{
2   	  createLanguage(input:{fields: {name: "Python", saveFormat:".py"}}){
3   	    language{
4   	      name,
5   	      saveFormat
6   	    }
7   	  }
8   	}
```

작업이 성공하면 GraphQL PlayGround의 오른쪽 코드 상자에서 이 메시지를 볼 수 있습니다:

```graphql
1       {
2   	  "data": {
3   	    "createLanguage": {
4    	      "language": {
5    		    "name": "Python",
6   		      "saveFormat": ".py"
7   	      }
8   	    }
9   	  }
10   	}
```

변경 사항을 만들거나 클래스를 생성하는 데 변형이 사용됩니다. 위의 변형을 실행하면 데이터 필드가 있는 Language라는 새 클래스를 생성합니다:

- **name: “Python”**
- **saveFormat: “.py”**

같은 클래스에서 두 개의 객체를 더 생성하는 과정을 반복하십시오:

- **name: “C” 및 saveFormat: “.c”**
- **name: “java” 및 saveFormat: “.java”.**

이것에 대한 변형은 다음과 같습니다:

```graphql
1       mutation CreateObject{
2   	  createLanguage(input:{fields: {name: "C", saveFormat:".c"}}){
3    	    language{
4    	      name,
5    	      saveFormat
6    	    }
7   	  }
8    	}
```

자바:

```graphql
1       mutation CreateObject{
2   	  createLanguage(input:{fields: {name: "Java", saveFormat:".java"}}){
3   	    language{
4   	      name,
5    	      saveFormat
6    	    }
7   	  }
8   	}
```

이제 우리 클래스 *Languages*의 모든 데이터를 살펴보겠습니다. 데이터를 읽기 위해 우리는 *query*를 사용합니다. 그러니 아래 명령어를 입력하세요.

```graphql
1       query FindLanguages{
2   	  languages{
3   	    count,
4   	    edges{
5   	      node{
6   		name,
7    		saveFormat
8   	      }
9   	    }
10  	  }
11  	}
```

‘<font color="#2166ae">`query FindLanguage`</font>’는 당신의 쿼리 명령어에 대한 이름일 뿐이며, 다른 어떤 이름으로도 지을 수 있습니다. 우리는 <font color="#2166ae">`find(className: "")`</font> 명령어를 사용하여 특정 클래스의 모든 요소를 찾습니다. <font color="#2166ae">`count`</font>,는 클래스의 요소 수를 반환하며 모든 요소는 <font color="#2166ae">`result`</font> 객체 안에 표시됩니다.

위 쿼리는 다음을 반환할 것입니다:

```graphql
1       {
2   	  "data": {
3   	    "languages": {
4   	      "count": 3,
5   	      "edges": [
6   		{
7   		  "node": {
8   		    "name": "Python",
9   		    "saveFormat": ".py"
10  		  }
11  		},
12  		{
13  		  "node": {
14  		    "name": "C",
15  		    "saveFormat": ".c"
16  		  }
17  		},
18  		{
19  		  "node": {
20  		    "name": "Java",
21  		    "saveFormat": ".java"
22  		  }
23  		}
24  	      ]
25  	    }
26  	  }
27  	}
```

다른 모든 쿼리는 다음 링크에서 확인할 수 있습니다:
[GraphQL 쿼리 - Back4App](https://blog.back4app.com/graphql-on-parse/)

이제 다음 단계로 진행합시다.

## 4 - 우리 앱에서 GraphQL 설정하기

우리 앱을 코딩하기 시작합시다. 이 전에, 당신은 다음을 해야 합니다.<font color="#2166ae">`lib\consonents.dart`</font> 파일에서:

1. GraphQL 창 상단의 히스토리 버튼 옆에 있는 GraphQL 링크를 복사하고, kUrl 문자열 데이터 유형으로 붙여넣습니다.
2. 이제 페이지 하단으로 이동하여 HTTP 헤더에서 코드를 복사합니다. 콜론(:) 오른쪽의 코드만 복사하고, 해당 이름과 함께 <font color="#2166ae">`lib\consonents.dart` </font> 파일에 붙여넣습니다:

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/ysPVIOchEBFZ182itNksQ_image.png)

파일에는 다음 코드가 포함되어야 합니다:

```graphql
1       String kParseApplicationId= "APPLICATION_ID_COPIED_FROM_HEADERS";
2    	String kParseClientKey = "CLIENT_KEY_COPIED_FROM_HEADER";
3   	String kUrl= "URL_COPIED";
4   	// replace "APPLICATION_ID_COPIED_FROM_HEADERS", "CLIENT_KEY_COPIED_FROM_HEADER", "URL_COPIED" with real keys/ids copied 
5   	//from Http Headers tab.
```

이제 <font color="#2166ae">`main.dart`</font> 파일로 이동하여 MyApp Stateless Widget으로 가서 <font color="#2166ae">`return`</font> 바로 위에 다음 코드를 추가하세요.<font color="#2166ae">`MaterialApp()`</font>:

```graphql
1       final HttpLink httpLink = HttpLink(
2         uri: kUrl,
3         headers: {
4           'X-Parse-Application-Id' : kParseApplicationId,
5           'X-Parse-Client-Key' : kParseClientKey,    
6         },
7       );
```

**HttpLink**는 *flutter\_graphql.dart*에서 가져온 것으로, 두 개의 매개변수를 가진 위젯 HttpLink()를 사용합니다. 첫 번째는 Back4App의 GraphQL API URL입니다. 두 번째는 Back4App API에서 인증하는 데 필요한 헤더입니다. 이 섹션 이후에는 GraphQL 클라이언트 코드를 포함해야 합니다(무엇인지 설명), 아래 코드를 복사한 후 HttpLink 섹션 아래에 붙여넣으세요:

```graphql
1       ValueNotifier<GraphQLClient> client = ValueNotifier(
2   	      GraphQLClient(
3   		    cache: OptimisticCache(dataIdFromObject: typenameDataIdFromObject),
4   		    link: httpLink,
5   	      ),
6    	    );
```

이제 우리는 GraphQLClient에 링크와 캐시 방법을 제공했습니다. 우리는 이를 ValueNotifier를 통해 수행하였고, 이를 client라고 명명했습니다. 이제 MyHomePage() 위젯을 MaterialApp의 자식으로 GraphQLProvider로 감싸고 MyHomePage()를 그 클라이언트로 전달합시다. GraphQLProvider 내부에 client라는 또 다른 매개변수를 추가하고 그 안에 client(우리의 ValueNotifier의 이름)를 전달합니다. 이제 MyApp 클래스는 다음과 같아야 합니다:

```graphql
1   class MyApp extends StatelessWidget {
2     @override
3     Widget build(BuildContext context) {
4       final HttpLink httpLink = HttpLink(
5         uri: kUrl,
6         headers: {
7           'X-Parse-Application-Id' : kParseApplicationId,
8           'X-Parse-Client-Key' : kParseClientKey,        
9           //'X-Parse-REST-API-Key' : kParseRestApiKey,
10        },//getheaders()
11      );
12      ValueNotifier<GraphQLClient> client = ValueNotifier(
13        GraphQLClient(
14          cache: OptimisticCache(dataIdFromObject: typenameDataIdFromObject),
15          link: httpLink,
16        ),
17      );
18      return MaterialApp(
19        home: GraphQLProvider(
20          child: MyHomePage(),
21          client: client,
22        ),
23      );
24    }
25  }
```

API를 호출하고 데이터를 가져옵시다.

## 5 - API 호출하기

이제 MyHomePageState에서 작업할 것입니다. 우리는 ‘query’라는 이름의 String 데이터 유형을 초기화하고, 이를 통해 Language 클래스에서 모든 데이터를 찾기 위한 쿼리 문을 할당/전달할 것입니다. 쿼리가 여러 줄이므로, 우리는 쿼리를 삼중 따옴표로 전달할 것입니다. 다음은 그 모습입니다:

```graphql
1   String query='''
2   query FindLanguages{
3   languages{
4     count,
5     edges{
6       node{
7         name,
8         saveFormat
9       }
10    }
11  }
12 }
13  ''';
```

이제 Query() 위젯으로 가서 Scaffold의 body 매개변수 안에 두 가지 속성이 있습니다:

- ***옵션***
- ***빌더***

그리고 두 개 모두에 대해 null을 전달합니다. 이것이 귀하의 빌드 메서드가 어떻게 보일지입니다:

```graphql
1     Widget build(BuildContext context) {
2       return SafeArea(
3         child: Scaffold(
4           appBar: AppBar(
5             title: Text('Parsing data using GraphQL',
6             ),
7           ),
8             body: Query(
9                 options: null,
10                builder: null
11            ),
12      ),);
13    }
```

“<font color="#2166ae">`Query()`</font> 위젯은 우리가 GraphQL 쿼리를 작성하는 데 도움을 주며, 데이터를 읽고 가져오는 데 도움을 줄 것입니다. 우리는 옵션에서 문자열로 가져온 쿼리 문을 전달하고 빌더 매개변수로 위젯을 빌드할 것입니다.

따라서 다음과 같이 옵션에 QueryOptions() 위젯을 전달합니다:

```graphql
1   options: QueryOptions(
2               documentNode: gql(query),
3             ),
4
```

쿼리는 QueryOptions의 documentNode 매개변수를 통해 전달됩니다. 이제 builder 매개변수의 도움으로 빌드를 해봅시다. builder 메서드는 세 개의 매개변수를 가진 함수를 받습니다.

- **QueryResult result;**
- **Refetch refetch;**
- **FetchMore fetchmore.**

현재 우리는 쿼리의 결과를 제공하는 QueryResult에 대해서만 걱정하면 됩니다. 우리는 <font color="#2166ae">`result.data`</font>에 접근할 수 있습니다.
그러니 아래 코드를 작성해봅시다:

```graphql
1   builder : (QueryResult result, { Refetch refetch,FetchMore fetchMore,})
2            {
3              if(result.data==null){
4                return Center(child: Text("Loading...",style: TextStyle(fontSize: 20.0),));
5              }else{
6                return Text('SUCCESS');
7              }
8            },
```

위 코드에서는 데이터를 접근하고 있습니다. 데이터가 없으면 *‘Loading…’*&#xB77C;는 텍스트 위젯을 반환하고, 그렇지 않으면 *‘SUCCESS’*&#xB77C;는 Text() 위젯을 반환합니다.

여기 당신의 <font color="#2166ae">`myHomePage`</font> 클래스는 <font color="#2166ae">`main.dart`</font> 다음과 같아야 합니다:

```dart
1   class MyHomePage extends StatefulWidget {
2     @override
3     _MyHomePageState createState() => _MyHomePageState();
4   }
5
6   class _MyHomePageState extends State<MyHomePage> {
7     String name;
8     String saveFormat;
9     String objectId;
10   
11    String query = '''
12    query FindLanguages{
13    languages{
14      count,
15      edges{
16        node{
17          name,
18          saveFormat
19        }
20      }
21    }
22  }
23    ''';
24  
25    @override
26    Widget build(BuildContext context) {
27      return SafeArea(
28        child: Scaffold(
29          appBar: AppBar(
30            title: Text(
31              'Parsing data using GraphQL',
32            ),
33          ),
34          body: Query(
35              options: QueryOptions(
36                documentNode: gql(query),
37              ),
38              builder: (
39                  QueryResult result, {
40                    Refetch refetch,
41                    FetchMore fetchMore,
42                  }) {
43                if (result.data == null) {
44                  return Center(
45                    child: Text(
46                      "Loading...",
47                      style: TextStyle(fontSize: 20.0),
48                    ),
49                  );
50                } else{
51                  return Text('SUCCESS');
52                }
53              }
54          ),
55        ),
56      );
57    }
58  }
```

이제 앱을 시작하고 재시작 후 몇 초 동안 기다리세요. 화면에 *‘SUCCESS’*&#xAC00; 보이면 ***축하합니다! 연결을 설정하고 API를 호출했습니다.***

## 6 - API에서 데이터 가져오기 및 표시하기

Text 위젯을 반환하는 대신, 원본 데이터로 *ListView\.builder()* 위젯을 반환할 것입니다. return 대신 다음 코드를 작성하세요 <font color="#2166ae">`Text('SUCCESS')`</font>.

```graphql
1   return ListView.builder(
2                       itemBuilder: (BuildContext context, int index){
3                         return ListTile(
4                           title: Text(result.data["languages"]["edges"][index]["node"]['name']),
5                           trailing: Text(result.data["languages"]["edges"][index]["node"]['saveFormat']),
6                         );
7                       },
8                       itemCount: result.data["languages"]["edges"].length,
9                     );
```

이제 Back4App의 API 콘솔에서 find 메서드를 입력했던 GraphQL 결과 화면을 다시 보면, 결과는 다음과 같았습니다:

```graphql
1   {
2     "data": {
3       "languages": {
4         "count": 3,
5         "edges": [
6           {
7             "node": {
8               "name": "Python",
9               "saveFormat": ".py"
10            }
11          },
12          {
13            "node": {
14              "name": "C",
15              "saveFormat": ".c"
16            }
17          },
18          {
19            "node": {
20              "name": "Java",
21              "saveFormat": ".java"
22            }
23          }
24        ]
25      }
26    }
27  }
```

따라서 위 코드에서 “Python”의 위치는:

- *“data”->&#x20;*“*languages” -> “count” -> “edges” -> “node” -> “name”*. 또한 name은 edges의 대괄호 ‘\[]’ 안에 있어 edges 목록/배열의 첫 번째 요소임을 나타냅니다.

따라서 우리는 “Python”을 얻기 위해 이 위치에 들어가야 하며, 다른 모든 것에 대해서도 마찬가지입니다. 우리가 <font color="#2166ae">`result.data`</font>, 를 작성할 때, 우리는 *“data”* 위치에 들어갑니다. 따라서 다른 위치를 제공하기 위해 <font color="#2166ae">`["location_name"]`</font>을 추가합니다. 따라서 “Python”의 위치는 <font color="#2166ae">`result.data["languages"]["edges"][0]["node"]["name"]`</font>이 될 것입니다.

“},\{<font color="#2166ae">`ListView`</font>”를 사용할 때, 두 개의 매개변수를 사용합니다. <font color="#2166ae">`itemCount`</font>, 이는 API 호출의 요소 수를 나타내고, <font color="#2166ae">`itemBuilder`</font>, 이는 <font color="#2166ae">`(BuildContext context, int index)`</font>라는 매개변수를 가진 함수를 사용하여 데이터 표시를 위한 목록 위젯을 반환합니다. 여기서는 ListTile 목록을 사용하여 데이터를 표시할 것입니다:

```dart
1   return ListView.builder(
2                        itemCount: result.data["languages"]["edges"].length,
3                       itemBuilder: (BuildContext context, int index){
4                         return ListTile(
5                           title: Text(result.data["languages"]["edges"][index]["node"]['name']),
6                           trailing: Text(result.data["languages"]["edges"][index]["node"]['saveFormat']),
7                         );
8                       },
9                       
10                    );
```

우리가 <font color="#2166ae">`Text('SUCCESS')`</font>를 위의 `ListView.builder()` 위젯으로 교체할 때, 우리는 먼저 itemCount를 전달하는데, 여기서 결과 리스트의 요소 수를 전달하므로 더 이상 걱정할 필요가 없습니다. itemBuilder에서는 <font color="#2166ae">`"name"`</font>의 <font color="#2166ae">`"Languages"`</font> 클래스의 ListTiles 목록을 반환하고, <font color="#2166ae">`"saveFormat"`</font>에서 후행으로 사용합니다. 결과 뒤에 어떤 숫자 대신 인덱스를 사용했다는 점에 유의하세요. 이것이 itemCount가 처리한 것입니다.

이제 당신의 <font color="#2166ae">`main.dart`</font>는 이렇게 보여야 합니다:

```dart
1   import 'package:flutter/material.dart';
2   import 'package:graphql_flutter/graphql_flutter.dart';
3   import 'consonents.dart';
4   import 'dart:ui';
5
6   void main() {
7     runApp(MyApp());
8   }
9 
10  class MyApp extends StatelessWidget {
11    @override
12    Widget build(BuildContext context) {
13      final HttpLink httpLink = HttpLink(
14        uri: 'https://parseapi.back4app.com/graphql',
15        headers: {
16          'X-Parse-Application-Id': kParseApplicationId,
17          'X-Parse-Client-Key': kParseClientKey,        
18        }, //getheaders()
19      );
20  
21      ValueNotifier<GraphQLClient> client = ValueNotifier(
22        GraphQLClient(
23          cache: OptimisticCache(dataIdFromObject: typenameDataIdFromObject),
24          link: httpLink,
25        ),
26      );
27 
28      return MaterialApp(
29        home: GraphQLProvider(
30          child: MyHomePage(),
31          client: client,
32        ),
33      );
34    }
35  }
36 
37  class MyHomePage extends StatefulWidget {
38    @override
39    _MyHomePageState createState() => _MyHomePageState();
40  }
41
42  class _MyHomePageState extends State<MyHomePage> {
43    String name;
44    String saveFormat;
45    String objectId;
46  
47    String query = '''
48    query FindLanguages{
49    languages{
50      count,
51      edges{
52        node{
53          name,
54          saveFormat
55        }
56      }
57    }
58  }
59    ''';
60
61    @override
62    Widget build(BuildContext context) {
63      return SafeArea(
64        child: Scaffold(
65          appBar: AppBar(
66            title: Text(
67              'Parsing data using GraphQL',
68            ),
69          ),
70          body: Query(
71            options: QueryOptions(
72              documentNode: gql(query),
73            ),
74            builder: (
75              QueryResult result, {
76              Refetch refetch,
77              FetchMore fetchMore,
78            }) {
79              if (result.data == null) {
80                return Center(
81                    child: Text(
82                  "Loading...",
83                  style: TextStyle(fontSize: 20.0),
84                ));
85              } else {
86                return ListView.builder(
87                  itemBuilder: (BuildContext context, int index) {
88                    return ListTile(
89                      title: Text(result.data["languages"]["edges"][index]["node"]
90                          ['name']),
91                      trailing: Text(result.data["languages"]["edges"][index]
92                          ["node"]['saveFormat']),
93                    );
94                  },
95                  itemCount: result.data["languages"]["edges"].length,
96                );
97              }
98            },
99          ),
100       ),
101     );
102   }
103 }
```

그리고 우리의 마지막 앱 화면:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/4US1H2nsHrXZvtZzrZw3k_image.png" size="50" width="249" height="441" position="center" showCaption="false"}

## 결론

이제 여러분은 Back4App에서 데이터를 저장하고 검색할 수 있는 GraphQL API에 연결된 Flutter 앱을 갖게 되었습니다.

우리는 json 데이터를 별도로 인코딩하거나 디코딩할 필요가 없었기 때문에 몇 줄의 코드로 작업이 더 쉽고 빨라졌습니다.

**좋은 하루 되세요!**
