※ 본 카테고리의 내용은 부스트캠프 챌린지 기간동안 학습한 내용을 바탕으로 정리한 내용입니다.

 

목차


    0. 플러터의 비동기

     

    출처 : https://learnjs.vlpt.us/async/

     

    Javascript에 어느 정도 익숙해져있다면, Dart의 비동기를 이해하는 것은 그렇게 어렵지 않습니다.

    하지만 저는 Javascripts에서도 아직 promise와 async/await을 제대로 이해하지 못했..

     

    자바스크립트의 Promise와 Dart의 Future는 굉장히 닮은 면이 많습니다.

    둘 다 싱글 스레드 환경에서 비동기 처리를 위해 존재하죠.

    Javascript의 Promise가 다음 동작을 수행하겠다는 약속을 의미한다면, Future는 완료되지 않은 미래를 의미합니다.

    사실상 거의 같다고 보실 수도 있겠죠?

     

    Future비동기 작업의 결과를 나타내고, 미완료 또는 완료의 두 가지 상태를 가질 수 있습니다.

    막 Future가 생성되었을 때는 미완료 상태인데, 이 때는 아직 어떤 값이 들어있는 지 알 수 없습니다.

    이 값은 미래에 함수의 비동기 작업이 완료하면 알 수 있습니다. (중간에 오류가 발생할 수도 있습니다!!)

    만약 비동기 작업이 완료하면 미래는 값으로 반환되고, 그렇지 않으면 오류로 반환되겠죠?!

     

    Future의 작동 순서는 아래와 같습니다. JS의 비동기와 같은 메커니즘이라고 생각하시면 됩니다!

     

    • Future 객체가 내부 배열에 등록
    • Future 관련 실행 코드가 이벤트 큐에 등록
    • 불완전한 상태의 Future 객체 반환
    • 동기방식 코드 먼저 실행
    • 최종 데이터 값이 Future 객체로 반환

     

    Future를 어떻게 사용할 수 있는지 간단하게 잘못된(?) 예를 들어보겠습니다.

    아래는 간단한 Dart 코드입니다. delayed는 그 시간만큼 늦게 출력한다는 명령어입니다.

    아래 예시에서는 4초 늦게 출력하겠네요! 결과가 예상이 가시나요?

     

    String propose() {
      var order = forwho();
      return 'What i want to tell you is i love $order';
    }
    
    Future<String> forwho() {
      // Imagine that this function is more complex and slow
      return Future.delayed(Duration(seconds: 4), () => 'You');
    }
    
    main() {
      print(propose());
    }

     

    아름다워 보이는 코드이지만, 아쉽게도 프로포즈는 실패입니다.

    4초가 지나기 전에 print가 실행이 되버리기 때문에 정상적인 끝맺음이 실패한 것이죠.

    나는 선물이 좋아 선물내놔

     

     

    그러면 원하는 결과를 얻기 위해서는 어떻게 해야할까요?

    Javascript와 정말 똑같은 기능을 하는 async / await 키워드를 사용합니다.

    async / await 키워드는 비동기 함수를 정의하고 그 결과를 동기적으로 사용할 수 있는 선언적 방법입니다.

     

    async는 함수의 앞에 붙여서 이 함수가 await을 이용해 비동기 처리를 할 수 있도록 표시해주는 역할을 합니다.

    await는 비동기식 함수를 동기식으로 얻을 수 있기 위해 async 내에서 작동하는 기능입니다.

    두 키워드를 이용해서 비동기 함수를 동기함수처럼 사용할 수 있게 되는 것이죠.

    await 키워드가 붙은 함수는 그 함수가 다 끝날 때까지 다음 작업으로 넘어가지 않게 만들어줍니다.

    또한 Future 형태의 반환값을 갖게 만들죠!

     

     

    그렇다면 이제 async / await 키워드를 사용해서 뜸을 좀 들여주면 어떻게 될까요..?

     

    Future<String> propose() async {
      var order = await forwho();
      return 'What i want to tell you is i love $order';
    }
    
    Future<String> forwho() {
      // Imagine that this function is more complex and slow
      return Future.delayed(Duration(seconds: 4), () => 'You');
    }
    
    main() async {
      print(await propose());
    }

     

    와! 4초라는 잉여시간이 흘렀지만 그래도 성공했습니다!

    조금 더 설명하자면, propose함수에는 async가 붙어있어서, await이 앞에 붙은 forwho가 완료될 때까지 다음으로 넘어가지 않습니다.

    forwho에서 4초가 걸리지만, 그걸 다 기다려준다는 말이죠!

    그리고 main 함수 내의 print 역시 async / await을 이용해서 출력을 하지 않고 propose함수가 완벽한 값을 반환할 때까지 기다립니다.

    기다림의 끝에 프로포즈가 있었네요 ㅎㅎㅎ 

     

     

    이제 잠깐 논점에서 벗어나서, 그렇다면 왜 비동기 작업이 필요할까요?

    네트워크나 하드디스크로부터 데이터를 가져오거나 읽어오는 경우 운이 좋지 않다면 큰 파일이 걸려서 긴 시간이 소요될 수 있습니다.

    만약 앞에 큰 작업이 대기하고 있고 뒤에 작은 작업들이 몰려있다면, 큰 작업을 수행하느라 뒤에 있는 작은 작업들은 한참동안이나 발을 동동 굴러야 하는 상황이 올 겁니다.

    이 때 해당 동작들이 완료되지 않은 상황에서도 다른 동작을 동시에 수행할 수 있다면 조금 더 효율적으로 일을 수행할 수 있겠죠? (이 부분은 운영체제의 프로세스 관리부분과 일맥상통합니다!)

     


    1. API 사용하기

    Flutter/Dart를 사용하는 곳이 안드로이드 스튜디오든 VScode든 API의 사용은 개발에 있어서 반필수적입니다.

    혼자 처음부터 끝까지 다 만들게 아니라면 말이죠 ㅎㅎ

     

    그런 API를 쉽게 사용할 수 있도록 Flutter 개발에서는 pubspec.yaml파일을 이용할 수 있습니다.

    마치 Node.js의 package.json과 같은 역할을 하는 이 친구는 패키지 의존성 관리 및 프로젝트 정의 등의 역할을 맡습니다.

    API의 각종 버전 환경 등도 담고 있죠.

     

    Pubspec은 확장자명처럼 YAML 규격으로 되어있습니다.

    사람이 쉽게 읽을 수 있도록 만들어진 규격이기 때문에 실제로도 처음 봤어도 쉽게 이해하실 수 있습니다.

     

    안드로이드 스튜디오의 pubspec.yaml

     

    간략하게 Pubspec의 구성에 대해 말씀드리자면 아래와 같습니다.

     

    • name : 패키지의 이름
    • description : 패키지의 설명
    • publish_to : 배포주소
    • version : 패키지의 버전
    • environment : Dart 2 이상 버전에 필요 (https://dart.dev/tools/pub/pubspec#sdk-constraints 참조!!)
    • depencencies : 패키지가 사용하는 의존성 목록(API)
    • dev_dependencies : 패키지가 사용하는 개발용 의존성 목록

     

    이 중에서 우리가 가장 신경써서 봐야할 부분은 바로 dependencies입니다.

    이 곳에 원하는 API의 버전을 넣고, Pub get을 해야 합니다.

     

    Pub get가 뭔지 알아보기 전에 먼저 Pub에 대한 이해가 필요합니다.

    Pub플러터가 제공하는 패키지 매니저입니다. Dart에서는 그대로 pub을 사용하고, 플러터는 flutter package 명령어를 사용한다고 합니다.

    우리는 Dart 환경에서 진행하므로 pub을 사용하면 되겠죠?

     

    pub get 명령어를 사용하게 되면 pubspec.yaml에 있는 내용들을 모두 다운로드합니다.

    각종 API를 추가해놓고, 한 번만 pub get을 하면 모두 다운로드 받을 수 있습니다. 참 편하죠?

    특히 안드로이드 스튜디오는 pubspec.yaml창에서 오른쪽 위를 보면 바로 Pub get을 할 수 있는 버튼이 있습니다.

     

     

    이제 pub get을 하기 위해 각종 API를 찾아봅시다.

    번역을 하기 위한 translator를 사용한다고 가정해보겠습니다.

    버전에 대한 정보는 구글에 검색하면 아주 쉽게 나오니 참고하시면 됩니다!

     

     

    translator | Dart Package

    A free and unlimited Google Translate API for Dart. You can use it for translate strings and text for educational purpose.

    pub.dev

     

    위 페이지에 들어가면 translator의 1.0.7버전의 명세를 확인할 수 있습니다.

    우리는 이걸 사용하기 위해 pubspec.yaml에 버전 정보를 추가해줘야 하는데요!

     

    아까 dependencies에 패키지가 사용하는 의존성 목록을 적는다고 했죠?

    이 곳에 API 이름: 버전 형태로 적어줍니다.

     

     

    이 상태로 오른쪽 위의 Pub get 버튼을 누르면 API를 받아올 수 있게 됩니다!

    잘 완료되면 exit 코드로 0번을 출력합니다.

     

     

    이제 각 명세에 맞게 dart 파일에서 import해서 사용하면 되겠죠!!

     

     


     

    반응형
    • 네이버 블로그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기