webpack-basic

배경

💡
문법 수준에서 모듈을 지원하기 시작한 것은 ES2015 부터이다.

import/export 구문이 없었을때

  • math.js
    function sum(a, b) {
      return a + b;
    }
  • app.js
    console.log(sum(1,2))

아래와 같이 하나의 html 파일 안에서 로딩해야 실행 가능

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="src/app.js"></script>
		<script src="src/math.js"></script>
</body>
</html>

문제점

math.js에서 선언한 함수가 전역공간에 노출되기에 다른 파일에서 math.js에서 선언한 함수와 동일한 이름으로 다시 선언했을때 충돌이 발생

 

IIFE 방식의 모듈

위의 문제를 예방하기 위해 스코프를 사용

  • 함수 스코프를 만들어 외부에서 안으로 접근하지 못하도록 공간을 격리

math.js

var math = math || {} // math 네임스페이스

;(function () {
  function sum(a, b) {
    return a + b
  }
  math.sum = sum // 네이스페이스에 추가
})()

app.js에서 math.sum으로 호출하여 사용

다양한 모듈 스펙

CommonJS

💡
자바스크립트를 사용하는 모든 환경에서 모듈을 사용하는 것이 목표
  • exports 키워드로 모듈을 만들고 require()함수로 불러 들이는 방식

math.js

exports function sum(a, b) { return a + b; }

app.js

const math = require("./math.js")
math.sum(1, 2) // 3

AMD(Asynchronous Module Definition)

비동기로 로딩되는 환경에서 모듈을 사용하는 것이 목표다. 주로 브라우져 환경이다.

UMD(Universal Module Definition)

AMD기반으로 CommonJS 방식까지 지원하는 통합 형태다.

💡
이렇게 각 커뮤니티에서 각자의 스펙을 제안하다가 ES2015에서 표준 모듈 시스템 을 내 놓았다. 지금은 바벨과 웹팩을 이용해 모듈 시스템을 사용하는 것이 일반적이다.

ES2015 표준 모듈 시스템

export구문으로 모듈을 만들고 import 구문으로 가져올 수 있다.

math.js

export function sum(a, b) {
  return a + b
}

app.js

import * as math from "./math.js"
// or
import {sum} from "./math.js"
math.sum(1, 2) // 3

※ 출저

https://www.inflearn.com/course/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD/dashboard

 

프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 인프런 | 강의

이미 만들어 놓은 개발 환경을 이해할 수 있어요. 처음부터 직접 개발 환경을 만들 수 있어요., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90

'Study > webpack' 카테고리의 다른 글

webpack@4 - babel - basic  (0) 2022.06.04
webpack@4 - plugin  (0) 2022.06.04
webpack@4 - loader  (0) 2022.06.04
webpack@4 - 엔트리/아웃풋  (0) 2022.06.04
webpack@4 - 들어가기전 package.json  (0) 2022.06.04

package.json

  • name: 프로젝트 이름
  • version: 프로젝트 버전 정보
  • description: 프로젝트 설명
  • main: 노드 어플리케이션일 경우 진입점 경로. 프론트엔드 프로젝트일 경우 사용하지 않는다.
  • scripts: 프로젝트 명령어를 등록할 수 있다.초기화시 test 명령어가 샘플로 등록되어 있다
  • author: 프로그램 작성자
  • license: 라이센스

프로젝트 명령어

생성한 프로젝트는 package.json에 등록한 스크립트를 이용해 실행

주요 명령어

  • start: 어플리케이션 실행
  • test: 테스트
  • install: 패키지 설치
  • uninstall: 패키지 삭제

커스텀으로 등록한 명령어는 run을 추가해서 실행

패키지 설치

CDN을 이용한 방법

CDN(컨텐츠 전송 네트워크)로 제공하는 라이브러리를 직접 가져오는 방식

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>

직접 다운

NMP을 이용한 방법

NMP 저장소에서 찾아 우리 프로젝트로 다운로드 하는 명령어

package.json에 설치한 패키지 정보 기록

npm install

유의적 버전

프로젝트에 사용하는 버전 번호를 관리하기 위한 규칙

