Flutter #53 - Immutable

Pearl Lee·2022년 11월 15일
0

Flutter Basic

목록 보기
1/2

Flutter 일기 53번째
참고 : Dart Academy - Immutable Data Patterns in Dart and Flutter




Flutter 개발을 하다 보면 Immutable, Mutable이라는 용어가 자주 등장한다. 사전적인 의미는 아래와 같다.

mutable : 변할 수 있는
immutable : 변경할 수 없는, 불변의

변경이 안 된다! 라고만 하면 '아 변수의 값을 못 바꾸는 건가' 하고 생각했는데, Immutable이라는 속성은 단순히 그런게 아니었다.




Immutable Data

Dart Academy - Immutable Data Patterns in Dart and Flutter
여기의 글을 한번 읽어보았다.

우선 String, Numbers, Boolean 타입의 값은 생성되고 나면 변경이 안 된다고 한다.

 var str = 'Hello My Name is...';
 str = 'Hello';
 print(str);	// Console 출력 : Hello
  
 var booltype = true;
 booltype = false;
 print(booltype);	// Console 출력 : false

변수 값이 변하니까 겉으로는 변경이 잘 되는 것처럼 보인다.

하지만 Dart Academy의 설명에 따르면, String 변수는 문자열 자체를 담는 것이 아니라, String 데이터가 있는 위치의 주소를 담는 참조 변수가 되는 것이라고 한다.


새로운 문자열('Hello')의 메모리 주소를 기존의 변수(str)에 할당하는 것이다. 변수에 문자열 자체를 할당하는 것이 아니다. boolean타입 변수의 경우도 마찬가지이다.

즉, 데이터를 Immutable로 관리한다는 뜻. 이미 메모리에 할당된 데이터 값은 변함이 없고, 데이터를 가리킬 주소값(변수가 담을)은 변경이 가능하다.








그럼 변하기 전의 데이터는 어떻게 되는가?

원래의 문자열 자체는 변하진 않지만, 더 이상 이 데이터를 참조할 수 있는 변수가 없다. 메모리에 있긴 한데 접근할 방법이 없는 데이터가 되는 것... 이 경우 Dart의 Garbage Collector가 알아서 메모리를 정리해준다.

데이터 자체가 아닌 주소값으로 관리하기 때문에, 데이터를 안전하게 관리할 수 있고, 예상치 못한 데이터 변경 시도를 막기 위해 데이터를 복사하는(기계인간 John Grib - Defensive copy)등의 대응책을 쓰지 않아도 된다는 장점이 있다. Immutable이 아닐 경우 데이터를 가져오는 과정에서 데이터 변경 시도가 있을 수 있기 때문!










Immutable variable - Final & Const

대부분 데이터는 일단 Immutable이라는 걸 알았는데, 변수를 Immutable로 관리하려면 어떻게 할까? Final, Const를 이용해보자.

1. final, const 변수는 초기화를 한 이후 변경할 수 없다는 공통점이 있다.

final String strFinal = 'Hello';
const int intConst = 1;
strFinal = 'hello world';  	// error1
intConst = 2;					// error2

dartpad에서 위의 코드를 입력해보면,

error1 : The final variable 'strFinal' can only be set once.
error1 : Constant variables can't be assigned a value.

요렇게 된다.






2. final 변수는 런타임에, const 변수는 컴파일 타임에 상태가 정해진다는 차이점이 있다.

final String strFinal;
const int intConst;			// error
strFinal = 'hello world';	// 가능!
The constant 'intConst' must be initialized.
Try adding an intialization to the declaration.

final 변수는 선언( final String strFinal )과 동시에 초기화( strFinal = '---' )할 필요는 없고, 나중에 해줘도 된다. Flutter 코드를 작성할 때 final로 선언하고, 이후에 다른 코드에서 초기화를 하는 경우는 꽤 빈번하다.

하지만 const로 선언해 constant, 즉 상수가 되면 선언과 초기화를 반드시 힘께 해줘야 한다. final로 설정한 변수의 경우 런타임에 그 값을 알 수 있으면 되지만, Constant 값의 경우 컴파일 단계에서 값이 확정되어야 하기 때문에 선언과 동시에 초기화를 해주어야 한다.

+) Compile time vs Run time
컴파일 타임 : 사람이 작성한 코드를 기계어로 번역 -> 실행 가능한 프로그램이 되도록 만드는과정
런타임 : 컴파일이 된 프로그램, 즉 앱을 실행하는 과정.





다만 Dart.dev - guides에서 final 객체는 변경이 안되지만 필드는 수정 가능하다고 한다.

이게 무슨 말인지... 행복한 개발자님의 블로그를 보고 알았다.

final List<int> intList = [];
intList = [1];		// error
intList.add(1);		// 가능!

위 코드를 Dart Pad에서 실행해보면, 두번째 줄에서만 에러가 난다.

The final variable 'intList' can only be set once.

객체에 아예 다른 값을 설정하는 건 안되지만, 값을 수정하는 정도는 되는 모양이다. 하지만 const 로 선언하면 수정이고 뭐고 아무것도 안 됨!






const 적용 안되는 대표적인 예시 2가지

  1. DateTime.now()
const DateTime nowTime = DateTime.now();	// error

DateTime.now()의 경우 실행 시간에 그 값이 결정되기 때문에, const로 초기화할 수 없다. final은 가능!

  1. Instance Variables (인스턴스 변수)
    클래스가 있는 객체지향 프로그래밍에서, 클래스에 정의된 변수를 인스턴스 변수라고 한다.
class Person{
	final String name;
	final int age;
}

위 코드에서 변수 하나라도 const로 바뀌면 에러.
const를 꼭 써야 한다면 앞에 static을 붙여 정적 변수로 만들고, 클래스 내부에서 미리 초기화를 해준다면 쓸 순 있다. 다만 해당 변수는 모든 객체에서 똑같은 값을 갖게 된다.

static const int age = 10;
profile
안 되면 되게 하라

0개의 댓글