swift - Lazy Property

pcsoyeon·2021년 10월 31일
0

Lazy Properties

swift의 여러 특징 중 하나는 메모리에 예민한 언어라는 것이다. 그리고 이는 곧 메모리를 보다 효율적으로 상사용한다는 것을 의미하기도 한다.

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

애플 공식 문서에서는 lazy 프로퍼티에 대해 위와 같이 말하고 있다.
lazy 변수는 처음 사용되기 전까지 연산이 되지 않는다.

예를 들어 인스타그램을 생각해보자.
앱에 접속하면 가장 상단에 사용자가 팔로워하고 있는 사람들의 프로필 아이콘을 볼 수 있고 이 아이콘을 클릭하면 해당 유저가 올린 스토리를 확인할 수 있다.

이 때, 앱에 접속한 순간 해당 스토리의 모든 사진 및 영상을 모두 서버로부터 가져오는 것일까? 만일 이렇게 작동한다면 이는 쓸데없이 메모리만 차지하고 앱을 실행할 때 딜레이도 존재할 수 있다.

그렇기 때문에 여기서 필요한 작업은 사용자가 프로필 아이콘을 클릭했을 때 서버로부터 데이터를 받으면 된다. 즉, 처음 사용되기 전까지는 로드 되지 않았다가 영상을 보려고 클릭하면 해당 영상을 서버로부터 로드하는 것이다.

When we use

앞서 말한 것과 같이 lazy 프로퍼티는 실제로 해당 변수가 사용될 때까지 그 생성을 지연시킬 수 있고 이는 속성을 마치 computed property처럼 작동하도록 만든다.
*computed property(= 연산 프로퍼티) : 저장된 속성 외에 클래스, 구조 및 열거형은 실제로 값을 저장하지 않는 계산된 속성을 정의할 수 있다. 대신 getter와 setter를 제공하여 다른 속성과 값을 간접적으로 검색하고 설정한다. 값을 저장하기 위한 프로퍼티로 그 때 마다의 특정한 연산을 통해 값을 리턴하거나 변환한다.

그러나 computed property와 다르게 계산된 결과를 저장하기 때문에 속성에 대한 후속 접근이 불가하다. 이를 통해 해당 변수를 사용하지 않을 때 코드가 실행되지 않기 떄문에 추가 성능을 제공할 수 있다. 또한 값이 캐시도기 때문에 반복적으로 사용할 경우 성능이 향상된다.

그렇다고 해서 아무때나 lazy 프로퍼티를 사용하면 안된다.
다음과 같이 computed property를 사용해야 하는 경우도 있다.

  1. lazy 프로퍼티를 사용할 때 미리 느린 작업을 수행하고 방해가 되지 않도록 해야 한다.
  2. lazy 프로퍼티는 항상 값을 저장하고 이 값은 다시 사용하지 않기 때문에 불필요하거나 무의미 할 수 있다.
  3. lazy 프로퍼티는 기본 개체를 변경하므로 let 구조에서는 사용할 수 없다.

Conditons for using Lazy

  1. lazy는 반드시 var와 함께 쓰여야 한다.
    lazy 프로퍼티로 선언된 변수는 초기에는 값이 존재하지 않고 이후에 값이 생기므로 let으로 선언할 수 없다.

2. struct, class 에서만 사용할 수 있다.

그러나, 최근 wwdc21에서 발표한 것에 따르면 함수 안에서도 lazy property를 사용할 수 있다.

  1. computed 프로퍼티에서는 lazy 키워드를 사용할 수 있다.
    computed 프로퍼티의 경우 사용할 때마다 값을 연산하여 사용하기 때문에 처음 사용될 때 메모리에 값을 올리고 그 이후로부터는 메모리에 올라온 값을 사용하는 lazy 키워드를 사용할 수 있다.

  2. lazy and closure
    lazy에 어떤 특별한 연산을 통해 값을 넣어주기 위해서는 코드 실행 블록인 closure를 사용한다. 그리고 그 내에서는 self를 통해 접근이 가능하다.

What's new in WWDC21

앞서 말한 것과 같이 wwdc21에서 lazy 프로퍼티에 관한 변화가 있었다.
기존에는 lazy 키워드는 저장된 프로퍼티 안에서만 작성이 가능했지만 swift 5.5이후부터는 함수 안에서도 해당 키워드를 사용할 수 있게 되었다.

아래와 같이 로컬 함수에서 활용이 가능하다.

func greeting(to: String) -> String {

    print("In greeting()")
    return "Hello, \(to)"
}

func lazyFunction() {

    print("Before lazy")
    lazy var myGreeting = greeting(to: "Adam")
    print("After lazy")
    print(myGreeting)
}

lazyFunction()

해당 코드를 실행시키면

위와 같은 결과가 나온다.
(기존의 lazy 키워드의 실행 방식과 비슷하게 실행된다.)

profile
Slowly But Surely

0개의 댓글