๐Ÿ“š Today I Learned 7ํšŒ์ฐจ(1) - Dart ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ์ดˆ 2ํšŒ์ฐจ ๐Ÿ’ก

11 ๋ถ„ ์†Œ์š”

๐Ÿ“– Dart ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ์ดˆ 2ํšŒ์ฐจ

๐ŸŽฏ ํ•™์Šต ๋ชฉํ‘œ

  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ ํ•จ์ˆ˜๋“ค์„ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํด๋ž˜์Šค, ์†์„ฑ, ๋ฉ”์„œ๋“œ ๊ฐœ๋…์„ ์ˆ™์ง€ํ•œ๋‹ค
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์•ˆ์ •์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…์„ ํŒŒ์•…ํ•œ๋‹ค

๐Ÿ“š ์ฃผ์š” ๋‚ด์šฉ

โญ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜

๐Ÿ”„ ํ˜•๋ณ€ํ™˜ ํ•จ์ˆ˜

  • toString(): ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
  • int.parse(''): String ํƒ€์ž…์˜ ๊ฐ’์„ int ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜
  • double.parse(''): String ํƒ€์ž…์˜ ๊ฐ’์„ double ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜
  • toList(): Collection ํƒ€์ž…์˜ ๊ฐ’์„ List ํƒ€์ž…์œผ๋กœ ํ˜• ๋ณ€ํ™˜
    Set<String> fruitSet = {'์‚ฌ๊ณผ', '์˜ค๋ Œ์ง€', '์ˆ˜๋ฐ•'};
    var fruitList = fruitSet.toList();
    print(fruitList); // [์‚ฌ๊ณผ, ์˜ค๋ Œ์ง€, ์ˆ˜๋ฐ•]
    print(fruitList.runtimeType); // List<String>
    

๐Ÿ’ก ์ฃผ์˜: Map ํƒ€์ž…์€ toList() ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

  • toSet(): ํŠน์ • Collection ํƒ€์ž…์˜ ๊ฐ’์„ Set ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜
    List<String> fruitList = ['์‚ฌ๊ณผ', '์˜ค๋ Œ์ง€', '์ˆ˜๋ฐ•'];
    var fruitSet = fruitList.toSet();
    print(fruitSet); // {์‚ฌ๊ณผ, ์˜ค๋ Œ์ง€, ์ˆ˜๋ฐ•}
    print(fruitSet.runtimeType); // Set<String>
    
  • asMap(): ํŠน์ • Collection ํƒ€์ž…์˜ ๊ฐ’์„ Map ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜
    List<String> fruitList = ['์‚ฌ๊ณผ', '์˜ค๋ Œ์ง€', '์ˆ˜๋ฐ•'];
    var fruitMap = fruitList.asMap();
    print(fruitMap); // {0: ์‚ฌ๊ณผ, 1: ์˜ค๋ Œ์ง€, 2: ์ˆ˜๋ฐ•}
    

    ๐Ÿ’ก ํ•ต์‹ฌ: List์˜ Index๊ฐ€ Map์˜ ํ‚ค๋กœ, List์˜ ๊ฐ’์ด Map์˜ ๊ฐ’์œผ๋กœ ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. Map์˜ ํ‚ค๋Š” ๊ณ ์œ ํ•˜๊ณ  List์˜ Index๋„ ๊ณ ์œ ํ•˜๋ฏ€๋กœ ์™„๋ฒฝํ•œ ์กฐํ•ฉ์ž…๋‹ˆ๋‹ค! ๐Ÿ‘๐Ÿผ

    List<String> fruitList = ['์‚ฌ๊ณผ', '์˜ค๋ Œ์ง€', '์ˆ˜๋ฐ•', '์‚ฌ๊ณผ'];
    var fruitMap = fruitList.asMap();
    print(fruitMap); // {0: ์‚ฌ๊ณผ, 1: ์˜ค๋ Œ์ง€, 2: ์ˆ˜๋ฐ•, 3: ์‚ฌ๊ณผ}
    

    โš ๏ธ ์ค‘์š” ํฌ์ธํŠธ:

    • Map์˜ ๊ฐ’์€ ์ค‘๋ณต์ด ํ—ˆ์šฉ๋˜๋ฏ€๋กœ List์˜ ์ค‘๋ณต ๊ฐ’๋„ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค
    • List โ†’ Map ๋ณ€ํ™˜ ์‹œ index๊ฐ€ key, List์˜ ๊ฐ’์ด value๊ฐ€ ๋ฉ๋‹ˆ๋‹ค
    • Set์€ index๊ฐ€ ์—†์–ด ์ง์ ‘ Map ๋ณ€ํ™˜ ๋ถˆ๊ฐ€ โ†’ Set์„ List๋กœ ๋จผ์ € ๋ณ€ํ™˜ ํ›„ Map์œผ๋กœ!

