개요

Dart에서는 변수를 선언할 때 다양한 키워드를 사용할 수 있습니다. 각 키워드는 서로 다른 특성과 용도를 가지고 있어, 상황에 맞게 적절한 키워드를 선택하는 것이 중요합니다. 이번 글에서는 각 키워드의 특징과 사용법에 대해 자세히 알아보겠습니다.
 
 
 

var

var는 타입 추론을 사용하는 변수 선언 방식입니다. 변수를 초기화할 때 할당되는 값의 타입에 따라 자동으로 변수의 타입이 결정됩니다.
 

void main() {
  var name = 'John';     // String으로 추론
  var age = 25;          // int로 추론
  var height = 175.5;    // double로 추론
  var isStudent = true;  // bool로 추론
  var numbers = [1,2,3]; // List<int>로 추론
}

 
 

특징

한번 추론된 타입은 변경할 수 없습니다.

void main() {
    var name = 'Jone';
    name = 'Jane';
    
    name = 10; // ERROR !!
}

 
 
초기값을 지정하지않으면 dynamic 타입이 됩니다.

void main() {
    var name;
    name = 'Jane';
    
    name = 10; // OK
}

 
 
 

dynamic

dynamic은 모든 타입의 값을 저장할 수 있는 특별한 타입입니다. 런타임에 타입 체크가 이루어집니다.
 

void main() {
  dynamic value = 'Hello';
  print(value.runtimeType);  // String
  
  value = 42;
  print(value.runtimeType);  // int
  
  value = true;
  print(value.runtimeType);  // bool
}

 
 

특징

타입에 제약을 받지않고 할당할 수 있습니다.

dynamic value = 'Hello';
value = 42;        // OK
value = true;      // OK
value = [1,2,3];   // OK

 
다만, 런타임 에러의 위험이 있습니다.

dynamic value = 42;
print(value.length);  // Runtime Error

 
주로 JSON 파싱과 같이 타입이 동적으로 결정되는 경우 사용됩니다.
 
 
 

final

final은 한 번만 값을 할당할 수 있는 불변 변수를 선언할 때 사용합니다.

void main() {
  final String name = 'John';
  final age = 25;  // 타입 추론 가능
  
  name = 'Jane';  // Error
}

 
 

특징

런타임에 값이 결정될 수 있습니다.

final time = DateTime.now();  // OK
final random = Random().nextInt(100);  // OK

 
클래스의 인스턴스 변수로 사용 가능합니다.

class Person {
  final String name;
  final int age;
  
  Person(this.name, this.age);
}

 
 
 

late

late는 변수를 나중에 초기화할 것임을 명시하는 키워드입니다.

void main() {
  late String name;
  
  // 나중에 초기화
  name = 'John';
  print(name);  // OK
}

 
 

특징

null safety와 함께 사용됩니다.

class Person {
  late String name;  // null이 아닌 값으로 반드시 초기화되어야 함
  
  void init(String userName) {
    name = userName;
  }
}

 
초기화하기전에 에러가 발생합니다.

late String name;
print(name);  // Error: LateInitializationError

 
lazy initialization 이 가능합니다.

late String expensiveOperation = _loadData();
// expensiveOperation이 실제로 사용될 때만 _loadData() 호출

 
 
 

const

const는 컴파일 타임 상수를 선언할 때 사용합니다.

void main() {
  const PI = 3.14159;
  const int maxAttempts = 3;
  const String greeting = 'Hello';
}

 
 

특징

컴파일 타임에 값이 결정되어야합니다.

const time = DateTime.now();  // Error: 컴파일 타임에 값을 알 수 없음
const random = Random().nextInt(100);  // Error

 
깊은 불변성을 가집니다.

const list = [1, 2, 3];  // 리스트의 내용도 변경 불가
const map = {'name': 'John', 'age': 25};  // 맵의 내용도 변경 불가

 
메모리 효율성이 있습니다.

const v1 = [1, 2, 3];
const v2 = [1, 2, 3];
print(identical(v1, v2));  // true: 같은 메모리 공간 공유

 
 
 
 

성능과 메모리 고려사항

const vs final

  • const는 컴파일 타임 상수로, 메모리를 더 효율적으로 사용
  • final은 런타임에 값이 결정되어 약간의 오버헤드 발생

var vs dynamic

  • var는 타입이 고정되어 있어 성능상 이점
  • dynamic은 런타임 타입 체크로 인한 오버헤드 발생

late 키워드의 영향

  • 초기화 체크로 인한 약간의 런타임 오버헤드
  • 메모리는 실제 초기화 시점에만 할당

 

결론

각 키워드는 그만의 특징과 용도가 있습니다. 상황에 맞는 적절한 키워드를 선택하는 것이 중요합니다:

  • var: 지역 변수, 타입이 명확한 경우
  • dynamic: 타입이 동적으로 변하는 경우
  • final: 한 번 초기화 후 변경되지 않는 값
  • late: 지연 초기화가 필요한 경우
  • const: 컴파일 타임 상수

코드의 가독성, 유지보수성, 그리고 성능을 고려하여 적절한 키워드를 선택하시기 바랍니다.

+ Recent posts