저장 속성(Stored Properties)
- 저장 속성은 인스턴스가 가지고 있는 고유한 값을 저장하는 변수 또는 상수이다
- 구조체와 클래스 모두 사용 가능하며, 인스턴스가 생성될 때 메모리에 저장된다
특징
var로 선언하면 값을 변경할 수 있다 (let으로 선언하면 값 변경 불가)
- 인스턴스 생성 시 반드시 초기화되어야 한다
- 각각의 인스턴스가 독립된 메모리 공간을 가진다
- 인스턴스 생성과 동시에 메모리에 저장된다
struct Animal {
var species: String
var age: Int
init(species: String, age: Int) {
self.species = species
self.age = age
}
func sound() {
print("\(species)가 소리를 냅니다.")
}
}
var cat = Animal(species: "고양이", age: 2)
print(cat.species)
cat.age = 3
print(cat.age)
var dog = Animal(species: "강아지", age: 1)
dog.sound()
지연 저장 속성(Lazy Stored Properties)
- 지연 저장 속성은 인스턴스가 초기화될 때 메모리에 바로 저장되지 않고, 처음 접근하는 순간 초기화되는 저장 속성이다
- 즉, 필요할 때까지 값을 저장하지 않기 때문에 메모리 낭비를 방지할 수 있다
특징
- 초기화 지연: 인스턴스 생성 시 메모리에 공간이 생기지 않으며, 접근되는 순간 초기화된다
- 메모리 절약: 메모리 사용을 줄이기 위해, 꼭 필요할 때까지 메모리를 사용하지 않는다
var로만 선언 가능: let으로 선언할 수 없다(lazy let 불가능)
- 클로저 형태로 초기화 가능: 복잡한 계산이 필요한 경우 클로저를 사용하여 선언 가능하다
- 구조체와 클래스 모두 사용 가능: 다만 구조체의 경우 복사되기 전 초기화가 필요하다
지연 저장 속성의 초기화 방식과 주의사항
지연 저장 속성의 초기화 방식
- 선언 시점에 기본값을 저장해야 한다
- 지연 저장 속성은 초기화 시점이 아닌, 해당 변수에 처음 접근하는 순간에 초기화된다
- 선언 시점에 값(상수 / 변수), 표현식(함수 실행문), 클로저 등을 사용하여 초기화할 수 있다
struct Vehicle {
var type: String
lazy var description: String = {
print("설명이 생성됩니다.")
return "이것은 \(type)입니다."
}()
lazy var defaultName: String = "자동차"
lazy var weight: Int = calculateWeight()
init(type: String) {
self.type = type
}
func calculateWeight() -> Int {
print("무게 계산 중...")
return 1500
}
}
var car = Vehicle(type: "SUV")
print(car.type)
print(car.defaultName)
print(car.description)
print(car.weight)
지연 저장 속성을 사용하는 이유
1. 메모리 절약
- 메모리를 많이 차지하는 데이터(이미지, 대형 데이터)를 사용해야 할 때 활용된다
- 필요하지 않으면 메모리를 차지하지 않도록 할 수 있다
class DataLoader {
lazy var data: [String] = {
print("데이터가 로드됩니다.")
return ["Apple", "Banana", "Cherry"]
}()
init() {
print("DataLoader가 초기화되었습니다.")
}
}
let loader = DataLoader()
print("인스턴스가 만들어졌습니다.")
print(loader.data)
DataLoader가 초기화되었습니다.
인스턴스가 만들어졌습니다.
데이터가 로드됩니다.
["Apple", "Banana", "Cherry"]
2. 다른 속성에 의존하는 경우
- 초기화 시점에 다른 속성의 값이 필요할 때 지연 속성을 사용하여 값을 계산할 수 있다
class Employee {
var salary: Int
lazy var annualSalary: Int = {
return salary * 12
}()
init(salary: Int) {
self.salary = salary
}
}
let worker = Employee(salary: 3000)
print("월급: \(worker.salary)")
print("연봉: \(worker.annualSalary)")
주의사항 정리
- 선언 시점에 기본값을 설정해야 한다:
- 생성자에서 초기화하는 것이 아닌, 선언부에서 기본값을 설정하거나 클로저를 사옹해서 초기화해야 한다
lazy var로만 선언 가능:
- 초기화를 지연시키기 때문에
let으로 선언할 수 없다
- 구조체 사용 시 주의:
- 구조체는 값 타입이기 때문에 복사되기 전에 반드시 초기화되어야 한다
- 복사된 후에도 지연 저장 속성의 초기화 상태가 유지된다
- Thread-safety 문제:
- 멀티스레드 환경에서 여러 스레드가 동시에 접근하면 충돌이 발생할 수 있으므로 주의해야 한다
요약
- 지연 저장 속성은 인스턴스 생성 시 초기화되지 않고, 처음 접근할 때 초기화되는 속성이다
- 선언 시점에 기본값, 표현식, 함수, 클로저 등으로 초기화할 수 있다
- 메모리 절약, 계산 지연 등을 위해 유용하게 사용된다