본문 바로가기
iOS/Study

[Study/iOS] unowned vs weak

by Callie_ 2023. 11. 14.

 

해당 게시글은 iOS 면접스터디 SweepSwift에서 진행한 질문 중 제가 담당 했던 질문의 답변 내용을 정리 및 보강한 내용입니다.

 

 


 

 

🔴 unowned와 weak의 차이점을 설명하세요.

캡처 리스트, 객체간의 참조 등의 경우인 강한 참조 순환(Strong Reference Cycle)로 인한 메모리 누수를 방지하기 위해 사용되는 참조 타입입니다. 차이점은 아래와 같습니다.

 

 

 

📌 unowned

 

  1. unwoned를 참조하는 경우 값(value)이 항상 존재한다고 가정하기 때문에 할당해제를 해도 인스턴스가 메모리에서 해제되지 않습니다.
  2. unowned는 값에 바로 접근할 수 있습니다. 대신 unowned 참조는 할당해제가 된 상태일 때 nil로 설정되지 않기 때문에 (즉, 객체가 ARC에 의해 메모리가 해제되어도 값이 있다고 인지하기 때문에) 할당해제된 객체에 접근할 때 fatal error가 발생할 수 있습니다. ==> 메모리에 대한 주소값을 그대로 가지고 있어서, 메모리에서 인스턴스가 사라졌다고 하더라도 인스턴스를 참조하고 있는 오너라는 곳에선 여전히 보유하고 있기 때문에, 오너를 호출하면 유저값을 가지고 오려고 합니다. 이러한 과정 때문에 런타임 오류가 발생합니다.
  3. 참조하는 인스턴스의 수명이 짧아 먼저 해제할 수 있는 경우 사용합니다.

 

📌 weak

  1. weak의 경우에 참조하고 있는 인스턴스의 값이 nil일 가능성을 고려합니다. 특정 인스턴스의 참조가 할당해제 되었을 경우 참조를 nil로 설정하게 됩니다. 
  2. weak를 참조할 경우 nil의 설정 되어 있을 가능성이 있기 때문에 항상 optional로 선언됨으로, unrapping하는 과정이 필요합니다.
  3. 참조하는 인스턴스의 수명이 비슷하거나 더 긴 경우에 사용합니다. 

 

 

 

 

❓받았던 질문

이었는데 확실하게 대답을 못 해서 정리.

 

* unowned와 weak는 언제 사용이 되는 차이가 있으며, unowned가 실제로는 잘 쓰이지 않는 이유가 무엇인가요?

 

이 질문을 받고 개념만 준비했던 터라 조금 당황 했었는데, 생각해보면 사용 시점의 차이는 간단했다. 앞서 정리했던 차이점이 곧 unowned와 weak 사용의 차이점이었다. nil값이 나올 수 있는 상황에선 nil의 상황을 고려하는 weak를 사용하고, 무조건 값이 있는 경우엔 unowned를 쓴다. 그리고 참조하는 인스턴스의 수명에 따라 상황에 맞춰 쓰면 된다. 즉, unowned는 값이 항상 존재하는 상황에서만 사용되어야 하고, weak는 참조하고 있는 인스턴스의 수명에 대한 불확실성이 있는 경우에 사용된다.

 

스터디에서 unowned가 실제로는 잘 쓰이지 않는 이유에 대해 서로 의견을 조금 나누었었는데, 아무래도 안정성이 가장 큰 장점인 swift 기반에서의 시스템이라 nil의 여부가 그 이유로 가장 컸던 것 같다. 혹여라도 nil이 나오는 경우, 에러가 나기 때문에 사전 방지를 위해 unowned보다 nil이 나오는 경우를 고려하는 weak가 더 자주 사용되어 왔던 것. 

 

(+)

 

Use an unowned reference only when you are sure that the reference always refers to an instance that hasn’t been deallocated. If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.

nil 유무에 대해서 공식문서에도 특별히 주의를 주고 있다. 런타임 에러 없이 unowned를 사용할려면 할당해제가 되지않은 인스턴스를 참조하고 있음을 확신할 수 있을 때 사용해야한다고.

 

 

 

 

 


 

