大器晩成

지연 저장 속성 (Lazy Stored Properties) 본문

iOS/Swift 문법

지연 저장 속성 (Lazy Stored Properties)

zerobugpark 2024. 11. 21. 23:56

 

지연 저장프로퍼티(Lazy Stored Property)

  • 일반적으로 저장 프로퍼티는 클래스 인스턴스가 처음 생성될 때 함께 초기화되지만, 저장프로퍼티 정의 앞에 lazy키워드가 붙으면 예외입니다.
  • lazy키워드가 붙은 프로퍼티는 선언만 될 뿐 초기화되지 않고 계속 대기하고 있다가 프로퍼티가 호출되는 순간에 초기화됩니다. 만약 이 프로퍼티에 클래스나 구조체 인스턴스가 대입된다면, 프로퍼티가 호출되기 전까지는 해당 인스턴스는 초기화되지 않습니다.
  • 호출되기 전에는 선언만 된 상태로 대기하다가 실제로 호출되는 시점에서 초기화가 이루어지는 저장 프로퍼티를 지연 저장 프로퍼티라고 합니다.
struct Dog {
    var name: String
    lazy var weight: Double = 10.0 //선언 및 초기화
    
    init(name: String) {
        self.name = name
        //self.weight = 0.2 // name처럼 초기화 하지 않은 상태에는 생성자내애서 초기화 불가능.
    }
    
    func sit() {
        print("앉습니다.")
    }
}

var aDog = Dog(name: "강아지")   // weight 속성 초기화 안됨
aDog.weight  // <======== 해당 변수에 접근하는 이 시점에 초기화됨 (메모리 공간이 생기고 숫자가 저장됨)
//aDog.weight = 20.0 // 가능
//print(aDog.weight)


위의 weight이라는 속성은 초기화 시점에 메모리 공간이 생기는 것이 아님
예를 들어, 인스턴스가 생기고 난 후, aDog.weight 이렇게 접근하는 순간 메모리 공간을 만들고 숫자를 저장 하게됨
  • 지연 저장 속성은 "해당 저장 속성"의 초기화를 지연시키는 것입니다.
  • 인스턴스가 초기화되는 시점에 해당 속성이 값을 갖고 초기화되는 것이 아닙니다.(메모리에 공간과 값을 갖지 않습니다.)
  • 해당 속성(변수)에 접근하는 순간에 (해당 저장 속성만) 개별적으로 초기화됩니다.
    -> 따라서, 상수로의 선언은 안되고 변수(var)로의 선언만 가능 ➡︎ lazy var만 가능(lazy let 불가능)
  • 지연 저장 속성은 "선언시점에 기본값을 저장" 해야합니다.
  • 지연 저장 속성은 구조체와 클래스 모두 동일합니다.
  • 값을 넣거나, 표현식(함수 실행문)을 넣을 수 있습니다.
  • 모든 형태의 표현식 - 함수 호출코드, 계산코드, 클로저 코드 등 모두 가능합니다.
    -> 저장하려는 속성과 "리턴형"만 일치하면 됩니다.
  • 메모리 공간에 없다가 처음접근 하는 순간에 (해당 속성만) 개별적으로 초기화됩니다.

 

클로저를 이용한 저장 프로퍼티 초기화

let/var 프로퍼티명: 타입 = {
    정의 내용
    return 반환값
 }()
//이렇게 정의된 클로저 구문은 클래스나 구조체의 인스턴스가 생성될 떄 함께 실행되어 초기값을 반환하고, 
//이후로는 해당 인스턴스 내에서 재실행되지 않는다.

class PropertyInit {
    
    //저장 프로퍼티 - 인스턴스 생성 시 최초 한 번만 실행
    var value01: String! = {
        print("value01 execute")
        return "value01"
    }()
    
    //저장 프로퍼티 - 인스턴스 생성 시 최초 한 번만 실행
    var value02: String! = {
        print("value02 execute")
        return "value02"
    }()
    
    lazy var value03: String! = {
        print("value03 execute")
        return "value03"
    }()
}

let s = PropertyInit() //클로저 구문을 이용하여 초기화하기 때문에 print문이 출력된다. (value03은 제외)
//value01 execute
//value02 execute


// 저장 프로퍼티를 단순히 참조만 하면 새로운 로그도 출력되지 않는다,
s.value01 = {"Hello"}()
print(s.value01) // Optional(Hello)
s.value02


//실제로 참조하는 시점에 실행될 수 있도록 정의하는 방법 lazy 사용
 lazy let/var 프로퍼티명: 타입 = {
    정의 내용
    return 반환값
 }()

let s1 = PropertyInit()

s1.value03 // value03 execute 실행
s1.value03 // 실행결과 없음
  • 저장프로퍼티 중의 일부는 연산이나 로직 처리를 통해 얻어진 값을 이용하여 초기화해야 하는 경우가 있습니다. 스위프트에서는 이와 같은 경우 클로저를 사용하여 필요한 로직을 실행한 다음, 반환되는 값을 이용하여 저장 프로퍼티를 초기화할 수 있도록 지원합니다.
  • lazy 키워드를 붙여서 정의한 저장 프로퍼티를 클로저 구문으로 초기화하면 최초 한 번만 로직이 실행되는 데다 실제로 참조되는 시점에 맞추어 초기화되기 때문에 메모리 낭비를 줄일 수 있습니다.

 

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

@MainActor // UIImageView 에러방지
class AView {
    var a: Int
    
    // 1) 메모리를 많이 차지할때
    lazy var view = UIImageView()     // 객체를 생성하는 형태
    
    // 2) 다른 속성을 이용해야할때(다른 저장 속성에 의존해야만 할때)
    //var b = a * 10 // 오류
     
    lazy var b: Int = {
        return a * 10
    }()
    
    lazy var c = a * 20
    
    init(num: Int) {
        self.a = num
    }
}

var test = AView(num: 10)
test.b // 100
test.c // 200
  • 메모리 공간을 많이 차지하는 이미지 등의 속성에 저장할 때
    - 반드시 메모리에 다 올릴 필요가 없으므로 지연 저장 속성으로 선언하는 경우가 있습니다. (메모리 낭비 막기 위함)
  • 다른 속성 또는 메서드들을 이용해야 할 때
    - 초기화 시점에 모든 속성들이 동시에 메모리 공간에 저장되므로 어떤 한 가지 속성이 다른 속성이나 메서드에 접근할 수가 없습니다.
    - 지연 저장 속성을 이용하는 경우 지연으로 저장된 속성은 먼저 초기화된 속성이나 메서드에 접근할 수 있게 됩니다.
728x90

'iOS > Swift 문법' 카테고리의 다른 글

타입속성 (Type Properties)  (0) 2024.11.22
계산/연산 속성(Computed property)  (0) 2024.11.22
저장속성(Stored Properties)  (0) 2024.11.21
초기화(initializer)  (0) 2024.11.21
클래스와 구조체의 차이  (0) 2024.11.21