유의적 버전은 주(Major), 부(Minor), 수(Patch) 세 가지 숫자를 조합해서 버전을 관리한다. 위에 설치한 react의 버전은 v16.12.0인데 주 버전이 16, 부 버전이 12, 수 버전이 0인 셈이다.

각 버전을 변경하는 기준은 다음과 같다

  • 주 버전(Major Version): 기존 버전과 호환되지 않게 변경한 경우
  • 부 버전(Minor version): 기존 버전과 호환되면서 기능이 추가된 경우
  • 수 버전(Patch version): 기존 버전과 호환되면서 버그를 수정한 경우

틸트(~) 는 마이너 버전이 명시되어 있으면 패치버전만 변경한다. 예를 들어 ~1.2.3 표기는 1.2.3 부터 1.3.0 미만 까지를 포함한다. 마이너 버전이 없으면 마이너 버전을 갱신한다. ~0 표기는 0.0.0부터 1.0.0 미만 까지를 포함한다.

캐럿(^) 은 정식버전에서 마이너와 패치 버전을 변경한다. 예를 들어 ^1.2.3 표기는 1.2.3부터 2.0.0 미만 까지를 포함한다. 정식버전 미만인 0.x 버전은 패치만 갱신한다. ^0 표기는 0.0.0부터 0.1.0 미만 까지를 포함한다.

※ 출저

https://www.inflearn.com/course/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD/dashboard

 

프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 인프런 | 강의

이미 만들어 놓은 개발 환경을 이해할 수 있어요. 처음부터 직접 개발 환경을 만들 수 있어요., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90

'Study > webpack' 카테고리의 다른 글

webpack@4 - babel - basic  (0) 2022.06.04
webpack@4 - plugin  (0) 2022.06.04
webpack@4 - loader  (0) 2022.06.04
webpack@4 - 엔트리/아웃풋  (0) 2022.06.04
webpack@4 - basic  (0) 2022.06.04

Factory 패턴

팩토리 메서드 패턴(Factory method pattern)은 객체지향 디자인 패턴이다. Factory method는 부모(상위) 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며. 자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이기도 하다.

장점

싱글톤 패턴 : static을 사용한 효과로 객체를 생성하지 않고도 패턴을 사용가능.

예제

피자 가게에서 피자를 주문하고 그 가격을 출력해주는 예제

객체 생성 로직을 어디서 하는가 ?

Factory 패턴을 사용하지 않은 예제

void main(){
	var userSelectedPizza = PizzaType.HamMushroom;
	Pizza pizza;
	switch (userSelectedPizza){
		case PizzaType.HamMushroom;
			pizza = HamAndMushroomPizza();
			break;
		case PizzaType.Deluxe;
			pizza = DeluxePizza();
			break;
		case PizzaType.Seafood;
			pizza = SeafoodPizza();
			break;
	}
	print(pizza.getPrice());
}
// 피자 종류
enum PizzaType { HamMushroom, Deluxe, Seafood }

abstract class Pizza{
	double getPrice();
}

class HamAndMushroomPizza implements Pizza{
	double price = 10.5;
	@override
	double getPrice(){
		return price;
	}
}

class DeluxePizza implements Pizza{
	double price = 5.5;
	@override
	double getPrice(){
		return price;
	}
}

class SeafoodPizza implements Pizza{
	double price = 7.8;
	@override
	double getPrice(){
		return price;
	}
}

Factory 패턴을 사용한 예제

void main(){
	var userSelectedPizza = PizzaType.HamMushroom;
	print(Pizza.pizzaFactory(userSelectedPizza).getPrice());
}
// 피자 종류
enum PizzaType { HamMushroom, Deluxe, Seafood }

abstract class Pizza{
	double getPrice();
	// 팩토리 패턴
	static pizzaFactory(PizzaType type){
		switch (userSelectedPizza){
		case PizzaType.HamMushroom;
			return HamAndMushroomPizza();
			break;
		case PizzaType.Deluxe;
			return DeluxePizza();
			break;
		case PizzaType.Seafood;
			return SeafoodPizza();
			break;
		}
	}
}

class HamAndMushroomPizza implements Pizza{
	double price = 10.5;
	@override
	double getPrice(){
		return price;
	}
}

class DeluxePizza implements Pizza{
	double price = 5.5;
	@override
	double getPrice(){
		return price;
	}
}

