Flutter
GraphQL
Flutter GraphQL 프로젝트 설정 및 데이터 활용 가이드
26 분
소스 코드가 포함된 flutter graphql 프로젝트 다운로드 및 back4app 사용 시작하기 소개 이 튜토리얼에서는 graphql을 통해 back4app 백엔드에서 데이터를 파싱하는 애플리케이션을 구축할 것입니다 아시다시피, graphql은 api를 위한 오픈 소스 데이터 쿼리 및 조작 언어이며, 기존 데이터를 사용하여 쿼리를 수행하는 런타임입니다 back4app은 개발자가 확장 가능하고 확장 가능한 모바일 및 웹 애플리케이션을 빠른 속도로 구축할 수 있도록 돕는 저코드 백엔드 서비스(오픈 소스 parse 플랫폼 기반)입니다 목표 주요 목표는 프로그래밍 언어 목록과 해당 저장 형식을 보여주는 간단한 앱을 만드는 것입니다 이 기사 끝에서 여러분은 다음을 할 수 있을 것으로 기대합니다 graphql을 사용하여 back4app에서 api 호출하기; graphql api에서 데이터 가져오기; flutter 앱에서 데이터 가져오기 전제 조건 이 튜토리얼을 완료하려면 다음이 필요합니다 android studio 또는 flutter와 같은 flutter 코드를 작성할 수 있는 ide 그러나 이 튜토리얼에서는 android studio를 사용할 것입니다 여기에서 생성할 수 있는 back4app 계정 back4app graphql flutter https //pub dev/packages/graphql flutter 1 github에서 android studio로 프로젝트 복제하기 다음으로 가세요 github 저장소 https //github com/templates back4app/flutter graphql , zip 파일을 다운로드하고, 압축을 풀고, flutter ide에서 엽니다 이 단계를 완료하려면, zip 파일 안의 폴더를 바탕 화면으로 드래그하고 android studio를 열고 '기존 android studio 프로젝트 열기'를 클릭하세요 프로젝트 디렉토리는 보통 ' c \users\username\desktop\back4app graphql starting code ’입니다 하지만 이는 사용자마다 다를 수 있습니다 프로젝트를 열고 lib\main dart lib\main dart 파일로 가세요 거기에는 많은 오류가 보일 것입니다 걱정하지 마세요, ' get dependencies '를 모두 눌러주세요 그러면 모든 오류가 사라질 것입니다 만약 그렇지 않다면 ' upgrade dependencies '를 눌러주세요 당신의 main dart main 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’ 인 appbar만 표시됩니다 우리는 main dart main dart 파일에서 작업할 것이며, 우리의 중요한 값은 consonents dart consonents dart 에 저장되어 있으며, 우리는 거기에서 직접 사용할 수 있습니다 우리는 앱에서 graphql을 사용하기 위해 graphql flutter graphql flutter 의존성이 필요합니다 graphql flutter graphql flutter 는 flutter를 위한 가장 인기 있는 graphql 클라이언트입니다 이는 우리 코드에서 직접 graphql 쿼리를 사용할 수 있도록 도와줍니다 이는 우리에게 graphqlclient graphqlclient , graphqlprovider graphqlprovider 및 데이터베이스에서 데이터를 직접 파싱하는 데 도움이 되는 많은 유용한 위젯을 제공합니다 streambuilder streambuilder 조차 사용하지 않고도 말이죠 이 패키지는 다음과 같은 많은 기능을 제공합니다 구독 메모리 캐시 오프라인 캐시 동기화 낙관적인 결과 graphql 파일 업로드 다음 코드를 pubspec yaml pubspec yaml 파일에 작성하여 가져올 수 있습니다 자세한 내용은 graphql flutter graphql flutter 에서 확인하세요 graphql flutter 문서 모든 종속성이 이미 사전 설치되어 있으며 이제 다음 단계로 진행할 수 있습니다 2 back4app에서 백엔드 생성하기 back4app 웹사이트에 가입한 후, 다음 단계로 진행하여 새 앱을 생성할 수 있습니다 back4app https //www back4app com/ 를 클릭하세요 ‘새 앱 만들기’ 를 클릭합니다 여기서 프로젝트 이름과 동일한 이름을 부여하세요 즉, ‘back4app graphql’ 입니다 이제 왼쪽에서 서버 설정 으로 스크롤하여 설정 관리 파서 서버 카드를 선택한 다음, 목록에서 ‘3 10 0 parse server 3 10 0’ 옵션을 선택합니다 이제 아래의 저장 버튼을 눌러 저장될 때까지 기다리세요 이제 코어 로 돌아가서 (왼쪽), api 콘솔 을 선택하고 그 안에서 graphql 콘솔 을 선택하세요 이곳은 graphql 쿼리/변경 코드 작성 및 테스트를 할 수 있는 창입니다 다음 단계로 진행합시다 3 graphql을 통한 데이터 생성 및 가져오기 이제 graphql api 콘솔을 사용하여 back4app에서 graphql api를 테스트해 보겠습니다 먼저, 왼쪽 코드 상자에 다음 쿼리를 붙여넣으세요 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”라는 이름의 클래스를 생성합니다 이 새로운 클래스를 몇 개의 행으로 채워봅시다 1 mutation createobject{ 2 createlanguage(input {fields {name "python", saveformat " py"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } 작업이 성공하면 graphql playground의 오른쪽 코드 상자에서 이 메시지를 볼 수 있습니다 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” 이것에 대한 변형은 다음과 같습니다 1 mutation createobject{ 2 createlanguage(input {fields {name "c", saveformat " c"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } 자바 1 mutation createobject{ 2 createlanguage(input {fields {name "java", saveformat " java"}}){ 3 language{ 4 name, 5 saveformat 6 } 7 } 8 } 이제 우리 클래스 languages 의 모든 데이터를 살펴보겠습니다 데이터를 읽기 위해 우리는 query 를 사용합니다 그러니 아래 명령어를 입력하세요 1 query findlanguages{ 2 languages{ 3 count, 4 edges{ 5 node{ 6 name, 7 saveformat 8 } 9 } 10 } 11 } ‘ query findlanguage query findlanguage ’는 당신의 쿼리 명령어에 대한 이름일 뿐이며, 다른 어떤 이름으로도 지을 수 있습니다 우리는 find(classname "") find(classname "") 명령어를 사용하여 특정 클래스의 모든 요소를 찾습니다 count count ,는 클래스의 요소 수를 반환하며 모든 요소는 result result 객체 안에 표시됩니다 위 쿼리는 다음을 반환할 것입니다 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 설정하기 우리 앱을 코딩하기 시작합시다 이 전에, 당신은 다음을 해야 합니다 lib\consonents dart lib\consonents dart 파일에서 graphql 창 상단의 히스토리 버튼 옆에 있는 graphql 링크를 복사하고, kurl 문자열 데이터 유형으로 붙여넣습니다 이제 페이지 하단으로 이동하여 http 헤더에서 코드를 복사합니다 콜론( ) 오른쪽의 코드만 복사하고, 해당 이름과 함께 lib\consonents dart lib\consonents dart 파일에 붙여넣습니다 파일에는 다음 코드가 포함되어야 합니다 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 이제 main dart main dart 파일로 이동하여 myapp stateless widget으로 가서 return return 바로 위에 다음 코드를 추가하세요 materialapp() materialapp() 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 섹션 아래에 붙여넣으세요 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 클래스는 다음과 같아야 합니다 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 클래스에서 모든 데이터를 찾기 위한 쿼리 문을 할당/전달할 것입니다 쿼리가 여러 줄이므로, 우리는 쿼리를 삼중 따옴표로 전달할 것입니다 다음은 그 모습입니다 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을 전달합니다 이것이 귀하의 빌드 메서드가 어떻게 보일지입니다 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 } “ query() query() 위젯은 우리가 graphql 쿼리를 작성하는 데 도움을 주며, 데이터를 읽고 가져오는 데 도움을 줄 것입니다 우리는 옵션에서 문자열로 가져온 쿼리 문을 전달하고 빌더 매개변수로 위젯을 빌드할 것입니다 따라서 다음과 같이 옵션에 queryoptions() 위젯을 전달합니다 1 options queryoptions( 2 documentnode gql(query), 3 ), 4 쿼리는 queryoptions의 documentnode 매개변수를 통해 전달됩니다 이제 builder 매개변수의 도움으로 빌드를 해봅시다 builder 메서드는 세 개의 매개변수를 가진 함수를 받습니다 queryresult result; refetch refetch; fetchmore fetchmore 현재 우리는 쿼리의 결과를 제공하는 queryresult에 대해서만 걱정하면 됩니다 우리는 result data result data 에 접근할 수 있습니다 그러니 아래 코드를 작성해봅시다 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…’ 라는 텍스트 위젯을 반환하고, 그렇지 않으면 ‘success’ 라는 text() 위젯을 반환합니다 여기 당신의 myhomepage myhomepage 클래스는 main dart main 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’ 가 보이면 축하합니다! 연결을 설정하고 api를 호출했습니다 6 api에서 데이터 가져오기 및 표시하기 text 위젯을 반환하는 대신, 원본 데이터로 listview\ builder() 위젯을 반환할 것입니다 return 대신 다음 코드를 작성하세요 text('success') text('success') 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 결과 화면을 다시 보면, 결과는 다음과 같았습니다 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” > “ languages” > “count” > “edges” > “node” > “name” 또한 name은 edges의 대괄호 ‘\[]’ 안에 있어 edges 목록/배열의 첫 번째 요소임을 나타냅니다 따라서 우리는 “python”을 얻기 위해 이 위치에 들어가야 하며, 다른 모든 것에 대해서도 마찬가지입니다 우리가 result data result data , 를 작성할 때, 우리는 “data” 위치에 들어갑니다 따라서 다른 위치를 제공하기 위해 \["location name"] \["location name"] 을 추가합니다 따라서 “python”의 위치는 result data\["languages"]\["edges"]\[0]\["node"]\["name"] result data\["languages"]\["edges"]\[0]\["node"]\["name"] 이 될 것입니다 “},{ listview listview ”를 사용할 때, 두 개의 매개변수를 사용합니다 itemcount itemcount , 이는 api 호출의 요소 수를 나타내고, itembuilder itembuilder , 이는 (buildcontext context, int index) (buildcontext context, int index) 라는 매개변수를 가진 함수를 사용하여 데이터 표시를 위한 목록 위젯을 반환합니다 여기서는 listtile 목록을 사용하여 데이터를 표시할 것입니다 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 ); 우리가 text('success') text('success') 를 위의 listview\ builder() 위젯으로 교체할 때, 우리는 먼저 itemcount를 전달하는데, 여기서 결과 리스트의 요소 수를 전달하므로 더 이상 걱정할 필요가 없습니다 itembuilder에서는 "name" "name" 의 "languages" "languages" 클래스의 listtiles 목록을 반환하고, "saveformat" "saveformat" 에서 후행으로 사용합니다 결과 뒤에 어떤 숫자 대신 인덱스를 사용했다는 점에 유의하세요 이것이 itemcount가 처리한 것입니다 이제 당신의 main dart main 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 } 그리고 우리의 마지막 앱 화면 결론 이제 여러분은 back4app에서 데이터를 저장하고 검색할 수 있는 graphql api에 연결된 flutter 앱을 갖게 되었습니다 우리는 json 데이터를 별도로 인코딩하거나 디코딩할 필요가 없었기 때문에 몇 줄의 코드로 작업이 더 쉽고 빨라졌습니다 좋은 하루 되세요!