late 키워드와 널 안정성
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 26번째.
때때로 null을 허용하지 않는 변수가 필요하지만, 즉시 값을 할당할 수 없는 경우가 있습니다. late 키워드는 Dart에게 "사용하기 전에 반드시 초기화하겠다"고 약속하는 역할을 합니다.
late String description;
void setup() {
description = 'Initialized later';
}
void main() {
setup();
print(description); // 정상 작동 - 사용 전 초기화됨
}late가 없으면, Dart는 description이 초기화되지 않았다고 경고할 것입니다. late를 사용하면, 접근하기 전에 해당 변수에 값이 할당되도록 보장할 책임이 사용자에게 있습니다. 초기화하기 전에 읽으려고 하면 런타임 에러가 발생합니다.
일반적인 사용 사례는 실제로 필요할 때까지 지연시키고 싶은 비용이 많이 드는 계산입니다:
class DataProcessor {
late List<int> data = _loadData();
List<int> _loadData() {
print('Loading data...');
return [1, 2, 3, 4, 5];
}
}
DataProcessor processor = DataProcessor();
// 'Loading data...'가 아직 출력되지 않았습니다
print(processor.data); // 이제 데이터를 로드하고 출력합니다_loadData() 메서드는 객체가 생성될 때가 아니라 data에 처음 액세스할 때만 실행됩니다. 이러한 지연 초기화(lazy initialization)는 값이 전혀 필요하지 않을 수 있는 경우 성능을 향상시킬 수 있습니다.
변수가 사용되기 전에 초기화될 것이 확실하지만 선언 시점에 초기화할 수 없을 때 late를 사용하세요. 이것은 컴파일러와의 약속입니다. 그 약속을 어기면 프로그램이 충돌합니다.
챌린지
쉬움지연 초기화를 위한 late 변수의 강력함을 보여주는 설정 관리자(configuration manager)를 만들어 보겠습니다. 설정이 실제로 필요할 때만 비용이 많이 드는 설정 작업이 수행되는 시스템을 만들 것입니다.
코드를 두 개의 파일로 구성합니다:
config_manager.dart: 애플리케이션 설정을 처리하는ConfigManager클래스를 정의합니다. 클래스는 다음을 포함해야 합니다:- 생성자를 통해 전달되는
String appName - 나중에 설정 메서드를 통해 초기화될
late String databaseUrl - 처음 액세스할 때
Calculating max connections...를 출력하고100을 반환하는 지연 초기화 방식의late int maxConnections databaseUrl을 초기화하는setupDatabase(String url)메서드- 현재 설정을 출력하는
displayConfig()메서드
- 생성자를 통해 전달되는
main.dart: 설정 관리자를 가져와서 late 변수가 어떻게 작동하는지 보여줍니다:- 앱 이름을
'MyApp'으로 하여ConfigManager를 생성합니다. Config created를 출력합니다.- URL을
'localhost:5432/mydb'로 하여setupDatabase를 호출합니다. Accessing max connections...를 출력합니다.maxConnections값을 출력합니다.Accessing max connections again...을 출력합니다.maxConnections값을 다시 출력합니다 (계산 메시지가 반복되지 않는지 확인하세요).displayConfig()를 호출합니다.
- 앱 이름을
displayConfig() 메서드는 다음 형식으로 출력해야 합니다:
--- Configuration ---
App: [appName]
Database: [databaseUrl]
Max Connections: [maxConnections]지연 초기화되는 maxConnections 계산이 처음 액세스할 때 딱 한 번만 실행되는 방식에 주목하세요. 이것이 초기화 구문과 함께 사용하는 late의 장점입니다!
예상 출력 결과:
Config created
Accessing max connections...
Calculating max connections...
100
Accessing max connections again...
100
--- Configuration ---
App: MyApp
Database: localhost:5432/mydb
Max Connections: 100치트 시트
late 키워드를 사용하면 나중에 초기화될 null 허용 안 함(non-nullable) 변수를 선언할 수 있으며, 해당 변수는 사용되기 전에 반드시 초기화되어야 합니다:
late String description;
void setup() {
description = 'Initialized later';
}
void main() {
setup();
print(description); // Works - initialized before use
}late가 없으면 Dart는 즉시 초기화를 요구합니다. late를 사용하면 변수에 접근하기 전에 초기화하겠다고 약속하는 것입니다. 초기화되지 않은 late 변수를 읽으려고 하면 런타임 에러가 발생합니다.
지연 초기화(Lazy Initialization): late 변수에 초기화 구문이 있는 경우, 초기화는 변수에 처음 접근할 때까지 지연됩니다:
class DataProcessor {
late List<int> data = _loadData();
List<int> _loadData() {
print('Loading data...');
return [1, 2, 3, 4, 5];
}
}
DataProcessor processor = DataProcessor();
// 'Loading data...' hasn't printed yet
print(processor.data); // Now it loads and prints_loadData() 메서드는 객체가 생성될 때가 아니라 data에 처음 접근할 때만 실행됩니다. 이는 해당 값이 전혀 필요하지 않을 수도 있거나 초기화 비용이 많이 드는 경우 성능을 향상시킵니다.
직접 해보기
import 'config_manager.dart';
void main() {
// TODO: 앱 이름 'MyApp'으로 ConfigManager 생성하기
// TODO: 'Config created' 출력하기
// TODO: URL 'localhost:5432/mydb'로 setupDatabase 호출하기
// TODO: 'Accessing max connections...' 출력하기
// TODO: maxConnections의 값 출력하기
// TODO: 'Accessing max connections again...' 출력하기
// TODO: maxConnections의 값을 다시 출력하기
// (계산 메시지가 반복되지 않음에 유의하세요)
// TODO: displayConfig() 호출하기
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.