โšก ๊ณ ์ฐจ ํ•จ์ˆ˜

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ํ•จ์ˆ˜๋“ค์ž…๋‹ˆ๋‹ค.

๐Ÿ“‹ ์ฃผ์š” ๊ณ ์ฐจ ํ•จ์ˆ˜ ์ข…๋ฅ˜

๐Ÿ”„ map()

Collection ํƒ€์ž…์ธ ๋ฐ์ดํ„ฐ์˜ ๊ฐ ์š”์†Œ์— ํŠน์ • ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•œ ์ƒˆ๋กœ์šด Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  List<String> fruitList = ['์‚ฌ๊ณผ', '์˜ค๋ Œ์ง€', '์ˆ˜๋ฐ•'];
  var delicious = fruitList.map((fruit) {
    var word = '๋ง›์žˆ๋Š” ';
    word += fruit;
    return word;
  });
  print(delicious); // (๋ง›์žˆ๋Š” ์‚ฌ๊ณผ, ๋ง›์žˆ๋Š” ์˜ค๋ Œ์ง€, ๋ง›์žˆ๋Š” ์ˆ˜๋ฐ•)
  Set<String> carSet = {'BMW', 'ํ˜„๋Œ€', '๊ธฐ์•„'};
  var goodCar = carSet.map((car) {
    return '์งฑ ๋ฉ‹์ง„ $car';
  });
  print(goodCar); // (์งฑ ๋ฉ‹์ง„ BMW, ์งฑ ๋ฉ‹์ง„ ํ˜„๋Œ€, ์งฑ ๋ฉ‹์ง„ ๊ธฐ์•„)
  List<int> numbers = [1, 2, 3, 4, 5];
  var doubledNumbers = numbers.map((n) => n * 2);
  print(doubledNumbers); // (2, 4, 6, 8, 10)
๐Ÿ” where()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์—์„œ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๋“ค๋งŒ ํ•„ํ„ฐ๋งํ•œ ์ƒˆ๋กœ์šด Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  var result = numbers.where((number) {
	  return number > 5;
  });
  print(result); // (6, 7, 8, 9, 10)
  List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  var result = numbers.where((n) => n > 5);
  print(result); // (6, 7, 8, 9, 10)
๐ŸŽฏ firstWhere() & lastWhere()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์—์„œ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ/๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

// ๋ฌธ๋ฒ• ํ˜•ํƒœ
firstWhere(([๋งค๊ฐœ๋ณ€์ˆ˜]) { return [์กฐ๊ฑด์‹]; });
firstWhere(([๋งค๊ฐœ๋ณ€์ˆ˜]) => [์กฐ๊ฑด์‹]);
๐Ÿ”— reduce()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์— ์žˆ๋Š” ์š”์†Œ๋“ค์„ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.reduce((a, b) { // 15
    return a + b;
  });
๐Ÿ“ฆ fold()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์— ์žˆ๋Š” ์š”์†Œ๋“ค์„ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. reduce()์™€ ๋‹ฌ๋ฆฌ ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.fold(1, (a, b) { // 16
    return a + b 
  });

๐Ÿ’ก ํ•ต์‹ฌ ์ฐจ์ด์ : ์ดˆ๊ธฐ๊ฐ’(1)์„ ํ• ๋‹นํ•œ ํ›„ ๊ฐ ์š”์†Œ๋“ค์˜ ๊ฐ’์„ ํ•˜๋‚˜๋กœ ๊ฒฐํ•ฉ

  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.fold('', (a, b) => '$a' + '$b');
  print(result); // 12345
  print(result.runtimeType); // String

