3 minute read


1. Dart 란?

Dart(다트)는 2011년 구글에서 프론트엔드 개발을 위해 만든 언어로 다른 언어들과 유사한 방법으로 구현 및 사용이 가능하다.

안드로이드, iOS, web 등 멀티 플랫폼에 사용이 가능하며 처음에는 웹 브라우저 내에서 JavaScript를 대체하기 위해 개발되었지만 현재는 Flutter 프레임워크를 통해 Native App 개발에도 널리 사용되고 있다.

객체지향 언어이며 null Safety를 지원하고 JIT 방식으로 컴파일을 하기 때문에 매우 빠른 속도로 컴파일이 가능하고, 배포 시에는 AOT 방식으로 컴파일을 한다.



2. Dart의 기초

2.1 변수의 타입

타입 설명
var 타입을 따로 설정하지 않고 처음 선언한 값에 따라 데이터 타입이 결정된다.
int 정수
double 실수
boolean true/false
string 문자
dynamic 어떤 타입에도 사용이 가능하다.
final 변수 선언 뒤 변경이 불가능하다.
const 변수 선언 뒤 변경이 불가능하다.

위에서 정리한 내용을 보면 몇 가지 의문점이 생긴다. var과 dynamic은 어떤 타입에도 사용이 가능하다는 특징이 있고, final과 const는 변수를 선언한 뒤 변경이 불가능하다는 특징이 있다.

그럼 비슷해 보이는 타입들의 차이는 무엇일까?

2.1.1 var, dynamic의 차이

var과 dynamic은 선언한 변수의 타입을 변경 가능 여부 차이가 있다. 예를 들어 var test = “name”; 이라고 선언했다면 test = 25; 와 같이 다른 타입의 변수로 변경이 불가능하다.

하지만 dynamic은 dynamic test = “name”; 이라고 선언하고 뒤에서 dynamic test = 25; 로 변경이 가능하다.

ex) var 과 dynamic의 차이

1
2
3
4
5
6
7
8
9
var test1 = "name";
print(test1);   //result : "name"
test1 = 25;
print(test1);   //result : error

dynamic test2 = "name";
print(test2);   //result : "name"
dynamic test2 = 25;
print(test2);   //resutl : 25

2.1.2 final, const의 차이

final과 const는 변수를 선언한 뒤 변경이 불가능하다는 공통점을 가지고 있지만 빌드타임을 알아야한다는 차이가 있다.

DateTime을 활용해서 두 타입의 차이를 확인해 볼 수 있는데, DateTime은 빌드되는 시점이 아닌 코드가 실행되는 시점의 시간을 확인할 수 있다. 여기서 const는 빌드타임을 알아야 하기 때문에 실행 시점의 시간을 가져오는 DateTime을 사용하면 에러가 발생한다.

ex) final과 const의 차이

1
2
3
4
5
const DateTime now = DateTime.now();
print(now);   //result : 2023-11-21 01:18:26.573

final DateTime now = DateTime.now();
print(now);   //result : error


2.2 변수 타입 확인하기

String, int, double 등 선언 타입은 이미 지정된 타입이 있지만 var, dynamic, final 같은 타입은 지정된 타입이 따로 없다. 이 때 변수의 타입을 확인할 수 있는데 runtimeType을 사용하면 된다.

1
2
3
4
5
var test1 = "name";
print(test1.runtimeType);   //result : String

dynamic test2 = 25;
print(test2.runtimeType);   //result : int


2.3 nullable, non-nullable

변수에 null이 들어갈 수 있을까? 아래 코드를 테스트 해보면 선언된 변수에 null을 담으면 에러가 발생하는 것을 볼 수 있다.

1
2
3
4
5
String name = "Son";
print(name);    //result : "Son"

name = null;
print(name);    //result  : error

nullable 상태의 변수를 선언하려면 타입뒤에 ?를 붙여주면 된다.

1
2
3
4
5
String? name = "Son";
print(name);    //result : "Son"

name = null;
print(name);    //result  : null



3. 컬렉션(Collection)

3.1 List

리스트는 데이터를 순차적으로 담을 수 있는 인덱싱이 간으한 자료구조로 배열을 대신해서 사용할 수 있다. 데이터의 순서가 있고 중복을 허용한다는 특징이 있다.

1
2
3
4
5
6
7
8
9
10
11
12
//기본 형식
List<String> name = ['son', 'lee'];
List<int> num = [7,14];

//값의 추가 - list의 타입과 동일한 값만 추가 가능
name.add('hwang');

//특정 값의 삭제
name.remove('hwang');

//해당 value의 index를 가져오기
name.indexOf('son');


3.2 Map

Map은 key와 value로 구성되며 key는 고유 값이어야 한다. 이미 존재하는 key에 값을 넣으면 기존 값에 덮어 씌워진다. 따라서 key는 중복을 허용하지 않지만 value는 중복을 허용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//기본 형식
Map<String, String> dictionary = {
  'Son' : 'TOT',
  'Lee' : 'PAR',
};

//여러개의 값 추가
dictionary.addAll({
  'Kim' : 'BAY',
  'Hwang' : 'WOL'
});

//값의 추가
dictionary['Kim'] = "BAY";

//특정 값 삭제
dictionary.remove('Lee');

//기존 값 변경 - (변경할 값의 index, (value) => "변경할 값")
dictionary.update(1, (value) => "Lee");

 //key 값 가져오기
dictionary.keys;

//value 값 가져오기
dictionary.value;


3.3 Set

List와 동일하게 배열로 이루어지지만 데이터의 순서가 없고 중복을 허용하지 않는다. 중복 값을 제거할 때 자주 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
//기본 형식
final Set<string> names = {
  'son',
  'lee',
  'kim',
};

//값 추가 - 중복 값은 추가되지 않는다.
names.add('hwang');     

//값 삭제
names.remove('hwang');