노마드코더 - Dart 시작하기를 수강하고 정리한 글입니다.
Dart는 구글에서 개발한 객체지향 프로그래밍 언어로 Flutter 개발에 필수로 사용되는 언어다.
🚀 Dart의 장점
- 여러 플랫폼에서 사용 가능
- Dart는
Dart Native
,Dart Web
두 가지 컴파일러를 제공한다. - 웹, 모바일, 데스크탑 등 다양한 환경에서 실행할 수 있도록 컴파일할 수 있다.
- Dart는
- JIT / AOT 컴파일 모드 지원
JIT (Just In Time)
: 개발 중 빠른 빌드와 디버깅을 위해 사용.AOT (Ahead Of Time)
: 앱 배포 시 실행 성능을 최적화하기 위해 사용.
✍️ Dart 문법
기본
- 모든 코드는
main
함수에서 실행된다.- Go언어처럼 Dart에서도 모든 파일은 main 함수를 가지고, 코드는 그 안에서 실행된다.
- 모든 문장은 세미콜론
;
으로 끝난다.- Dart 포맷터가 상황에 따라 세미콜론을 자동 추가하지 않기 때문에 직접 신경 써야 한다.
📦 변수 (Variables)
var
- 타입을 추론해 변수 선언. 선언 후 타입이 고정된다.
void main() {
var name = '은지';
name = 1; // Error!
}
명시적 타입 지정
- 명확한 타입을 선언할 때 사용한다.
void main() {
String name = '은지';
}
dynamic
- 다양한 타입을 저장할 수 있는 변수 타입.
- 타입 체크는
변수 is 타입
으로 한다.
void main() {
dynamic changable = '은지';
changable = 12;
changable = false;
if (changable is String) { /* ... */ }
}
Null Safety
- 변수에
?
를 붙이면 null을 허용할 수 있다.
void main() {
String? name = '은지';
name = null;
if (name != null) name.isEmpty;
name?.length; // null이면 에러 없이 null 리턴
}
final
- 한 번만 값을 할당할 수 있다. 런타임에 값이 결정된다.
final name = '은지';
name = '응디'; // Error!
late
- 변수를 나중에 초기화할 때 사용한다.
- 컴파일러가 초기화 전에 접근하는 것을 방지해준다.
void main() {
late String name;
name = '은지';
}
const
- 컴파일 타임에 값이 확정되는 상수.
- 실행 중 API로 받은 데이터에는 사용할 수 없다.
const name = '은지';
🔢 데이터 타입
기본 타입
String
,bool
,int
,double
,num
num
은int
와double
을 모두 포함하는 타입.
void main() {
String name = 'nico';
bool alive = true;
int age = 18;
double money = 25.45;
num x = 12;
}
List
- 배열 형태의 자료구조.
collection if
,collection for
를 지원한다.
void main() {
var numbers = [1, 2, 3];
List<int> nums = [1, 2, 3];
var oldFriends = ['peter', 'jenny'];
var newFriends = [
'sana',
for (var friend in oldFriends) "💕$friend",
];
}
String Interpolation
${}
문법을 사용해 문자열 안에 변수를 삽입한다.
void main() {
var name = 'eunji';
var age = 18;
var greeting = 'Hello $name, I am ${age + 2} years old.';
}
Map
- 키-값 쌍으로 이루어진 자료구조.
void main() {
var player = {'name': 'nico', 'xp': 19.99};
Map<int, bool> book = {1: true, 2: false};
}
Set
- 중복을 허용하지 않는 컬렉션.
void main() {
var numbers = {1, 2, 3, 4};
}
Enum
- 열거형 타입.
enum Team { red, blue }
void main() {
Team myTeam = Team.red;
}
🛠️ 함수 (Functions)
기본 함수 선언
void sayHello(String name) {
print('Hello $name');
}
Fat Arrow Syntax (한 줄 리턴)
String greet() => 'Hello world';
Named Parameters
- 인자 이름을 명시해서 전달.
required
키워드로 필수 여부를 지정할 수 있다.
String sayHello({required String name, required int age}) {
return "Hello $name, you are $age years old.";
}
Optional Positional Parameters
- 대괄호로 감싸서 선택적 인자를 만든다.
String sayHello(String name, int age, [String? country]) {
return "Hello $name from $country";
}
Null 병합 연산자 (??)
- 왼쪽 값이 null이면 오른쪽 값을 반환.
String capitalizeName(String? name) => name?.toUpperCase() ?? "eunji";
Null 병합 할당 연산자 (??=)
- 변수가 null일 때만 값을 할당.
void main() {
String? name;
name ??= 'eunji';
}
📐 타입 별칭 (typedef)
- 타입을 짧게 별칭으로 정의할 수 있다.
typedef ListOfInts = List<int>;
ListOfInts reverseNums(ListOfInts list) {
return list.reversed.toList();
}
🏛️ 클래스 (Class)
기본 클래스
class Player {
final String name = 'eunji';
int xp = 1500;
void sayHello() {
print('Hi my name is $name');
}
}
생성자 (Constructor)
class Player {
final String name;
int xp;
Player(this.name, this.xp);
}
Named Constructor Parameters
class Player {
final String name;
int xp;
String team;
int age;
Player({
required this.name,
this.xp = 100,
required this.team,
required this.age,
});
}
Named Constructor
- 추가 생성자(이름을 붙인 생성자)를 정의할 수 있다.
class Player {
final String name, team;
int xp, age;
Player.createBluePlayer({required String name, required int age})
: this.name = name,
this.team = 'blue',
this.age = age,
this.xp = 0;
}
API 데이터로 객체 만들기 (fromJson)
class Player {
final String name, team;
int xp, age;
Player.fromJson(Map<String, dynamic> json)
: name = json['name'],
team = json['team'],
xp = json['xp'],
age = 18;
}
🏃♂️ Cascade Notation (연속 접근)
..
을 사용해 같은 객체에 여러 작업을 연속으로 적용.
void main() {
var player = Player(name: 'eunji', team: 'red', age: 18)
..name = 'babo'
..xp = 2000
..sayHello();
}
🚗 추상 클래스 (Abstract Class)
- 인터페이스처럼 메소드만 정의하고 구현하지 않는다.
abstract class Vehicle {
void moveForward(int meters);
}
class Car extends Vehicle {
@override
void moveForward(int meters) {
print('Moving forward $meters meters');
}
}
🧬 상속 (Inheritance)
class Human {
final String name;
Human({required this.name});
}
class Player extends Human {
final Team team;
Player({required this.team, required String name}) : super(name: name);
}
🧩 믹스인 (Mixins)
- 여러 클래스로부터 기능을 "복붙"하는 방식.
mixin Strong {
final double strength = 15000.24;
}
mixin QuickRunner {
void runQuick() => print('Running fast!');
}
class Player with Strong, QuickRunner {
final String name;
Player(this.name);
}