โšก ํ™œ์šฉ ํŒ: ์ดˆ๊ธฐ๊ฐ’ ํƒ€์ž…๊ณผ ๋ฆฌํ„ด ํƒ€์ž…์„ ์กฐ์ •ํ•˜์—ฌ ์ƒˆ๋กœ์šด ํƒ€์ž…์œผ๋กœ ํ˜•๋ณ€ํ™˜ ๊ฐ€๋Šฅ

โœ… any()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์— ์žˆ๋Š” ์š”์†Œ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.any((number) {
    return number.isEven; // ์ง์ˆ˜ ์—ฌ๋ถ€ ํ™•์ธ (boolean ๋ฐ˜ํ™˜)
  }); // ๊ฒฐ๊ณผ๊ฐ’๋„ boolean ํƒ€์ž…
  print(result); // true
  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.any((n) => n.isEven);
  print(result); // true
โœ… every()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์— ์žˆ๋Š” ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.every((number) {
    return number > 0;
  });
  print(result); // true
  List<int> numbers = [1, 2, 3, 4, 5];
  var result = numbers.every((number) => number > 0);
  print(result); // true
โžก๏ธ takeWhile()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์—์„œ ์กฐ๊ฑด์— ๋งž๋Š” ์š”์†Œ๋ฅผ ์—ฐ์†์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๋‹ค๊ฐ€, ์กฐ๊ฑด์— ๋งž์ง€ ์•Š๋Š” ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๋งŒ๋‚˜๋Š” ์ˆœ๊ฐ„ ์ž‘์—…์„ ๋ฉˆ์ถ”๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5, 6];
  var result = numbers.takeWhile((number) {
  return number < 4;
  });
  print(result); // (1, 2, 3)
  List<int> numbers = [1, 2, 3, 4, 5, 6];
  var result = numbers.takeWhile((number) => number < 4);
  print(result); // (1, 2, 3)
โฌ…๏ธ skipWhile()

Collection ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ์—์„œ ์กฐ๊ฑด์— ๋งž๋Š” ์š”์†Œ๋ฅผ ์—ฐ์†์ ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๋‹ค๊ฐ€, ์กฐ๊ฑด์— ๋งž์ง€ ์•Š๋Š” ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ๋งŒ๋‚˜๋Š” ์ˆœ๊ฐ„ ์ž‘์—…์„ ๋ฉˆ์ถ”๊ณ  ์ดํ›„ ๋ชจ๋“  ์š”์†Œ๋“ค์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  List<int> numbers = [1, 2, 3, 4, 5, 6];
  var result = numbers.skipWhile((number) {
  return number < 4;
  });
  print(result); // (4, 5, 6)
  List<int> numbers = [1, 2, 3, 4, 5, 6];
  var result = numbers.skipWhile((number) => number < 4);
  print(result); // (4, 5, 6)

๐Ÿข ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ Dart(1) - ํด๋ž˜์Šค์™€ ์†์„ฑ

๐Ÿ“Š ์†์„ฑ(Properties) ์ข…๋ฅ˜

์†์„ฑ ์ข…๋ฅ˜ ์„ค๋ช… ์‚ฌ์šฉ๋ฒ•
์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜ ๊ฐ์ฒด์— ์†ํ•ด ์žˆ๋Š” ๋ณ€์ˆ˜ String name;
์ง€์—ญ ๋ณ€์ˆ˜ ํŠน์ • ์ฝ”๋“œ ๋ธ”๋ก ์•ˆ์— ์„ ์–ธ๋œ ๋ณ€์ˆ˜ void method() { int temp = 5; }
์ •์  ๋ณ€์ˆ˜ ํด๋ž˜์Šค ์ž์ฒด์— ์†ํ•˜๋Š” ๋ณ€์ˆ˜ static int count;

๐Ÿข ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ Dart(2) - ํด๋ž˜์Šค์™€ ๋ฉ”์„œ๋“œ

๐Ÿ”„ ๋ฉ”์„œ๋“œ vs ํ•จ์ˆ˜

๊ตฌ๋ถ„ ๋ฉ”์„œ๋“œ ํ•จ์ˆ˜
์†Œ์† ํด๋ž˜์Šค์— ์ข…์† ํด๋ž˜์Šค์™€ ๋ฌด๊ด€
ํ˜ธ์ถœ ๊ฐ์ฒด.๋ฉ”์„œ๋“œ() ํ•จ์ˆ˜๋ช…()
์˜ˆ์‹œ car.start() print()

