TIL: 저장 속성(Stored Properties) / 지연 저장 속성(Lazy Stored Properties)

Royce·2025년 3월 22일

Swift 문법

목록 보기
25/63

저장 속성(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)               // 출력: 3

var dog = Animal(species: "강아지", age: 1)
dog.sound()                  // 출력: 강아지가 소리를 냅니다.

지연 저장 속성(Lazy Stored Properties)

  • 지연 저장 속성은 인스턴스가 초기화될 때 메모리에 바로 저장되지 않고, 처음 접근하는 순간 초기화되는 저장 속성이다
  • 즉, 필요할 때까지 값을 저장하지 않기 때문에 메모리 낭비를 방지할 수 있다

특징

  1. 초기화 지연: 인스턴스 생성 시 메모리에 공간이 생기지 않으며, 접근되는 순간 초기화된다
  2. 메모리 절약: 메모리 사용을 줄이기 위해, 꼭 필요할 때까지 메모리를 사용하지 않는다
  3. var로만 선언 가능: let으로 선언할 수 없다(lazy let 불가능)
  4. 클로저 형태로 초기화 가능: 복잡한 계산이 필요한 경우 클로저를 사용하여 선언 가능하다
  5. 구조체와 클래스 모두 사용 가능: 다만 구조체의 경우 복사되기 전 초기화가 필요하다

지연 저장 속성의 초기화 방식과 주의사항

지연 저장 속성의 초기화 방식

  • 선언 시점에 기본값을 저장해야 한다
  • 지연 저장 속성은 초기화 시점이 아닌, 해당 변수에 처음 접근하는 순간에 초기화된다
  • 선언 시점에 값(상수 / 변수), 표현식(함수 실행문), 클로저 등을 사용하여 초기화할 수 있다
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)                // 출력: SUV
print(car.defaultName)          // 출력: 자동차

// 처음 접근하는 시점에서 각각 초기화됨
print(car.description)          // 출력: 설명이 생성됩니다. / 이것은 SUV입니다.
print(car.weight)               // 출력: 무게 계산 중... / 1500

지연 저장 속성을 사용하는 이유

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 = {   // salary 속성을 이용해서 값을 계산하는 지연 속성
        return salary * 12
    }()
    
    init(salary: Int) {
        self.salary = salary
    }
}

let worker = Employee(salary: 3000)
print("월급: \(worker.salary)")            // 출력: 월급: 3000
print("연봉: \(worker.annualSalary)")       // 접근하는 순간 계산됨, 출력: 연봉: 36000

주의사항 정리

  1. 선언 시점에 기본값을 설정해야 한다:
    • 생성자에서 초기화하는 것이 아닌, 선언부에서 기본값을 설정하거나 클로저를 사옹해서 초기화해야 한다
  2. lazy var로만 선언 가능:
    • 초기화를 지연시키기 때문에 let으로 선언할 수 없다
  3. 구조체 사용 시 주의:
    • 구조체는 값 타입이기 때문에 복사되기 전에 반드시 초기화되어야 한다
    • 복사된 후에도 지연 저장 속성의 초기화 상태가 유지된다
  4. Thread-safety 문제:
    • 멀티스레드 환경에서 여러 스레드가 동시에 접근하면 충돌이 발생할 수 있으므로 주의해야 한다

요약

  • 지연 저장 속성은 인스턴스 생성 시 초기화되지 않고, 처음 접근할 때 초기화되는 속성이다
  • 선언 시점에 기본값, 표현식, 함수, 클로저 등으로 초기화할 수 있다
  • 메모리 절약, 계산 지연 등을 위해 유용하게 사용된다
profile
iOS 개발자 지망생

0개의 댓글