Dart는 강력한 정적 타입 언어로, 모든 변수는 특정 데이터 타입을 가진다. Dart의 데이터 타입은 크게 기본 타입과 컬렉션 타입으로 나눌 수 있으며, 사용자가 정의한 타입을 포함한 다양한 확장성도 제공한다.

숫자형 (Numbers)

Dart에서는 intdouble 두 가지 주요 숫자형 타입이 존재한다.

정수형 (int)

정수형은 부호가 있는 64비트의 정수로 표현되며, int 타입으로 선언한다. 다음은 정수형의 특징이다.

int x = 5;

실수형 (double)

실수형은 IEEE 754 표준에 따른 64비트 부동소수점으로 표현되며, double 타입으로 선언된다. 실수형은 매우 큰 값 또는 매우 작은 값을 표현할 때 사용한다.

double y = 3.14;

수학적 표현

변수 x 가 정수형이라면:

x \in \mathbb{Z}

변수 y 가 실수형이라면:

y \in \mathbb{R}

이렇게 정수형과 실수형을 사용하여 다양한 계산이 가능하다.

문자열 (Strings)

문자열은 String 타입으로 선언되며, 유니코드 텍스트를 포함할 수 있다. Dart에서 문자열은 큰따옴표(" ") 또는 작은따옴표(' ')로 감싸서 표현할 수 있다.

문자열 선언 예시:

String name = 'ChatGPT';

여러 줄 문자열

여러 줄 문자열은 세 개의 작은따옴표(''' ''') 또는 큰따옴표(""" """)로 감싸서 작성할 수 있다.

String multiline = '''
이 문자열은
여러 줄로 작성되었다.
''';

문자열 보간법

Dart에서는 문자열 내에서 변수를 쉽게 삽입할 수 있는 문자열 보간법을 제공한다. 문자열 보간은 $ 기호를 사용하여 변수를 삽입하거나 표현식을 중괄호({})로 감싸서 사용한다.

String greeting = 'Hello, $name!';

또는 표현식을 포함할 수 있다:

String message = '2 + 2 equals ${2 + 2}';

불리언 (Booleans)

불리언 타입은 bool로 선언되며, 두 가지 값만 가질 수 있다: true 또는 false. 불리언 값은 주로 조건문에서 사용된다.

예시:

bool isVisible = true;

컬렉션 타입 (Collections)

Dart는 List, Set, Map 등의 기본 컬렉션 타입을 제공한다. 각 컬렉션은 데이터를 저장하고 관리하는 데 사용되며, 각각의 특징이 다르다.

List

List는 순서가 있는 데이터의 집합이며, 배열처럼 사용할 수 있다. Dart의 List는 가변 길이를 지원하며, 고정 길이로도 선언할 수 있다.

List<int> numbers = [1, 2, 3, 4];

Set

Set은 순서가 없는 고유한 값들의 집합이다. Set은 중복된 요소를 허용하지 않는다.

Set<String> uniqueNames = {'Alice', 'Bob', 'Charlie'};

Map

Map은 키와 값의 쌍으로 이루어진 컬렉션이다. 각 키는 고유하며, 이를 통해 값에 접근할 수 있다.

Map<String, int> ages = {
  'Alice': 25,
  'Bob': 30,
};

Null 허용 및 Null 안전성 (Null Safety)

Dart에서는 Null Safety 기능을 통해 변수나 객체가 null 값을 가질 가능성을 명시적으로 제어할 수 있다. 기본적으로 Dart에서는 모든 변수는 null을 허용하지 않으며, 반드시 초기화되어야 한다. 만약 변수에 null 값을 허용하려면 타입 선언 시 ?를 추가해야 한다.

Null 허용 변수 선언 예시:

int? age = null;

위 코드에서 age 변수는 null 값을 가질 수 있는 정수형으로 선언되었다. 이를 통해 null 값에 안전하게 접근할 수 있다.

Null 값 접근 시 안전 연산자

변수에 null 값을 안전하게 접근하려면 Dart에서 제공하는 안전 연산자를 사용할 수 있다.

예시:

String? name;
print(name?.toUpperCase() ?? 'Unknown');

위 코드는 name이 null일 경우 'Unknown'을 출력하며, 그렇지 않으면 name의 값을 대문자로 변환해 출력한다.

동적 타입 (dynamic)

Dart에서는 dynamic 타입을 사용하여 특정 타입에 구애받지 않고 다양한 데이터 타입을 가질 수 있는 변수를 선언할 수 있다. 하지만 동적 타입의 사용은 타입 안전성을 감소시킬 수 있으므로 필요한 경우에만 사용하는 것이 권장된다.

동적 타입 예시:

dynamic variable = 'Hello';
variable = 42; // 가능

dynamic 타입은 컴파일 시 타입 검사를 생략하고, 런타임에 타입을 결정한다.

타입 추론

Dart에서는 타입 추론(Type Inference) 기능을 제공하여, 변수를 선언할 때 명시적으로 타입을 지정하지 않아도 Dart가 자동으로 타입을 추론할 수 있다. 이를 통해 코드가 더욱 간결해진다. Dart에서는 var 키워드를 사용하여 타입을 명시하지 않고 변수를 선언할 수 있다.

타입 추론 예시:

var number = 10; // int로 추론됨
var message = 'Hello'; // String으로 추론됨

주의할 점:

var 키워드로 선언된 변수는 최초 할당된 값에 따라 타입이 고정된다. 따라서 같은 변수에 다른 타입의 값을 할당할 수 없다.

var text = 'Hello';
// text = 42; // 컴파일 에러 발생

타입 캐스팅

Dart에서는 타입 캐스팅을 통해 특정 타입의 객체를 다른 타입으로 변환할 수 있다. as 키워드를 사용하여 명시적인 캐스팅을 수행할 수 있다.

타입 캐스팅 예시:

dynamic value = 'Hello';
String message = value as String;

캐스팅이 성공하면 변환된 값을 사용할 수 있으며, 캐스팅에 실패하면 런타임 오류가 발생할 수 있다. 이를 방지하기 위해 is 키워드를 사용하여 타입을 미리 확인할 수 있다.

타입 확인 예시:

if (value is String) {
  print('value는 문자열이다.');
}

is 키워드를 사용하면 객체가 특정 타입인지 확인한 후 안전하게 캐스팅할 수 있다.