Menu
Coddy logo textTech

Nullable vs Non-Nullable

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 24번째.

이제 널 안정성(null safety)이 왜 중요한지 이해하셨으므로, null을 가질 수 있는 변수를 선언하는 방법을 살펴보겠습니다. Dart에서는 타입 이름 뒤에 ?를 추가하여 타입을 nullable로 만듭니다.

String name = 'Alice';   // Non-nullable - 항상 값을 가져야 합니다
String? nickname;        // Nullable - null이거나 String일 수 있습니다

print(name);      // Alice
print(nickname);  // null

주요 차이점은 non-nullable 타입은 값이 존재함을 보장하는 반면, nullable 타입은 값이 없음을 명시적으로 허용한다는 것입니다. 이러한 구분은 모든 타입에 적용됩니다:

int count = 10;       // 반드시 값이 있어야 함
int? optionalCount;   // null일 수 있음

List<String> items = [];      // 반드시 리스트여야 함 (비어있을 수 있음)
List<String>? maybeItems;     // null일 수 있음 (리스트가 아예 없을 수 있음)

빈 리스트 []null과 다르다는 점에 유의하세요. 빈 리스트는 존재하지만 아무것도 포함하지 않습니다. null은 리스트가 전혀 존재하지 않음을 의미합니다.

컴파일러는 이러한 규칙을 엄격하게 적용합니다. null을 허용하지 않는(non-nullable) 변수에 null을 할당할 수 없으며, null 체크를 먼저 하지 않고 null을 허용하는(nullable) 변수를 null을 허용하지 않는 변수가 필요한 곳에 사용할 수 없습니다:

String? maybeName = 'Bob';
// String definite = maybeName;  // 에러! nullable을 non-nullable에 할당할 수 없습니다.

다음 레슨에서는 Dart가 nullable 값들을 안전하게 다루기 위해 제공하는 연산자들에 대해 배울 것입니다.

challenge icon

챌린지

쉬움

nullable 및 non-nullable 타입을 사용하여 필수 정보와 선택 정보의 차이를 보여주는 영화 시청 목록 시스템을 만들어 보겠습니다.

코드를 정리하기 위해 두 개의 파일을 생성합니다:

  • movie.dart: 시청 목록의 영화를 나타내는 Movie 클래스를 정의합니다. 모든 영화는 제목과 개봉 연도가 있어야 하지만(항상 필수), 일부 추가 세부 정보는 모든 영화에 대해 제공되지 않을 수 있습니다. 클래스에는 다음이 포함되어야 합니다:
    • non-nullable String title - 모든 영화는 제목이 있어야 합니다.
    • non-nullable int year - 모든 영화는 개봉 연도가 있어야 합니다.
    • nullable String? director - 감독은 알려지지 않았을 수 있습니다.
    • nullable double? rating - 모든 영화가 아직 평점을 받은 것은 아닙니다.
    • titleyear를 필수 매개변수로 받는 생성자
    • 영화 정보를 출력하는 displayInfo() 메서드. 감독 정보가 없으면 "Unknown"을, 평점 정보가 없으면 "Not rated"를 표시합니다.
  • main.dart: 영화 클래스를 가져와서 완전한 영화 데이터와 불완전한 영화 데이터를 모두 보여주는 작은 시청 목록을 만듭니다:
    • 제목이 'Inception'이고 연도가 2010인 영화를 생성한 다음, 감독을 'Christopher Nolan'으로, 평점을 8.8로 설정합니다.
    • 제목이 'The Matrix'이고 연도가 1999인 영화를 생성한 다음, 평점만 8.7로 설정합니다 (감독은 null로 둡니다).
    • 제목이 'Upcoming Film'이고 연도가 2025인 영화를 생성합니다 (감독과 평점 모두 null로 둡니다).
    • 위에 나열된 순서대로 각 영화에 대해 displayInfo()를 호출합니다.

displayInfo() 메서드는 정확히 다음 형식으로 출력해야 합니다:

[title] ([year])
Director: [director or "Unknown"]
Rating: [rating or "Not rated"]

non-nullable 필드(titleyear)는 항상 값이 보장되는 반면, nullable 필드(director?rating?)는 설정되지 않은 상태로 남을 수 있다는 점에 유의하세요. 이는 일부 데이터는 필수적이고 일부는 선택적인 실제 시나리오를 반영합니다.

예상 출력:

Inception (2010)
Director: Christopher Nolan
Rating: 8.8
The Matrix (1999)
Director: Unknown
Rating: 8.7
Upcoming Film (2025)
Director: Unknown
Rating: Not rated

치트 시트

Dart에서 타입을 null 허용(nullable)으로 만들려면, 타입 이름 뒤에 ?를 추가합니다:

String name = 'Alice';   // Non-nullable - 반드시 값을 가져야 함
String? nickname;        // Nullable - null이거나 String일 수 있음

이러한 구분은 모든 타입에 적용됩니다:

int count = 10;       // 반드시 값을 가져야 함
int? optionalCount;   // null일 수 있음

List<String> items = [];      // 반드시 리스트여야 함 (비어있을 수 있음)
List<String>? maybeItems;     // null일 수 있음 (리스트 자체가 없음)

비어 있는 리스트 []null과 다릅니다. 비어 있는 리스트는 존재하지만 아무것도 포함하지 않는 것이고, null은 리스트 자체가 존재하지 않음을 의미합니다.

컴파일러는 null 안정성(null safety) 규칙을 엄격하게 적용합니다. null 허용이 아닌(non-nullable) 변수에 null을 할당할 수 없으며, null 체크를 먼저 하지 않고 null 허용 변수를 non-nullable 변수가 필요한 곳에 사용할 수 없습니다:

String? maybeName = 'Bob';
// String definite = maybeName;  // 오류! null 허용 타입을 non-nullable 타입에 할당할 수 없음

직접 해보기

import 'movie.dart';

void main() {
  // TODO: 제목이 'Inception'이고 연도가 2010인 영화를 생성하세요
  // 그 다음 감독을 'Christopher Nolan'으로, 평점을 8.8로 설정하세요
  
  // TODO: 제목이 'The Matrix'이고 연도가 1999인 영화를 생성하세요
  // 그 다음 평점만 8.7로 설정하세요 (감독은 null로 둡니다)
  
  // TODO: 제목이 'Upcoming Film'이고 연도가 2025인 영화를 생성하세요
  // 감독과 평점 모두 null로 둡니다
  
  // TODO: 각 영화에 대해 순서대로 displayInfo()를 호출하세요
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