dart-1

Date:     Updated:

카테고리:

태그:

다트 소개

안드로이드와 iOS 등 멀티 플랫폼 상에서 동작되는 앱을 위해 디자인되었으며 떠오르는 크로스 플랫폼 앱 개발 프레임워크 Flutter에서 사용되는 프로그래밍 언어는 무엇일까요? 네, 바로 ‘Dart(다트)’입니다.

현재 구글 클래스룸, 알리바바, 구글 페이, 네이버 지식인 앱, 데마에칸(일본의 배민, 라인에서 운영) 등의 유수한 앱에서 Flutter에서 Dart를 활용해 앱을 제작하며, 혁신적인 IT 기업들의 사용빈도가 높아지고 있습니다. 이를 대변하듯이 티오베(TIOBE)에서 뽑은 2024년 주목할 언어 중 하나로 뽑혔는데요.

Dart는 2011년 GOTO 컨퍼런스에서 구글이 발표한 자바스크립트를 대체 가능한 크로스 플랫폼 프로그래밍 언어로, 발표 당시에는 주목을 못 받았지만 2017년 Dart를 사용하는 Flutter의 등장으로 수요가 높아지며 사용도가 급성장한 언어입니다.

기본적으로 C 언어의 문법과 비슷하며 Java, C#, JavaScript와 같은 기능적 스트럭처를 추가한 언어로, 간결하고 강력한 기능을 지원하기에 현대적이라는 평가를 받고 있습니다.

이 페이지에서는 주요 기능에 대한 샘플을 통해 Dart 언어에 대한 간략한 소개를 제공합니다.

Dart의 핵심 라이브러리에 대한 내용은 핵심 라이브러리 설명서를 확인하세요. 더욱 상호 작용적인 소개를 위해 Dart 치트시트 도 확인할 수 있습니다 .

hello world!

모든 앱에는 실행이 시작되는 최상위 main()함수가 필요합니다. 값을 명시적으로 반환하지 않는 함수는 void반환 유형을 갖습니다. 콘솔에 텍스트를 표시하려면 최상위 print()함수를 사용할 수 있습니다.

void main() {
  print('Hello, World!');
}

명령줄 인수에 대한 선택적 매개변수를 포함하여 Dart의 함수 main()에 대해 자세히 알아보세요 .

변수

유형 안전한 Dart 코드 에서도 .를 사용하여 유형을 명시적으로 지정하지 않고도 대부분의 변수를 선언할 수 있습니다 var. 유형 추론 덕분에 이러한 변수의 유형은 초기 값에 따라 결정됩니다.

var name = 'Voyager I';
var year = 1977;
var antennaDiameter = 3.7;
var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];
var image = {
  'tags': ['saturn'],
  'url': '//path/to/saturn.jpg'
};

Dart의 변수, 기본값, 키워드, 정적 유형에 대해 final자세히 const알아 보세요 .

제어 흐름 문장

# Dart는 일반적인 제어 흐름 명령문을 지원합니다.

if (year >= 2001) {
  print('21st century');
} else if (year >= 1901) {
  print('20th century');
}

for (final object in flybyObjects) {
  print(object);
}

for (int month = 1; month <= 12; month++) {
  print(month);
}

while (year < 2016) {
  year += 1;
}

Dart의 제어 흐름 문( break및continue , switch및case ) 에 대해 자세히 알아보세요 assert.

기능

# 각 함수의 인수와 반환 값의 유형을 지정하는 것이 좋습니다 .

