인프런 커뮤니티 질문&답변

조인택님의 프로필 이미지

작성한 질문수

앨런 iOS Concurrency(동시성) - 디스패치큐와 오퍼레이션큐의 이해

lazy var 관련 질문

21.05.28 13:21 작성

·

228

1

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

안녕하세요.

GCD 자료 277p에서 lazy var와 관련된 질문 사항인데요.

testVar라는 변수가 클로저에 ()가 붙여져 있는데,

제가 알기론 이렇게 되어있다면, testVar을 읽을 때마다 클로저가 호출되서 async로 보내든 말든 매번 랜덤한 수가 나와야되는데

실제론 그렇지 않더라구요.

GCD와 관련된 질문은 아니지만, 이걸 정확히 이해하면 뒷내용을 확실히 파악할 수 있을 것 같아서요.

혹시 이유를 알 수 있을까요?

사실상 저 변수는 클로저인데 사용할 때마다 매번 호출되어 {}에 있는 코드들이 매번 실행되어야하는 거 아닌가요?

감사합니다.

답변 1

0

앨런(Allen)님의 프로필 이미지
앨런(Allen)
지식공유자

2021. 05. 28. 20:53

안녕하세요 조인택 님.
좋은 질문 주셔서 감사합니다. ^^

해당 내용은, Swift 문법에서 지연 저장 속성과 클로저 부분에서 힌트를 얻으실 수 있는데요,

lazy var 변수는 초기화를 지연시킵니다. 즉, 메모리 공간을 미리 만들어 놓고 있는 것이 아니라 제일 처음 접근했을때 메모리 공간을 만듭니다.

그리고 클로저를 실행하는 { .... } ( ) 인 형태라고 하더라도, 계속 이 클로저를 실행시키는 것이 아니라.. 이 클로저를 lazy var 에 처음 접근하는 시점에 한번 실행하면.. return 타입을 해당 변수에 넣어놓고 계속 사용합니다. 즉, 옵션키를 누르고, testVar변수의 타입을 확인해보시면, Int 타입이라는 것을 알 수 있습니다.

Int 타입의 인스턴스로 (여기서는 랜덤 정수값) 한번 초기화를 시키면 그 해당 값을 계속 사용합니다.

예를 들어, 잘 생각해보시면, 스토리보드가 아닌 코드로 UI를 만든다고 할때,

lazy var label: UILabel = {

          let label = UILabel( )

          .....
         return label

} ( )

우리가 자주보던, 이런 코드를 한번 떠올려보시면, label을 계속 생성하는 것이 아니라.. 초기화 시점에 레이블을 한번 생성해서 변수에 넣고 계속 사용한다는 것을 아실 수 있을 것 같아요. 즉, 접근하는 시점에 한번 초기화를 해서 레이블을 변수에 저장하면 계속 사용하는 것이지요.

그런데, 제 강의에서 말씀드린... 여기서 문제가 되는 것은.. lazy var 변수의 경우에 Thread-safe하지 않습니다. 즉, 거의 동시 시점에 여러개의 쓰레드에서 접근하면.. 
잘못하다간.. testVar변수를 여러개 만들 수도 있게 되는 것이지요. (왜냐하면, 실제 메모리에 testVar변수를 만드는 데는 heap메모리에 변수를 생성하므로.. 시간이 좀 걸리는데.. 그 사이에 여러쓰레드에서 더 빠른 동작을 하게되면.. 다른 쓰레드(예를들어, 2번쓰레드)에서는 아직 testVar변수가 생성 중이란 것을 모를 수 있습니다. 그래서 lazy var의 경우엔 문제가 생기게 되는 것이고요.

간단하게 설명드려 보려고 했는데, 이해하시려나요? 혹시나 이해가 안되시면 다시 질문 주세요. :)


고맙습니다. :)