Flutter
GraphQL
GraphQL을 활용한 Flutter CRUD 앱 템플릿 구현 가이드
17 분
graphql을 사용한 flutter crud 앱 예제 소개 첫 번째 flutter graphql 가이드에서는 graphql api를 사용하여 back4app에서 간단한 데이터에 연결하고 쿼리하는 flutter 프로젝트를 설정하는 방법을 배웠습니다 또한, back4app graphql playground를 사용하여 쿼리/변경 작업을 실행하여 앱 데이터베이스를 생성/채우는 방법도 배웠습니다 이 튜토리얼에서는 graphql 변형을 사용하여 앱에서 back4app 백엔드에서 직접 데이터를 생성, 업데이트 및 삭제하는 기능을 추가할 것입니다 목표 이 기사의 끝에서 여러분이 할 수 있기를 기대하는 것은 graphql api를 사용하여 백엔드에 데이터를 생성합니다 graphql api를 사용하여 백엔드에서 데이터를 업데이트합니다 graphql api를 사용하여 백엔드에서 기존 데이터를 삭제합니다 전제 조건 이 튜토리얼을 완료하려면 다음이 필요합니다 이 가이드를 이해하기 위해 이전 가이드를 읽어야 합니다 “flutter graphql 프로젝트” 이전 프로젝트를 사용할 예정입니다 없다면 여기에서 다운로드하세요 android studio 또는 vs code와 같은 flutter 코드를 작성할 수 있는 ide 다음에서 계정을 생성할 수 있는 back4app back4app graphql flutter 의존성 https //pub dev/packages/graphql flutter 참고 back4app graphql api에 대한 더 나은 이해를 원하신다면 graphql 요리책 https //www back4app com/docs/parse graphql/graphql getting started 을 확인하고 api 플레이그라운드에서 graphql 스키마도 확인하세요 1 gui 설정하기 새 파일을 생성하세요 mutation page dart mutation page dart 여기서 우리는 사용자로부터 입력을 받고 변이 작업을 수행하기 위한 gui를 생성할 것입니다 이제 다음 코드를 mutation page dart mutation page dart 에 붙여넣으세요 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 senddatabuttonpressed (){ 23 }, 24 deletedatabuttonpressed (){ 25 }, 26 updatebuttonpressed (){ 27 }, 28 ); 29 } 30 } appui() appui() 위젯은 이미 만들어졌습니다 그래서 우리는 mutationpage mutationpage 라는 이름의 클래스를 생성하고 appui appui 위젯을 반환했습니다 또한 텍스트 필드에 대한 콜백 함수를 초기화하여 첫 번째 텍스트 필드의 텍스트는 langname langname , 두 번째는 saveformat saveformat 에 저장되고 마지막으로 objectid objectid 에 저장됩니다 이제 main dart main dart 로 진행하여 floatingactionbutton floatingactionbutton 매개변수를 scaffold() scaffold() 위젯의 myhomepage myhomepage 클래스에 추가하고 다음 코드를 전달하세요 1 floatingactionbutton row( 2 mainaxisalignment mainaxisalignment end, 3 children \[ 4 floatingactionbutton( 5 herotag 'mutation page', 6 child text('m', 7 style textstyle( 8 color colors white, 9 ), 10 ), 11 onpressed (){ 12 navigator pushreplacement(context, materialpageroute( 13 builder ((context){ 14 return mutationpage(); 15 }) 16 )); 17 }, 18 ), 19 ], 20 ), 이것은 우리가 홈 페이지에서 mutationpage() mutationpage() 로 이동할 floating button을 생성합니다 이제 우리의 gui가 설정되었습니다 이제 앱을 hot restart하여 gui를 확인할 수 있습니다 당신의 main dart main dart 는 다음과 같아야 합니다 1 import 'package\ back4appgraphqldemo/mutation page dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ graphql flutter/graphql flutter dart'; 4 import 'consonents dart'; 5 import 'dart\ ui'; 6 7 void main() { 8 runapp(myapp()); 9 } 10 11 class myapp extends statelesswidget { 12 @override 13 widget build(buildcontext context) { 14 final httplink httplink = httplink( 15 uri 'https //parseapi back4app com/graphql', 16 headers { 17 'x parse application id' kparseapplicationid, 18 'x parse client key' kparseclientkey, 19 'x parse master key' kparsemasterkey, 20 //'x parse rest api key' kparserestapikey, 21 }, //getheaders() 22 ); 23 24 valuenotifier\<graphqlclient> client = valuenotifier( 25 graphqlclient( 26 cache optimisticcache(dataidfromobject typenamedataidfromobject), 27 link httplink, 28 ), 29 ); 30 31 return materialapp( 32 home graphqlprovider( 33 child myhomepage(), 34 client client, 35 ), 36 ); 37 } 38 } 39 40 class myhomepage extends statefulwidget { 41 @override 42 myhomepagestate createstate() => myhomepagestate(); 43 } 44 45 class myhomepagestate extends state\<myhomepage> { 46 string name; 47 string saveformat; 48 string objectid; 49 50 string query = ''' 51 query findlanguages{ 52 languages{ 53 count, 54 edges{ 55 node{ 56 name, 57 saveformat 58 } 59 } 60 } 61 } 62 '''; 63 64 @override 65 widget build(buildcontext context) { 66 return safearea( 67 child scaffold( 68 appbar appbar( 69 title text( 70 'parsing data using graphql', 71 ), 72 ), 73 floatingactionbutton row( 74 mainaxisalignment mainaxisalignment end, 75 children \[ 76 floatingactionbutton( 77 herotag 'mutation page', 78 child text('m', 79 style textstyle( 80 color colors white, 81 ), 82 ), 83 onpressed (){ 84 navigator pushreplacement(context, materialpageroute( 85 builder ((context){ 86 return mutationpage(); 87 }) 88 )); 89 }, 90 ), 91 ], 92 ), 93 body query( 94 options queryoptions( 95 documentnode gql(query), 96 ), 97 builder ( 98 queryresult result, { 99 refetch refetch, 100 fetchmore fetchmore, 101 }) { 102 if (result data == null) { 103 return center( 104 child text( 105 "loading ", 106 style textstyle(fontsize 20 0), 107 )); 108 } else { 109 return listview\ builder( 110 itembuilder (buildcontext context, int index) { 111 return listtile( 112 title text(result data\["languages"]\["edges"]\[index]\["node"] 113 \['name']), 114 trailing text(result data\["languages"]\["edges"]\[index] 115 \["node"]\['saveformat']), 116 117 ); 118 }, 119 itemcount result data\["languages"]\["edges"] length, 120 ); 121 } 122 }, 123 ), 124 ), 125 ); 126 } 127 } 2 데이터베이스에 데이터 생성/추가하기 진행하면 graphql configration dart graphql configration dart 를 볼 수 있으며, 이미 graphqlclient graphqlclient 을 설정했습니다 이제 어디서나 사용할 수 있습니다 다음으로 database utils dart database utils dart 파일을 생성하고 데이터 생성 작업을 수행합니다 databaseutils{} databaseutils{} 클래스를 생성하고 우리가 작업할 데이터 매개변수를 받을 생성자를 만듭니다 여기서는 langname langname , saveformat saveformat , 그리고 objectid objectid 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 final string langname,saveformat,objectid; 6 databaseutils({this langname="",this saveformat="",this objectid=""}); 7 } 함수 adddata() adddata() 를 생성합니다 이 함수는 데이터를 생성하고 graphqlclient graphqlclient 를 초기화하는 비동기 함수가 될 것입니다 graphqlconfigration graphqlconfigration 클래스를 초기화합니다 다음 코드를 senddata() senddata() 함수에 붙여넣습니다 1 future\<queryresult> senddata() async{ 2 string adddata=''' 3 mutation createobject(\\$input createlanguagefieldsinput){ 4 createlanguage(input {fields \\$input}){ 5 language{ 6 name, 7 saveformat 8 } 9 } 10 } 11 '''; 12 final variable ={ 13 "input" { 14 "name" langname, 15 "saveformat" saveformat, 16 } 17 }; 18 19 graphqlconfiguration configuration = graphqlconfiguration(); 20 graphqlclient client = configuration clienttoquery(); 21 22 } 여기에서 우리는 adddata adddata 변수를 초기화하고 데이터를 생성하기 위한 쿼리를 전달했으며 변수 변수 를 전달할 쿼리 변수를 초기화했습니다 또한 쿼리를 전달하는 데 도움이 되는 graphqlclient graphqlclient 를 초기화했습니다 아래와 같은 방식으로 쿼리를 전달할 수 있습니다 1 queryresult queryresult = await client query( 2 queryoptions(documentnode gql(adddata), variables variable), 3 ); 4 return queryresult; 우리는 graphqlclient graphqlclient 인스턴스를 사용하여 queryoptions() queryoptions() 를 수용하는 쿼리를 작성했습니다 이는 지난 튜토리얼에서 보았던 것처럼 쿼리를 전송하는 데 도움이 됩니다 결과는 queryresult queryresult 당신의 database utils dart database utils dart 는 다음과 같아야 합니다 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 final string langname,saveformat,objectid; 6 databaseutils({this langname="",this saveformat="",this objectid=""}); 7 future\<queryresult> senddata() async{ 8 string adddata=''' 9 mutation createobject(\\$input createlanguagefieldsinput){ 10 createlanguage(input {fields \\$input}){ 11 language{ 12 name, 13 saveformat 14 } 15 } 16 } 17 '''; 18 final variable ={ 19 "input" { 20 "name" langname, 21 "saveformat" saveformat, 22 } 23 }; 24 25 graphqlconfiguration configuration = graphqlconfiguration(); 26 graphqlclient client = configuration clienttoquery(); 27 28 queryresult queryresult = await client query( 29 queryoptions(documentnode gql(adddata), variables variable), 30 ); 31 return queryresult; 32 } 33 } 이제 ui 클래스 mutation page dart mutation page dart 데이터를 전송하는 버튼을 코딩합시다 이는 senddatabuttonpressed senddatabuttonpressed 매개변수 안에 코딩할 수 있습니다 langname과 saveformat이 필요하므로 먼저 비어 있지 않은지 확인한 후 databaseutils databaseutils 의 인스턴스를 생성하고 langname langname 과 saveformat saveformat 매개변수를 전달합니다 1 if(langname isnotempty && saveformat isnotempty){ 2 utils = databaseutils( 3 langname langname, 4 saveformat saveformat , 5 ); 6 } 이후 senddata() senddata() 함수를 databaseutils databaseutils 인스턴스에서 호출합니다 이제 당신은 hot restart 앱을 실행하고 두 개의 텍스트 필드에 각각의 데이터를 입력한 후 데이터 전송 버튼을 누를 수 있습니다 이제 플로팅 액션 버튼을 눌러 쿼리 페이지로 돌아가면 테이블에 하나의 데이터가 더 추가된 것을 볼 수 있습니다 이것이 당신의 mutationpage 클래스의 모습입니다 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 senddatabuttonpressed (){ 23 if(langname isnotempty && saveformat isnotempty){ 24 utils = databaseutils( 25 langname langname, 26 saveformat saveformat , 27 ); 28 utils senddata(); 29 } 30 }, 31 deletedatabuttonpressed (){ 32 }, 33 updatebuttonpressed (){ 34 }, 35 ); 36 } 37 } 3 데이터 업데이트 에서 databaseutils databaseutils 함수를 생성합니다 future future updatedata() updatedata() string update string update 를 초기화하고 업데이트 쿼리와 쿼리 변수 를 final variables final variables 1 future\<queryresult> updatedata() async{ 2 string update=''' 3 mutation updateobject(\\$id id!,\\$input updatelanguagefieldsinput){ 4 updatelanguage(input {id \\$id, fields \\$input}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 "input" { 15 "name" langname 16 } 17 }; 18 } 이제 우리의 graphqlclient graphqlclient 를 초기화하고 쿼리를 queryoptions() queryoptions() 를 통해 전송합니다 이렇게 하면 코드가 다음과 같이 보입니다 1 future\<queryresult> updatedata() async{ 2 3 string update=''' 4 mutation updateobject(\\$id id!,\\$input updatelanguagefieldsinput){ 5 updatelanguage(input {id \\$id, fields \\$input}){ 6 language{ 7 name, 8 id 9 } 10 } 11 } 12 '''; 13 14 final variable={ 15 "id"\ objectid, 16 "input" { 17 "name" langname 18 } 19 }; 20 21 graphqlconfiguration configuration = graphqlconfiguration(); 22 graphqlclient client = configuration clienttoquery(); 23 24 queryresult queryresult = await client query( 25 queryoptions(documentnode gql(update), variables variable), 26 ); 27 return queryresult; 28 } 이제 mutaion page dart mutaion page dart 로 돌아가서 updatebuttonpressed updatebuttonpressed 매개변수에 코드를 작성하세요 langname langname , objectid objectid 및 saveformat saveformat 이 비어 있지 않은지 확인한 후 updatedata() updatedata() 함수를 databaseutils databaseutils 클래스에서 호출하세요 1 updatebuttonpressed (){ 2 if(langname isnotempty && saveformat isnotempty && objectid isnotempty){ 3 utils = databaseutils( 4 langname langname, 5 saveformat saveformat , 6 objectid objectid 7 ); 8 utils updatedata(); 9 } 10 }, back4app 대시보드로 가서 업데이트할 언어를 선택한 다음 해당 objectid를 복사하세요 핫 리스타트 를 통해 앱을 다시 시작하고 3개의 텍스트 필드를 모두 채우세요 첫 번째 텍스트 필드에 삽입할 언어의 새로운 이름 과 두 번째 필드에 새로운 저장 형식 및 세 번째 필드에 objectid 를 입력하세요 이제 데이터 업데이트 버튼을 눌러 앱에서 업데이트된 정보를 확인하세요 오른쪽 하단의 q 플로팅 액션 버튼을 클릭하세요 4 데이터 삭제 다음과 같이 deletedata() deletedata() 비동기 함수를 databaseutils databaseutils 에서 생성하고 string delete string delete 를 초기화한 후, 데이터를 삭제하기 위한 graphql 쿼리를 전달합니다 최종 변수 최종 변수 를 가져와 쿼리 변수를 전달합니다 1 future\<queryresult> deletedata() async{ 2 string delete=''' 3 mutation deleteobject(\\$id id!){ 4 deletelanguage(input {id \\$id}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 }; 15 } 여기서 우리는 삭제해야 할 행의 objectid objectid 만 필요합니다 graphqlclient graphqlclient 를 초기화하고 queryoptions() queryoptions() 를 통해 쿼리를 전송합니다 1 future\<queryresult> deletedata() async{ 2 string delete=''' 3 mutation deleteobject(\\$id id!){ 4 deletelanguage(input {id \\$id}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 }; 15 16 graphqlconfiguration configuration = graphqlconfiguration(); 17 graphqlclient client = configuration clienttoquery(); 18 19 queryresult queryresult = await client query( 20 queryoptions(documentnode gql(delete), variables variable), 21 ); 22 23 return queryresult; 24 } 에서 mutationpage mutationpage 의 deletedatabuttonpressed deletedatabuttonpressed 매개변수는 objectid objectid 가 비어 있거나 null이 아닌지 확인하고 deletedata() deletedata() 함수를 호출합니다 핫 리스타트 애플리케이션에서 삭제할 행의 objectid 를 입력하고 데이터 삭제 버튼을 누릅니다 특정 행이 language language 클래스에서 삭제되어야 합니다 성공 적으로 앱이 마침내 변환 작업을 완료했습니다 !!! main dart main dart 는 다음과 같아야 합니다 1 import 'package\ back4appgraphqldemo/mutation page dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ graphql flutter/graphql flutter dart'; 4 import 'consonents dart'; 5 import 'dart\ ui'; 6 7 void main() { 8 runapp(myapp()); 9 } 10 11 class myapp extends statelesswidget { 12 @override 13 widget build(buildcontext context) { 14 final httplink httplink = httplink( 15 uri 'https //parseapi back4app com/graphql', 16 headers { 17 'x parse application id' kparseapplicationid, 18 'x parse client key' kparseclientkey, 19 'x parse master key' kparsemasterkey, 20 //'x parse rest api key' kparserestapikey, 21 }, //getheaders() 22 ); 23 24 valuenotifier\<graphqlclient> client = valuenotifier( 25 graphqlclient( 26 cache optimisticcache(dataidfromobject typenamedataidfromobject), 27 link httplink, 28 ), 29 ); 30 31 return materialapp( 32 home graphqlprovider( 33 child myhomepage(), 34 client client, 35 ), 36 ); 37 } 38 } 39 40 class myhomepage extends statefulwidget { 41 @override 42 myhomepagestate createstate() => myhomepagestate(); 43 } 44 45 class myhomepagestate extends state\<myhomepage> { 46 string name; 47 string saveformat; 48 string objectid; 49 50 string query = ''' 51 query findlanguages{ 52 languages{ 53 count, 54 edges{ 55 node{ 56 name, 57 saveformat 58 } 59 } 60 } 61 } 62 '''; 63 64 @override 65 widget build(buildcontext context) { 66 return safearea( 67 child scaffold( 68 appbar appbar( 69 title text( 70 'parsing data using graphql', 71 ), 72 ), 73 floatingactionbutton row( 74 mainaxisalignment mainaxisalignment end, 75 children \[ 76 floatingactionbutton( 77 herotag 'mutation page', 78 child text('m', 79 style textstyle( 80 color colors white, 81 ), 82 ), 83 onpressed (){ 84 navigator pushreplacement(context, materialpageroute( 85 builder ((context){ 86 return mutationpage(); 87 }) 88 )); 89 }, 90 ), 91 ], 92 ), 93 body query( 94 options queryoptions( 95 documentnode gql(query), 96 ), 97 builder ( 98 queryresult result, { 99 refetch refetch, 100 fetchmore fetchmore, 101 }) { 102 if (result data == null) { 103 return center( 104 child text( 105 "loading ", 106 style textstyle(fontsize 20 0), 107 )); 108 } else { 109 return listview\ builder( 110 itembuilder (buildcontext context, int index) { 111 return listtile( 112 title text(result data\["languages"]\["edges"]\[index]\["node"] 113 \['name']), 114 trailing text(result data\["languages"]\["edges"]\[index] 115 \["node"]\['saveformat']), 116 117 ); 118 }, 119 itemcount result data\["languages"]\["edges"] length, 120 ); 121 } 122 }, 123 ), 124 ), 125 ); 126 } 127 } database utils dart database utils dart 는 다음과 같아야 합니다 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 6 final string langname,saveformat,objectid; 7 8 databaseutils({this langname="",this saveformat="",this objectid=""}); 9 10 string delete=''' 11 mutation delete languages(\\$id id!){ 12 deletelanguage(input {id \\$id}){ 13 language{ 14 name, 15 id 16 } 17 } 18 } 19 '''; 20 21 string adddata=''' 22 mutation create languages(\\$input createlanguagefieldsinput){ 23 createlanguage(input {fields \\$input}){ 24 language{ 25 name, 26 saveformat 27 } 28 } 29 } 30 '''; 31 string update=''' 32 mutation update languages(\\$id id!,\\$input updatelanguagefieldsinput){ 33 updatelanguage(input {id \\$id, fields \\$input}){ 34 language{ 35 name, 36 id 37 } 38 } 39 } 40 '''; 41 42 future\<queryresult> senddata() async{ 43 44 final variable ={ 45 "input" { 46 "name" langname, 47 "saveformat" saveformat, 48 } 49 }; 50 print('sendingdata'); 51 52 graphqlconfiguration configuration = graphqlconfiguration(); 53 graphqlclient client = configuration clienttoquery(); 54 55 queryresult queryresult = await client query( 56 queryoptions(documentnode gql(adddata), variables variable), 57 ); 58 return queryresult; 59 60 } 61 future\<queryresult> updatedata() async{ 62 final variable={ 63 "id"\ objectid, 64 "input" { 65 "name" langname 66 } 67 }; 68 69 graphqlconfiguration configuration = graphqlconfiguration(); 70 graphqlclient client = configuration clienttoquery(); 71 72 queryresult queryresult = await client query( 73 queryoptions(documentnode gql(update), variables variable), 74 ); 75 return queryresult; 76 } 77 78 79 future\<queryresult> deletedata() async{ 80 final variable={ 81 "id"\ objectid, 82 }; 83 84 graphqlconfiguration configuration = graphqlconfiguration(); 85 graphqlclient client = configuration clienttoquery(); 86 87 queryresult queryresult = await client query( 88 queryoptions(documentnode gql(delete), variables variable), 89 ); 90 91 return queryresult; 92 } 93 } mutaion page dart mutaion page dart 는 다음과 같아야 합니다 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 23 senddatabuttonpressed (){ 24 if(langname isnotempty && saveformat isnotempty){ 25 utils = databaseutils( 26 langname langname, 27 saveformat saveformat , 28 ); 29 utils senddata(); 30 } 31 }, 32 deletedatabuttonpressed (){ 33 if(objectid isnotempty){ 34 utils = databaseutils( 35 objectid objectid, 36 ); 37 utils deletedata(); 38 } 39 }, 40 updatebuttonpressed (){ 41 if(langname isnotempty && saveformat isnotempty && objectid isnotempty){ 42 utils = databaseutils( 43 langname langname, 44 saveformat saveformat , 45 objectid objectid 46 ); 47 utils updatedata(); 48 } 49 }, 50 ); 51 } 52 } 결론 이 가이드에서는 flutter 앱에서 graphql 변이를 사용하여 back4app에서 새 객체를 생성합니다; back4app에서 객체를 업데이트합니다; back4app에서 객체를 삭제합니다 이 시점에서 여러분은 완전한 기능을 갖춘 flutter graphql crud 프로젝트를 가지고 있으며, 이를 시작점으로 삼아 다음 앱을 개발할 수 있습니다 다음 가이드에서는 쿼리에 대해 깊이 파고들어 back4app에서 데이터를 검색하고 flutter 앱에 표시하는 방법을 보여줄 것입니다 좋은 하루 되세요!