From 33c22a359eaeb9a59c0552fa0aba2da65a1a852b Mon Sep 17 00:00:00 2001 From: HakRimLee Date: Mon, 17 Oct 2022 15:59:46 +0900 Subject: [PATCH 1/6] blog 1 --- ...synchronous_programming_in_dart_flutter.md | 196 ++++++++++++++++++ assets/images/post-asyncDart/asynchronous.jpg | Bin 0 -> 52556 bytes 2 files changed, 196 insertions(+) create mode 100644 _posts/2022-10-17-asynchronous_programming_in_dart_flutter.md create mode 100644 assets/images/post-asyncDart/asynchronous.jpg diff --git a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md new file mode 100644 index 0000000000..15a90ca61c --- /dev/null +++ b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md @@ -0,0 +1,196 @@ +--- +layout: post +title: "Dart/Flutter에서 비동기처리하기" +authors: [hfjxjjd123] +tags: ["Dart","Flutter","asynchronous","다트","플러터"] +; image: assets/images/post-WebSocket/websocket.png +description: "Dart/Flutter에서 비동기처리하기" +featured: true +--- + +--- + ## 비동기처리(asynchronous programming)란? +
+ +비동기처리는 대기를 필요로하는 작업을 기다리면서도 프로세스가 다른 작업을 수행할 수 있도록 작업하는 방식을 말한다. + +따라서 프로세스가 외부에 요청을 던지는 작업을 할 때, 그 요청에 대한 결과값을 반환하기 위해 프로세스가 멈춰서 기다리는 일이 없기 때문에, 버리는 시간 없이 효율적으로 작업을 처리할 수 있게된다. +
+ +비동기처리가 쓰이는 예시 + +- 네트워크에서 데이터를 받아올 때 + +- 데이터베이스에 데이터를 작성할 때 + +- 파일로부터 데이터를 읽어올 때 +
+ +Dart언어에서는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. +
+ +## Stream이란? +
+다른 환경에서도 많이 사용해서 다소 익숙한 비동기처리 개념 중 하나인 Stream은 Flutter에선 비동기식 이벤트(값)의 연속된 소스를 의미한다. + +`Stream`도 그렇고 `Future`도 그렇고 비동기처리의 개념은 주로 외부에 사상/연산을 주고받고 하는 과정에서 사용되므로, 변수에 바로 `Stream`/`Future` 타입이 할당되기보단 외부작업을 맡기는 로직이 쓰이게 되는 함수 내에서 `Stream`/`Future` 객체의 개념을 요구하는 경우가 대부분이다. + +따라서 `Stream`/`Future` 객체는 함수에서 반환되는 경우가 많으며, 이 때 함수가 정의될 때 함수의 body에서 비동기처리 방식이 사용된다는 것을 아래 코드와 같이 명시해줘야 한다. + +```Stream``` 함수에는 `async*`, `Future` 함수에는 `async`라는 키워드를 통해서 함수 내에서 비동기처리방식이 쓰인다는 것을 명시할 수 있다. +```dart +Stream function() async*{ + ... +} + +Future function() async{ + ... +} +``` +`Stream`으로 정의된 함수는 선언 즉시 `Stream` 객체를 반환하며, 그 후엔 `Stream`의 데이터에 접근해 사용할 때까지 아무 일도 일어나지 않는다. +이후 `listen()`/`await for` 키워드를 통해 `Stream`객체의 데이터에 접근할 수 있으며, 이 때 `async*` 함수가 동작하게 된다. +```dart +stream.listen((int x) => print(x)); //listen() + +await for (final value in stream) { //await for + sum += value; +} +``` + +일반적으로 `Stream` 객체의 데이터에 접근하는 과정에서 iterator의 개념이 사용되는데, 가장 최근에 올라온 이벤트들을 하나씩 처리하고 지워나가면서 `Stream` 안에 남은이벤트가 없어질 때 까지 이를 계속하게 된다. +이렇게 한 이벤트는 한 번 사용하고 버리는 것을 단일구독스트림라고 한다. + +하나의 이벤트에 여러번 접근해서 값을 사용하고 싶다면 브로드캐스트스트림 형식을 사용하면 된다. +
+ +## Future란? +
+보통 외부의 결과에 영향을 받는 비동기식 작업은 의미적으로 2가지 상태로 구분된다. + +- 외부로부터 결과값을 받은 상태(#1) +- 외부로부터 결과값을 아직 받지 못한 상태(#2) + +`Future` 타입을 가지는 객체는 비동기식 작업을 수행할 때 그 작업의 상태(#1, #2)에 상관없이 `Future`라는 객체타입을 반환한다. + +따라서 `Stream`과 마찬가지로 `Future`가 의미적으로 포함하는 실제 데이터값에 접근하기 위해선 특수 키워드들이 사용되는데, `Future`에선 `await`, `then`을 사용한다. + +Flutter에서 데이터베이스를 다룰 때 주로 `Future`를 사용하므로 예제 소스코드 3개를 보면서 개념을 자세히 확인해 보자. + +참고로 `getString1()` / `getString3()`은 각각 1초, 3초 기다렸다 `String` 값을 의미적으로 받아오는 `Future` 타입의 함수이다. + +### 1. `then` 키워드 쓰임새 +```dart +import 'dart:async'; + +void main() async{ + + Future getString1(){ + return Future.delayed(Duration(seconds:1),()=>"연산1"); + } + Future getString3(){ + return Future.delayed(Duration(seconds:3),()=>"연산3"); + } + + getString3().then((String string){print(string);}); + //getString3() 요청 후 계속.. + getString1().then((String string){print(string);}); + //getString1() 요청 후 계속.. +``` +`getString3()`이 먼저 호출됐지만 비동기적 연산을 하므로`getString1()`의 호출도 즉시 이뤄진다. 이후 `then` 키워드를 통해 비동기연산의 결과(필요한 데이터)를 받아오는데, 1초 후 `getString1()`의 결과값이 먼저(`연산1`) 연산되며 이후 2초가 더 지난 뒤 `getString3()`의 결과값(`연산3`)이 처리되므로 `연산1`이 먼저 출력된 후 `연산3`이 출력된다. + +### 2. `await` 키워드 쓰임새 +```dart +import 'dart:async'; + +void main() async{ + + Future getString1(){ + return Future.delayed(Duration(seconds:1),()=>"연산1"); + } + Future getString3(){ + return Future.delayed(Duration(seconds:3),()=>"연산3"); + } + + print(await getString3()); + // getString3() 요청, await로 getString3()이 데이터값을 받아올 때 까지 기다림 + // 3초후 String 데이터값을 받아오고 계속 + print(await getString1()); + // getString1() 요청, await로 getString1()이 데이터값을 받아올 때 까지 기다림 + // 1초후 String 데이터값을 받아옴 +} +``` +`getString3()`이 먼저 호출됐으며, `await`라는 키워드로 `getString3()`의 결과값이 반환될 때 까지 프로세스는 기다린 후 그 결과값을 반환한다. +3초 후 `getString3()`이 반환되고 나서 `getString1()`이 호출되며 마찬가지로 결과값이 반환될 때 까지 프로세스가 기다린 후 그 결과값을 반환하게 되므로 `연산3`이 먼저 출력된 후에 `연산1`이 출력되게 된다. + +### 3. `await`의 필요성 +`await`는 얼핏보면 동기적 처리 성격을 가지고 있어서 일반적인 동기처리 방식으로 해결하면 되지 않나 하는 생각이 들 수 있지만 `await`는 연쇄적으로 `async`함수 , `Future`를 받아오는 상황에서 유용하게 쓰일 수 있다. + +```dart +onTap:() async{ + await updateModel(Model); + BLOC().add(getAllModel(Model.day)); + setState((){}); + } +``` +위의 코드는 `onTap`이라는 이벤트가 발생했을 때 `updateModel()` 메소드로 데이터를 데이터베이스에 업데이트 한 후 그 업데이트 된 데이터를 포함한 모든 `Model` 데이터를 받아오게 설계돼있다. + +그렇기 때문에 데이터베이스를 업데이트 해주는 `updateModel()`의 작업처리가 완료된 후 `getAllModel()` 메소드가 동작해야 하므로 `await`가 사용되어 `updateModel()`의 작업처리를 기다린 후 반환했다. + +하지만 `getAllModel`을 통해 받아온 데이터 모델들은 아직 데이터값으로 반환할 필요가 없기 때문에 `await` 사용 없이 `Future` 자료형인 채로 그대로 다음 메소드의 인자로 전달하여 처리를 미룰 수 있게 된다. + +이렇게 `await`는 필요한 순간에 데이터값을 반환하거나 완료를 기다릴 수 있도록 해주기 때문에 비동기처리에서 데이터를 다룰 때 유용하게 사용된다. +
+ +## 비동기처리 in Flutter +
+ +이제 Flutter에서 비동기처리방식, `Stream`과 `Future` 개념을 어떻게 사용하는지 알아보겠다. + +Flutter에서의 쓰임을 얘기하기 전에 간단하게 생소하실 Flutter의 구성에 대해 설명하면, Flutter는 `Widget`이라는 기본단위로 구성되어있다. `Widget`은 Flutter에서 화면에 보여지는 모든 UI (View)의 기본단위로써 의미를 가진다. + +`Widget`을 빌드할 때 사용될 정보가 데이터베이스에 있는 등의 상황에서, 비동기처리를 이용해 `Widget`을 렌더링 해야하는데, Flutter에선 이를 지원해주는 기본 빌더 `FutureBuilder`, `StreamBuilder`가 있다. + +기본적으로 `FutureBuilder` , `StreamBuilder` 모두 `AsyncSnapshot`이라는 객체를 추가적으로 다룬다. + +### `AsyncSnapshot`이란? + +비동기처리의 상태를 알 수 있게 해주는 객체이다. +앞서 얘기했지만 비동기처리는 다음과 같이 2가지 상태를 가질 수 있다. + +- 외부로부터 결과값을 받은 상태 +- 외부로부터 결과값을 아직 받지 못한 상태 +
+ +이 때, `snapshot.hasData`라는 필드에 접근해서 비동기처리의 상태를 알아낼 수 있다. +`true` => 외부로부터 결과값 or Error값을 받아온 상태 +`false` => 외부로부터 결과값을 받지 못한 상태 + +`snapshot.hasError`라는 필드를 통해선 반환값이 에러인지 확인가능하고, +`snapshot.data`필드를 통해 반환한 실제 데이터값을 얻어낼 수 있다. + + +### `StreamBuilder`, `FutureBuilder` 사용법 + +```dart +StreamBuilder( + stream: stream, // 위젯에서 다룰 정보를 가지는 Stream 객체 + builder: (BuildContext context, AsyncSnapshot snapshot) { + return (snapshot.hasData)? Widget('Result'):Widget('Waiting'); + } +) + +FutureBuilder( + future: future, // 위젯에서 다룰 정보를 가지는 Future 객체 + builder: (BuildContext context, AsyncSnapshot snapshot) { + return (snapshot.hasData)? Widget('Result'):Widget('Waiting'); + } +) +``` +다음과 같이 위젯을 구성하며,빌더는 인자로 들어간 `stream`, `future`의 `AsyncSnapshot`을 받아온 후 `snapshot.hasData`의 결과에 따라서 +`true` 일때는 `Widget('Result')`를, +`false`일 때는 `Widget('Waiting')`을 빌드한다는 것을 알 수 있다. + + +위젯은 `stream`, `future`가 데이터값을 반환할 때까지, 즉 `snapshot.hasData != null` 일 때까지 계속해서 위젯을 리빌딩한다. + +이를 통해서 Flutter에서 비동기적 방식으로 위젯을 빌드할 수 있는 것이다. diff --git a/assets/images/post-asyncDart/asynchronous.jpg b/assets/images/post-asyncDart/asynchronous.jpg new file mode 100644 index 0000000000000000000000000000000000000000..80f2efbee23da82620139c06bc5990d476aceb78 GIT binary patch literal 52556 zcmeI52V7Iln(%`lMMYFVK}u9mM2ga+6Hx&H5$Q^mE?s&j0wRJy1Ox#-Me@1yZ7F``+ghzok)^%=FH6b&(mh+0Y8MF0-ckSmX!t(odAJ| zfPWzTDChx*oRpM|^dvbM85soy`KdEBlxI$#K0|+jnu><$GMJg^G9%*^R&KT{*Em@i z8E*=*bKc?M=jR8r35yHyigEMt^BxyML_tAu=JXjlN=iE3tBhB9fAbIiJLo()i4fUq zVxnuH6X%JD&lBP6L13VsCy9Rf0sZlZ=maszNm4R$ic_b76N=7(P7o0jpCBPVd6I+# zINKBW9z=5f<+XM74ULGV=9Zq`zW#y1q2ZC~nc2Ddg~g@i zmF=C~J>>oY>JWY0E+P=|ADRWc{-I(2u3hJWcAX$0AtoU^ZWqxBXW$?{Pjd1q59tL- zB{F?m>TA5-~CwB&ws0Be{R^X?HU1{ zAtnMI9`Sh)1XLhJqfz=yNs0zUI0$_}V1U2?fdK*o1O^BU5EvjZKwyBt0D%Dl0|W*L z3=kL~FhF2{zyN^(0s{mF2n-MyATU5+fWQEO0RjUA1_%rg7$7h}V1U2?fq{Pv18VD{ zikBu#jMxj9NbO_sAU~y?8Y(=f6@ei`_k@4r&0?dw>xcWUcZh-sf5Twlu&Kj?cDC^#B3w~`mKPWgih`l2kSSb2 z7I+ZlXH_LB1J@r?G*5~Cj^iZPPa?tbat+330S|hO2QA$%a~oh_8nW?5`_U+=Ish;C zPX1mGr=kW83njjA+AiR+w#@<(@Acnv2wQ33?%R9H?9e{RHLuyB{=5SDkm*=Hgk;B% z12;JR_muq)yLNO755iOevOdQ^z0r@;7MtXrxo9oOXqv-rX{d*?98XLwn>bFPzOU)2n;QFb6Q) z5sham)!`->yMOaEujZ}Wg+K5h@mV~mx&dtFi*rZdL7ssp2*v-k&dJNdgPOQ)P*k`# z98tO9sxj>R%WBu94TC`6;}gr;gR#AbYSOY?&nNwY%9!IGCPo=T9dN3aHXHDkta$N` zcv+_lfjY-$DdpFcLvIPsjtO5Ml4ExgJW!mMZp1BP(idT`=A!g(rVLGvLn0U$j?#9L z;>GL2bl&`2R*1{N*}q!U0Fx?C)gDn=W;`SZSPznahy3|_WY>RjZK=dZZO-d7z<)2$ zN)8tdl;nMvrKwUbNt#>-1i}ZfJy<+gFZa2vd4|4HxAa|r0U&T%zc2_|wAtIpvz3&!&RfT1l9~{}=3C}^Vs;)Zb zFZZI(0Y2SD8YL;v|1XCu6?#6)Q5lSERbO4)wVA!G*dO1agJD}mUr7w)XcGqkX25?q zQsr?O)gRGDH7lQ&HM?+}o=S0g)2-bfml6ZfvkN|fH@}?tUv^LcB3x4#&H>ES`>u`on8Q*rE8kYU-H&fZs0+xeQ2Y}m6&3{3c1Xjwac4_VRz$=qfye+ z^cea}*Zd#*jEEJo8ky7o2s+56l?QLH395pqy9+yS!Sj{?5c2Nq{Y4a_Z=+MuD$8Mb zP^L|a#RF76QrZ#fe_L7wfNm8Q^AFSif2WP}b3Ly6Vqc=wGPB6g-FsPTyTf_ggK3BH z1A3U-pOmC%7viS>lKg-C8LOhQ91hJiAEm;)bjxdNso6?dYH?7K@-*Ak|4Uc=AN!2t z10IyCS)!^Ict^ia75)-x(^8r3bT-E=@af3pf}4<-n#fbzD7$`IjdiN^L#2KHeN5K- zBkr2eer$qFTalF7(Ssu|RnG)$%`M2c)kCsDIdBk;5g<|^9sAQ!TkkE4NFPFLcl_LYT1I4bd=H;~6TBm%n+ zsfD2)>~(HxLnjR}H*v#tuGk-I$*&wVT>niSey$w0;O*{_@9?9krT@HbNk^uXiw9)i zLVtAYEdE@HpX#>X!O*!uWz6E6Skd`Y9sW(-e(53Re{BbqV$}ykxs=^qN-TrF3Npq= zbiYM(*EcuDZ3KK|bTk&ZnOGtFvw--A{?3v2Z7U+BJ-Bk+R>;gi%q*7F@>B&Kc%AWT`Fq_8?N;WL;K0G#;Bv&n>~7mj@!M zpZ9*Dm!=4as0P$1Zsp##U|!T1$cT-g9l(QX*#RFMLhS_yi2GABZdK&))!RrrN1$XaT6D z6g~dW>yR{pDD^atZdTH<`Sq^QpXyQsdxh@j3rkhNWn_K*sS+_07YZG3S>N~p+|W$A z@~Seg&BJb5+jAcoHB?^}YFGjF(TT!f#(rtfpF7l(Y`^hR#Sx5Q_|eSE+|gg30StA2 zt!8my_LnaDQ&&?#r)P`1T)C^oD7e zFwrRK)cG{mv;mU?Ooi#QU5S6e zKK;)=%M;ut!}#X{o;=Q{>RRPwJ$Q$?0uO?sPwjt$%(nI-r3H%lfY=4vJ{EZWr-Xu$ zlpMHw`+CStFwW=JxN1+$9F;LJWdTGNmagRt{!quURy`jn21H2#-QQ|RYOu}Plo=zT z*vRshIgHf-XLTMP^ldO90uQRHTRh|wfu9xz3aqZ5|A$Jbf1qjgFRfR17j#b46c5tj z5Giy3AD$fs=7i)B=P~qXNR#b2a|DnUpq44&x0q$RHZxR*R62N24fdp)lxxj9$eg${ z4iDO+T{nUvqS97^EG$g`n{jVZ=x=?-zwtbxmCG6!@3orM2?&-%tvn+I+Qi(7s{-Os zT~bk1xp#N`;#j2hi|?x}|d8RtFVz=PcV zJ9kVRB`(?lC3*(50I&bw_{aaKw$M61iV^kH95K_fe0gXho*6;Q=M$@~_w-4}ViKT7 zrIG>Vw*sBy0_?S)-q0@6XoO<@9~{D`anjWzGJpM4r9Yl2xt{C>!LVv7VsL5Lok>79 z|N6VGtrU330TPV^&oL9q`?p>FKh=NQcMHTcM5@}lN?pdkWs7dz3a0IU)0#1DvPe3< z*B7m7rw(|A8m>gYMdtj5bIB5x%ZuU6QDzJi-*dlyG3MqaS5mJjcIZ6Bl^h4ET_b2` zT3J)rh3&-^)J)uL_B)~hBM-3l4u$~p{xM((u0oI2G@_N{kIqKz@*J5C?M<%7@!_C= zy$3|ge>y#nHxafbqSsb8DuGDFgDjWfyI7m!2sq^DyU{@PdvGSq!~5cbzZS2AEl7oS zB5Sbw9Bt`I$2YpO-rHiykEyPS_AmB?Dd2{CA&clqAQTV% z^^Uu@ZsO`vFm2)mYk#FhGW$%ofyDrD!(QmGH3a{3&&rlS$k$~kAC=`1^XETT5%8b> zcuU#^Re&P-!%y!2lwQ#gm{}dwDl9w_+ioqaUJs6S$kh!TrTo~Npr)#9UEh)w_7%`8 zE78Bdc`CKiz1Cq%O(a)bPLyae6X{JWuJ0MY0qTF&VEJw3(wetEsqE7U>lj}!qJL54 zN12j!B8Mh7JEW=ZOd5&XWx2n@ri`GC>!&gPG)1Lyk3vebsyB~+QMIzf<$0s3psm_V z1@Wi9J12tHT7h?;gSN`uRLi7snCd}H#(lH3-`3&4w6D$tAf8wUc5!5whF1~e%kUiq z8^{#2O`R?{DwA4B?q*`i-)u_%MloOPYqlC&DPw%x9&35ptHD9TzTFu?MX#L z;D-B?$bRUjgf%j)?MpZaU`d8Uf2qv-8F)~$ z0N_`?hVp4&cXoqg!nGhMvR#2%bvjRY)&;;B`E9^xIHy9J1%TL^Hy*^Jecg@i?ZgCx z_|bty`M8ncwOL`EI)S$=kMdM+xQ^3~<3VO94x9&c=R7c-04c=K;z1ISLvlPQm>F<9 zI8Mi2C!9m*9|9YMaY2v?1bOHLKU*`4JHVCQ-UYPQ&)UMu#c5NrwDgnNMVzX)r2W@i zX$z5lEnn?y`USyBAev|o1hljcV|>!8@gUd{9KABx)<-)~{NJ{ORQDl3sX&BWN8>Qi zCoTWDR2%e4P21Cb;vCe^R>6wbwL!~0_om2|*7X~YcG8IFe@N750t=tsOv>UxUj&!n z)7l@+6(p}S1Tg-h>}qX*;71q3p5j&#j@pwA_j)oB2+yyZL)m7?D5RXBTc4L9d!$%u z%*~(6kSWT*z~B9q5|{_lcD$~<`l#WI2T@dq<3aaqx{v1}6!zd~Vy^%kjk_ki8RcE8 zq%(=RfmXy4)ja%Vsza~`xfdj%=_`fC(UYkRA6oA>bDRA2$g>LYS zd-`T26>Xc6t5Q=_3w(TTFt*ztrI$ql#Kx_ElgF962}BRWEL`y*Vw^##+{Rw#;f)gb z7G#0rjC5;1MeKDNC9R-;*38>Kqg;-ky>nZ~5f71Ly*P=UtLezEhf)N@MjT+EW59%x zI?m)v#wMW47jfk!y8vWTnlAm){n8JBPKobQ&RHT;*(NdDHD)pZFbAPBUHwbNVF){ziSc@s_(@&^Zib{=!PCSbl#x6{ z?yJy3Df(tc+Sy0x?||`^@Oz3wGgYUEDQqqDT)jn4+Lo>#pH^f`qonkNF(3h8O#L^> zx&MKI@gLUY67KmQ*C`YFgwQ7h1_%rg7$7h}V1U2?fdK*o1O^BU5E%HEGeD$9KX#4X z#PBt!`9^t_;CD^G9?mGcl*D+aP+(~bx9@JwZK9Xmhm@IZ-m&?Q>?D?$6bDPD%ohVZ z^sy1IEVGkjxm7(j@E}L={INkUxnBFZRF2TJx^}VKovsdueka(Hc@?5AJuuuVU8F?+ z)(NT^9_=GktFBX1^@#XIR>V%0x~^z{&K%f`XIy5C*ALpmor@2d-s+%*7eITvB zpYHuGmNVThZF?OxpyMu{(;iuq964~A?xT4|~ zhC_}vb~LEuUUVF=g7aSOU)cqF7FLI&v2tsX4|TaRd=+K}b8;aQm&q|+718fT%320h zn+35?mRQ>nEu#kQw{~&&q9Di}=pJpZRwH~zKnF_=OlZ-zp9*t~)vaB50j&D#`JIO- z;#>MR^S%_pHe062iru@$i-?oDG1S~ysZwr(K14U165c!0H@XET%z)3ze-UFyrAFKo zdiD90jCI;b6kj)3agMVUaDVWs05}-V&3 z>UdQiSvE@KA@ua~H;C4%XKqZ5z>22^b^8&Qz_qqy3L{;HrhTUN*d0Y=_R;v=gD2s}^MxP6dtXgqsUE1A_Y2wE=X_tn z2v5H&IxvVHp~mQ?Y!Gs!Fa(9J`&+vk>SzD(wneQXKw9#E*T9|}_IJh=kVADj&i zxmL!k;tBOf&Ti*sA!48-4r&!jQAHl`14S}qgW;_(KjVvg`hB}1H**xvF5^KXZtFQ^ z+K37d_(q80V()ftv;eIW-Wj}2t>*hGaowfA%No_y1Jpyt!|NXa<- zg=g6nx0xz%V>xW7kSyQ{YnjATJjglAE7nWkyNeA@S^q`@J~Tc@0?QE7uytm=xWDfBinR5W(U`Q; z6the<1vuC>GGmrY8E3L{!{Qm=PO=Oc^ZKAboJd4w7TfN{G6Apg4>J!{W7wRhr@KXNy}i-^!oszpm$ewyyI zQOCjK9Q)HV5Ya&ysV*m0W&|Q}ww6>9n!)X;eQ*x2XCDtjv@dMxw8F5YiQ6{s zZ+wkiM!TQ z{WT7?0%e2^WJWyCI1>5nUG|e`&aSe#S2ZZ6?^3*S@%s7A2;2(BcUPi6Y)XTG;=s>EHvDPmRmg0&U zfW68HYzfv;Z-FB2nPnuLB$z`!Z2PvR$^9=fbF)s*s8m)p3OoI`tG+d7Xv>9t z?Tk80I%)7oSYWgzv>e7Gsdlw&iCmbpa#wA8es@A-dGuO|il2#28*WjYBP33)UxQPx zO*0e~UVHxKfb`Dk+U~cf=UXHU6cd=B-2H7@qwS6&k|b8Fxvw&lSO-$`XXMAN2gteK zym;6UAQ_CvXBmZeROp>t%Fs_qS$jv>-m=k*qgf*x%&}gPixBNp=VMVsxpRE+yuaDP zhI?MmE7KPbiF;X6H-6iu)zO8a?^`Ia3T411pwjRa_uRK$)}7g)2v`3J!!at!P3?NO zg)GKugB3xo@?8!_tfW|9qrgI0Z1&~PF(uwMmWF28bC+!MuHT>jjs}*Mh-t9vex8QV z+|4iV*?n0dHAZ)af~0vuPkqU{=2WTSB~Iv&07bUAWbONS#eRf!jbjd zy+J{`VGyr1%LXudrxa*cTBy}YI~WvDo~)sqF~QC6;C~qG%b3;sivBTX_pen{{Bh(i zAob{1qIye)7k(M%rj#(J)foRL+txXTuW}ERwWZ)O!k?XF^2Gw5(D~=oDG5xTo>+Pz zSFd3Cge0BEcSBU2$z3)7N4D8X#XC9=LPLk&N}>nfi+praUr8g)qf+ZrkawU6eAgqA z$Zl%*I+Is6x90KI$^Lo^F3ijjvqurb=j}C!X3dm1?ZvT`f-Ahj9A{<5iG941=e(Hr zHZQsqYcag--CH=#3p*aa`^-qbEMdjr-qXOcoqspjzX?D<+M|sz|*Qt4fLdlh7f_MV_kc>s-NdXGpgfHk-Lwxrkv=zK zhf9HM55v(aak_FIVc%0+ED)(eZBEmZ!7T z7|&lrHQG3986q~!x8l0EbO&;3u|YBN;>Hd8nsZ1Z-21c)WHe%_=19OA1$m0=+Sp8|8rI(Y480AyXZ&w%+~dTnjB10)NTrBr=DX^iQ;pQrJ~OD=T5WkQ7sqy9w4= zPmA9w2Jla=<=D-f)P9I)gJFAdjIi2o7TuN5)I+p`#!`)Vg%$LG3dQKe=JRMz+t+S1Ywn&0ar=*?6t)+IehT~6-YxG&$}^hV^R#qvt775aO?+B@^O&AOr?%|_J5TKH|f zdZ?cruZ3oEUKNrdaS}P~kIW6Pt>&oExi89ff2x(Fk~1v+>HcCVx=)UFrtD+x<=7l# za7UcOz@QS{ye^^?NmdHjKreYLdKFLW(y<0VAe!G86JefB1IIZ?h(;+?=D&Sry*^hS zuwBG@ra@6R9)-1t+}cmVM&)X0Q@=Z~49E8Vz?9=?6JyilR;5qoU2w4~Bz+yww%tP2 zUSLhW-iIEbbQ^qMhzG4xQ9YqCc?9)<`|I@z%oXad2-oTSIO&L%@&2sbGhG?E_ucrU zkE>Q`Cz&vl+aO=sa1}1W<|W)s<1}1y45zkIj+}W}%^00JbR2dTA{$O z_eyWq=;u|mq+`NI8U&;1qFSHdoqg587q~2tcaoA#E^^x@#=!5MA_sjd(Vzsf4ai-9 zn1dj@p>gh(84PKg_al@U7M958z_pRrvNKAD=oiZsU*}pUJ};sO{`R#gKw9ru9uC?7 zL-H|K|B#Jxi_CoSSI3&mlR9H!P8S&5jfIqJJh9E|D0M4%pyOxZdLQ)jdt%9L+Tc#K z@?0L5jm?$5l3djNU73Jf7F&CBk@6s3tV~*!eZ>0ROHWrXKh|I%3Y>vNQ%TfAd3430 zR{P@83!}p4TAHYG&)(WX8jCh+eUWlo*@K^$)RQjIY2sqBz8}#FuPd27RKZXrrOdBI z?S6T=-gMr#t0r#>@+sH1A)d{ONqwN#tRmF;BFi-aBqB#a^PBy?!@=nfd3EEQx7!_E zwEB1fk@;o7BxMWzGRchp2rd-jkwHp_rBa;NZi|`7;;c3_2bAlaTpjqHh=%bL9z>(9 zrwujLtBJm>EaEJ zxbxd;V`v|2K)IB+B^>07m4%N2g$ZF0`qPpPk3hpzT5dlqx%8I z`k>xlFvj(^nBQO4Vp2CEmAS6pbd)K?w(>+~dh^M)-h1QxQY*-l7vJ*G!})P(UG7J{ zanD=4IzDN`akLvzB{&HiLAMQU=#l^|19f6$;%;QE?JF_~t>7G#6C}mHX4Eb3^8(aN zXA`;m8DmkfmG<7ax>N_E^rEK(osl1m=sG&;Yt~3D%X`(gdmtS=%p_MHORMigc|P}$ zmM^&e%%JCN`+4Re^R6owuAaV2Hlgwz^7Iu1Y(51b2YUzX9|d=mv-hd7w7p&_f|KNi zC%3zmwDZ8MsaqQDzB_hSiOO!#w)e>kU>b*?8A)eFVLTz4d&0`X)E6=%NCew^ugrnJ z2MvB+jTfjYFLNn8q^$ZD%W-=G>amaE2#e6{zjW)UA)|bfiof=gR@T>vl#j4hD|^jF z-%b8^F$;p1?zSF8OVfKL^-g4Jx+Fa>j5E5_(?T?V!(aspS=LQT)0N6LJ2$q*ti8N@ zbMSxQZT>i0aoXUbtGUS>Gj-bi`n9Y#8OPW&{o za~iR@u4A8`bXGrN4^FK2hY^15c!Y=Ut)p;il{HijUuy*Vr){3Lkl}n)TnZW}ll%$` zMy$t=$2QL%GWUdny;`ImPZ2}TM9)`5*V%}6u$7vW6L8)L5NE!((X zCbGAz_y!3ed+HSj#X8KYJ1jP<Q{x>y5BsHKI$J_d6tzwrXp5&@KoM zD$&D6W>G6YE#V+_X#n!3u!!iLMJYM1(sL_J`x?C!PZS@XVni|*MdU2|%JipxyKtCz zC(UcTtcfgbRtHhnd3Zt_Sc}&TXgu{Yo6FFqe&;-K(XjNv*d{&fhKx|K^_TFm*iyfPSIM}{BZpe4C-Z$3M*{H}LY48HtiJMEp#x+78A zh}^(ZI(?jw3ESjXv~q^BUB=qZ-1{{ge(5Cz}OSd~s)}Uh^?#X!Z*rUbC0`f>qa8 z(hIj2@@%|?-p)fub<%dh(^~s_=PYkrwO*euVM9eNDq&#DK+b~4U-#y_INhJ#z1;5o zBXDKp36(7#GyutQg$3+UC#(<|Ue7T(naGxoRN2d_CaH{Ja?#?TKC?6$ReY}rk_x%J zBylA%?kpM0g4Syybe8F%20wL@Mi`pMvQtpz<+u*TnY1e*ja4BXFN?;Bn7*^yQ)m$9 zvz&nt$848xRx_`NCY1HYl|5K!6o-)^5sO*|2`={BzNVCp*85TRT1|Jhg{9HHfg9D# z%STtr`n2s9TY`?xDz3s>zG0kGKM6E#80tl?%SiSk$j};ACuF84DQ{XD3{bY?dL1Fr zkQ^!V%D#y5fY{q1j^JX88dLQ)r>p`TiL1>LQB)io7QHVxuUB=zn{A=cPj^Fw~Z^fF{ddExJ@i^aMA}-kltl_b1RAApN`7;gx=mZZ zdHl}Zx9FK0N6jqkXy2zAnnQ`txY>%r+e%^{!Rf{sXob*$vZj$vrVER>YDJt+QM=2` zeH>e~>~iC_1+Xnesuz=J+q zFTr}iuqU%Rv;VwlHiQ9n52iPm@{<4b;ib3dB&brQIT|g7DrNDYYZD20khW%}Qxe(M z*9S=tSOa~t&T)*~PCgJXoN-2tV=%xMbM*@Kp}r6*KN7Cjz1}R|#R*byTGQe5# z={int9?}7(HF^WyQFXd;a))CKS_wy=OVdMjQIG9p0+I7m;_vJHB^Y~mfe46tW!Rnp zdg`o?I?i#`ive&>Z4?3GICNz_kGCyDko`5$xnhC{UZu6moE%mO&l-hJpP)uIDz55^ z+KcMwD7;$a;)sGM+v_$bm%<-@d*$NpaGa&ar7gdZPwdH^riMocG+%3Ia>VvGl*9aNRcL~QywLid>7P+jeQ%xI6 z>gG+=9MW1z02!4MVs-+NFj98CQ^SkZK+|C{E}hePPfg=o{BhD;4{#MVySd@t-Nx?D zDDY0#+IVgiFjKIcgh~c397Dr$5uiY4@^HY|d^w|6>4n=y-gL0w^YHdKX5nqvT^1j& zs$jc8I2E@Fm$55j($TjJmBS!BNUr|t_LKZHP^eBpBg99k(yJ2oeNf7DoBB&tKDv?% zONAN~Nz;YbZun)i=qps)Ynfog7_x6_$2R>Sq$%o0cnZ>RjtJS}GX5_c7RQ@l{7w`~HgPL0u z53KRgS?xf}g&}ao#;ON8^34twpDbA>ZEvk9m2wkJ#lkHIg}08L>|`(YF?pH6BK@(U zgS(KHoYiapF0j4ZKiZ|UVV9zxWMTUlB z%q?svP=P%w9Pe^yWU2l2CfT0auWC+i0YiQT*nt`j#s-6beq+)84yT6oKxB+)Yo#EA zB6m|SzHBK+vRtdw+!&GPXwFHY3uC)E>F1W_FDA=eT>vXMyzo$_xyDIyv&&6`YZfcm z)OW4#yqD}CaQ{k3J@i)RnXwzwS6M#y*mOi^j_P{D*>~=3h@3y9)-9HX=b6Q>l@)!2 z!e2?bRB3+ev*BMBYn6|_YB*>%g_U`rLz{ji&%f3+BKm&PKe99OTV)svc39&TrV)~3 zUovrKz|z~;+xndI>p7ebRIb8wn^@`1$#Nft&=m=3NEA55px7NDI4rEgqdy5^PEj&nR z$B{mpsrvb#9o0UNe>Vr-lI`)JcfZvl{pPfP*y5NSByawi3U=I-IY{J#2c#FXF718* z<~*GbnXthXLq)=8E+#GLj4m%taz1FY#dR;Ep(4v3d?qo9ZxeW@PqW7>yBnFpzaZvy z^)n`llQPD1CG0sOLHkVpQ#?|T33dA=-wfJ3j2AE}buIy#Y;}iU7u?6>BJlv$W>D$# zt9%#~`&E1gX&^wRA-{;=evb>XTSZ^Rqql)nHkWrN&jHhW4e8K9XPo1bE(IU~btkcl zfD8+E-Fyd~GXO*jkYi3{HUVQ6VC_cbbM?H70U2?$4zMj`@)<7ThfAVU={DCcb=)^g zu+%JCw*$&L!eKfBL%QEuF6 zh77XyhGMpP8tgkTM2aKyEM&kO@(2&wH($){OvIb1$-*_8*qA_)OI=^6sW$s0!P#3i2%vfUi8+i zEE+kWI5i0|&6pV}S?{vaUJeqU-#2 zW;@cL?Rki-@QtuQj<2Q#OWj<>e#UfDoD}d}UJHb^sm13EQ~M|&XpteDXVepC+HE=H z@JH=YA6lqfY5j}#plx`AO0j!75;@^qTo&jcxKFHhkv^3$%wld+-%a5G||QoSna(Yw)?PD(W=xw`JUGbIVM1`Sih3*2(Gt90!c zVA;tt0yfH!VaxHLwW3*jp)glQ2NO1Ap0QHJed2*pFlwEy=G$GDDnM=cinB~FV!XMb zt8+j$Lk{hdV91<#1sd4U%aMihc=M7ke`$~lb~JDCaXSqYtN{hk?mB7P10;w4P##%H zo%0}dQr^mL`f6DtgA-EjZ0|eX*{LRI}w!tNVtwR}zNfbDx-S=JM;JhNMHo?10_d z3nE?u-NTrN(XVb>Dq%G*j-nZX$FQ;&3{@QH_sb4mxY_z}_6%8G&Ghr~h-HlVl4iW9 zlp{{KTmNh6Tl6rAZHHX>&F_?hEUQ?K54q*`DllHa-J<>P@2B}MbmCvq#o}7EA}!`I z4{iCV3P;mrX^>YOY<4H|D`lplP0PY|I*Ei9`xO;yOS3pegC&-^t&CsJ>%M`q ztZT`KdeobHN2UvO6``4{eFZX5r_P}KIk`Og+<~k@8V|M@^SQL`gx&-ylfUve0zpj z=!)`l(OE3B?H!3P#E3;$OWEYR%dqgYA20kD;!0|cvU-s?wX*5=(bgDYW6tmX!zFB` zDzBkefgFv&GDq@yWf4ydgASFjmoQHhXLUWv1(iG3!h+oT{_J(NW{rsVIf*o+^bPOK zeBiU97s@@%Y6#lXV}v&43t}CBxw+>$h=5A9)Rl71NI=NMv?W_VK1(%F>V`OdiSGFq zN!@0^q`m}Lwdg5$OQm%cmF#wWgmJQ_mi*#j=)?3O7|Rt;bK9pM6U(0R`2gb#)?Bli z1Qpo>6PX7{#Gvg6`>=1)>QI zzBf^I<{s0Iq#G4)*qnFT^)DBhDaYP>jv^_5Od0X3OW7hejcR``i zPBK(;BGHTV}Y}iNK8IaLjD_~?p7Q&*d2u5$FF(N*mEdh<@ zG}f?tVY-_qp5pf==~A2bNw>~7MXG&!LLa~Kje67g)-X}c0Fep-?Op-VoEzKLR$z+| za*8-v_q*;CbRODVKd~>Yub_OO7Po5XitkcP#B0LyzA6n90XBrRsTXa zIr5wHp?uzy3?xN|`TEuvTf5dLVz+EI$d~LS&1|(42ER6&lPGg{vzo$9L!Ph7SA*Y@ zcdE0LFnaNO-0Oe(;9?YmaVy1jg#Hjz@4Hf#3yz0DDy6oeli48&(# z=zQgUMd?`0x~=;;b17U?%XPxyTWHxGp)2U#914+qGh!k0n~CLb-7mcbo`zO05OD|` z4Ac8l@+ympZj5otv!(sW0#}@olAl#ZD7>STBl@CNMzZ$0vkCp)jj~r;A5Cv`g)UW- z^eeB*9TAso<`lekPY?rt-#%1_1c~w4(yqls#44~}i0jEb^U->d*+0iF(m8xc=X!hL zTj8g3cXE#&Z)215GtGJUFC4fu&O!W@(0v`T%boG34v0Il^0%OGO=I@CvR+n{7U1S>j@R2j-QcAjj`$F%ifpk^0%&ARz_oLou!!2T*|rCUWNWrhqy zrU;QtO*7JFI@bfS7mnmqY}?C+gE7(z!n6prD}j+aJ2SZD4QnG_xy9?S!{w*yduHxJ zL+97+Sv7ORmU51=(jQT-)%l_aVdj?|2cqq|bZWax#V!chymAj*5)+)g)T6H@+B9PE z)Js~gGJayFd~e&yTg=s>fw;WVDip23uO>&Coa>jrfL0Ii%+}^~>ME}FGJ8~e^8nIQ z<k}{wAYEA z+#KbZ{prj65%(Lj?>uwtfJB&JBr8L#o{aR9bCDQTi(W*4KY-(2npZ=-4PWjxMbC** z7}F_jkg1?%O4!rakuOv6wL%)&;x5XpZ>MAnZj^5ev;b#^+I+Hd#GbcaZTI3qVKu;-K-RNS@upkkUfH6MwrY+Rt^CXqU znN+%=*EjRh%ELG1<~xhsHH>F&(+%q_^^80_tTsyKxTvk~2A_vDmTE54sn}MgR2(Nd zD}QT+QdGjVZpDkqH&xPlF~`n;y*2vDX(hghtvCB!C?D2}K*5j~hRg;&w6F)ArHEM_Sdas~ zfcRZ@&RJ3mgGa&Ag6u0~H76<$)FTIUG-oU>)RK8Fm%a$vky(sc<=10=m+(m7(RfP` z#q1pXz#mDoQtQ!@EHPzzZfUzrMqORSC;N_+Zuj2j98I*4Rd?|Q!yNG&=H$U7I5o;{ zjx=oLB4n?JB^1a}Guv3s6su)5p30IaMXz)id+JG*baq0zcF#7`oRcoNDzxcjB2PNf zgbv(M=~RTAJU4Dp;Cu7@cmIP|8BNS{2Lhp*`pY7=gRi9CGnC|4`>a4}sQsBy>$)ZB z!;*PR%XBXcJ|b?F6iecsV^$FyeIAtdTnK+!BeHW%-AT-|zF6DmGqXmiCHES(bH8wU zNOUFCN3pd$6}`QEyq0gisMlpt>Bywqs=t6K6PVxdX4XPe)t1HdQl8bcXge?PtAm<* z9F(d$4obP6Im=QSJev5GZ8!Jm*>+@vXVUlxkm5V6QO)@VDO4or;dSQ;K^Rx)-&o!*- z-`FtdjN;5*4fXZ0hzw%QY%XNUK|wPU`O!u>K8x+|#XBVQ4?$3o&y5pI@heIh!;MB( z2`0hPicEB8F}A2vQ!^3M5yk<-tPdiLg{}-bC%fSIE;nS>|3EN17+%53*wjYI*#}{h zK~s;eOa-0S@%O2Ohz)M9Xq@NOYG`wRD_CM6?yo%v1Q982znzn?(7C78pCDQjX(6h* zjf~~_X4YM}6CbjoMuvo>u&ZS#*)`rJf}a!M4{6~NVBnRjl?AOOr7b`s)KIp#0wuHz z9#o(~@8~GL-WDZzf&Ti3`A>tA)09q~4=w7P7rgdvjK7bM?%d6cV7ttH`c<(X>>YH6 z0Wc2o^nr+VIn3EJ&F=66*~01gH_?Z%V`aEB z!4G(T>YKl~y?i|zECu~J+{T?zG%f4i;jis=pzkoxQ_W)-_akx6G4r;7W_;o4nRU4< zJnP~IKEFKEpS&#ErJAjnWyr9eX&cTov;eC|KMK?2dHS);(mUSqST=RaZ*gZvX=)5H z`NOSZiTnPj18@I92bTX)2j2RV4lH(#x_If2hT<8H>RvIZDW`c%kRnOdIO#7saFB7i zBld7A&z9Ly2j+|6v*lXTjF?kkJkQjf6?DlO!R(vkFu4`xV&fdQpDyS)KF>7SDiEE4 z!u7Bk^(L4lukBE#L(Zn{C90YCY3B#O&Yz7_CMaa$MMgBI=== zutmkn%F>#0_s`L1!pfQrmFj<7mlh{JVd17)70XG!4?Yg3Q~===GMw71a$9$o}o?p)aM6i4Y+XJFwthg3+MshzRgJO9Eto`0+FKm}?xEN$fZMd5N#ct{YL zmryQ=PqGg=OS-_svIOK^W4?Ll9a}`)xh9D@Ck%%XDyq&NERg%f1o<)qs`TuBil%&| zQYoX}TQLFK%n2E>ZQf@IXWHtRO}`@1gElicYW!6fEbmZvqzXkBMdv=#; z)zRKQkUJKQSqWQJmp`ED?w7*2oD0O2pLIYZZ{-|>IDCF2H@s06 zj#5+2^xaV0qdirmr4|0PtRQhYBiZcfFbAm-y%W>Wj^g27p3qNDzxk3bPY6fWYMk1f z85{do>9SL#8)RZ*of|NzAB$L9RdZU&~o3RPx%Yi9H)5V9_yMy2Bpx;qK-kCk#rM^X+;it zTcIwd5~d?uyMq$4ojdKOE4q;Uw|8|U*h-@cghqVP@Scw=ed%SY&L@C%w56EOqE{rt zZ9l>!gQz;$c5+G6s;b~mE5cS5?(dW}vmH{I`;@ak2s?EJ$iedRU$yk@#3QbSvhY?P zwutSx^pp?@pF%)tQJK5>_1upPYfQ%UJn~bM$zVHFM%h1o|9CJbchTUg&W|SgsSNNy z)mc6IC8dT+-Ah8#>UWzlh}~Sb{##NbJf)wo)*H8}P{wcA%pTRBJA2qjgb{}Lxn8$K zy|2HpTB2Y4X?+&hn}JK4$j_KwE|t+4I{xEww!f$BAV3a~zwa-JX8 z)37bEN7y_r)8bO^nJ*}2j~Hcsy^DUj-$h|nsPJUP_KZ5;1{?j$7H=e5ikpK4)mt&1 z-E&ff&)JSPpbfzfJ&Y5`ORyC<;`w4|gslYIwy1^m*Lyikv8Go9H6+q79DYY~>+BrY zoP`gKT^C%9tUA`716u%MjA=A%C4Wb$dXG1q5Dr2g5EvjZKwyBt0D%Dl0|W*L3=kL~ zFhF2{zyN^(0s{mF2n-MyATU5+fWQEO0RjUA1_%rg7$7h}V1U2?fdK*o1O^BU5EvjZ QKwyBt!2eYS$neAe50kDHfB*mh literal 0 HcmV?d00001 From 379c99c6da1bae70e9e4e2143a48e242c1a14505 Mon Sep 17 00:00:00 2001 From: HakRimLee Date: Mon, 17 Oct 2022 16:05:55 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=EC=B2=AB=EC=A0=9C=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...synchronous_programming_in_dart_flutter.md | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md index 15a90ca61c..695925417b 100644 --- a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md +++ b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md @@ -3,15 +3,18 @@ layout: post title: "Dart/Flutter에서 비동기처리하기" authors: [hfjxjjd123] tags: ["Dart","Flutter","asynchronous","다트","플러터"] -; image: assets/images/post-WebSocket/websocket.png +image: assets/images/post-asyncDart/asynchronous.jpg description: "Dart/Flutter에서 비동기처리하기" featured: true --- ---- + ## 비동기처리(asynchronous programming)란?
+ ![image](../assets/images/post-asyncDart/asynchronous.jpg) + + 비동기처리는 대기를 필요로하는 작업을 기다리면서도 프로세스가 다른 작업을 수행할 수 있도록 작업하는 방식을 말한다. 따라서 프로세스가 외부에 요청을 던지는 작업을 할 때, 그 요청에 대한 결과값을 반환하기 위해 프로세스가 멈춰서 기다리는 일이 없기 때문에, 버리는 시간 없이 효율적으로 작업을 처리할 수 있게된다. @@ -27,6 +30,8 @@ featured: true
Dart언어에서는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. + +

## Stream이란? @@ -61,6 +66,8 @@ await for (final value in stream) { //await for 이렇게 한 이벤트는 한 번 사용하고 버리는 것을 단일구독스트림라고 한다. 하나의 이벤트에 여러번 접근해서 값을 사용하고 싶다면 브로드캐스트스트림 형식을 사용하면 된다. + +

## Future란? @@ -78,6 +85,9 @@ Flutter에서 데이터베이스를 다룰 때 주로 `Future`를 사용하므 참고로 `getString1()` / `getString3()`은 각각 1초, 3초 기다렸다 `String` 값을 의미적으로 받아오는 `Future` 타입의 함수이다. +
+ + ### 1. `then` 키워드 쓰임새 ```dart import 'dart:async'; @@ -98,6 +108,8 @@ void main() async{ ``` `getString3()`이 먼저 호출됐지만 비동기적 연산을 하므로`getString1()`의 호출도 즉시 이뤄진다. 이후 `then` 키워드를 통해 비동기연산의 결과(필요한 데이터)를 받아오는데, 1초 후 `getString1()`의 결과값이 먼저(`연산1`) 연산되며 이후 2초가 더 지난 뒤 `getString3()`의 결과값(`연산3`)이 처리되므로 `연산1`이 먼저 출력된 후 `연산3`이 출력된다. +
+ ### 2. `await` 키워드 쓰임새 ```dart import 'dart:async'; @@ -122,6 +134,8 @@ void main() async{ `getString3()`이 먼저 호출됐으며, `await`라는 키워드로 `getString3()`의 결과값이 반환될 때 까지 프로세스는 기다린 후 그 결과값을 반환한다. 3초 후 `getString3()`이 반환되고 나서 `getString1()`이 호출되며 마찬가지로 결과값이 반환될 때 까지 프로세스가 기다린 후 그 결과값을 반환하게 되므로 `연산3`이 먼저 출력된 후에 `연산1`이 출력되게 된다. +
+ ### 3. `await`의 필요성 `await`는 얼핏보면 동기적 처리 성격을 가지고 있어서 일반적인 동기처리 방식으로 해결하면 되지 않나 하는 생각이 들 수 있지만 `await`는 연쇄적으로 `async`함수 , `Future`를 받아오는 상황에서 유용하게 쓰일 수 있다. @@ -139,6 +153,8 @@ onTap:() async{ 하지만 `getAllModel`을 통해 받아온 데이터 모델들은 아직 데이터값으로 반환할 필요가 없기 때문에 `await` 사용 없이 `Future` 자료형인 채로 그대로 다음 메소드의 인자로 전달하여 처리를 미룰 수 있게 된다. 이렇게 `await`는 필요한 순간에 데이터값을 반환하거나 완료를 기다릴 수 있도록 해주기 때문에 비동기처리에서 데이터를 다룰 때 유용하게 사용된다. + +

## 비동기처리 in Flutter @@ -152,6 +168,8 @@ Flutter에서의 쓰임을 얘기하기 전에 간단하게 생소하실 Flutter 기본적으로 `FutureBuilder` , `StreamBuilder` 모두 `AsyncSnapshot`이라는 객체를 추가적으로 다룬다. +
+ ### `AsyncSnapshot`이란? 비동기처리의 상태를 알 수 있게 해주는 객체이다. @@ -168,6 +186,7 @@ Flutter에서의 쓰임을 얘기하기 전에 간단하게 생소하실 Flutter `snapshot.hasError`라는 필드를 통해선 반환값이 에러인지 확인가능하고, `snapshot.data`필드를 통해 반환한 실제 데이터값을 얻어낼 수 있다. +
### `StreamBuilder`, `FutureBuilder` 사용법 From 84fdcd854992a7b0328c924305fa1b59a0cea2a2 Mon Sep 17 00:00:00 2001 From: HakRimLee Date: Fri, 28 Oct 2022 19:11:14 +0900 Subject: [PATCH 3/6] =?UTF-8?q?2022-10-28=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...synchronous_programming_in_dart_flutter.md | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md index 695925417b..75e3edf2f1 100644 --- a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md +++ b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md @@ -28,21 +28,14 @@ featured: true - 파일로부터 데이터를 읽어올 때
- -Dart언어에서는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. - -

-## Stream이란? -
-다른 환경에서도 많이 사용해서 다소 익숙한 비동기처리 개념 중 하나인 Stream은 Flutter에선 비동기식 이벤트(값)의 연속된 소스를 의미한다. +Dart언어에서는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. `Stream`도 그렇고 `Future`도 그렇고 비동기처리의 개념은 주로 외부에 사상/연산을 주고받고 하는 과정에서 사용되므로, 변수에 바로 `Stream`/`Future` 타입이 할당되기보단 외부작업을 맡기는 로직이 쓰이게 되는 함수 내에서 `Stream`/`Future` 객체의 개념을 요구하는 경우가 대부분이다. 따라서 `Stream`/`Future` 객체는 함수에서 반환되는 경우가 많으며, 이 때 함수가 정의될 때 함수의 body에서 비동기처리 방식이 사용된다는 것을 아래 코드와 같이 명시해줘야 한다. -```Stream``` 함수에는 `async*`, `Future` 함수에는 `async`라는 키워드를 통해서 함수 내에서 비동기처리방식이 쓰인다는 것을 명시할 수 있다. ```dart Stream function() async*{ ... @@ -52,8 +45,23 @@ Future function() async{ ... } ``` +위와 같이 다루는 타입에 따라서 `Stream` 함수엔 `async*`, `Future` 함수엔 `async`라는 서로 다른 키워드를 통해서 함수 내에서 비동기처리방식이 쓰인다는 것을 명시할 수 있다. + +다만 이 함수들의 반환형이 꼭 `Stream`, `Future`일 필요는 없다. `async*`/`async` 키워드는 함수의 body내에서 비동기처리가 있다는 것을 명시할 뿐 그 함수의 반환형에 대한 정보를 의미하는 것이 아니다. + +
+
+ +## Stream이란? +
+다른 환경에서도 많이 사용해서 다소 익숙한 비동기처리 개념 중 하나인 Stream은 Flutter에선 비동기식 이벤트(값)의 연속된 소스를 의미한다. + + + +
+ `Stream`으로 정의된 함수는 선언 즉시 `Stream` 객체를 반환하며, 그 후엔 `Stream`의 데이터에 접근해 사용할 때까지 아무 일도 일어나지 않는다. -이후 `listen()`/`await for` 키워드를 통해 `Stream`객체의 데이터에 접근할 수 있으며, 이 때 `async*` 함수가 동작하게 된다. +이후 `listen()`/`await for` 키워드를 통해 `Stream`객체의 데이터에 접근할 수 있으며, 이 때 `async*` 함수가 동작하게 된다. ```dart stream.listen((int x) => print(x)); //listen() @@ -62,7 +70,7 @@ await for (final value in stream) { //await for } ``` -일반적으로 `Stream` 객체의 데이터에 접근하는 과정에서 iterator의 개념이 사용되는데, 가장 최근에 올라온 이벤트들을 하나씩 처리하고 지워나가면서 `Stream` 안에 남은이벤트가 없어질 때 까지 이를 계속하게 된다. +일반적으로 `Stream` 객체의 데이터에 접근하는 과정에서 iterator의 개념이 사용되는데, 가장 최근에 올라온 이벤트들을 하나씩 처리하고 지워나가면서 `Stream` 안에 남은 이벤트가 없어질 때 까지 이를 계속하게 된다. 이렇게 한 이벤트는 한 번 사용하고 버리는 것을 단일구독스트림라고 한다. 하나의 이벤트에 여러번 접근해서 값을 사용하고 싶다면 브로드캐스트스트림 형식을 사용하면 된다. @@ -172,16 +180,18 @@ Flutter에서의 쓰임을 얘기하기 전에 간단하게 생소하실 Flutter ### `AsyncSnapshot`이란? -비동기처리의 상태를 알 수 있게 해주는 객체이다. +비동기처리의 상태를 알 수 있게 해주는 객체이며, 외부의 데이터를 받아 완료된 상태라면 받아 온 데이터를 조회할 수도 있다. + 앞서 얘기했지만 비동기처리는 다음과 같이 2가지 상태를 가질 수 있다. - 외부로부터 결과값을 받은 상태 - 외부로부터 결과값을 아직 받지 못한 상태
-이 때, `snapshot.hasData`라는 필드에 접근해서 비동기처리의 상태를 알아낼 수 있다. -`true` => 외부로부터 결과값 or Error값을 받아온 상태 -`false` => 외부로부터 결과값을 받지 못한 상태 +편의상 `snapshot`을 `AsyncSnapshot`의 객체라 할 때, `snapshot.hasData`라는 필드에 접근해서 비동기처리의 상태를 알아낼 수 있다. + +`snapshot.hasData == true` => 외부로부터 결과값 or Error값을 받아온 상태
+`snapshot.hasData == false` => 외부로부터 결과값을 받지 못한 상태 `snapshot.hasError`라는 필드를 통해선 반환값이 에러인지 확인가능하고, `snapshot.data`필드를 통해 반환한 실제 데이터값을 얻어낼 수 있다. @@ -205,7 +215,7 @@ FutureBuilder( } ) ``` -다음과 같이 위젯을 구성하며,빌더는 인자로 들어간 `stream`, `future`의 `AsyncSnapshot`을 받아온 후 `snapshot.hasData`의 결과에 따라서 +위젯의 기본 구성은 다음과 같으며,빌더는 인자로 들어간 `stream`, `future`의 `AsyncSnapshot`을 받아온 후 `snapshot.hasData`의 결과에 따라서 `true` 일때는 `Widget('Result')`를, `false`일 때는 `Widget('Waiting')`을 빌드한다는 것을 알 수 있다. From bd884462b33f51ae2d82cfcf9c99fd1f8e9c2925 Mon Sep 17 00:00:00 2001 From: HakRimLee Date: Thu, 10 Nov 2022 15:33:16 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=EB=9D=84=EC=96=B4=EC=93=B0=EA=B8=B0/?= =?UTF-8?q?=EB=A7=9E=EC=B6=A4=EB=B2=95/=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...synchronous_programming_in_dart_flutter.md | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md index 75e3edf2f1..ef1816866b 100644 --- a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md +++ b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md @@ -12,10 +12,7 @@ featured: true ## 비동기처리(asynchronous programming)란?
- ![image](../assets/images/post-asyncDart/asynchronous.jpg) - - -비동기처리는 대기를 필요로하는 작업을 기다리면서도 프로세스가 다른 작업을 수행할 수 있도록 작업하는 방식을 말한다. +비동기처리는 대기를 필요로 하는 작업을 기다리면서도 프로세스가 다른 작업을 수행할 수 있도록 작업하는 방식을 말한다. 따라서 프로세스가 외부에 요청을 던지는 작업을 할 때, 그 요청에 대한 결과값을 반환하기 위해 프로세스가 멈춰서 기다리는 일이 없기 때문에, 버리는 시간 없이 효율적으로 작업을 처리할 수 있게된다.
@@ -30,11 +27,11 @@ featured: true

-Dart언어에서는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. +Dart언어는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. -`Stream`도 그렇고 `Future`도 그렇고 비동기처리의 개념은 주로 외부에 사상/연산을 주고받고 하는 과정에서 사용되므로, 변수에 바로 `Stream`/`Future` 타입이 할당되기보단 외부작업을 맡기는 로직이 쓰이게 되는 함수 내에서 `Stream`/`Future` 객체의 개념을 요구하는 경우가 대부분이다. +`Stream`도 그렇고 `Future`도 그렇고 비동기처리 개념은 주로 외부에 사상/연산을 주고받고 하는 과정에서 사용되므로, 변수에 바로 `Stream`/`Future` 타입이 할당되기보단 외부작업을 맡기는 로직이 쓰이는 함수 내에서 `Stream`/`Future` 객체의 개념을 요구하는 경우가 대부분이다. -따라서 `Stream`/`Future` 객체는 함수에서 반환되는 경우가 많으며, 이 때 함수가 정의될 때 함수의 body에서 비동기처리 방식이 사용된다는 것을 아래 코드와 같이 명시해줘야 한다. +따라서 `Stream`/`Future` 객체는 함수에서 반환되는 경우가 많으며, 함수가 정의될 때 함수의 body에서 비동기처리 방식이 사용된다는 것을 아래 코드와 같이 명시해줘야 한다. ```dart Stream function() async*{ @@ -45,22 +42,22 @@ Future function() async{ ... } ``` -위와 같이 다루는 타입에 따라서 `Stream` 함수엔 `async*`, `Future` 함수엔 `async`라는 서로 다른 키워드를 통해서 함수 내에서 비동기처리방식이 쓰인다는 것을 명시할 수 있다. +위와 같이 `Stream`을 다루는 함수엔 `async*`, `Future`를 다루는 함수엔 `async`라는 서로 다른 키워드를 통해서 함수 내에서 비동기처리방식이 쓰인다는 것을 명시할 수 있다. -다만 이 함수들의 반환형이 꼭 `Stream`, `Future`일 필요는 없다. `async*`/`async` 키워드는 함수의 body내에서 비동기처리가 있다는 것을 명시할 뿐 그 함수의 반환형에 대한 정보를 의미하는 것이 아니다. +다만 이 함수들의 반환형이 꼭 `Stream`, `Future`일 필요는 없다. `async*`/`async` 키워드는 함수의 body 안에 비동기작업이 있다는 것을 명시할 뿐 그 함수의 반환형에 대한 정보를 의미하는 것은 아니다.

## Stream이란?
-다른 환경에서도 많이 사용해서 다소 익숙한 비동기처리 개념 중 하나인 Stream은 Flutter에선 비동기식 이벤트(값)의 연속된 소스를 의미한다. +다른 환경에서도 많이 사용해서 다소 익숙한 비동기처리 개념 중 하나인 Stream은 Flutter에선 비동기적 이벤트(값)의 연속된 소스를 의미한다.
-`Stream`으로 정의된 함수는 선언 즉시 `Stream` 객체를 반환하며, 그 후엔 `Stream`의 데이터에 접근해 사용할 때까지 아무 일도 일어나지 않는다. +`Stream`으로 정의된 함수는 선언 즉시 `Stream` 객체를 반환하며, 그 후엔 `Stream`의 데이터에 접근해서 사용할 때까지 아무 일도 일어나지 않는다. 이후 `listen()`/`await for` 키워드를 통해 `Stream`객체의 데이터에 접근할 수 있으며, 이 때 `async*` 함수가 동작하게 된다. ```dart stream.listen((int x) => print(x)); //listen() @@ -70,10 +67,10 @@ await for (final value in stream) { //await for } ``` -일반적으로 `Stream` 객체의 데이터에 접근하는 과정에서 iterator의 개념이 사용되는데, 가장 최근에 올라온 이벤트들을 하나씩 처리하고 지워나가면서 `Stream` 안에 남은 이벤트가 없어질 때 까지 이를 계속하게 된다. -이렇게 한 이벤트는 한 번 사용하고 버리는 것을 단일구독스트림라고 한다. +일반적으로 `Stream` 객체의 데이터에 접근하는 과정에서 iterator의 개념이 사용되는데, 가장 최근에 올라온 이벤트들을 하나씩 처리하고 지워나가면서 `Stream` 안에 남은 이벤트가 없어질 때까지 이를 계속하게 된다. +이렇게 한 이벤트는 한 번 사용하고 버리는 것을 단일구독스트림이라고 한다. -하나의 이벤트에 여러번 접근해서 값을 사용하고 싶다면 브로드캐스트스트림 형식을 사용하면 된다. +하나의 이벤트에 여러 번 접근해서 값을 사용하고 싶다면 브로드캐스트스트림 형식을 사용하면 된다.

@@ -85,7 +82,7 @@ await for (final value in stream) { //await for - 외부로부터 결과값을 받은 상태(#1) - 외부로부터 결과값을 아직 받지 못한 상태(#2) -`Future` 타입을 가지는 객체는 비동기식 작업을 수행할 때 그 작업의 상태(#1, #2)에 상관없이 `Future`라는 객체타입을 반환한다. +`Future` 타입을 가지는 객체는 비동기식 작업을 수행할 때 그 작업의 상태(#1, #2)에 상관없이 `Future`라는 타입을 반환한다. 따라서 `Stream`과 마찬가지로 `Future`가 의미적으로 포함하는 실제 데이터값에 접근하기 위해선 특수 키워드들이 사용되는데, `Future`에선 `await`, `then`을 사용한다. @@ -114,7 +111,7 @@ void main() async{ getString1().then((String string){print(string);}); //getString1() 요청 후 계속.. ``` -`getString3()`이 먼저 호출됐지만 비동기적 연산을 하므로`getString1()`의 호출도 즉시 이뤄진다. 이후 `then` 키워드를 통해 비동기연산의 결과(필요한 데이터)를 받아오는데, 1초 후 `getString1()`의 결과값이 먼저(`연산1`) 연산되며 이후 2초가 더 지난 뒤 `getString3()`의 결과값(`연산3`)이 처리되므로 `연산1`이 먼저 출력된 후 `연산3`이 출력된다. +`getString3()`이 먼저 호출됐지만 비동기적 연산을 하므로`getString1()`의 호출도 즉시 이뤄진다. 이후 `then` 키워드를 통해서 비동기연산의 결과(필요한 데이터)를 받아오는데, 1초 후 `getString1()`의 결과값이 먼저(`연산1`) 연산되며 이후 2초가 더 지난 뒤 `getString3()`의 결과값(`연산3`)이 처리되므로 `연산1`이 먼저 출력된 후 `연산3`이 출력된다.
@@ -139,13 +136,13 @@ void main() async{ // 1초후 String 데이터값을 받아옴 } ``` -`getString3()`이 먼저 호출됐으며, `await`라는 키워드로 `getString3()`의 결과값이 반환될 때 까지 프로세스는 기다린 후 그 결과값을 반환한다. -3초 후 `getString3()`이 반환되고 나서 `getString1()`이 호출되며 마찬가지로 결과값이 반환될 때 까지 프로세스가 기다린 후 그 결과값을 반환하게 되므로 `연산3`이 먼저 출력된 후에 `연산1`이 출력되게 된다. +`getString3()`이 먼저 호출됐으며, `await`라는 키워드로 `getString3()`의 결과값이 반환될 때까지 프로세스는 기다린 후 그 결과값을 반환한다. +3초 후 `getString3()`이 반환되고 나서 `getString1()`이 호출되며 마찬가지로 결과값이 반환될 때까지 프로세스가 기다린 후 그 결과값을 반환하게 되므로 `연산3`이 먼저 출력된 후에 `연산1`이 출력된다.
### 3. `await`의 필요성 -`await`는 얼핏보면 동기적 처리 성격을 가지고 있어서 일반적인 동기처리 방식으로 해결하면 되지 않나 하는 생각이 들 수 있지만 `await`는 연쇄적으로 `async`함수 , `Future`를 받아오는 상황에서 유용하게 쓰일 수 있다. +`await`는 얼핏보면 동기 처리 성격을 가지고 있어서 일반적인 동기 처리 방식으로 해결하면 되지 않나 하는 생각이 들 수 있지만 `await`는 연쇄적으로 `async`함수 , `Future`를 받아오는 상황에서 유용하게 쓰일 수 있다. ```dart onTap:() async{ @@ -158,9 +155,9 @@ onTap:() async{ 그렇기 때문에 데이터베이스를 업데이트 해주는 `updateModel()`의 작업처리가 완료된 후 `getAllModel()` 메소드가 동작해야 하므로 `await`가 사용되어 `updateModel()`의 작업처리를 기다린 후 반환했다. -하지만 `getAllModel`을 통해 받아온 데이터 모델들은 아직 데이터값으로 반환할 필요가 없기 때문에 `await` 사용 없이 `Future` 자료형인 채로 그대로 다음 메소드의 인자로 전달하여 처리를 미룰 수 있게 된다. +하지만 `getAllModel`을 통해 받아온 데이터 모델들은 아직 데이터 값으로 반환할 필요가 없기 때문에 `await` 사용 없이 `Future` 자료형인 채로 그대로 다음 메소드의 인자로 전달하여 처리를 미룰 수 있게된다. -이렇게 `await`는 필요한 순간에 데이터값을 반환하거나 완료를 기다릴 수 있도록 해주기 때문에 비동기처리에서 데이터를 다룰 때 유용하게 사용된다. +이렇게 `await`는 필요한 순간에 데이터 값을 반환하거나 완료를 기다릴 수 있도록 해주기 때문에 비동기처리에서 데이터를 다룰 때 유용하게 사용된다.

@@ -170,17 +167,17 @@ onTap:() async{ 이제 Flutter에서 비동기처리방식, `Stream`과 `Future` 개념을 어떻게 사용하는지 알아보겠다. -Flutter에서의 쓰임을 얘기하기 전에 간단하게 생소하실 Flutter의 구성에 대해 설명하면, Flutter는 `Widget`이라는 기본단위로 구성되어있다. `Widget`은 Flutter에서 화면에 보여지는 모든 UI (View)의 기본단위로써 의미를 가진다. +Flutter에서의 쓰임을 얘기하기 전에 Flutter의 구성에 대해 간단하게 설명하면, Flutter는 `Widget`이라는 기본 단위로 구성되어있다. `Widget`은 Flutter에서 화면에 보여지는 모든 UI (View)의 기본 단위로써 의미를 가진다. `Widget`을 빌드할 때 사용될 정보가 데이터베이스에 있는 등의 상황에서, 비동기처리를 이용해 `Widget`을 렌더링 해야하는데, Flutter에선 이를 지원해주는 기본 빌더 `FutureBuilder`, `StreamBuilder`가 있다. -기본적으로 `FutureBuilder` , `StreamBuilder` 모두 `AsyncSnapshot`이라는 객체를 추가적으로 다룬다. +기본적으로 `FutureBuilder` , `StreamBuilder` 모두 `AsyncSnapshot`라는 객체를 추가적으로 다룬다.
### `AsyncSnapshot`이란? -비동기처리의 상태를 알 수 있게 해주는 객체이며, 외부의 데이터를 받아 완료된 상태라면 받아 온 데이터를 조회할 수도 있다. +비동기처리의 상태를 알 수 있게 해주는 객체이며, 비동기처리가 완료된 상태라면 데이터를 조회할 수도 있다. 앞서 얘기했지만 비동기처리는 다음과 같이 2가지 상태를 가질 수 있다. @@ -215,11 +212,11 @@ FutureBuilder( } ) ``` -위젯의 기본 구성은 다음과 같으며,빌더는 인자로 들어간 `stream`, `future`의 `AsyncSnapshot`을 받아온 후 `snapshot.hasData`의 결과에 따라서 -`true` 일때는 `Widget('Result')`를, +위젯의 기본 구성은 다음과 같으며,빌더는 인자로 들어간 `stream`, `future`의 `AsyncSnapshot`을 받아온 후 `snapshot.hasData`의 결과 상태에 따라서 +`true` 일 때는 `Widget('Result')`를, `false`일 때는 `Widget('Waiting')`을 빌드한다는 것을 알 수 있다. -위젯은 `stream`, `future`가 데이터값을 반환할 때까지, 즉 `snapshot.hasData != null` 일 때까지 계속해서 위젯을 리빌딩한다. +위젯은 `stream`, `future`가 데이터 값을 반환할 때까지, 즉 `snapshot.hasData != null` 일 때까지 계속해서 위젯을 리빌딩한다. 이를 통해서 Flutter에서 비동기적 방식으로 위젯을 빌드할 수 있는 것이다. From 0ee4288cba261a200094495a33ce37602a7a4f7a Mon Sep 17 00:00:00 2001 From: HakRimLee Date: Thu, 10 Nov 2022 16:17:05 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EB=B0=B0=EC=B9=98=20=EC=88=98=EC=A0=95=20#?= =?UTF-8?q?1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...synchronous_programming_in_dart_flutter.md | 78 ++++++++++++------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md index ef1816866b..bafd3e4e72 100644 --- a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md +++ b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md @@ -10,28 +10,32 @@ featured: true ## 비동기처리(asynchronous programming)란? -
- + --- +
비동기처리는 대기를 필요로 하는 작업을 기다리면서도 프로세스가 다른 작업을 수행할 수 있도록 작업하는 방식을 말한다. -따라서 프로세스가 외부에 요청을 던지는 작업을 할 때, 그 요청에 대한 결과값을 반환하기 위해 프로세스가 멈춰서 기다리는 일이 없기 때문에, 버리는 시간 없이 효율적으로 작업을 처리할 수 있게된다.
-비동기처리가 쓰이는 예시 +따라서 프로세스가 외부에 요청을 던지는 작업을 할 때, 그 요청의 결과값을 반환하기 위해 프로세스가 멈춰서 기다리는 일이 없기 때문에, 버리는 시간 없이 효율적으로 작업을 처리할 수 있게된다. + +
+ +※   비동기처리가 쓰이는 예시 - 네트워크에서 데이터를 받아올 때 - 데이터베이스에 데이터를 작성할 때 - 파일로부터 데이터를 읽어올 때 +

Dart언어는 `Stream``Future`, 2가지 종류로 비동기처리를 지원한다. -`Stream`도 그렇고 `Future`도 그렇고 비동기처리 개념은 주로 외부에 사상/연산을 주고받고 하는 과정에서 사용되므로, 변수에 바로 `Stream`/`Future` 타입이 할당되기보단 외부작업을 맡기는 로직이 쓰이는 함수 내에서 `Stream`/`Future` 객체의 개념을 요구하는 경우가 대부분이다. - -따라서 `Stream`/`Future` 객체는 함수에서 반환되는 경우가 많으며, 함수가 정의될 때 함수의 body에서 비동기처리 방식이 사용된다는 것을 아래 코드와 같이 명시해줘야 한다. +`Stream`, `Future`와 같은 비동기처리 개념은 주로 외부에 사상/연산을 주고받고 하는 과정에서 사용되므로, +변수에 바로 `Stream`/`Future` 타입이 할당되기보단 외부작업을 맡기는 로직이 쓰이는 함수 내에서 `Stream`/`Future` 객체의 개념을 요구하는 경우가 대부분이다. + 따라서 `Stream`/`Future` 객체는 함수에서 반환되는 경우가 많으며, 함수가 정의될 때 함수의 body에서 비동기처리 방식이 사용된다는 것을 아래 코드와 같이 명시해줘야 한다. ```dart Stream function() async*{ @@ -50,15 +54,13 @@ Future function() async{
## Stream이란? +---
-다른 환경에서도 많이 사용해서 다소 익숙한 비동기처리 개념 중 하나인 Stream은 Flutter에선 비동기적 이벤트(값)의 연속된 소스를 의미한다. - - +Flutter에서 Stream은 비동기적 이벤트(값)의 연속된 소스를 의미한다.
-`Stream`으로 정의된 함수는 선언 즉시 `Stream` 객체를 반환하며, 그 후엔 `Stream`의 데이터에 접근해서 사용할 때까지 아무 일도 일어나지 않는다. -이후 `listen()`/`await for` 키워드를 통해 `Stream`객체의 데이터에 접근할 수 있으며, 이 때 `async*` 함수가 동작하게 된다. +`Stream`으로 정의된 함수는 선언 즉시 `Stream` 객체를 반환하며, 그 후엔 `Stream`의 데이터에 접근해서 사용할 때까지 아무 일도 일어나지 않는다. 이후 `listen()`/`await for` 키워드를 통해 `Stream`객체 안의 데이터에 접근할 수 있으며, 이 때 `async*` 함수가 동작하게 된다. ```dart stream.listen((int x) => print(x)); //listen() @@ -67,6 +69,9 @@ await for (final value in stream) { //await for } ``` +
+ + 일반적으로 `Stream` 객체의 데이터에 접근하는 과정에서 iterator의 개념이 사용되는데, 가장 최근에 올라온 이벤트들을 하나씩 처리하고 지워나가면서 `Stream` 안에 남은 이벤트가 없어질 때까지 이를 계속하게 된다. 이렇게 한 이벤트는 한 번 사용하고 버리는 것을 단일구독스트림이라고 한다. @@ -76,24 +81,28 @@ await for (final value in stream) { //await for
## Future란? +---
보통 외부의 결과에 영향을 받는 비동기식 작업은 의미적으로 2가지 상태로 구분된다. - 외부로부터 결과값을 받은 상태(#1) - 외부로부터 결과값을 아직 받지 못한 상태(#2) -`Future` 타입을 가지는 객체는 비동기식 작업을 수행할 때 그 작업의 상태(#1, #2)에 상관없이 `Future`라는 타입을 반환한다. - -따라서 `Stream`과 마찬가지로 `Future`가 의미적으로 포함하는 실제 데이터값에 접근하기 위해선 특수 키워드들이 사용되는데, `Future`에선 `await`, `then`을 사용한다. +
-Flutter에서 데이터베이스를 다룰 때 주로 `Future`를 사용하므로 예제 소스코드 3개를 보면서 개념을 자세히 확인해 보자. +`Future` 타입을 가지는 객체는 비동기식 작업을 수행할 때 그 작업의 상태(#1, #2)에 상관없이 `Future`라는 타입을 반환한다. +따라서 `Future`가 의미적으로 포함하는 실제 데이터값에 접근하기 위해선 `await`, `then`와 같은 특수 키워드을 사용한다. -참고로 `getString1()` / `getString3()`은 각각 1초, 3초 기다렸다 `String` 값을 의미적으로 받아오는 `Future` 타입의 함수이다. +Flutter에서 데이터베이스를 다룰 때 주로 `Future`를 사용하므로 예제 소스코드 3개를 보면서 개념을 자세히 확인해 보자. +`getString1()` / `getString3()`은 각각 1초, 3초 기다렸다 `String` 값을 의미적으로 받아오는 `Future` 타입의 함수이다.
### 1. `then` 키워드 쓰임새 + +
+ ```dart import 'dart:async'; @@ -113,9 +122,13 @@ void main() async{ ``` `getString3()`이 먼저 호출됐지만 비동기적 연산을 하므로`getString1()`의 호출도 즉시 이뤄진다. 이후 `then` 키워드를 통해서 비동기연산의 결과(필요한 데이터)를 받아오는데, 1초 후 `getString1()`의 결과값이 먼저(`연산1`) 연산되며 이후 2초가 더 지난 뒤 `getString3()`의 결과값(`연산3`)이 처리되므로 `연산1`이 먼저 출력된 후 `연산3`이 출력된다. +

### 2. `await` 키워드 쓰임새 + +
+ ```dart import 'dart:async'; @@ -139,10 +152,14 @@ void main() async{ `getString3()`이 먼저 호출됐으며, `await`라는 키워드로 `getString3()`의 결과값이 반환될 때까지 프로세스는 기다린 후 그 결과값을 반환한다. 3초 후 `getString3()`이 반환되고 나서 `getString1()`이 호출되며 마찬가지로 결과값이 반환될 때까지 프로세스가 기다린 후 그 결과값을 반환하게 되므로 `연산3`이 먼저 출력된 후에 `연산1`이 출력된다. +

### 3. `await`의 필요성 -`await`는 얼핏보면 동기 처리 성격을 가지고 있어서 일반적인 동기 처리 방식으로 해결하면 되지 않나 하는 생각이 들 수 있지만 `await`는 연쇄적으로 `async`함수 , `Future`를 받아오는 상황에서 유용하게 쓰일 수 있다. + +
+ +`await`는 얼핏보면 동기 처리 성격을 가지고 있어서 일반적인 동기 처리 방식으로 해결하면 되지 않나 하는 생각이 들 수 있지만 연쇄적으로 `async`함수 , `Future`를 받아오는 상황에서 유용하게 쓰일 수 있다. ```dart onTap:() async{ @@ -151,11 +168,8 @@ onTap:() async{ setState((){}); } ``` -위의 코드는 `onTap`이라는 이벤트가 발생했을 때 `updateModel()` 메소드로 데이터를 데이터베이스에 업데이트 한 후 그 업데이트 된 데이터를 포함한 모든 `Model` 데이터를 받아오게 설계돼있다. - -그렇기 때문에 데이터베이스를 업데이트 해주는 `updateModel()`의 작업처리가 완료된 후 `getAllModel()` 메소드가 동작해야 하므로 `await`가 사용되어 `updateModel()`의 작업처리를 기다린 후 반환했다. - -하지만 `getAllModel`을 통해 받아온 데이터 모델들은 아직 데이터 값으로 반환할 필요가 없기 때문에 `await` 사용 없이 `Future` 자료형인 채로 그대로 다음 메소드의 인자로 전달하여 처리를 미룰 수 있게된다. +위의 코드는 `onTap`이라는 이벤트가 발생했을 때 `updateModel()` 메소드로 데이터를 업데이트 한 후 그 업데이트 된 데이터를 포함한 모든 `Model` 데이터를 받아오게 설계돼있다. 그렇기 때문에 `updateModel()`의 작업처리가 완료된 후 `getAllModel()` 메소드가 동작해야 하므로 `await`로 `updateModel()`의 작업처리를 기다린 후 반환했다. +하지만 `getAllModel()`을 통해 받아온 데이터 모델들은 아직 반환할 필요가 없기 때문에 `await` 사용 없이 `Future` 자료형인 채로 다음 메소드의 인자로 전달하여 처리를 미룰 수 있다. 이렇게 `await`는 필요한 순간에 데이터 값을 반환하거나 완료를 기다릴 수 있도록 해주기 때문에 비동기처리에서 데이터를 다룰 때 유용하게 사용된다. @@ -163,9 +177,10 @@ onTap:() async{
## 비동기처리 in Flutter +---
-이제 Flutter에서 비동기처리방식, `Stream`과 `Future` 개념을 어떻게 사용하는지 알아보겠다. +이제 Flutter에서 비동기처리방식, `Stream`과 `Future` 개념을 어떻게 사용하는지 알아보자. Flutter에서의 쓰임을 얘기하기 전에 Flutter의 구성에 대해 간단하게 설명하면, Flutter는 `Widget`이라는 기본 단위로 구성되어있다. `Widget`은 Flutter에서 화면에 보여지는 모든 UI (View)의 기본 단위로써 의미를 가진다. @@ -177,26 +192,35 @@ Flutter에서의 쓰임을 얘기하기 전에 Flutter의 구성에 대해 간 ### `AsyncSnapshot`이란? -비동기처리의 상태를 알 수 있게 해주는 객체이며, 비동기처리가 완료된 상태라면 데이터를 조회할 수도 있다. +
+ +`AsyncSnapshot`은 비동기처리의 상태를 알 수 있게 해주는 객체이며, 비동기처리가 완료된 상태라면 데이터를 조회할 수도 있다. + +
앞서 얘기했지만 비동기처리는 다음과 같이 2가지 상태를 가질 수 있다. - 외부로부터 결과값을 받은 상태 - 외부로부터 결과값을 아직 받지 못한 상태 +
-편의상 `snapshot`을 `AsyncSnapshot`의 객체라 할 때, `snapshot.hasData`라는 필드에 접근해서 비동기처리의 상태를 알아낼 수 있다. +편의상 `snapshot`을 `AsyncSnapshot`의 인스턴스라 할 때, `hasData`라는 필드에 접근해서 비동기처리의 상태를 알아낼 수 있다. `snapshot.hasData == true` => 외부로부터 결과값 or Error값을 받아온 상태
`snapshot.hasData == false` => 외부로부터 결과값을 받지 못한 상태 -`snapshot.hasError`라는 필드를 통해선 반환값이 에러인지 확인가능하고, +
+ +추가로 `snapshot.hasError`라는 필드를 통해선 반환값이 에러인지 확인가능하고, `snapshot.data`필드를 통해 반환한 실제 데이터값을 얻어낼 수 있다.
### `StreamBuilder`, `FutureBuilder` 사용법 +
+ ```dart StreamBuilder( stream: stream, // 위젯에서 다룰 정보를 가지는 Stream 객체 From 47904ca95feae987a466e39ef1ca02446a0686b3 Mon Sep 17 00:00:00 2001 From: SSUHYUNKIM <43875264+SSUHYUNKIM@users.noreply.github.com> Date: Thu, 10 Nov 2022 22:39:08 +0900 Subject: [PATCH 6/6] Update 2022-10-17-asynchronous_programming_in_dart_flutter.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit markdown 문법 오류 수정 --- _posts/2022-10-17-asynchronous_programming_in_dart_flutter.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md index bafd3e4e72..593795ede3 100644 --- a/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md +++ b/_posts/2022-10-17-asynchronous_programming_in_dart_flutter.md @@ -8,8 +8,7 @@ description: "Dart/Flutter에서 비동기처리하기" featured: true --- - - ## 비동기처리(asynchronous programming)란? +## 비동기처리(asynchronous programming)란? ---
비동기처리는 대기를 필요로 하는 작업을 기다리면서도 프로세스가 다른 작업을 수행할 수 있도록 작업하는 방식을 말한다.