보강 부분

 

 

 

📖 ARC

본격 ARC를 정리하기 전, ARC의 짝궁(?) deinit 이야기를 안 할 수가 없다.

 

deinit{
        print("deinit", self)
    }

 

deinit이란?

 

- 페이지가 계속 쌓이는 걸 방지하기 위함.
- 화면이 떴다가 사라졌다고 사용자 눈 뿐만 아니라 실제로 새로운 화면이 메모리에 올라갔다가 메모리에 사라지게 함.

 

정도로 정리할 수 있는데, 더 간단하게 정리하자면 메모리에서 인스턴스가 떠돌고 있지 않는지 개발자가 직접 확인할 수 있는 코드라고 볼 수 있다. 화면상에선 사라졌는데, 메모리에선 제대로 해제되지 메모리를 차지하고 있다면......... 곤란해지는데, 그걸 개발자가 직접 확인할 수 있단 뜻!

 

 

ARC 등장 이전엔 MRC가 있었는데, 수동이라는 특징이있다. 사실 수업 때 이런 게 있다~ 식으로 접하며 ARC와의 차이점에 중점을 두고 배워서 ARC 공부하는 김에 조금 더 찾아보았다.

 

 

 

MRC

Manual Reference Counting

 

- 무려 object-c 때 사용 된 메모리 관리법.

- 이름에서 나타나있듯이 수동으로 관리하는 방법이다. 이때, retain (객체의 증가), relese (객체의 감소) 등을 통해 관리한다.

- 런타임 시점에 결정되는데, 하나씩 다 계산하는 방식이라 앱이 조금 힘들어할 수 있단 단점이 있다.

 

 

참고로, Refrence Counting (이하 RC)는 애플에서 메모리를 관리하는 방법으로, 참조해서 사용할때 카운팅을 하는 방식으로 메모리를 관리하는 것이다. 참조할 때 레퍼런스 카운트를 증가시키고, 사용을 다하면 레퍼런스 카운트를 감소하는 방식이다. RC가 0인 경우가 메모리 누수가 생기지 않고 있을 때이자, 우리가 메모리 관리를 위해 유지해주어야하는 경우이기도 하다.

 

 

이렇게 수동으로 관리되던 메모리는 WWDC 11에 ARC가 등장하며 달라졌는데 ....... 

 

 

 

 

ARC

Automatic Reference Counting

 

Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you don’t need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.

 

중요한 개념이라 공식문서를 확인해보았다. 간략하게 정리하자면, ARC는 앱의 메모리 사용을 추적 및 관리를 해주는 역할을 하고 있으며, 대부분의 경우 swift 환경일 시 자동으로 메모리 관리를 해주기 때문에 개발자들은 크게 염두하지 않아도 된다는 것. 

 

그런데 본문 속 ARC 자랑을 본격적으로 하기 전 내 눈에 들어온

 

 

"In most cases"

"In most cases"

"In most cases"

"In most cases"

 

 

즉 예외의 경우도 있다는 것........

 

그렇기 때문에 알아야 했던 게 unowned와 weak 였다. 보통의 경우 swift가 알아서 ARC를 통해 메모리 관리를 해주겠지만, 강한 순한참조의 상황에선 ARC가 메모리 관리를 제대로 해줄 수가 없어서 memory leak... 메모리 누수가 발생하기 때문에 이런 경우엔 별도의 처리가 필요한데, 그 역할을 unowned와 weak가 처리 해주고 있던 것. 

 

 

 

 

 

 

 

 

 

📍Refereances

 

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/

 

 

'iOS > Study' 카테고리의 다른 글

[iOS] Keychain vs UserDefaults  (0) 2023.12.17
[Study/iOS] Method Dispatch  (0) 2023.12.02
[iOS] 앱의 생명주기  (0) 2023.11.27
[Swift] Enum with Reusable VC  (0) 2023.10.10
[iOS] Shadow vs ClipsToBound  (0) 2023.07.23