๐Ÿ“Š ๋ฉ”์„œ๋“œ ์ข…๋ฅ˜

๐Ÿ’ต ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ
  • ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ
  • ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜์— ์ ‘๊ทผ ๊ฐ€๋Šฅ
โšก ์ •์  ๋ฉ”์„œ๋“œ
  • ํด๋ž˜์Šค๋ช…์„ ํ†ตํ•ด ์ง์ ‘ ํ˜ธ์ถœ
  • ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์—†์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ
๐Ÿ  ์ƒ์„ฑ์ž (Constructor)

โš ๏ธ ์ค‘์š”: ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ธฐ๋ณธ ์ƒ์„ฑ์ž์—์„œ ๋ชจ๋‘ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1๏ธโƒฃ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ƒ์„ฑ์ž ```dart // Dart๋งŒ์˜ ๊ฐ„๊ฒฐํ•œ ๋ฌธ๋ฒ• class Car { String name; List models;

    Car(this.name, this.models);
  }
  ```
  ```dart
  // C++ ์Šคํƒ€์ผ ์ƒ์„ฑ์ž
  class Car {
    String name;
    List<String> models;

    Car(String name, List<String> models)
        : this.name = name,
          this.models = models;
  }
  ```
  ```dart
  // Java ์Šคํƒ€์ผ ์ƒ์„ฑ์ž
  class Car {
    String name = '';
    List<String> models = [];

    Car(String name, List<String> models) {
      this.name = name;
      this.models = models;
    }
  }

2๏ธโƒฃ ๋„ค์ž„๋“œ ์ƒ์„ฑ์ž (Named Constructor)

ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ์ƒ์„ฑ์ž

// ๋ฌธ๋ฒ•: [ํด๋ž˜์Šค๋ช…].[๋ฉ”์„œ๋“œ๋ช…]([ํƒ€์ž…] [๋งค๊ฐœ๋ณ€์ˆ˜๋ช…]) : this.๋ณ€์ˆ˜;
  ```dart
  class Car {
    String name;
    List<String> models;

    Car.fromList(List values)
        : this.name = values[0],
          this.models = values[1];
  }
  ```
  ```dart
  class Car {
    String name;
    List<String> models;

    Car.fromList(List values)
        : this.name = values[0],
          this.models = values[1];

    void speakName() {
      print('์ €ํฌ๋Š” $name ์ž…๋‹ˆ๋‹ค !');
    }

    void speakModels() {
      print('$models ๋ชจ๋ธ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค !');
    }
  }

  void main() {
    Car car = Car.fromList([
      'BMW',
      ['320i', '340i', 'M3']
    ]);
    car.speakName(); // ์ €ํฌ๋Š” BMW ์ž…๋‹ˆ๋‹ค !
    car.speakModels(); // [320i, 340i, M3] ๋ชจ๋ธ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค !
  }
  ```

๐Ÿ”„ ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค

๋‹ค์–‘ํ•œ ํƒ€์ž…์— ๋Œ€ํ•ด ๋™์ผํ•œ ๋กœ์ง์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

  class Box<T> {
    T value;

    Box(this.value);

    T getValue() {
      return value;
    }
  }

๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ Dart(3) - ๊ฐ์ฒด ์ง€ํ–ฅ๊ณผ ์ƒ์†

์ƒ์†

  • super ๋ฅผ ํ†ตํ•ด ์ž์‹ ํด๋ž˜์Šค ๊ฐ€ ๋ถ€๋ชจ ํด๋ž˜์Šค ์˜ ์†์„ฑ ๊ณผ ๋ฉ”์„œ๋“œ ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ์ž์‹ ํด๋ž˜์Šค ๋Š” ์ƒ์† ๋ฐ›์€ ์†์„ฑ ๊ณผ ๋ฉ”์„œ๋“œ ๋ฅผ ์žฌ์ •์˜ (Overriding) ํ•˜๊ฑฐ๋‚˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๊ทผ๋ฐ์š” .. ์–ด๋–ค ํด๋ž˜์Šค ๋Š” ์ƒ์† ๋‹นํ•˜์ง€ (?) ์•Š๊ฒŒ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” final ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์š”
    final class Person {
      void eat() {
        print('๋ƒ ๋ƒ  !');
      }
    }
    
    class Student extends Person {
      // Error: The type 'Student' must be 'base', 'final' or 'sealed' because the supertype 'Person' is 'final'.
    }
    

๐Ÿ”„ extends vs implements

๊ตฌ๋ถ„ extends implements
๐ŸŽฏ ๋ชฉ์  ํด๋ž˜์Šค ํ™•์žฅ ๋ฐ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ๋ฐ ๊ทœ๊ฒฉ ์ค€์ˆ˜
๐Ÿ’ป ์ฝ”๋“œ ๋ถ€๋ชจ์˜ ๊ตฌํ˜„๋œ ์ฝ”๋“œ๋ฅผ ๋ฌผ๋ ค๋ฐ›์Œ ๋ถ€๋ชจ์˜ ๊ตฌํ˜„๋œ ์ฝ”๋“œ๋Š” ๋ฌผ๋ ค๋ฐ›์ง€ ์•Š์Œ
โš–๏ธ ์˜๋ฌด ๋ฉ”์„œ๋“œ ์žฌ์ •์˜๋Š” ์„ ํƒ ์‚ฌํ•ญ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ์žฌ์ •์˜ํ•ด์•ผ ํ•จ
๐Ÿ“Š ๊ฐœ์ˆ˜ ๋‹จ์ผ ์ƒ์†๋งŒ ๊ฐ€๋Šฅ ๋‹ค์ค‘ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅ

โš ๏ธ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋กœ ๋‹จ๋‹จํ•œ ์ฝ”๋“œ ๋งŒ๋“ค๊ธฐ

๐Ÿšจ ์˜ˆ์™ธ(Exception) ์ข…๋ฅ˜

  • DeferredLoadException: ํ•„์š”ํ•œ ์‹œ์ ์— ๋กœ๋“œ๋˜๋„๋ก ์„ค์ •ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋กœ๋“œ๋˜์ง€ ๋ชป ํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
  • FormatException: ๋ฐ์ดํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๊ฐ€ ์•„๋‹ˆ์–ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์šธ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
  • IOException: ์ž…์ถœ๋ ฅ ๊ด€๋ จ ๋™์ž‘์„ ํ•˜๋Š” ์ค‘์— ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜ ๐Ÿšจ
    • FileSystemException
    • HttpException
    • ProcessException
    • SignalException
    • SocketException
    • StdinException
    • StdoutException
    • TlsException
    • WebSocketException
  • OSError: ์šด์˜์ฒด์ œ ๋ ˆ๋ฒจ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜ ๐Ÿฅน
  • TimeoutException: ๋น„๋™๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ํŠน์ • ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ •์˜ํ•œ ์˜ˆ์™ธ:
    class AgeException implements Exception {
      final String? message;
        
      AgeException(this.message);
        
      @override
      String toString() => message ?? 'AgeException ์ด ๋ฐœ์ƒํ–ˆ์–ด์š” !';
    }
    

๊ด€๋ จ ํ‚ค์›Œ๋“œ

  • try
  • catch
  • on: try ์˜ ์ฝ”๋“œ ๋ธ”๋ก์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ ์ค‘ ํŠน์ • ํƒ€์ž…์˜ ์˜ˆ์™ธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ถ€๋ถ„
    on IOException catch (e) {
      // IOException ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์‹คํ–‰ํ•  ์ฝ”๋“œ
    }
    
  • finally

์˜ค๋ฅ˜(Error)

์ข…๋ฅ˜

  • ArgumentError
  • AssertionError
    void checkAge(int age) {
      assert(age > 0, 'Age must be positive');
    }
    
    void main() {
      checkAge(-5); // AssertionError ๋ฐœ์ƒ
    }
    
    assert(text != null);
    assert(number < 100, '100 ์ด์ƒ์ด๋ฉด ์•ˆ ๋ผ์š” !');
    
  • RangeError: ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฒ”์œ„์˜ ๊ฐ’์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•ด์š”.
  • IndexError
  • NoSuchMethodError: ํ•จ์ˆ˜ ๋‚˜ ๋ฉ”์„œ๋“œ ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•ด์š”.
  • OutOfMemoryError
  • StackOverflowError
  • StateError: ๊ฐ์ฒด์˜ ํ˜„์žฌ ์ƒํƒœ๋กœ๋Š” ํŠน์ • ๋™์ž‘ ์ˆ˜ํ–‰์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•ด์š”.
    List<int> numbers = [];
    print(numbers.first);
    
  • TypeError
  • UnimplementedError
  • UnsupportedError: ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋  ์ˆ˜ ์—†๋Š” ๋™์ž‘์ผ ๋•Œ ๋ฐœ์ƒํ•ด์š”.

๐Ÿ†š ์˜ˆ์™ธ vs ์˜ค๋ฅ˜ ๋น„๊ต

๊ตฌ๋ถ„ ์˜ˆ์™ธ (Exception) ์˜ค๋ฅ˜ (Error)
๐ŸŽฏ ๋ฐœ์ƒ ์›์ธ ์ฝ”๋“œ๊ฐ€ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋งž์ง€ ์•Š๊ฑฐ๋‚˜ ๋ถ€์ ์ ˆํ•œ ๊ฐ’ ์ž…๋ ฅ ์‹œ์Šคํ…œ ๋ฌธ์ œ (๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ๋“ฑ)
๐Ÿ”ฎ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์Œ ์˜ˆ์ƒํ•  ์ˆ˜ ์—†์Œ
๐Ÿ› ๏ธ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ์„ฑ try-catch๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ ๋ฐœ์ƒ์„ ์˜ˆ์ƒํ•  ์ˆ˜ ์—†์–ด ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€๋Šฅ
๐Ÿ“ ์˜ˆ์‹œ FormatException, TimeoutException OutOfMemoryError, StackOverflowError

๐Ÿ’ก ํ•ต์‹ฌ ํฌ์ธํŠธ: ์˜ˆ์™ธ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜ˆ์ƒํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์˜ค๋ฅ˜๋Š” ์‹œ์Šคํ…œ ๋ ˆ๋ฒจ์˜ ๋ฌธ์ œ๋กœ ์˜ˆ์ƒํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๐Ÿ“ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ํ™•์žฅํ•˜๊ธฐ

๐ŸŒ ๋ชจ๋“  ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • dart:core: Dart์˜ ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (์ž๋™ import)
  • dart:async: ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง€์›
  • dart:collection: ์ปด๋ ‰์…˜ ํƒ€์ž… ์ถ”๊ฐ€ ๊ธฐ๋Šฅ
  • dart:convert: JSON, UTF-8 ๋“ฑ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜
  • dart:developer: ๋””๋ฒ„๊น… ๋ฐ ๊ฐœ๋ฐœ ๋„๊ตฌ
  • dart:math: ์ˆ˜ํ•™ ๊ด€๋ จ ํ•จ์ˆ˜๋“ค

๐Ÿ’ป Native platform์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • dart:ffi: C API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” Foreign Function Interface
  • dart:io: ํŒŒ์ผ ์‹œ์Šคํ…œ, ๋„คํŠธ์›Œํฌ, ํ”„๋กœ์„ธ์Šค ์ฒ˜๋ฆฌ

๐ŸŒ Web platform์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • package:web: ์›น ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • dart:js_interop: JavaScript์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ
  • dart:html: HTML DOM ์กฐ์ž‘ ๋ฐ ์›น API

๐ŸŒ Dart SDK์— ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Pub.dev์—์„œ ๋‹ค์–‘ํ•œ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์ฐพ์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐Ÿคฉ

๐Ÿ”ฅ ๋งŽ์ด ์“ฐ์ด๋Š” ์ธ๊ธฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

| ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ | ๊ธฐ๋Šฅ ์„ค๋ช… | |:โ€”|:โ€”| | cupertino_icons | iOS ์Šคํƒ€์ผ ์•„์ด์ฝ˜ | | intl | ๋ฒˆ์—ญ, ๋‚ ์งœ/์ˆซ์ž ํฌ๋งทํŒ… ๋“ฑ ๊ตญ์ œํ™” ๊ธฐ๋Šฅ | | shared_preferences | ๋กœ์ปฌ ๋ฐ์ดํ„ฐ ์ €์žฅ (iOS NSUserDefaults, Android SharedPreferences) | | url_launcher | URL, ์ด๋ฉ”์ผ, ์ „ํ™” ๋“ฑ ์™ธ๋ถ€ ์•ฑ ์—ฐ๋™ | | image_picker | iOS/Android์—์„œ ์‚ฌ์ง„ ์„ ํƒ ๋ฐ ์ดฌ์˜ | | firebase_core & firebase_auth | Firebase ์„œ๋น„์Šค ํ†ตํ•ฉ ๋ฐ ์ธ์ฆ | | google_fonts | Google Fonts ์‚ฌ์šฉ | | permission_handler | iOS/Android ๊ถŒํ•œ ๊ด€๋ฆฌ | | custom_lint | ์ปค์Šคํ…€ Lint ๊ทœ์น™ ์ ์šฉ | | flutter_svg | SVG ์ด๋ฏธ์ง€ ๋ Œ๋”๋ง | | cached_network_image | ๋„คํŠธ์›Œํฌ ์ด๋ฏธ์ง€ ์บ์‹ฑ | | flutter_local_notifications | ๋กœ์ปฌ ์•Œ๋ฆผ ๊ธฐ๋Šฅ | | path_provider | ์‹œ์Šคํ…œ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ ์ œ๊ณต | | geolocator | GPS ์œ„์น˜ ์ •๋ณด ์ฒ˜๋ฆฌ | | dio | ๊ฐ•๋ ฅํ•œ HTTP ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ |

๐Ÿ“ ์ฐธ๊ณ : pub.dev์— ์žˆ๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ package: ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค.

๐Ÿ”ง ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ํŠน์ง•

๐Ÿท๏ธ ๋ณ„์นญ(Alias) ์‚ฌ์šฉ
import 'package:http/http.dart' as http;
๐ŸŽฏ ์„ ํƒ์  Import (show)
import 'package:lib1/lib1.dart' show foo;
๐Ÿšซ ์ œ์™ธ Import (hide)
import 'package:lib2/lib2.dart' hide foo;
โณ ์ง€์—ฐ ๋กœ๋”ฉ (deferred as)

โš ๏ธ ์ฃผ์˜: ๋ชจ๋“  ํ”Œ๋žซํผ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉฐ, Web platform์—์„œ๋งŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

import 'package:greetings/hello.dart' deferred as hello;

Future<void> greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

โฑ๏ธ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ Dart

์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์ธ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๊ฐ’์ด ๋‚˜์˜ค๋Š” ๋™์•ˆ CPU ๋ธ”๋Ÿญ์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ ๋น„๋™๊ธฐ ๋™์ž‘์„ ์‹คํ–‰ํ•˜์—ฌ ํšจ์œจ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

๐Ÿ“Š ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

  • ๐Ÿ“ ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ๋•Œ
  • ๐Ÿ’พ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ๋•Œ
  • ๐ŸŒ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ

๐Ÿ”ฎ Future

์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ•ด๋‹น ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์‹คํ–‰์„ ์ข…๋ฃŒํ•˜๋Š” ์ผํšŒ์„ฑ ๋น„๋™๊ธฐ ์ž‘์—…์ž…๋‹ˆ๋‹ค.

Future<String> introduce(String name) async {
	print('$name์˜ ์ž๊ธฐ์†Œ๊ฐœ ์‹œ์ž‘ !');
  
  await Future.delayed(Duration(seconds: 2), () {
    print('์•ˆ๋…• ? ๋‚˜๋Š” $name ~');
  });
	
	print('$name์˜ ์ž๊ธฐ์†Œ๊ฐœ ๋ !');
  
  return '์ด๋ฆ„์€ $name ~';
}

void main() async {
  var riverfuture = await introduce('๊ฐ•๋ฏธ๋ž˜');
  var riverpresent = await introduce('๊ฐ•ํ˜„์žฌ');
  print('๋‚˜์˜ $riverfuture ๋„ˆ์˜ $riverpresent');
}

/*
๊ฐ•๋ฏธ๋ž˜์˜ ์ž๊ธฐ์†Œ๊ฐœ ์‹œ์ž‘ !
์•ˆ๋…• ? ๋‚˜๋Š” ๊ฐ•๋ฏธ๋ž˜ ~
๊ฐ•๋ฏธ๋ž˜์˜ ์ž๊ธฐ์†Œ๊ฐœ ๋ !
๊ฐ•ํ˜„์žฌ์˜ ์ž๊ธฐ์†Œ๊ฐœ ์‹œ์ž‘ !
์•ˆ๋…• ? ๋‚˜๋Š” ๊ฐ•ํ˜„์žฌ ~
๊ฐ•ํ˜„์žฌ์˜ ์ž๊ธฐ์†Œ๊ฐœ ๋ !
๋‚˜์˜ ์ด๋ฆ„์€ ๊ฐ•๋ฏธ๋ž˜ ~ ๋„ˆ์˜ ์ด๋ฆ„์€ ๊ฐ•ํ˜„์žฌ ~
*/

## ๐Ÿ’ป ์‹ค์Šต ๋ฐ ์˜ˆ์ œ

์œ„์—์„œ ํ•™์Šตํ•œ ๋‚ด์šฉ๋“ค์€ ๋ชจ๋‘ **์‹ค์ œ ์ฝ”๋“œ ์˜ˆ์ œ**์™€ ํ•จ๊ป˜ ์ œ์‹œ๋˜์–ด ์žˆ์–ด ๋ฐ”๋กœ ์‹ค์Šตํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

## ๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ

### โœ… ์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ
- **ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ**: `map()`, `where()`, `reduce()`, `fold()` ๋“ฑ ๊ณ ์ฐจ ํ•จ์ˆ˜๋“ค์˜ ํ™œ์šฉ๋ฒ•
- **๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ**: ํด๋ž˜์Šค, ์†์„ฑ, ๋ฉ”์„œ๋“œ, ์ƒ์†์˜ ๊ฐœ๋…๊ณผ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•
- **์˜ˆ์™ธ ์ฒ˜๋ฆฌ**: Exception๊ณผ Error์˜ ์ฐจ์ด์ ๊ณผ `try-catch` ๊ตฌ๋ฌธ ์‚ฌ์šฉ๋ฒ•
- **๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ**: Dart ๋‚ด์žฅ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์™ธ๋ถ€ ํŒจํ‚ค์ง€ ํ™œ์šฉ๋ฒ•
- **๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ**: `Future`์™€ `Stream`์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ํ™œ์šฉ๋ฒ•

### ๐Ÿš€ ๋‹ค์Œ ๊ณ„ํš
- **๊ณ ๊ธ‰ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ**: `async`/`await` ํŒจํ„ด ์‹ฌํ™” ํ•™์Šต
- **Flutter ์œ„์ ฏ**: Dart ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ํ•œ Flutter UI ๊ตฌํ˜„
- **์ƒํƒœ ๊ด€๋ฆฌ**: Provider, Riverpod ๋“ฑ ์ƒํƒœ ๊ด€๋ฆฌ ํŒจํ„ด ํ•™์Šต
- **์‹ค์ „ ํ”„๋กœ์ ํŠธ**: ํ•™์Šตํ•œ ๊ฐœ๋…๋“ค์„ ํ™œ์šฉํ•œ ์‹ค์ œ ์•ฑ ๊ฐœ๋ฐœ

โš ๏ธ Future์˜ ํ•œ๊ณ„ ๐Ÿฅบ

  • ํ•˜๋‚˜์˜ ์ž‘์—…๋‹น ๊ฒฐ๊ณผ๊ฐ’์„ 1๋ฒˆ๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์ผํšŒ์šฉ)
  • ํ•˜๋‚˜์˜ ์ž‘์—…์— ๊ฒฐ๊ณผ๊ฐ’์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋‚˜์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!
  • ์ด๋Ÿฌํ•œ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด Stream์ด ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค! ๐Ÿš€

๐ŸŒŠ Stream

์‹œ๊ฐ„์— ๋”ฐ๋ผ ์—ฐ์†์ ์ธ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๊ฐ’์ด ์•„๋‹Œ ์—ฌ๋Ÿฌ ๊ฐ’์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก Future vs Stream: Future๋Š” ๋‹จ์ผ ๊ฒฐ๊ณผ, Stream์€ ์—ฐ์†์ ์ธ ๋‹ค์ค‘ ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌ!

Stream<int> emitNumbers(int first) async* {
  for (var i = first; i >= 0; i--) {
    yield i;
    
    await Future.delayed(Duration(seconds: 1));
  }
}

void main() {
  emitNumbers(10).listen((number) {
    print(number);
  });
}

/*
10
9
8
7
6
5
4
3
2
1
0
*/

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