스위프트의 lazy 속성은 처음 접근할 때만 계산됩니다. 이는 자원이 많이 드는 객체(예: 무거운 계산, 네트워크 로드)와 같이 즉시 필요하지 않은 경우에 자주 사용됩니다. lazy 키워드를 사용하여 선언됩니다:
class DataFetcher { lazy var data: Data = self.loadData() func loadData() -> Data { /* … */ } }
특징 및 주의 사항:
lazy 속성은 변수(var)에 대해서만 허용되며, 상수(let)에 대해서는 허용되지 않습니다.lazy 속성이 작동하지 않으며, 구조체가 immutable일 경우 사용할 수 없습니다.lazy 값은 각 인스턴스 별로 캐시됩니다.질문: "클래스 인스턴스가 초기화될 때 lazy property의 값이 생성되나요?"
답변: 아니요, 값은 속성에 처음 접근할 때만 계산되며, 초기화 시점에서는 계산되지 않습니다.
class Expensive { init() { print("init") } } class Example { lazy var heavy = Expensive() } let foo = Example() // 아무 출력도 없음 _ = foo.heavy // 이제 "init"
이야기
두 플랫폼을 위한 프로젝트에서 이미지 캐시를 저장하기 위해 lazy 배열을 사용했습니다. 여러 스레드에서 동시에 접근할 때 경합 조건이 발생했으며, lazy var를 뮤텍스(mutex)로 감쌌지만 lazy를 잊어버려서 앱이 충돌하게 되었습니다.
이야기
어린 개발자가 무거운 계산을 캐시하기 위해 lazy let을 선언하려고 했습니다. 코드가 컴파일되지 않았으며, lazy는 var에 대해서만 허용되기 때문에 아키텍처를 재검토해야 했습니다.
이야기
개발자가 초기화 시 closure 내부에서 self를 캡처하여 lazy 속성을 선언했습니다. 이로 인해 순환 참조가 발생하여 객체는 모든 화면에서 나가더라도 비해제되지 않았습니다.