"값이 없을 수 있다(null)"를 타입으로 명시해 런타임 오류를 막는 Dart의 핵심 개념. (일반 개념)
| 기호 | 뜻 | 예 |
|---|---|---|
Type? |
null일 수 있는 타입 | String? name; |
?. |
null이면 건너뛰기 (안전 접근) | user?.name |
?? |
null이면 기본값 | name ?? "이름없음" |
! |
"절대 null 아니야" 강제 단언 | name! (위험) |
!는 가급 피하라 (이 프로젝트 핵심 규칙)!는 "믿고 밀어"라 말하는 거라, 실제 null이면 바로 크래시. 대신 지역 변수에 담아 null 체크 후 쓴다.
// ❌ 위험
if (widget.nextRoute != null) context.go(widget.nextRoute!);
// ✅ 안전
final nextRoute = widget.nextRoute;
if (nextRoute != null) context.go(nextRoute);
JS의 optional chaining(?.)·nullish(??)과 개념은 같지만, Dart는 컴파일 단계에서 null 가능성을 강제로 검사한다.
late final Database db; // 선언은 지금, 할당은 나중 (단, 쓰기 전에 반드시 채워야 함)
초기값을 당장 못 정하지만 null로 두긴 싫을 때. 쓰기 전에 안 채우면 런타임 에러.