class SeafoodPizza implements Pizza{
	double price = 7.8;
	@override
	double getPrice(){
		return price;
	}
}

로직 변경

DeluxePizza 객체 생성할때 orderNumber가 필요하다고 수정

class DeluxePizza implements Pizza{
	double price = 5.5;
	String orderNumber;
	DeluxePizza(this.orderNumber);
	@override
	double getPrice(){
		return price;
	}
}

Factory 패턴을 사용하지 않은 예제

void main(){
	var userSelectedPizza = PizzaType.HamMushroom;
	Pizza pizza;
	var orderNumber = '1234';
	switch (userSelectedPizza){
		case PizzaType.HamMushroom;
			pizza = HamAndMushroomPizza();
			break;
		case PizzaType.Deluxe;
			pizza = DeluxePizza(orderNumber);
			break;
		case PizzaType.Seafood;
			pizza = SeafoodPizza();
			break;
	}
	print(pizza.getPrice());
}

Factory 패턴을 사용한 예제

void main(){
	var userSelectedPizza = PizzaType.HamMushroom;
	String orderNumber = '1234';
	print(Pizza.pizzaFactory(userSelectedPizza,orderNumber).getPrice());
}
// 피자 종류
enum PizzaType { HamMushroom, Deluxe, Seafood }

abstract class Pizza{
	double getPrice();
	// 팩토리 패턴
	static pizzaFactory(PizzaType type, String orderNumber){
		switch (userSelectedPizza){
		case PizzaType.HamMushroom;
			return HamAndMushroomPizza();
			break;
		case PizzaType.Deluxe;
			return DeluxePizza(orderNumber);
			break;
		case PizzaType.Seafood;
			return SeafoodPizza();
			break;
		}
	}
}

Factory 패턴을 사용한 예제에서 Map 타입으로 데이터 넘겨주기

void main(){
	var userSelectedPizza = PizzaType.HamMushroom;
	String orderNumber = '1234';
	Map<String, dynamic> json = {
		'type': PizzaType.HamMushroom,
		'orderNumber' : '1234',
	}
	print(Pizza.pizzaFactory(json).getPrice());
}
// 피자 종류
enum PizzaType { HamMushroom, Deluxe, Seafood }

abstract class Pizza{
	double getPrice();
	// 팩토리 패턴
	static pizzaFactory(Map<String, dynamic> json){
		switch (json['type'] as PizzaType){
		case PizzaType.HamMushroom;
			return HamAndMushroomPizza();
			break;
		case PizzaType.Deluxe;
			return DeluxePizza(json['orderNumber'] as String);
			break;
		case PizzaType.Seafood;
			return SeafoodPizza();
			break;
		}
	}
}

Factory 패턴을 사용한 예제에서 Map 타입으로 데이터 넘겨줄때 Factory 타입으로 리턴

void main(){
	var userSelectedPizza = PizzaType.HamMushroom;
	String orderNumber = '1234';
	Map<String, dynamic> json = {
		'type': PizzaType.HamMushroom,
		'orderNumber' : '1234',
	}
	print(Pizza.fromJson(json).getPrice());
}
// 피자 종류
enum PizzaType { HamMushroom, Deluxe, Seafood }

abstract class Pizza{
	double getPrice();
	// 팩토리 패턴
	Factory Pizza.fromJson(Map<String, dynamic> json){
		switch (json['type'] as PizzaType){
		case PizzaType.HamMushroom;
			return HamAndMushroomPizza();
			break;
		case PizzaType.Deluxe;
			return DeluxePizza(json['orderNumber'] as String);
			break;
		case PizzaType.Seafood;
			return SeafoodPizza();
			break;
		default:
			return SeafoodPizza();
		}
	}
}

참고

https://www.youtube.com/watch?v=ZikfiBnFMk8 

 

728x90

'Study > Flutter' 카테고리의 다른 글

[Flutter] Provider pattern (bloc -> provider )  (0) 2021.06.16
[Flutter] Stateful widget  (0) 2021.06.14
[UI초급] Container, materialApp, Scaffold  (0) 2021.06.07

factory

factory는 새로운 인스턴스를 생성하고 싶지 않을 때 사용하는 생성자이다. 이와 같은 개념은 새로운 게 아니다. 소프트웨어 디자인 패턴 중 '싱글톤 패턴'을 따른 것이다.

