개발을 하다보면 null 객체에 접근하여 에러가 발생하는 일이 많습니다. 이 에러를 피하기 위해 null check 코드를 추가하여 예외처리를 하게 되는데요. null check 코드를 넣다보면 어느새 매우 많은 null check로 코드가 길어지고 지저분해지기도 합니다.

이 글은 Dart에서 null check를 하는 방법과 Dart에서 지원하는 null safety(null 안정성)에 대해서 소개하려고 합니다.

1. if문과 삼항연산자로 null check

다른 언어와 동일하게 if문으로 다음과 같이 null check를 할 수 있습니다.

if (variable != null) {
  // null이 아닌 경우
} else {
  // null인 경우
}

또는, 다음과 같이 삼항연산자를 사용하여 어떤 값이 null이면 default로 다른 값을 입력하도록 구현할 수도 있습니다.

void main() {
  String? variable = null;
  String defaultVal = "default value";

  var newString = (variable != null) ? variable : defaultVal;
  print(newString); // default value
}

2. null-aware 연산자(??)로 null check

Dart에서는 ??라는 null-aware 연산자를 제공하며, 위의 삼항연산자 예제처럼 null check를 할 수 있습니다.

  • variable이 null 인 경우, defaultVal을 newString에 대입
  • variable이 null이 아닌 경우, variable을 newString에 대입
void main() {
  String? variable = null;
  String defaultVal = "default value";

  var newString = variable ?? defaultVal;
  print(newString); // default value
}

3. 메소드에서 null-aware 연산자(.?)

메소드에서도 null-aware 연산자를 사용할 수 있는데, variable?.toString()는 variable이 null일 때 null을 리턴하며, null이 아니면 toString() 메소드의 결과를 리턴합니다. ?.를 사용하면 전통적인 null check 코드(if 같은)를 줄여 코드 가독성을 높일 수 있습니다.

void main() {
  String? variable = null;
  String defaultVal = "default value";

  var newString = variable?.toString();
  print(newString); // null
}

만약 variable가 null이면 variable?.toString()이 null을 리턴하게 되는데, null 대신 다른 값을 전달하게 만드려면 아래와 같이 ??를 함께 사용하면 됩니다. variable?.toString()에서 null이 리턴되어 ??"default value"가 리턴됩니다.

void main() {
  String? variable = null;
  String defaultVal = "default value";

  var newString = variable?.toString() ?? "default value";
  print(newString); // default value
}

4. null safety (null 안정성)

Dart의 변수는 기본적으로 non-null 변수로, null을 대입하려고 하면 컴파일 에러가 발생합니다. 따라서 Runtime에 발생하는 문제를 컴파일 타임에 찾고 해결할 수 있습니다.

예를 들어, 아래와 같이 null일 입력하려고 하면

String variable = null;

아래와 같은 에러가 발생합니다.

bin/dart_application_1.dart:2:21: Error: The value 'null' can't be assigned to a variable of type 'String' because 'String' is not nullable.
  String variable = null;

null을 입력하고 싶다면 타입에 ?를 추가해야 합니다.

String? variable = null;

다른 예제로, 타입이 맞지 않는 경우 컴파일 에러가 발생하는데, 아래 예제의 int?int처럼 null을 허용하는 타입과 허용하지 않는 타입을 구분하여 컴파일 에러를 발생시킵니다.

int sum(int a, int b) {
  return a + b;
}

void main() {
  int a = 10;
  int? b = null;
  int result = sum(a, b);
  print(result);
}

Output:

/home/mjs/blog-code/dart-example/dart_application_1/bin/node_48e9d556665c7.tmp.js:1
int sum(int a, int b) {
    ^^^

SyntaxError: Unexpected identifier
    at internalCompileFunction (node:internal/vm:74:18)
    at wrapSafe (node:internal/modules/cjs/loader:1141:20)
    at Module._compile (node:internal/modules/cjs/loader:1182:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1272:10)