ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (Swift) lazy 변수형 사용 방법
    Programing Language/Swift 2019. 10. 25. 12:04
    728x90
    반응형

    애플에 공식문서는 다음과 같이 lazy 변수형 대해 설명하고 있다.

    "A lazy stored property is a property whose initial value is not calculated until the first time it is used"

    리스트로 예를 들어 설명하면 리스트의 0번째 value가 읽히기 전까지는 메모리에 그 값을 할당시키기 않는다는 말이다.

    다른 예 

    인스타그램을 예로 들어보도록 하겠습니다. 인스타그램을 실행시키면 가장 상단에 본인의 팔로워들의 아이콘들이 존재하고 이 아이콘을 클릭하면 해당 유저가 올린 스토리 영상을 확인할 수 있습니다. 여러분이 인스타그램을 실행시켰을 때 이러한 영상들도 모두 서버로부터 가져오는 작업을 할까요? 만일 여러분이 어플리케이션을 실행하는 동안 한번도 스토리들을 클릭하여 확인하지 않는다면 이는 쓸데 없이 메모리만 차지하고 어플리케이션을 실행할 때 딜레이도 존재할 수 있습니다. 해당 영상들은 여러분이 클릭했을 때만 보여주기만 하면 되기 때문입니다. 

    출처 : https://baked-corn.tistory.com/45  

    lazy를 사용하기 위해서는 다음과 같은 고려사항이 필요합니다.

     

    1. lazy는 반드시 var와 함께 쓰여야 한다.


      lazy 는 반드시 var와 사용되어야 합니다. 이는 한번만 생각해보시면 쉽게 이해하실 수 있습니다. 기본적으로 lazy로 선언된 변수는 초기에는 값이 존재하지 않고 이후에 값이 생기는 것이기 때문에 let 으로는 선언될 수 없습니다.
    2. struct, class


      기본적으로 lazy는 struct와 class에서만 사용할 수 있습니다

       

    3. lazy vs Computed Property


      Computed Property에는 lazy 키워드를 사용할 수 없습니다. lazy는 처음 사용될 때 메모리에 값을 올리고 그 이후 부터는 계속해서 메모리에 올라온 값을 사용합니다. 사용할 때마다 값을 연산하여 사용하는 Computed Property에는 사용할 수 없습니다.

       

    4. lazy and closure


      lazy에 어떤 특별한 연산을 통해 값을 넣어주기 위해서는 코드 실행 블록인 closure를 사용합니다.

      class나 struct의 다른 프로퍼티의 값을 lazy 변수에서 사용하기 위해서는 closure내에서 self를 통해 접근이 가능합니다. 기본적으로 일반 변수들은 클래스가 생성된 이후에 접근이 가능하기 때문에 클래스내의 다른 영역(메소드, 일반 프로퍼티)에서는 self를 통해 접근할 수 없지만 lazy키워드가 붙으면 생성 후 추후에 접근할 것이라는 의미이기 때문에 closure내에서 self로 접근이 가능합니다.

     

    class Person {
        var name:String
        
        lazy var greeting:String = {
            return "Hello my name is \((self.name))"
        }()
      
        init(name:String){
            self.name = name
        }
    }
    
    var me = Person(name:"John")
    
    print(me.greeting // Hello my name is John
    
    me.name = "James"
    
    print(me.greeting // Hello my name is John

    lazy var greeting을 보시면 클로저 내부에서 self.name을 통해 name프로퍼티에 접근하는 것을 보실 수 있습니다. 이전 포스팅을 보셨던 분들이라면 이렇게 클래스 내부의 클로저에서 클래스 객체를 self 로 참조한다면 메모리 누수가 발생하는 위험이 있다는 것을 아실 것입니다. 하지만 뒤의 ()를 통해 그 즉시 실행하고 결과를 돌려주고 끝나버리기 때문에 메모리 누수의 걱정은 없습니다

     

    또한 프로퍼티가 James으로 변경이 되어도 처음 사용할 때 메모리에는 John이 올라가 있기 때문에 John이 출력이 됩니다.

    class Person {
        var name:String
        
        lazy var greeting: ()->String = { [weak self] in
            return "Hello my name is \(((self?.name))!)"
        }
        init(name:String){
            self.name = name
        }
    }
    
    var me = Person(name:"John")
    
    print(me.greeting()) // Hello my name is John
    
    me.name = "James"
    
    print(me.greeting()) // Hello my name is James

    만일 변수가 lazy var greeting:String이 아닌 lazy var greeting:()->String으로 클로저 실행의 결과를 담는 것이 아닌 클로저 자체를 담고 있는 변수라면 반드시 [weak self]를 통해 메모리 누수를 방지해주어야 합니다.

     

    또한 값이 아닌 클로저 자체가 메모리에 올라가 있고 self 는 내부에서 계속해서 클래스를 참조하기 때문에 계속 John이 출력이 되는 것이 아닌 James가 출력이 되는 것입니다.

     

    https://baked-corn.tistory.com/45

     

    [Swift] lazy Variables

    Lazy variables 이전의 글들을 보셨거나 스위프트 문법 공부를 해보신 분들이라면 스위프트에서 메모리는 굉장히 예민한 주제인 것을 알 수 있습니다. 저 역시 그렇게 느꼈고, 그런 예민함이 보다 메모리를 효율적..

    baked-corn.tistory.com

     

    728x90
    반응형
Designed by Tistory.