Singleton 패턴

전역 변수를 사용하지 않고 객체를 하나만 생성 하도록 하며, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 패턴

싱글톤 패턴의 사용하는 이유

메모리 측면

최초 한번의 new 연산자를 통해서 고정된 메모리 영역을 사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비를 방지

이미 생성된 인스턴스를 활용하니 속도 측면에서도 이점

데이터 공유가 쉽다

싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있다

도메인 관점에서 인스턴스가 한 개만 존재하는 것을 보증하고 싶은 경우 싱글톤 패턴을 사용

factory의 특징

  • 기존에 이미 생성된 인스턴스가 있다면 return 하여 재사용한다.
  • 하나의 클래스에서 하나의 인스턴스만 생성한다(싱글톤 패턴).
  • 서브 클래스 인스턴스를 리턴할 때 사용할 수 있다.
  • Factory constructors 에서는 this 에 접근할 수 없다.

factory는 '클래스와 같은 타입의 인스턴스' 또는 '메서드를 구현하는 인스턴스'를 리턴하기만 하면 된다. 이렇게 생성된 인스턴스는기존에 생성된 인스턴스가 아니라면 새롭게 생성되고, 기존 인스턴스가 있다면 기존 것을 리턴한다.

factory 보단 warehouse 창고의 의미와 유사하다.

실사용 예

class NewsArticle {
  final String title, description, urlToImage, url;

  NewsArticle({this.title, this.description, this.urlToImage, this.url});

  factory NewsArticle.fromJSON(Map<String, dynamic> json) {
    return NewsArticle(
      title: json["title"],
      description: json["description"],
      urlToImage: json["urlToImage"],
      url: json["url"],
    );
  }
}
class AccountModel {
  AccountModel({
    this.avatar,
    this.id,
    this.iso6391,
    this.iso31661,
    this.name,
    this.includeAdult,
    this.username,
  });

  Avatar? avatar;
  int? id;
  String? iso6391;
  String? iso31661;
  String? name;
  bool? includeAdult;
  String? username;

  factory AccountModel.fromJson(Map<String, dynamic> json) => AccountModel(
        avatar: Avatar.fromJson(json["avatar"]),
        id: json["id"],
        iso6391: json["iso_639_1"],
        iso31661: json["iso_3166_1"],
        name: json["name"],
        includeAdult: json["include_adult"],
        username: json["username"],
      );

  Map<String, dynamic> toJson() => {
        "avatar": avatar!.toJson(),
        "id": id,
        "iso_639_1": iso6391,
        "iso_3166_1": iso31661,
        "name": name,
        "include_adult": includeAdult,
        "username": username,
      };
}
class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to
  // the _ in front of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    return _cache.putIfAbsent(
        name, () => Logger._internal(name));
  }

  factory Logger.fromJson(Map<String, Object> json) {
    return Logger(json['name'].toString());
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}
728x90

'Study > Dart' 카테고리의 다른 글

[Dart] future, async, await, 실행순서  (0) 2021.06.15
[Dart] const 와 final 이해하기  (0) 2021.06.15
[Dart] Future, Isolate  (0) 2021.06.08
[Dart] 상속을 쓰는 이유  (0) 2021.06.07
[Dart] 상속  (0) 2021.06.07

2021.06.16 - [Usage/Flutter] - [Flutter] Bloc Pattern (stateful -> bloc -> skip event bloc )

 

[Flutter] Bloc Pattern (stateful -> bloc -> skip event bloc )

BLOC Bussiness Logic Component 비즈니스 로직과 ui를 구분 짓고 필요에 따라 원하는 부분만 데이터 처리 실 사용 예제 버튼 클릭시 증감 1. Stateful version ui widget - 버튼 클릭시 증감 //stateless widge..

mugon-devlog.tistory.com

Install package

https://pub.dev/packages/provider

Project 구조

main.dart
src
 - count_home.dart 
 - count_provider.dart
 - count_home_widget.dart // statelesswidget

main.dart

