본문 바로가기
삽질하는 개발자 hashblown

프론트엔드 개발자의 TIL #019

by hashblown 2019. 11. 27.

TIL #019

191127 수

 


오늘 배운 점

<Flutter>

1. Async & Await

  • 이 두 syntax는 비동기 데이터 처리를 하기 위한 코드를 좀 더 깔끔하고 읽기 편하게 작성될 수 있도록 돕는다. 
Future<int> _loadFromDisk() {}

Future<String> _fetchNetworkData(int id) {}

class ProcessedData {
  ProcessedData(this.data);
  final String data;
  
}

Future<ProcessedData> createData() {
  return _loadFromDisk().then((id) {
    return _fetchNetworkData(id);
  }).then((data) {
    return ProcessedData(data);
  });
}
  • 처리된 데이터를 다루는 class가 있고, disk id를 정수형태로 받아온 후 네트워크 데이터를 불러오는 예시가 있다고 하자. (네트워크와 파일 I/O는 비동기적으로 운영되므로 Future값을 내보낸다.) Dart의 Future API로 이 과정을 createData()처럼 then으로 결합시킬 수 있다. 첫번째 future의 완성된 값이 다음 콜백을 위한 매개 변수가 될 수 있도록 하는 것이다. Future API의 장점 중 하나는 이벤트에 따라 코드가 어떻게 분류되는지를 쉽게 확인할 수 있다는 점이다. (이전 TIL에 언급한 대로, 이 경우에는 에러를 다룰 때 catchError, whenComplete 등을 사용한다.)
Future<ProcessedData> createData() async {
  final id = await _loadFromDisk();
  final data = await _fetchNetworkData(id);
  return ProcessedData(data);
}
  • async와 await을 사용하면 방금 then을 활용한 chain과 동일한 코드를 위와 같이 synchronous 코드를 작성하는 모양 그대로 Future를 만들 수 있다. await 수식에 따라 코드 줄 별로 예쁘게 정리된 진행상황을 확인할 수 있다. 이 방식대로라면 실행 후 첫번째 await을 마주치면 id를 받을 때까지 기다렸다가 다시 진행되다가 두번째 await을 만나면 id를 가지고 data를 받고, 네트워크 이벤트가 끝나면 그 data를 가지고 반환한다.
  • 결국 두 방법 다 같은 event loop가 행동을 제어하고, Future를 활용한다. 차이점은 async/await을 사용하면 함수가 작아지고 더 동기화된 코드처럼 보이게 해준다는 것이다.
  • 그렇기 때문에 에러는 동기화 코드에서처럼 핸들링된다. 즉, try, catch를 활용해서 에러를 핸들링한다는 것.
Future<ProcessedData> createData() async {
  try {
    final id = await _loadFromDisk();
    final data = await _fetchNetworkData(id);
    return ProcessedData(data);
  } on HttpException catch (err) {
    print('Network error: $err');
    return ProcessedData.empty();
  } finally {
    print('All done!');
  }
}
  • 에러 처리를 할 때 추가적인 콜백을 해야 하는 Future API와 달리, 코드를 try로 감싼 후 on ~ catch로 특정 유형의 예외들을 잡아두면 된다.
  • 마지막으로 자주 사용되지는 않지만 for문을 활용하여 await을 처리하는 방법을 더 공부해보았다. Stream 형태로 숫자를 받아와서 다 더해주는 함수를 만들어보자.(정확하게는 숫자들이 도착할 때마다 비동기적으로 더해놓고, Stream이 끝나면 그 합을 반환하는 방식이다.) 일반적인 sync 코드와 함께 비교해보면 다음과 같다. 거의 코드 구조는 유지하고, await로 이벤트를 기다리기 전과 후의 실행 명령을 구분해준다.
  • 단, 확실히 완료가 될 것임을 아는 stream에만 사용해야 한다. 끝나지 않고 계속 for loop이 대기하게 되는 상황이 생길 수 있기 때문이다!
//동기 데이터 처리
int getTotal(List<int> numbers) {
  int total = 0;
  
  for (final value in numbers) {
    total += value;
  }
  
  return total;
}


//비동기 데이터 처리
Future<int> getTotal(Stream<int> numbers) async {
  int total = 0;
  
  await for (final value in numbers) {
    total += value;
  }
  
  return total;
}

내일 배울 점

<Flutter>

1. Generators (생성자 함수)

2. 마이스튜디오 화면별 진행 상황


더보기

- 아니 벌써..다음주부터 기말고사 시작..!

 

댓글