Dart 의 비동기/동기(async/ sync programming) 표현 방법은 상당히 직관적이면서도 편리한 부분들이 많습니다.
효율적인 동작을 위한 코딩을 하려다 보면 필연적으로 async로 코드 작성이 필요로 하게 되죠.
아래 간단한 주제를 가지고 한번 얘기 해보고자 합니다.
| A라는 데이타 목록을 가지고 B라는 과정을 거쳐서 C라는 결과를 도출하고 D라는 데이타 목록으로 저장을 하려고 합니다. 1. A의 각 항목들은 B라는 과정을 거칠때 1~2 초 정도 시간이 걸린다. 2. B 과정을 입력 A 데이타에 따라 처리 시간이 달라진다.(1초 또는 2초) 3. D에 저장 되는 순서는 A의 순서와 같아야 한다. |
일단 A항목들을 순차적으로 처리하게 되면, A의 개수만큼 시간이 늘어나게 됩니다.
따라서 비동기(async)프로그래밍를 고려하게 될 것입니다.
위의 상황에 대해서 코딩을 해보면, 가장먼저 다음과 같이 생각해볼 수 있을 것입니다.
A = srcData, B =Future.delayed() , C = A와 같은 type , D = dstData 라고 합시다.
import 'dart:async';
import 'dart:math';
List<String> srcData=[];
List<String> dstData=[];
init(){
for( int i = 0;i<24; i++ ){
srcData.add('mmm_${i}');
}
}
Future copyToDst(int i){// test를 위해서 1~2초의 랜덤 수행 순서로, src에서 dstData 에 copy 하는 내용.
return Future.delayed(Duration(seconds: Random().nextInt(2)),(){
dstData.add(srcData[i]);
print('src[$i]=>dst');
});
}
fillDest() async{
init();
print("fillDest: length=${srcData.length}");
for(int s = 0; s<srcData.length ;s++){
copyToDst(s);
}
}
void main() async{
await fillDest();
await Future.delayed(Duration(seconds: 5));
print(dstData);
}
1초 또는 2초에 처리가 완료 되면, dstData에 저장을 하게 됩니다.
실행 결과는 아래와 같습니다.
기본적인 동작은 하는것 처럼 보입니다.
<실행 결과>
|
fillDest: length=24
src[3]=>dst
src[4]=>dst
src[5]=>dst
src[8]=>dst
src[10]=>dst
src[11]=>dst
src[15]=>dst
src[16]=>dst
src[20]=>dst
src[21]=>dst
src[22]=>dst
src[0]=>dst
src[1]=>dst
src[2]=>dst
src[6]=>dst
src[7]=>dst
src[9]=>dst
src[12]=>dst
src[13]=>dst
src[14]=>dst
src[17]=>dst
src[18]=>dst
src[19]=>dst
src[23]=>dst
[mmm_3, mmm_4, mmm_5, mmm_8, mmm_10, mmm_11, mmm_15, mmm_16, mmm_20, mmm_21, mmm_22, mmm_0, mmm_1, mmm_2, mmm_6, mmm_7, mmm_9, mmm_12, mmm_13, mmm_14, mmm_17, mmm_18, mmm_19, mmm_23]
|
음... 그런데 결과에서 보듯이 "mmm_숫자" 결과의 순서가 srcData의 순서와 맞지 않는 것을 볼수 있습니다.
이제 여기서 몇가지 고민을 하게 되겠죠? 가령 "어떻게 순서를 맞출 것인가? " 와 같은 것 말이죠.
대략 한 3가지 방법을 생각해 볼 수 있을것 같네요..
첫번째, copyToDest를 await 으로 처리하는 방법입니다.
for(int s = 0; s<srcData.length ;s++){
await copyToDst(s);
}
직접 실행해보면, .. 으악... 이런 최악의 수네요..ㅠ_ㅠ 실행시간이 너무 오래걸려요.
두번째, map을 이용하는 방법이 있겠네요.
map을 이용해서 srcData의 순서를 map의 index로 사용하는 방법이죠.
import 'dart:async';
import 'dart:math';
List<String> srcData=[];
Map<int, String> dstData={};
init(){
for( int i = 0;i<24; i++ ){
srcData.add('mmm_${i}');
}
}
Future copyToDst(int i){// test를 위해서 1~2초의 랜덤 수행 순서로, src에서 dstData 에 copy 하는 내용.
return Future.delayed(Duration(seconds: Random().nextInt(2)),(){
dstData[i] = srcData[i];
print('src[$i]=>dst');
});
}
fillDest() async{
init();
print("fillDest: length=${srcData.length}");
for(int s = 0; s<srcData.length ;s++){
copyToDst(s);
}
}
void main() async{
await fillDest();
await Future.delayed(Duration(seconds: 5));
print(dstData);
}
<실행결과>
|
fillDest: length=24
src[0]=>dst
src[1]=>dst
src[2]=>dst
src[3]=>dst
src[5]=>dst
src[6]=>dst
src[7]=>dst
src[11]=>dst
src[12]=>dst
src[16]=>dst
src[18]=>dst
src[21]=>dst
src[22]=>dst
src[4]=>dst
src[8]=>dst
src[9]=>dst
src[10]=>dst
src[13]=>dst
src[14]=>dst
src[15]=>dst
src[17]=>dst
src[19]=>dst
src[20]=>dst
src[23]=>dst
{0: mmm_0, 1: mmm_1, 2: mmm_2, 3: mmm_3, 5: mmm_5, 6: mmm_6, 7: mmm_7, 11: mmm_11, 12: mmm_12, 16: mmm_16, 18: mmm_18, 21: mmm_21, 22: mmm_22, 4: mmm_4, 8: mmm_8, 9: mmm_9, 10: mmm_10, 13: mmm_13, 14: mmm_14, 15: mmm_15, 17: mmm_17, 19: mmm_19, 20: mmm_20, 23: mmm_23}
|
실행결과를 보시면 데이타의 순서는 처리속도에 따라 순서가 달라졌지만, 우리는 map의 index를 사용할 수 있기 때문에 index 순서로 결과를 뽑아볼수 있습니다. ^^ 매우 좋은 결과네요.
속도도 거의 차이가 없고, 결과도 좋고요.
한가지 걸리는 것은 , dstData를 얻기까지 1~2초가 걸리는데, data가 정상적으로 들어왔는지, 언제 사용해야 하는지가 약간은 애매하네요.
세번째, dstData를 Future List로 변경하는 방법인데요.
dstData 의 형태를 List<String> 에서 List<Future<String>> 변경하고 copyToDst의 형태도 dstData에 Future<String>을 추가하도록 변경되었습니다.
이렇게 하면 dstData 에는 실행 결과가 들어가는 것이 아니라 실행 명령 순서인 Future<String> 을 저장하는 것을 의도 합니다.
import 'dart:async';
import 'dart:math';
List<String> srcData=[];
List<Future<String>> dstData=[];
init(){
for( int i = 0;i<24; i++ ){
srcData.add('mmm_${i}');
}
}
Future copyToDst2(int i)async{// test를 위해서 1~2초의 랜덤 수행 순서로, src에서 dstData 에 copy 하는 내용.
return dstData.add(Future<String>.delayed(Duration(seconds: Random().nextInt(2)),(){
print('src[$i]=>dst');
return srcData[i];
}));
}
fillDest() async{
init();
print("fillDest: length=${srcData.length}");
for(int s = 0; s<srcData.length ;s++){
copyToDst2(s);
}
}
void main() async{
await fillDest();
await Future.delayed(Duration(seconds: 5));
List<String> l=[];
for (var d in dstData){
l.add(await d);
}
print(l);
}
추후 Future<String>의 결과를 얻기 위해서는 await dstData[i] 형태로 사용하면 String을 얻어올 수 있게 됩니다.
<실행 결과>
|
fillDest: length=24
src[0]=>dst
src[1]=>dst
src[2]=>dst
src[3]=>dst
src[5]=>dst
src[6]=>dst
src[7]=>dst
src[10]=>dst
src[11]=>dst
src[12]=>dst
src[16]=>dst
src[20]=>dst
src[23]=>dst
src[4]=>dst
src[8]=>dst
src[9]=>dst
src[13]=>dst
src[14]=>dst
src[15]=>dst
src[17]=>dst
src[18]=>dst
src[19]=>dst
src[21]=>dst
src[22]=>dst
[mmm_0, mmm_1, mmm_2, mmm_3, mmm_4, mmm_5, mmm_6, mmm_7, mmm_8, mmm_9, mmm_10, mmm_11, mmm_12, mmm_13, mmm_14, mmm_15, mmm_16, mmm_17, mmm_18, mmm_19, mmm_20, mmm_21, mmm_22, mmm_23]
|
추가로,
map을 사용했을때 " dstData 언제 사용해야 하는지가 약간은 애매하네요." 라고 했던 부분에 대해서 추가로 생각해보자면,
List<Future<String>> 을 사용했던것 처럼, map<int , Future<String>> 으로 사용하게 되면, 필요한 데이타를 사용할때 await을 활용하여 data 결과가 채워지기를 기다릴 수 있겠는데요 ?
아무튼 async 프로그래밍을 다루기에 편리한 언어인 dart 인데 이를 활용 안할 이유가 없을것 같죠? 그렇죠?
다들 dart의 async, async* sync, sync* 에 대해서 찾아보시고 알아두시면 즐거운 코딩 생활에 도움이 될것 같습니다.
'Dart,Flutter' 카테고리의 다른 글
| [Flutter] permission 설정하기 (0) | 2022.10.24 |
|---|---|
| [Flutter] App route 구성하기. (0) | 2022.10.19 |
| [Flutter] flutter_blue 설치 에러(\macos\Classes\FlutterBluePlugin.h' (OS Error)) (0) | 2022.09.17 |
| [Flutter] \macos\Classes\FlutterBluePlugin.h' (OS Error: The client does not hav (0) | 2022.09.15 |
| android wifi hotspot enable (0) | 2022.09.14 |