Null Safety
null이 될 수 있는 값과 될 수 없는 값을 타입으로 구분해 런타임 오류를 줄입니다.
개념 먼저 보기
Null Safety의 기본 개념부터 잡기
Null Safety 문서는 먼저 용어의 뜻을 잡고, 그 다음 Flutter 코드에서 어디에 쓰이는지 연결해서 읽는 것이 좋습니다.
아래 항목들은 이 문서에서 다루는 내용을 작은 단위로 나눈 것입니다. 각 항목을 읽은 뒤 예제를 보면 코드가 훨씬 덜 추상적으로 느껴집니다.
종류별로 하나씩
Null Safety에서 나눠 볼 핵심 요소
기본 규칙
String은 null이 될 수 없고, String?은 null이 될 수 있습니다.
언제 쓰나: nullable 값을 사용할 때는 null 검사 후 접근해야 합니다.
Flutter에서: ! 연산자는 개발자가 null이 아니라고 보장하는 표현이므로 신중하게 사용합니다.
// Null Safety 예제입니다.
// 먼저 코드의 큰 흐름을 보고, 주석을 따라 각 줄의 역할을 확인하세요.
String? nickname;
final label = nickname ?? '손님';
void greet(String? name) {
if (name == null) return;
print('Hello $name');
}
Flutter에서 자주 보는 패턴
위젯 생성자에서 required를 사용해 필수 값을 강제합니다.
언제 쓰나: late는 나중에 초기화되는 값을 표현하지만 초기화 전에 읽으면 오류가 납니다.
Flutter에서: ?. 와 ?? 연산자는 nullable 값을 안전하게 다루는 데 유용합니다.
// Null Safety 예제입니다.
// 먼저 코드의 큰 흐름을 보고, 주석을 따라 각 줄의 역할을 확인하세요.
String? nickname;
final label = nickname ?? '손님';
void greet(String? name) {
if (name == null) return;
print('Hello $name');
}
부연 설명
기본 규칙
- String은 null이 될 수 없고, String?은 null이 될 수 있습니다.
- nullable 값을 사용할 때는 null 검사 후 접근해야 합니다.
- ! 연산자는 개발자가 null이 아니라고 보장하는 표현이므로 신중하게 사용합니다.
부연 설명
Flutter에서 자주 보는 패턴
- 위젯 생성자에서 required를 사용해 필수 값을 강제합니다.
- late는 나중에 초기화되는 값을 표현하지만 초기화 전에 읽으면 오류가 납니다.
- ?. 와 ?? 연산자는 nullable 값을 안전하게 다루는 데 유용합니다.
깊게 이해하기
Null safety의 핵심은 null 가능성을 코드의 타입에 드러내는 것입니다. 이 덕분에 런타임에 갑자기 null 오류가 터지기 전에 컴파일 단계에서 위험을 발견할 수 있습니다.
다만 ! 연산자를 습관적으로 사용하면 null safety의 장점을 스스로 무너뜨리게 됩니다. null 검사를 하거나 기본값을 제공하는 방식으로 흐름을 명확히 만드는 편이 좋습니다.
상세 예제
사용자 프로필처럼 선택 입력이 많은 모델에서 nullable 값을 안전하게 다루는 예제입니다.
// 사용자의 선택 입력을 담는 모델입니다.
class UserProfile {
const UserProfile({required this.name, this.nickname, this.age});
// name은 필수값이므로 null이 될 수 없는 String입니다.
final String name;
// nickname은 사용자가 입력하지 않을 수 있으므로 String?입니다.
final String? nickname;
// age도 선택 입력이므로 int?입니다.
final int? age;
// 닉네임이 비어 있지 않으면 닉네임을, 없으면 이름을 표시합니다.
String get displayName => nickname?.trim().isNotEmpty == true
? nickname!
: name;
// age가 null이면 기본 문구를 보여 줍니다.
String get ageLabel => age == null ? '나이 미입력' : '$age세';
}
void printProfile(UserProfile profile) {
// getter를 사용하면 화면 코드에서 null 처리 로직이 단순해집니다.
print(profile.displayName);
print(profile.ageLabel);
}
실무에서 주의할 점
- nullable 값에 바로 접근하지 말고 null 검사, ?., ?? 중 하나를 선택하세요.
- late는 편리하지만 초기화 시점을 보장할 수 있을 때만 쓰세요.
- required는 null safety와 함께 생성자의 의도를 명확하게 만듭니다.