Dart Reference
Dart 프로그래밍 레퍼런스
Dart Reference 소개
Dart 레퍼런스는 Flutter와 서버사이드 Dart 개발에 필요한 전체 Dart 언어를 다루는 포괄적인 검색 가능 치트 시트입니다. 기본문법(var/final/const, 문자열 보간, 조건문, 반복문, 열거형, 화살표 함수), 클래스(클래스 정의, 네임드 생성자, 상속, 믹스인, 팩토리 생성자), 비동기(Future/async/await, Stream, Future.wait/any, StreamController, Completer), 컬렉션(List, Map, Set, where/map/reduce, spread 및 collection-if/for), Null Safety(Type?, ?./??/??=, null 단언 !, late), 제네릭(제네릭 클래스, 함수, extends 제약) 등 6개 카테고리로 구성됩니다.
이 레퍼런스는 크로스 플랫폼 모바일/데스크톱/웹 앱을 개발하는 Flutter 개발자에게 특히 유용합니다. Null Safety 섹션은 사운드 null safety가 강제되는 Flutter 3.x 이후 버전에서 특히 중요합니다. 조건부 접근자(?.), null 병합 연산자(??), null 병합 할당(??=), null 단언(!), 사용 전 보장되는 필드를 위한 late 초기화 등 모든 null 안전 연산자를 다룹니다.
비동기 섹션은 Dart의 전체 비동기 모델을 다룹니다. Future/async/await는 HTTP 요청이나 파일 읽기처럼 한 번만 완료되는 비동기 작업을 처리합니다. Stream과 async* 제너레이터는 실시간 데이터, 청크 파일 읽기, WebSocket 연결 등 연속적인 값의 시퀀스를 처리합니다. Future.wait()는 여러 Future를 동시에 실행하고, Future.any()는 가장 먼저 완료되는 Future를 반환합니다. Completer 클래스는 비동기 함수 외부에서 Future를 수동으로 완료할 수 있게 합니다.
주요 기능
- 6개 카테고리: 기본문법, 클래스, 비동기, 컬렉션, Null Safety, 제네릭
- 완전한 Null Safety 커버리지: Type?, ?., ??, ??=, ! 단언, late 초기화
- 비동기 모델 전체: Future/async/await, async* Stream, StreamController, Future.wait, Completer
- 클래스 기능: 네임드 생성자, Point.fromJson(), with 믹스인, 캐싱을 위한 팩토리 생성자
- 컬렉션: List/Map/Set 연산, where/map/reduce 변환, spread 연산자, collection if/for
- var(변경 가능), final(런타임 불변), const(컴파일 타임 불변) 차이 예제 포함
- extends 제약 조건을 사용한 제네릭 클래스와 함수 (T extends Comparable<T>)
- Dart 고유 기능: 연쇄 연산자(..), 화살표 함수, ${expr} 문자열 보간
자주 묻는 질문
Dart에서 var, final, const의 차이는 무엇인가요?
var는 타입 추론을 사용하는 가변 변수를 선언합니다. 타입은 컴파일 타임에 추론되지만 값은 재할당 가능합니다. final은 런타임 불변 변수로, 한 번만 설정할 수 있지만 값은 런타임에 결정될 수 있습니다. const는 컴파일 타임 상수로, 값은 컴파일 타임에 알려져야 하며 깊이 불변입니다. 예를 들어 const pi = 3.14159는 컴파일 타임에 평가되고, final startTime = DateTime.now()는 실행 시 한 번 설정됩니다.
Dart의 Null Safety는 어떻게 작동하나요?
Dart의 사운드 null safety는 ? 접미사로 명시적으로 nullable로 선언하지 않으면 변수가 null이 될 수 없음을 의미합니다(String? name). 조건부 접근자(?.)는 객체가 null이 아닐 때만 메서드나 프로퍼티를 호출합니다. name?.length는 name이 null이면 null을 반환합니다. null 병합 연산자(??)는 기본값을 제공합니다. name ?? "Guest"는 name이 null이면 "Guest"를 반환합니다. ??= 할당은 변수가 null일 때만 값을 설정합니다. ! 연산자는 nullable 값이 null이 아님을 단언하며, 실제로 null이면 예외를 던집니다.
Future와 Stream의 차이는 무엇인가요?
Future는 미래의 어느 시점에 사용 가능해질 단일 비동기 값을 나타냅니다. HTTP 응답이나 파일 읽기처럼 한 번만 완료되는 작업에 사용합니다. Stream은 시간이 지남에 따라 발생하는 비동기 이벤트의 시퀀스를 나타냅니다. 소켓 메시지, 사용자 이벤트, 비동기 제너레이터에 사용합니다. Future는 await로 값을 얻고, Stream은 listen하거나 await for로 각 이벤트를 처리합니다. async*와 yield로 Stream 제너레이터를 만들고, await for로 소비합니다.
Dart의 믹스인이란 무엇이고 언제 사용하나요?
믹스인은 상속 없이 여러 클래스 계층 간에 코드를 재사용하는 방법입니다. mixin 키워드로 정의하고 with 키워드로 클래스에 추가합니다. 예를 들어 mixin Swimmer는 swim() 메서드를 추가하고 class Duck with Swimmer처럼 어떤 클래스에도 붙일 수 있습니다. 상속과 달리 하나의 클래스에 여러 믹스인을 적용할 수 있습니다. 로깅, 직렬화, 애니메이션 같은 동작을 관련 없는 클래스들 간에 공유할 때 사용하세요.
Dart의 팩토리 생성자란 무엇인가요?
팩토리 생성자는 항상 새 인스턴스를 생성하지 않는 특수 생성자입니다. 캐시에서 기존 인스턴스를 반환할 수 있습니다. 이는 Dart에서 싱글톤이나 인스턴스 캐싱 패턴을 구현하는 표준 방법입니다. 예를 들어 Logger 클래스는 정적 맵을 캐시로 사용하여 같은 이름의 Logger 인스턴스가 이미 있으면 기존 것을 반환합니다. factory 키워드로 선언하며 클래스 타입의 인스턴스를 반환해야 합니다.
Dart의 컬렉션 연산자(spread, collection-if, collection-for)는 어떻게 사용하나요?
Dart는 강력한 컬렉션 리터럴을 제공합니다. spread 연산자(...)는 한 컬렉션의 모든 요소를 다른 컬렉션에 삽입합니다: [0, ...list, 3]. null 안전 spread(...?)는 nullable 컬렉션을 안전하게 처리합니다. collection-if는 조건부로 요소를 추가합니다: [if (isLoggedIn) dashboardRoute]. collection-for는 이터러블에서 요소를 생성합니다: [for (var item in items) item.toUpperCase()]. 이 연산자들로 임시 변수 없이 단일 표현식으로 복잡한 컬렉션을 선언적으로 구성할 수 있습니다.
StreamController는 무엇이고 언제 필요한가요?
StreamController는 Stream을 수동으로 제어할 수 있게 합니다. 이벤트 추가(controller.add(value)), 에러 추가(controller.addError()), 스트림 닫기(controller.close())가 가능합니다. controller.stream을 공개 프로퍼티로 노출하고 코드의 다른 곳에서 구동합니다. 콜백이나 이벤트 리스너 같은 비동기 API를 Dart 스트림으로 연결하거나, StreamController.broadcast()로 여러 리스너에게 이벤트를 멀티캐스트해야 할 때 유용합니다.
Dart에서 제네릭 제약 조건은 어떻게 작동하나요?
제네릭 매개변수의 extends 키워드는 타입 제약 조건을 추가합니다. 예를 들어 T max<T extends Comparable<T>>(T a, T b)는 T가 Comparable<T>를 구현해야 함을 요구하여 함수 내부에서 compareTo() 메서드에 접근할 수 있습니다. 제약 조건이 없으면 제네릭 매개변수에서 특정 타입의 메서드를 호출할 수 없습니다. 제약 조건을 통해 조건을 만족하는 모든 타입에서 작동하는 재사용 가능하고 타입 안전한 유틸리티 함수를 작성할 수 있습니다.