Moon Work

[Swift] 메모리 참조 strong, weak, unowned 비교 본문

Swift

[Swift] 메모리 참조 strong, weak, unowned 비교

moonkey 2023. 2. 9. 17:45

시작하며

기본적으로 iOS에서는 ARS(Automatic Reference Counting)을 통해 클래스의 인스턴스가 얼마나 많이 참조(retain)을 받고 있는지를 추적한다. 만약 어떤 인스턴스도 해당 객체를 참조하고 있지 않다면 자동으로 메모리에서 해제한다. 하지만 두개 이상의 인스턴스가 서로를 강하게 참조하고 있는 순환(cycle)이 발생한다면 어떤 인스턴스를 메모리에서 해제하려해도 다른 인스턴스가 참조하고 있는 상황이라 해제가 불가능하게 된다. 이를 위해 Swift에서는 strong, weak, unowned 세가지 방식으로 참조를 가능하게 하여 이러한 순환 참조가 일어나지 않게 방지할 수 있는 기능을 제공해주었다. 

 

Strong - 강한 참조

  • 기본적으로 서로의 인스턴스끼리 참조가 이루어지면 강한 참조를 가진다.
  • 강한 참조는 위에서 말한 참소 횟수(retain count)를 증가시킨다.

weak - 약한 참조

  • 참조를 하지만 참조를 하는 인스턴스가 자신을 가리키지 않는다면 nil이다.
  • 자신이 참조하는 인스턴스의 참조횟수를 증가시키지 않는다.
  • 값이 변경될 수 있기 때문에 항상 optional과 var를 사용해야 한다. 
  • 아래의 경우 Test()로 인스턴스 할당이 이루어졌지만 해당 인스턴스에 대해 약한 참조를 가지고 있기 때문에 해당 인스턴스의 retain count가 올라가지 않아서 nil이 할당된다.
  • 예시로는 delegate 패턴을 사용하는 textField를 가져왔을 때 weak를 사용한다.
weak var test = Test()

//예시
@IBOutlet weak var textField: UITextField!

 

unowned - 약한 참조

  • weak와 마찬가지로 참조하는 인스턴스의 retain count를 증가시키지 않는다. 
  • weak와 다르게 weak는 해당 인스턴스를 추적하다가 객체가 사라질 경우 nil이 되지만 unowned는 기본적으로 해당 인스턴스가 있다고 가정을 하기 때문에 해당 인스턴스의 주소를 가리키는 댕글포인터만 가지게 된다.
  • 참조하는 대상이 자신보다 더 긴 생명주기를 가지고 있는 경우 ( 카드-고객의 관계)
  • 댕글 포인터만 가지게 될 경우 crash를 발생시킨다. 
unowned var test = Test()