void main() {
  runApp(MyApp());
    // runApp에서 provider를 불러오면 MyApp에서 접근 가능
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MultiProvider(
        providers: [
          ChangeNotifierProvider(
              create: (BuildContext context) => CounterProvider())
        ],
                // child의 모든 하위 요소들은 CounterProvider에 접근 가능
        child: Home(),
      ),
      // home: ChangeNotifierProvider(
      //   create: (BuildContext context) => CounterProvider(),
      //   child: Home(),
      // ),
    );
  }

count_provider.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

// ChangeNotifier 상속
// bloc 에서 stream 처리, sink 주입 했던 것을 처리해줌
class CounterProvider extends ChangeNotifier {
    // private
    // 이곳에서 선언되는 모든 변수는 상태관리 대상
  int _count = 0;
    // get 함수를 사용해서 private한 변수에 접근 가능하도록 만듦
  int get count => _count;
  add() {
    _count++;
        // 상태값이 update 되었다는 신호를 보내줌
    notifyListeners();
  }

  subtract() {
    _count--;
    notifyListeners();
  }
}

count_home.dart

class Home extends StatelessWidget {
  const Home({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
        // Provider.of로 사용할 provider를 가져옴
        // listen을 false로 해주면 현재의 widget은 rebuilding이 안됨
    CounterProvider countProvider =
        Provider.of<CounterProvider>(context, listen: false);
    return Scaffold(
      appBar: AppBar(
        title: Text("Provider"),
      ),
      body: CountView(),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () => countProvider.add(),
          ),
          IconButton(
            icon: Icon(Icons.remove),
            onPressed: () => countProvider.subtract(),
          ),
        ],
      ),
    );
  }

count_home_widget.dart

class CountView extends StatelessWidget {
  const CountView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
                // Provider.of를 통해 접근해서 count값 가져옴
                // build 전체를 rebuilding 함
        Provider.of<CounterProvider>(context).count.toString(),
      ),
    );
  }
}

// 특정 위젯만 rebuilding
class CountView extends StatelessWidget {
  const CountView({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
     return Center(
            // consumer를 사용해서 특정 위젯만 rebuilding
       child: Consumer<CounterProvider>(
                builder: (context, provider, child) {
         return Text(
           provider.count.toString(),
         );
       }),
    );
  }
}

참고

https://www.youtube.com/watch?v=AmmjdvhQG1s 

 

728x90

'Study > Flutter' 카테고리의 다른 글

[Flutter] Factory 패턴  (0) 2021.07.13
[Flutter] Stateful widget  (0) 2021.06.14
[UI초급] Container, materialApp, Scaffold  (0) 2021.06.07

Thread

프로세스 내에서 실행되는 흐름의 단위

Event loop

Dart는 Single Thread로 운영됨 → Event loop를 통해 복잡한 작업들을 효율적으로 처리

Flutter 앱을 실행시키는 순간 isolate라고 불리는 새로운 thread process가 하나 생성됨

이 thread가 앱 전체를 총괄하는 단일 thread가 됨

thread가 생성되는 순간 dart는 자동적으로 3가지 작업을 하게됨

  1. 내부적으로 First In First Out(FIFO)방식으로 MicroTask 와 Event 준비 MicroTask : event queue로 넘어가기 전에 아주 짧은 시간 동안 비동기적으로 먼저 실행되고 끝나는 작은 작업
  2. 앱의 시작점인 main 함수 실행
  3. Event loop 실행

Dart는 하나의 단일 thread가 실행되는 순간 내부적으로 event loop process를 통해 순서대로 대기열에 있는 micro task와 event를 처리

더 이상 내부적으로 진행할 micro task가 없다면 event loop는 외적으로 전달되는 각종 이벤트 (gesture, drawing, reading files, fetching data, button tap, future, stream 등)를 순서대로 처리하게 됨

각종 외적인 이벤트들이 이벤트 큐에 등록되고 이벤트 루프를 통해 처리

Future

비동기 방식으로 미래의 어느시점에 완성되어서 실제적인 데이터가 되거나 에러를 반환하는 객체

코드상에서 새로운 future를 객체화 시키면

  1. 다트에 의해서 future 객체가 내부적인 배열에 등록
  2. Future 관련해서 실행되어야하는 코드들이 이벤트 큐(대기열)에 등록
  3. 불완전한 future 객체가 반환
  4. Synchronous 방식으로 실행되어야 할 코드 먼저 실행
  5. 최종적으로 실제적인 data 값이 future 객체로 전달

Async method

async 키워드를 사용한 순간

