Flutter

[Flutter] Dart 기본 문법 #4 Null Safety

ekkkang 2025. 1. 6. 18:40

 

널 세이프티(Null Safety)는 개발자가 널 에러를 피할 수 있도록 도와주는 다트 프로그래밍 언어의 기능입니다.

이 기능은 사운드 널 세이프티 인 다트(Sound Null Safety in dart)라고 불리며, 이를 통해 개발자는 코드 작성 시점에 널 에러를 잡을 수 있습니다.

 

Sound Null Safety in dart 이란? (Sound Type System)

 

런타임 중에 null 포인터 예외를 방지하기 위해 Dart 컴파일러가 코드를 분석하고 컴파일할 때 타입 시스템에서 엄격한 규칙을 적용하는 것을 의미합니다.

 

정리하면, Dart 컴파일러가 코드를 분석하고, null이 될 수 있는 타입과 null이 될 수 없는 타입을 분명히 구분해 주기 때문에, 우리가 실수로 null을 넣거나 반환하게 되면 빌드(컴파일) 시점에 오류를 발견할 수 있습니다.

이를 사운드 널 세이프티(Sound Null Safety)라고 합니다.

런타임 중에 null 포인터 예외를 방지하기 위해 Dart 컴파일러가 코드를 분석하고 컴파일할 때 타입 시스템에서 엄격한 규칙을 적용하는 것을 의미합니다.

 

정리하면, Dart 컴파일러가 코드를 분석하고, null이 될 수 있는 타입과 null이 될 수 없는 타입을 분명히 구분해 주기 때문에, 우리가 실수로 null을 넣거나 반환하게 되면 빌드(컴파일) 시점에 오류를 발견할 수 있습니다.

이를 사운드 널 세이프티(Sound Null Safety)라고 하며, 런타임에서의 null 참조 에러 를 효과적으로 예방해줍니다.

 

Null Safety 란?
  • 개발자가 널 에러를 피할 수 있도록 도와주는 다트 언어의 기능이다.
// 코드의 시작점
void main() {
  String name = '길동';
  int age = 30;

  // String? 옵셔널 타입이다.
  // null 을 허용할 수 있다.
  String? nullableName;
  int? nullableAge;

  print('name : ${name}');
  // print('nullAbleName : ${nullableName.length}'); 컴파일 시점에 오류를 미리 확인할 수 있다.
  print('nullAbleAge : ${nullableAge}');

  // 방어적 코드도 작성해 보자.
  if (nullableName != null) {
    print(nullableName.length);
  }
} // end of main

 

 

null check 연산자와 null 병합 연산자

  • 널 체크 연산자( ?. ) 사용
  • 널 병합 연산자( ?? ) 사용
// 코드의 시작점
void main() {
  // 1. 널 체크 연산자
  String? userName = getNullableUserName();
  // 널 체크 연산자
  int? userNameLength = userName?.length;
  print('사용자 이름의 길이 값 : ${userNameLength}');
  print('----------------------------------------');

  // 2. 널 병합 연산자
  String finalUsersName = userName ?? '홍길동';
  print('finalUserName : ${finalUsersName}');

  // 3. ?. 와 ?? 를 함께 사용하는 예시
  String upperOrNoName = userName?.toUpperCase() ?? 'NO_NAME';
}

// 함수를 만들어 보자.
// 선택적 명명 매개변수
String? getNullableUserName({String? name}) {
  return name;
}

 

 

null 억제 연산자 ( ! )

  • 개발자가 해당 값이 null이 아님을 확신하고, 예외를 발생시키지 않을 때 유용하게 사용할 수 있다.
void main() {
  // 이 코드는 절대 null이 될 수 없다.
  String? nullableName = getNullableName();

  // 1. 널 억제 연산자 사용해 보기
  // 널체크 연산자 또는 널병합 연산자를 사용할 수 있지만
  // null 아님을 확신한다면 개발자가 널 억제 연산자를 사용할 수 있다.
  String forcedName = nullableName!;
  print('forcedName = ${nullableName}');
}

String? getNullableName() {
  // return null;
  return '홍길동';
}

 

 

 late 키워드

  • 게으른
  • 지연 초기화를 의미하며 변수를 선언만 해두고 나중에 필요할 때 초기화 하도록 도와 줍니다.
  • 보통은 final 키워드와 함께 많이 사용이 됩니다.
void main() {
  // 1. late 키워드를 사용해 보자.
  late String greeting;

  greeting = getGreetingMessage();
  print(greeting);

  print('-----------------------------------');

  // 2. late final 변수
  late final int number;
  number = 100;
  print(number);

  // 컴파일 시점에 사용시 오류 확인
  late String notAssigned;
  // print(notAssigned);
}

String getGreetingMessage() {
  print('함수 호출'); // 로깅을 찍어 본다. 디버깅
  return 'Hello, Dart!';
}