int fibonacci(int n) {
  if (n == 0 || n == 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

var result = fibonacci(20);

단축형 =>( 화살표 ) 구문은 단일 문장을 포함하는 함수에 유용합니다. 이 구문은 익명 함수를 인수로 전달할 때 특히 유용합니다.

flybyObjects.where((name) => name.contains('turn')).forEach(print);

익명 함수(의 인수 where())를 보여주는 것 외에도, 이 코드는 함수를 인수로 사용할 수 있음을 보여줍니다. 최상위 print()함수는의 인수입니다 forEach().

선택적 매개변수, 기본 매개변수 값, 어휘 범위를 포함한 Dart의 함수에 대해 자세히 알아보세요 .

코멘트

Dart 주석은 일반적으로 .으로 시작합니다 //.

// This is a normal, one-line comment.

/// This is a documentation comment, used to document libraries, /// classes, and their members. Tools like IDEs and dartdoc treat /// doc comments specially.

/* Comments like these are also supported. */

Dart의 주석에 대해 자세히 알아보고 문서화 툴의 작동 방식도 알아보세요.

# 다른 라이브러리에 정의된 API에 액세스하려면 .을 사용합니다 import.

// Importing core libraries
import 'dart:math';

// Importing libraries from external packages
import 'package:test/test.dart';

// Importing files
import 'path/to/my_other_file.dart';

Dart의 라이브러리와 가시성, 라이브러리 접두사 및 키워드를 통한 지연 로딩에 대해 show자세히 hide알아 보세요deferred .

클래스

다음은 세 개의 속성, 두 개의 생성자, 그리고 메서드가 있는 클래스의 예입니다. 속성 중 하나는 직접 설정할 수 없으므로 게터 메서드(변수 대신)를 사용하여 정의됩니다. 이 메서드는 문자열 보간을 사용하여 문자열 리터럴 내부에 변수의 문자열 동등물을 인쇄합니다.

class Spacecraft {
  String name;
  DateTime? launchDate;

  // Read-only non-final property
  int? get launchYear => launchDate?.year;

  // Constructor, with syntactic sugar for assignment to members.
  Spacecraft(this.name, this.launchDate) {
    // Initialization code goes here.
  }

  // Named constructor that forwards to the default one.
  Spacecraft.unlaunched(String name) : this(name, null);

  // Method.
  void describe() {
    print('Spacecraft: $name');
    // Type promotion doesn't work on getters.
    var launchDate = this.launchDate;
    if (launchDate != null) {
      int years = DateTime.now().difference(launchDate).inDays ~/ 365;
      print('Launched: $launchYear ($years years ago)');
    } else {
      print('Unlaunched');
    }
  }
}

문자열 보간, 리터럴, 표현식 및 메서드를 포함하여 문자열에 대해 자세히 알아보세요toString() .

다음과 같이 클래스를 사용할 수 있습니다 Spacecraft.

var voyager = Spacecraft('Voyager I', DateTime(1977, 9, 5));
voyager.describe();

var voyager3 = Spacecraft.unlaunched('Voyager III');
voyager3.describe();

new초기화 목록, 선택적 및 const, 리디렉션 생성자, factory생성자, 게터, 세터 등을 포함하여 Dart의 클래스에 대해 자세히 알아보세요 .

열거형

# 열거형은 다른 유형의 인스턴스가 존재하지 않도록 하는 방식으로 미리 정의된 값이나 인스턴스 집합을 열거하는 방법입니다.

enum미리 정의된 행성 유형의 간단한 목록을 정의하는 간단한 예는 다음과 같습니다 .

enum PlanetType { terrestrial, gas, ice }

다음은 행성을 설명하는 클래스의 향상된 열거형 선언의 예입니다. 정의된 상수 인스턴스 집합, 즉 우리 태양계의 행성이 있습니다.

/// Enum that enumerates the different planets in our solar system
/// and some of their properties.
enum Planet {
  mercury(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  // ···
  uranus(planetType: PlanetType.ice, moons: 27, hasRings: true),
  neptune(planetType: PlanetType.ice, moons: 14, hasRings: true);

  /// A constant generating constructor
  const Planet(
      {required this.planetType, required this.moons, required this.hasRings});

  /// All instance variables are final
  final PlanetType planetType;
  final int moons;
  final bool hasRings;

  /// Enhanced enums support getters and other methods
  bool get isGiant =>
      planetType == PlanetType.gas || planetType == PlanetType.ice;
}

열거형을 다음과 같이 사용할 수 있습니다 Planet.

final yourPlanet = Planet.earth;

if (!yourPlanet.isGiant) {
  print('Your planet is not a "giant planet".');
}

Dart의 열거형에 대해 자세히 알아보세요 . 여기에는 향상된 열거형 요구 사항, 자동으로 도입된 속성, 열거형 값 이름 액세스, switch 문 지원 등이 포함됩니다.

계승

Dart는 단일 상속을 갖습니다.

class Orbiter extends Spacecraft {
  double altitude;

  Orbiter(super.name, DateTime super.launchDate, this.altitude);
}

클래스 확장, 선택적 @override주석 등에 대해 자세히 알아보세요 .

믹스인

# 믹스인은 여러 클래스 계층에서 코드를 재사용하는 방법입니다. 다음은 믹스인 선언입니다.

mixin Piloted {
  int astronauts = 1;

  void describeCrew() {
    print('Number of astronauts: $astronauts');
  }
}

클래스에 믹스인의 기능을 추가하려면 믹스인으로 클래스를 확장하기만 하면 됩니다.

class PilotedCraft extends Spacecraft with Piloted {
  // ···
}

PilotedCraft이제 astronauts필드와 describeCrew()메서드도 갖게 되었습니다.

믹스인에 대해 자세히 알아보세요 .

인터페이스와 추상 클래스

# 모든 클래스는 암묵적으로 인터페이스를 정의합니다. 따라서 모든 클래스를 구현할 수 있습니다.

class MockSpaceship implements Spacecraft { // ··· } 콘텐츠_복사 암시적 인터페이스 나 명시 interface적 키워드 에 대해 자세히 알아보세요 .

구체적 클래스에 의해 확장(또는 구현)될 추상 클래스를 만들 수 있습니다. 추상 클래스는 추상 메서드(빈 본문 포함)를 포함할 수 있습니다.

abstract class Describable {
  void describe();

  void describeWithEmphasis() {
    print('=========');
    describe();
    print('=========');
  }
}

모든 클래스 확장에는 확장자의 구현을 호출하는 메서드 Describable가 있습니다 .describeWithEmphasis()describe()

추상 클래스와 메서드에 대해 자세히 알아보세요 .

비동기

async콜백 지옥을 피하고 and 를 사용하면 코드의 가독성이 훨씬 높아집니다 await.

const oneSecond = Duration(seconds: 1); // ··· Future printWithDelay(String message) async { await Future.delayed(oneSecond); print(message); }

위의 방법은 다음과 같습니다.

Future<void> printWithDelay(String message) {
  return Future.delayed(oneSecond).then((_) {
    print(message);
  });
}

다음 예제에서 보듯 async이 , await비동기 코드를 읽기 쉽게 만드는 데 도움이 됩니다.

Future<void> createDescriptions(Iterable<String> objects) async {
  for (final object in objects) {
    try {
      var file = File('$object.txt');
      if (await file.exists()) {
        var modified = await file.lastModified();
        print(
            'File for $object already exists. It was modified on $modified.');
        continue;
      }
      await file.create();
      await file.writeAsString('Start describing $object in this file.');
    } on IOException catch (e) {
      print('Cannot create description for $object: $e');
    }
  }
}

async*또한 , 스트림을 구축하는 멋지고 읽기 쉬운 방법을 제공하는 를 사용할 수도 있습니다 .

Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
  for (final object in objects) {
    await Future.delayed(oneSecond);
    yield '${craft.name} flies by $object';
  }
}

async함수, Future, Stream및 비동기 루프( ) 를 포함한 비동기 지원에 대해 자세히 알아보세요await for .

예외

예외를 발생시키려면 다음을 사용합니다 throw.

if (astronauts == 0) {
  throw StateError('No astronauts.');
}
예외를 포착하려면 다음 try 같이 onor catch(또는  ) 포함된 명령문을 사용합니다.

Future<void> describeFlybyObjects(List<String> flybyObjects) async {
  try {
    for (final object in flybyObjects) {
      var description = await File('$object.txt').readAsString();
      print(description);
    }
  } on IOException catch (e) {
    print('Could not describe object: $e');
  } finally {
    flybyObjects.clear();
  }
}

위 코드는 비동기식입니다. try동기식 코드와 async함수 내의 코드 모두에 적용됩니다.

스택 추적을 포함한 예외 와 , 그리고 rethrow의 차이점에 대해 자세히 알아보세요 .ErrorException

중요한 개념

Dart 언어에 대해 계속 학습하면서 다음과 같은 사실과 개념을 명심하세요.

변수에 넣을 수 있는 모든 것은 객체 이고, 모든 객체는 클래스 의 인스턴스입니다 . 숫자, 함수, 조차도 객체입니다. ( 사운드 널 안전성을 활성화하는 경우 ) null를 제외하고 모든 객체는 클래스에서 상속합니다.nullObject

버전 참고 Null 안전성은 Dart 2.12에서 도입되었습니다. Null 안전성을 사용하려면 최소 2.12 이상의 언어 버전이 필요합니다.

Dart는 강력하게 타입화되어 있지만 Dart가 타입을 추론할 수 있기 때문에 타입 주석은 선택 사항입니다. 에서 는 var number = 101타입 number으로 추론됩니다 int.

null 안전성을 활성화하면 변수는 사용자가 허용한다고 명시하지 않는 한 포함할 수 없습니다 . 변수의 유형 끝에 null물음표( )를 넣어 변수를 null 허용으로 만들 수 있습니다 . 예를 들어, 유형의 변수는 정수일 수도 있고, . 표현식이 로 평가되지 않지만 Dart에서 그렇지 않다는 것을 알고 있다면 를 추가 하여 null이 아니라고 단언하고(그리고 null인 경우 예외를 throw) 할 수 있습니다. 예:?int?nullnull!int x = nullableButNotNullInt!

어떤 유형이든 허용된다는 것을 명시적으로 말하고 싶을 때는 type Object?(null 안전성을 활성화한 경우) 을 사용 Object하거나, 런타임까지 유형 검사를 연기해야 ​​하는 경우 특수 유형dynamic .을 사용합니다 .

ListDart는 (정수 목록)이나 List(모든 유형의 객체 목록) 과 같은 일반 유형을 지원합니다 .

Dart는 최상위 함수(예: main())와 클래스나 객체에 연결된 함수( 각각 정적 및 인스턴스 메서드 )를 지원합니다. 함수 내에서 함수를 생성할 수도 있습니다( 중첩 또는 로컬 함수 ).

마찬가지로 Dart는 최상위 변수 는 물론 클래스나 객체에 연결된 변수(정적 및 인스턴스 변수)도 지원합니다. 인스턴스 변수는 때때로 필드 또는 속성 이라고도 합니다 .

Java와 달리 Dart에는 키워드 public, protected, private. 식별자가 밑줄( _)로 시작하면 라이브러리에 비공개입니다. 자세한 내용은 라이브러리 및 가져오기를 참조하세요 .

식별자는 문자나 밑줄( _)로 시작할 수 있으며, 그 뒤에 해당 문자와 ​​숫자를 조합한 형태가 올 수 있습니다.

Dart에는 표현식 (런타임 값이 있음)과 문장 (값이 없음)이 모두 있습니다. 예를 들어, 조건 표현식은 or condition ? expr1 : expr2값을 갖습니다 . 값이 없는 if-else 문장 과 비교해 보세요 . 문장은 종종 하나 이상의 표현식을 포함하지만, 표현식은 문장을 직접 포함할 수 없습니다.expr1expr2

Dart 도구는 경고 와 오류 라는 두 가지 종류의 문제를 보고할 수 있습니다 . 경고는 코드가 작동하지 않을 수 있다는 표시일 뿐, 프로그램 실행을 방해하지는 않습니다. 오류는 컴파일 타임 또는 런타임 중 하나일 수 있습니다. 컴파일 타임 오류는 코드가 전혀 실행되지 못하게 하고, 런타임 오류는 코드가 실행되는 동안 예외가 발생합니다.

Dart 카테고리 내 다른 글 보러가기

댓글 남기기