  1. 메서드를 통해서 나오는 결과물들은 future라는 것을 알게 됨
  2. await 키워드를 만날때까지 synchronous 방식으로 코드 처리
  3. await 키워드를 만나면 future가 완료될 때까지 대기
  4. future가 완료 되자마자 그 다음 코드들을 실행

전체 앱의 실행이 중지되지 않고 future 부분은 건너띄고 그 아래에 있는 코드들을 synchronous하게 처리

예시

String createOrderMessage(){
    var order = fetchUserOrder();
    return 'Your order is: $order';
}

Future<String> fetchUserOrder(){
    return Future.delayed(
        Duration(second: 2), ()=>'Large Latte',
    );
}

void main(){
    print('Fetching user order...');
    print(createOrderMessage());
}

실행시 에러 → main()의 두번째 print에서 createOrderMessage()는 미완성의 객체를 반환하고 있기 때문

fetchUserOrder()에서 2초를 기다리고 fetchUserOrder()가 반환해야 하는데 기다리지 않고 즉시 반환하기 때문 → 이를 해결하기 위해 async 키워드 사용

createOrderMessage() 수정

  1. 비동기 방식으로 실행된 결과의 String 값을 리턴해줘야하므로 타입 변경 String → Future
  2. order 변수에 fetchUserOrder 함수의 리턴값을 할당해줄려면 즉시할당하는 synchronous 방식이 아니라 기다렸다가 값이 전달되는 비동기 방식어야함 createOrderMessage()가 비동기 방식으로 처리되어야함을 dart에게 알려줘야함 → async 키워드 추가
  3. fetchUserOrder()의 실행이 끝날때까지 기다렸다가 order 변수에 값을 할당해줘야함 → await 추가
// 1
Future<String> createOrderMessage() async{ // 2
              // 3
    var order = await fetchUserOrder();
    return 'Your order is: $order';
}

main() 수정

  1. main()에서 호출되는 createOrderMessage()가 비동기 방식으로 처리되는 함수이므로 main()도 비동기 방식으로 처리됨을 알려줘야함 → async 추가
  2. createOrderMessage()의 리턴값이 출려되려면 order변수의 값이 할당될 때까지 기다려야함 → await 추가
// 1
void main() async{
    print('Fetching user order...');
    // 2
    print(await createOrderMessage());
}

정리

async 키워드는 future 자체를 대신하는 것이 아니라 비동기 방식으로 실행되는 함수라는 것을 dart에게 알려주는 기능을 하는 것이며 await 키워드와 함께 미래의 어느 시점에 전달될 값을 기다리는 것

future는 하나의 객체로서 객체가 생성되는 순간에는 미완성으로 존재하다가 미래의 어느 시점에 데이터를 전달받은 온전한 객체가 되거나 데이터에 문제가 생긴다면 에러를 반환

심화 예제

void main() async {
  methodA(); // 1
  await methodB(); // 3
  await methodC('main'); // 9
  methodD(); // 12
}

methodA(){
  print('A'); // 2
}

methodB() async {
  print('B start'); // 4
  await methodC('B'); // 5
  print('B end'); // 8
}

methodC(String from) async {
  print('C start from $from'); // 6 'b' // 10 'main'

  Future((){
    print('C running Future from $from'); // 14 'b' // 16 'main'
  }).then((_){
    print('C end of Future from $from'); // 15 'b' // 17 'main'
  });

  print('C end from $from'); // 7 'b' // 11 'main'
}

methodD(){
  print('D'); // 13
}

//////
A
B start
C start from B
C end from B
B end
C start from main
C end from main
D
C running Future from B
C end of Future from B
C running Future from main
c runngin Future from main
///

참고

https://www.youtube.com/watch?v=HjhPhAUPHos&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=12 

 

728x90

'Study > Dart' 카테고리의 다른 글

[Dart] factory 패턴  (0) 2021.06.24
[Dart] const 와 final 이해하기  (0) 2021.06.15
[Dart] Future, Isolate  (0) 2021.06.08
[Dart] 상속을 쓰는 이유  (0) 2021.06.07
[Dart] 상속  (0) 2021.06.07

+ Recent posts