[Flutter] FutureBuilder를 사용한 비동기 통신

ERror.ASER·2020년 2월 6일
0

Flutter

목록 보기
2/2

Future란?
이제 서버와 Flutter의 통신에 대해서 본격적으로 다룰 것입니다. 통신 방법에는 비동기(Asynchronous) 적인 방법과 동기적(Synchronous)인 방법 두 가지가 존재합니다. 동기적인 방법은 우리가 일반적으로 알고 있는 프로그램이 동작되는 방식입니다. 앞선 코드의 실행이 완료되기 전에 뒤의 코드가 실행되지 않는 것이 동기적인 방식입니다. 따라서, 동기적인 방법으로 통신하게 되면 서버로부터 정보를 받아오는 것이 완료되기 전에는 다른 작업이 실행되지 않을 것입니다. 이것의 장점이자 단점은 프로그램의 실행 흐름을 알기 쉽다는 것입니다. 그러나 이런점 때문에 서버로부터 불러오는 데이터가 큰 경우, 데이터를 다 받아오기 전까지는 화면이 멈춰있게 됩니다. 그렇기에 우리는 비동기 통신을 주로 사용하는 것입니다. 비동기 통신을 사용한다면 화면이 동작하는 것과 서버로부터 데이터를 불러오는 작업이 따로 실행되기 때문에 사용자 경험 측면에서 훨씬 좋은 결과를 낼 수 있습니다.
Flutter(Dart)에는 Future라는 클래스가 존재합니다. Future는 미래의 잠재적인 값 혹은 에러를 뜻합니다. 즉 특정 시간 이후의 결과를 나타냅니다. 예를 들어 인터넷에서 API를 사용하여 특정한 정보를 불러오고자 할 때, 어플리케이션에서는 이 정보가 어느 시점에 도착하는지 보장할 수 없습니다. 따라서 Future 클래스를 사용하여 미래 시점의 결과를 다루는 것입니다.
Future는 여러가지 형태로 사용 가능합니다. 먼저 then과 catchError를 사용한 방식입니다.

먼저, getData()는 string 타입의 값을 반환하는 비동기 함수입니다. 서버로부터 데이터를 불러오는 함수라고 생각해도 좋습니다. getData()가 반환하는 타입이 string 이긴 하지만, 언제 반환되는지 보장할 수 없는 Future 타입이므로, then과 catchError를 통하여 결과가 반환되었을 때의 값을 다룹니다. 두 메소드 모두 함수를 인자로 전달 받습니다.
getData 함수가 실제로 호출되는 것은 두번째 줄부터입니다. 먼저 then은 getData 오류 없이 실행되었을 때, 인자로 전달받은 함수를 실행합니다. catchError는 getData 함수 실행 중 오류가 발생했을 시에 인자로 전달받은 함수를 실행합니다. 물론 위와 같은 방법을 사용해도 비동기 작업을 다루는 것에는 문제가 없지만, 만약 여러개의 비동기 작업을 연속으로 다루어야 한다면 코드가독성이 떨어진다는 단점이 있습니다. 따라서 최근에는 async와 await 키워드를 사용하여 비동기 작업을 다룹니다.
아래는 then과 catchError를 사용한 코드를 async await 키워드를 를 사용하여 바꾼 것입니다.

구조 자체가 간결해짐에 따라 코드의 내용을 파악하기 수월해졌습니다. 앞으로도 이 책에서는 이와 같은 방식으로 통신하는 코드를 다룰 것입니다. 참고로, await 키워드를 사용하기 위해서는 함수 선언부에 async 키워드를 추가하여 사용하여야 합니다. 이것은 앞으로 예제코드를 보면서 확인해볼 수 있습니다
.
FutureBuilder 위젯을 사용하는 이유
그렇다면 FutureBuilder를 사용하는 이유는 무엇일까요? 우리가 서버와 통신할 때, 동기가 아닌 비동기 방식을 사용하는 이유와 비슷합니다. 어플리케이션의 페이지에는 서버로부터 받아온 데이터를 사용하여 화면에 표시하는 부분이 있고, 그렇지 않는 부분이 있을 것입니다. 만약 FutureBuilder를 사용하지 않고 서버로부터 받아온 데이터를 표시하고자 한다면, 데이터가 모두 도착하기를 기다린 다음에 화면을 그리거나, setState() 메소드를 호출하여 화면을 새로고침 해야합니다. (setState() 메소드를 자주 호출하는 것이 왜 나쁜지는 이후에 설명) 따라서, 우리는 FutureBuilder를 사용하여 서버로부터 받아온 데이터를 사용하는 부분만 데이터가 도착한 후에 표시하고 그렇지 않은 부분은 화면에 바로 표시할 수 있어야 합니다.
날씨 API를 사용한 예제
이제 지금까지 배운 내용을 바탕으로 실제 어플리케이션에 적용하여 어떻게 동작하는지 확인해보겠습니다. FutureBuilder를 사용하여 날씨 정보를 보여주는 간단한 프로그램을 작성할 것입니다. 날씨 정보는 openweathermap.org의 샘플 API를 이용해서 받아올 것입니다. API에 관한 자세한 정보는 https://openweathermap.org/current를 참고하면 됩니다. 그리고 예제에 사용된 모든 코드는 https://github.com/chinapoopoo/flutter_weather_app 에서 확인이 가능하며, 브랜치를 전환함으로써 단계별로 확인이 가능합니다.
먼저 Flutter Application 프로젝트를 생성합니다. Android Studio를 이용하여도 좋고, flutter create 명령어를 사용하여 생성해도 좋습니다. 생성이 완료되었으면 아래와 같이 main.dart의 불필요한 내용은 지워 다음과 같이 코드를 변경합니다. 혹은 1-Initial 브랜치로 전환하여 사용하면 됩니다.

