Dart는 Google이 만든 프로그래밍 언어로, 크로스 플랫폼 프레임워크인 Flutter를 위해 특별히 만들어졌습니다. JIT 컴파일을 통한 초고속 핫 리로드와 AOT 컴파일을 통한 릴리스 빌드의 네이티브 성능을 결합합니다. Dart는 모바일 개발뿐만 아니라 웹 애플리케이션(AngularDart) 및 서버 측 솔루션에도 사용됩니다. 언어의 기능에 대한 자세한 내용은 Dart 공식 문서를 참조하세요.
핵심 요점
Dart는 C와 유사한 구문을 가진 프로그래밍 언어로, Google이 Lars Bak(Eclipse 창시자)의 주도로 개발했습니다. 첫 번째 릴리스는 2011년이었지만, Dart가 진정한 인기를 얻은 것은 2018년 Flutter 1.0 출시 이후입니다. 이 언어는 사용자 인터페이스 구축을 위해 설계되었으며, 스트림, 퓨처 및 리액티브 패턴에 대한 내장 지원을 제공합니다.
Dart의 철학은 「성능과 생산성의 균형」입니다. 이 언어는 두 가지 컴파일 전략을 지원합니다: 핫 리로드를 이용한 개발용 JIT(Just-In-Time)와 네이티브 성능의 릴리스 빌드용 AOT(Ahead-Of-Time)입니다. JIT 컴파일러는 APK 재컴파일 없이 밀리초 단위로 실행 중인 애플리케이션에 수정된 코드를 주입합니다 — 이것이 모바일 개발에서 다른 언어에 비해 Dart의 핵심 장점입니다.
Dart의 주요 기능은 Dart 2.12(2021)에 도입된 sound null safety입니다. 타입 시스템은 변수가 명시적 선언(int?) 없이는 null이 될 수 없음을 보장합니다. 이는 컴파일 타임에 NullPointerException을 제거합니다. Google에 따르면 null safety 도입으로 프로덕션 환경에서 Flutter 애플리케이션의 충돌률이 30% 감소했습니다.
Dart 생태계는 세 가지 주요 영역으로 구성됩니다: Flutter(모바일 및 데스크톱 애플리케이션), AngularDart(웹 애플리케이션), Dart Server(서버 측 솔루션). Flutter가 지배적인 플랫폼입니다: Statista(2025)에 따르면 Flutter는 크로스 플랫폼 모바일 프로젝트의 46%에서 사용되어 React Native(38%) 및 Xamarin(8%)을 앞서고 있습니다.
Dart 구문은 Java 및 JavaScript와 유사하지만 고유한 구조를 가지고 있습니다. Dart에서는 모든 것이 객체입니다 — int, double, bool도 Object를 상속합니다. 타입 지정은 선택 사항입니다: var로 선언된 변수는 자동으로 타입을 추론하지만, 가독성과 성능을 위해 타입을 명시적으로 지정하는 것이 좋습니다.
Dart는 int, double, String, bool, List, Set, Map, Record, Symbol 및 Runes를 지원합니다. Nullable 타입 — 접미사 ?가 있는 모든 타입(int?, String?). ?? 연산자(null-aware)는 왼쪽이 null인 경우 오른쪽 값을 반환합니다. 계단식 표기법(..)을 사용하면 참조를 반복하지 않고 동일한 객체에서 여러 메서드를 호출할 수 있습니다.
// Dart의 기본 타입 및 선언
void main() {
// 명시적 타입 지정
int age = 25;
double price = 19.99;
String name = 'Dart';
bool isValid = true;
// Null safety — 변수가 null일 수 있음
int? nullableAge = null;
int result = nullableAge ?? 0; // null-aware 연산자
// 제네릭을 사용한 컬렉션
List<String> items = ['Dart', 'Flutter', 'Mobile'];
Map<String, dynamic> config = {
'version': '3.0',
'mode': 'debug',
};
// 계단식 표기법
final list = <String>[]
..add('one')
..add('two')
..sort();
}
// Record — 익명 불변 타입
(String, int) user = ('Alice', 30);
print(user.$1); // 'Alice'dynamic 타입은 타입 검사를 비활성화합니다 — JSON 또는 동적 데이터로 작업할 때만 사용하세요. Record는 Dart 3.0의 새로운 타입으로, 별도의 클래스를 만들지 않고 값을 그룹화할 수 있습니다. Null-aware 연산자 ??는 긴 if-else 검사를 대체하여 nullable 값으로 작업하는 표준 방법입니다.
Dart의 클래스 — 단일 상속(extends), 믹스인(mixin)을 통한 다중 상속. Dart는 인터페이스를 별도의 개념으로 지원하지 않습니다 — 모든 클래스는 구현(implements)될 수 있습니다. 믹스인은 생성자가 없는 클래스로, with 키워드를 사용하여 모든 클래스에 메서드와 필드를 추가할 수 있습니다.
// Dart의 클래스, 상속 및 믹스인
abstract class Animal {
void sound(); // 추상 메서드
}
mixin Swimmer {
void swim() => print('Swimming...');
}
mixin Flyer {
void fly() => print('Flying...');
}
class Duck extends Animal with Swimmer, Flyer {
@override
void sound() => print('Quack!');
}
void main() {
final duck = Duck();
duck.sound(); // Quack!
duck.swim(); // Swimming...
duck.fly(); // Flying...
}
// 명명된 생성자
class Config {
final String env;
Config.development() : env = 'dev';
Config.production() : env = 'prod';
}Duck 클래스는 Animal을 상속하고 Swimmer와 Flyer라는 두 개의 믹스인을 사용합니다. 이는 다이아몬드 문제 없이 다중 상속을 보여줍니다: 믹스인은 선형적으로 해결됩니다(super chain). 명명된 생성자(Config.development)는 미리 설정된 매개변수로 객체를 생성하기 위한 정적 팩토리 메서드의 대안입니다.
Dart의 비동기는 Future(단일 값), Stream(값의 시퀀스) 및 async/await를 통해 구현됩니다. Dart는 JavaScript와 유사한 이벤트 루프가 있는 단일 스레드 모델을 사용하지만, 중요한 차이점이 있습니다: Dart 코드가 Isolate(공유 메모리가 없는 별도의 스레드)에서 실행되므로 긴 계산이 UI를 차단하지 않습니다.
Future는 일정 시간 후에 완료될 비동기 작업을 나타냅니다. Future는 보류 중(대기), 값으로 완료(성공) 또는 오류로 완료(오류) 상태일 수 있습니다. .then().catchError() 체인은 async/await의 대안이지만, 가독성을 위해 await를 사용하는 것이 좋습니다.
// Future와 Stream을 사용한 비동기 데이터 로딩
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
final String baseUrl;
ApiService(this.baseUrl);
// 단일 요청을 위한 Future
Future<Map<String, dynamic>> fetchUser(int id) async {
final response = await http.get(
Uri.parse('$baseUrl/users/$id'),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load user: ${response.statusCode}');
}
}
// 데이터 시퀀스를 위한 Stream
Stream<int> countStream(int max) async* {
for (var i = 1; i <= max; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
}
void main() async {
final api = ApiService('https://api.example.com');
// await 사용
final user = await api.fetchUser(1);
print('User: ${user['name']}');
// await for로 Stream 처리
await for (final count in api.countStream(5)) {
print('Count: $count');
}
}ApiService 클래스는 두 가지 유형의 비동기를 보여줍니다: HTTP 요청(단일 응답)을 위한 Future와 순차 카운터(async* 및 yield를 사용한 생성기)를 위한 Stream입니다. Stream은 센서, 위치 정보, Firebase Realtime Database 등 데이터가 지속적으로 도착하는 모든 곳에서 효과적입니다. Isolate는 별도의 메모리를 사용하며 데이터는 SendPort/ReceivePort를 통해 전송됩니다.
Dart와 Flutter는 단일 스택을 형성합니다: Flutter는 UI 프레임워크, Dart는 UI 설명 언어입니다. Flutter에서는 버튼부터 전체 애플리케이션까지 모든 것이 위젯(Widget)입니다. 위젯은 stateful(변경 가능한 상태)과 stateless(변경 불가능)일 수 있습니다. Dart는 선언적 UI를 설명합니다: build()는 Flutter가 Skia(iOS에서는 Impeller)를 사용하여 렌더링하는 위젯 트리를 반환합니다.
Dart의 Flutter 애플리케이션은 main() → runApp(MyApp()) → MaterialApp으로 구성됩니다. MaterialApp에는 라우팅(routes), 테마(theme) 및 지역화가 포함됩니다. 각 화면은 AppBar, Body(일반적으로 Column/ListView) 및 BottomNavigationBar를 포함하는 Scaffold입니다. Navigator.push/pop 또는 명명된 라우트를 통한 탐색.
// Dart의 간단한 Flutter 애플리케이션
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dart Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Dart + Flutter')),
body: Center(
child: Text('Counter: $_counter'),
),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: Icon(Icons.add),
),
);
}
}HomeScreen 위젯은 내부 상태 _counter를 가진 StatefulWidget입니다. setState()를 호출하면 Flutter에 UI 재구축이 알려집니다 — Dart 코드가 build()를 다시 실행하여 새 위젯 트리를 만듭니다. Flutter는 이전 트리와 새 트리를 효율적으로 비교(diff)하여 화면의 변경된 부분만 업데이트합니다. Hot Reload는 _counter 상태를 재설정하지 않고 build()를 대체합니다.
Dart 컴파일은 하이브리드입니다: 개발용 JIT와 프로덕션용 AOT입니다. 디버그 모드에서 Dart VM은 코드 핫 스왑 기능으로 바이트코드를 해석하는 JIT 컴파일러를 실행합니다. 릴리스 모드에서 dart compile exe 또는 flutter build는 특정 아키텍처(arm64, x86_64, armv7)에 대한 네이티브 AOT 바이너리를 생성합니다.
| 모드 | 컴파일 | 실행 속도 | 바이너리 크기 | 핫 리로드 |
|---|---|---|---|---|
| Debug | JIT (VM) | 중간 | ~50 MB | 예 |
| Release | AOT (네이티브) | 최대 | ~15-20 MB | 아니오 |
| Web | dart2js | 브라우저에 따라 다름 | 가변 | 개발 서버 |
디버그 모드에서 Dart JIT 컴파일은 약 1초 만에 핫 리로드를 제공합니다 — 개발자는 애플리케이션 상태를 잃지 않고 UI 변경 사항을 확인합니다. AOT 컴파일은 네이티브 Swift/Kotlin 애플리케이션에 가까운 성능을 제공합니다. Google에 따르면 Dart AOT의 Flutter는 중간급 기기에서도 60 FPS 애니메이션을 달성합니다.
Dart 개발자 도구에는 Dart SDK(dart 컴파일러, dartanalyzer, dartfmt, pub), Flutter SDK 및 IDE 플러그인이 포함됩니다. Dart SDK는 Flutter SDK와 함께 flutter/bin/cache/dart-sdk 폴더에 설치됩니다. Pub은 pubspec.yaml을 읽고 pub.dev에서 종속성을 다운로드하는 패키지 관리자입니다.
dart analyze — 타입, 사용되지 않는 가져오기 및 잠재적 오류를 확인하는 정적 분석기. dart format — 코드를 일관된 스타일로 자동으로 포맷하는 포맷터. dart doc — /// 주석에서 문서를 생성하는 생성기. Flutter DevTools — 위젯 트리 검사기, 로그, 메모리 및 네트워크가 있는 프로파일러. Dart VM Service — WebSocket을 통한 실행 중인 애플리케이션 디버깅.
# pubspec.yaml — Dart 프로젝트 구성
name: my_flutter_app
description: A new Flutter project.
version: 1.0.0
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
provider: ^6.1.0
shared_preferences: ^2.2.0
json_annotation: ^4.8.0
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.0
json_serializable: ^6.7.0
flutter_lints: ^3.0.0pubspec.yaml 파일은 Dart 프로젝트 종속성을 설명합니다. environment:sdk 필드는 Dart 버전을 지정합니다 — 현재 안정 버전은 3.x입니다. Dependencies는 주요 라이브러리이고, dev_dependencies는 테스트 및 코드 생성을 위한 것입니다. json_annotation + json_serializable은 build_runner를 통해 JSON 직렬화 코드를 생성합니다. flutter_lints는 분석기를 위한 규칙 세트입니다.
자주 묻는 질문
Dart는 Google(2011)의 프로그래밍 언어로, Flutter를 사용한 크로스 플랫폼 개발을 위해 설계되었습니다. C와 유사한 구문, 강력한 타입 지정, JIT 및 AOT 컴파일을 지원합니다. sound null safety(Dart 2.12부터)와 Future 및 Stream을 통한 비동기 처리가 특징입니다. 모바일, 웹 및 데스크톱 애플리케이션에 사용됩니다.
Dart는 네이티브 코드(AOT) 또는 JS(dart2js)로 컴파일되고, JavaScript는 인터프리트됩니다. Dart는 sound null safety, 내장 클래스 및 믹스인을 갖춘 강력한 타입 지정이 있습니다. Dart의 비동기는 Isolate(공유 메모리가 없는 별도의 스레드) 기반이고, JS는 Web Workers를 사용한 이벤트 루프 기반입니다. 모바일 시나리오에서 Dart AOT 성능은 V8 JIT보다 30-50% 높습니다.
Dart는 Dart Native를 통해 AOT로 네이티브 ARM 코드로 컴파일됩니다. 디버그 모드에서 Dart VM은 핫 리로드와 함께 JIT를 사용합니다. Flutter Engine(C++)은 Skia/Impeller를 통해 UI를 렌더링합니다. Android의 경우 flutter build apk, iOS의 경우 flutter build ios입니다. 웹 빌드는 dart2js 또는 dart2wasm을 사용합니다. 릴리스 APK 크기는 15-20MB입니다(AAB 분할 제외).
Dart는 기본 타입(int, double, String, bool), 컬렉션(List, Set, Map, Record), 특수 타입(Symbol, Runes, Null)을 지원합니다. 기본 타입을 포함한 모든 것이 객체입니다. Null safety: int?는 null을 허용하고, int는 절대 null이 아닙니다. ??, ??= 연산자로 안전한 null 처리를 합니다. 제네릭: List<String>, Map<String, dynamic>.
Flutter SDK에는 Dart SDK, Flutter Engine 및 위젯 라이브러리가 포함됩니다. IDE — Flutter 플러그인이 있는 Android Studio 또는 VS Code. DevTools — 위젯 검사기가 있는 프로파일러. Pub.dev — 45,000개 이상의 라이브러리를 갖춘 패키지 관리자. dart analyze 및 dart format 도구는 코드 품질을 보장합니다. JSON 모델의 코드 생성을 위한 Build_runner.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.