위 코드의 실행결과는 다음화면과 같습니다.

이번 챕터에서는 서버로부터 불러온 날씨 정보만 간단하게 화면에 표시하는 작업까지만 진행할 것입니다. 먼저 http 통신을 위해 http 패키지를 프로젝트에 추가하여야 합니다. https://pub.dev/packages/http#-installing-tab- 위 링크에 접속하여 설치방법에 따라 pubspec.yaml 파일에 http: ^0.12.0+2 를 추가하면 됩니다.

이렇게 추가가 완료되었다면, 터미널에서 flutter packages get 명령어를 입력해 패키지를 설치하도록 합니다.
그럼 이제 다음과 같이 API를 호출하여 서버로부터 데이터를 불러오는 함수를 작성해봅시다. 먼저 main.dart 최 상단에 다음과 같이 http 패키지와 convert 라이브러리를 불러옵니다. http는 서버 통신에 사용되고, convert는 서버에서 불러온 데이터를 변환하기 위해 사용됩니다.
그 다음 fetchData라는 함수를 다음과 같이 작성합니다. _MyHomePageState 클래스 내에 작성하면 됩니다.

fetchData 함수는 서버에서 데이터를 불러오는 간단한 함수입니다. response 변수에 API 요청에 대한 응답이 저장됩니다. 따라서 우리가 요청한 날씨정보가 저장될 것입니다. 그리고 json.decode 함수를 사용하여, API로 부터 받아온 데이터를 Flutter에서 사용할 수 있게 Map 형태로 변환하고 있습니다.
이제 다음과 같이 build 함수를 수정해봅시다.

먼저 body의 위젯을 Column으로 수정하고 children을 FutureBuilder와 원래 있는 Text 위젯으로 수정합니다. FutureBuilder의 동작을 조금 더 자세하게 알아보기 위함입니다. 이제 FutureBuilder의 내용을 보면 먼저 future 인자에 아까 작성한 fetchData() 함수를 전달하고, builder 인자에는 데이터를 받아왔을 때, 화면에 어떤 위젯을 보여줄 것인지 작성합니다. 위 예시는 데이터를 서버로부터 받아왔을 때, 그 데이터를 Text 위젯으로 보여줍니다.
그렇다면 snapshot.hasData == false라는 조건문은 왜 필요한 것일까요? 이 부분은 서버로부터 데이터가 아직 도착하지 않았거나, API 호출은 종료되었지만 데이터가 없는 경우를 처리하기 위해 필요합니다.
예를 들어 데이터가 아직 도착하지 않았지만, builder 내에서 데이터에 참조하고자 하는 경우 에러가 발생할 것입니다. 따라서 위와 같은 조건문이 필요한 것입니다. 이 조건문 안에는 주로 로딩 상태를 보여주는 위젯을 넣어 데이터를 받아오는 중임을 나타냅니다.
이제 실행결과를 확인해보면 아래와 같은 화면이 출력될 것입니다.

서버에서 받아온 데이터를 화면에 잘 보여주고 있습니다. 실제로 프로그램을 돌려보면, 서버에서 데이터를 받아오기 전까지는 화면에 Initial State라는 텍스트만 보여지다가, 데이터가 도착하면 화면에 데이터가 표시됩니다. 이처럼 FutureBuilder를 사용하면 비동기 통신도 큰 어려움 없이 다룰 수 있습니다. 마지막으로 데이터를 조금 다듬어서 화면에 출력해보겠습니다.

코드는 아래와 같습니다.
이 챕터의 결과 코드는 2-FutureBuilder 브랜치로 이동하면 바로 확인이 가능합니다.

profile
지우의 블로그

2개의 댓글

comment-user-thumbnail
2020년 2월 6일

저기요 저가 누군지 아시겠나요??? 저는 당신이 누군지 알고있는 옆자리에서 코딩을 하고있는 사람이랍니다. 제 블로그에 참고좀 할거에요 그렇게 아세요 당신이 싫다고 해도 어쩔수 없어요 참고도 남길게 ㅇㅇ

답글 달기
comment-user-thumbnail
2023년 4월 13일

저기요 저가 누군지 아시겠나요??? https://stumbleguys3.com/

답글 달기