🦜 Swift

[iOS] weak var

ji-hyun 2023. 5. 4. 16:59

React 와 Flutter 를 경험해 본 나는 weak var 부터 보자마자 굉장한 낯설음을 느꼈다.

이에 대해 weak var 부터 모르는 것 하나하나 chatGPT 에 물어보았다.

온전히 chatGPT 를 통해 공부해서 정리한 내용을 기록해본다.

 

 

weak var 그게 뭔데 - 내 심정

 


weak var 선언하는 이유


iOS 개발에서 `weak var`로 선언하는 이유는 메모리 관리와 관련이 있습니다.

Swift에서 메모리 관리는 ARC (Automatic Reference Counting)에 의해 처리됩니다. ARC는 인스턴스가 얼마나 많은 참조자를 가지고 있는지 추적하고, 해당 인스턴스가 더 이상 참조되지 않을 때 인스턴스를 자동으로 해제하여 메모리를 해제합니다.

일반적으로 iOS 애플리케이션에서는 강한 참조(`strong reference`)를 사용하여 인스턴스를 참조합니다. 강한 참조는 인스턴스가 해제되지 않도록 참조하는 것입니다. 그러나 강한 참조를 유지하면 참조 사이클(`retain cycle`)이 발생할 수 있습니다. 이는 두 개 이상의 객체가 서로를 강하게 참조하여 메모리 누수(`memory leak`)를 일으키는 문제입니다.

따라서, `weak var`를 사용하여 참조를 유지하는 것이 좋습니다. `weak var`는 참조를 유지하지만, 참조되는 인스턴스가 해제될 때 자동으로 `nil`로 설정됩니다. 이를 통해 참조 사이클을 방지하고 메모리 누수를 방지할 수 있습니다.

즉, `weak var`를 사용하여 참조하면, 해당 인스턴스가 해제되었을 때 `weak var`의 값은 자동으로 `nil`로 설정되기 때문에, 참조된 인스턴스가 메모리에서 해제될 때 메모리 누수를 방지할 수 있습니다.

 

 

👉 [요약]

weak var 는 참조되는 인스턴스가 해제되면 자동으로 nil 로 설정되며, 이를 통해 메모리 누수를 방지할 수 있다. 즉 약한 참조라고 볼 수 있다.

그럼 강한 참조는 어떤 것일까?

 

 

강한 참조(`strong reference`)는 일반적으로 객체를 참조할 때 사용됩니다. 다음은 강한 참조를 사용하는 예시입니다.

 

var person1: Person? // 참조 개수: 0
var person2: Person? // 참조 개수: 0
var person3: Person? // 참조 개수: 0

person1 = Person(name: "Alice") // 참조 개수: 1
person2 = person1 // 참조 개수: 2
person3 = person1 // 참조 개수: 3

person1 = nil // 참조 개수: 2
person2 = nil // 참조 개수: 1
person3 = nil // 참조 개수: 0 (메모리에서 해제됨)



위의 예시에서, Person 클래스는 강한 참조를 사용하여 참조됩니다. `person1`, `person2`, `person3` 세 변수는 모두 `Person` 클래스의 객체를 참조하고 있으며, 이 객체는 `name` 속성을 가지고 있습니다. 

객체 참조를 해제하는 부분에서, `person3` 변수를 `nil`로 설정하여 객체 참조를 해제하면서 객체가 메모리에서 해제됩니다. 

 

 


weak var 는 보통 언제 쓸까

 

weak var 는 메모리 누수 방지를 위해 쓰이며, 약한 참조라는 것을 chatGPT 를 통해 대략적으로 알게 되었다.

그런데 weak var 를 보통 언제 쓰게 되는 것일까?

 

 

`weak var`는 다음과 같은 상황에서 주로 사용됩니다.

1. Delegate 패턴 구현
Delegate 패턴에서는 주로 프로토콜을 정의하고, 해당 프로토콜을 구현한 객체를 참조하기 위해 `weak var`를 사용합니다. Delegate 객체는 보통 해당 객체의 생명주기를 제어하지 않고, 그저 필요한 기능을 구현하기 때문에 `weak var`를 사용하여 참조하게 됩니다. 이를 통해 Delegate 객체가 참조 사이클을 일으키지 않도록 할 수 있습니다.

 


2. Closure 사용 시 캡처링
클로저를 사용하는 경우, 해당 클로저가 참조하는 객체를 `weak var`로 선언하여 참조 사이클을 방지할 수 있습니다. 클로저는 보통 외부 변수나 객체를 캡처링하여 사용하는데, 이때 캡처된 객체가 강한 참조(`strong reference`)를 유지하게 되면 참조 사이클을 일으킬 수 있습니다. 따라서, 캡처된 객체가 `weak var`로 선언되면 클로저가 참조하는 객체가 메모리에서 해제될 때, 해당 객체의 참조 카운트가 감소하여 메모리 누수를 방지할 수 있습니다.

 


3. 순환 참조 방지
두 객체가 서로를 강한 참조(`strong reference`)하고 있는 경우, 참조 사이클이 발생하여 메모리 누수를 일으킬 수 있습니다. 이때 두 객체 중 하나를 `weak var`로 선언하여 참조하면, 참조 사이클을 방지할 수 있습니다. 이를 통해 하나의 객체는 강한 참조(`strong reference`)를 유지하면서, 다른 객체는 약한 참조(`weak reference`)를 유지하게 됩니다.

 


따라서, `weak var`는 주로 Delegate 패턴, Closure 사용 시 캡처링, 순환 참조 방지와 같은 상황에서 사용됩니다.

 

 

👉 [요약]

위와 같은 여러가지 상황에서 weak var 는 사용된다.

위와 같은 상황은 공통적으로 보면, 참조 사이클을 방지하기 위해 weak var 를 사용한다는 것을 알아두자.

 

 


메모리 leak 문제라면 다 약한 참조를 쓰면 안될까?

 

이러한 무지한 질문에 chatGPT 의 답변은 다음과 같다.

 

객체의 수명을 고려하여 적절한 참조 방식을 선택하는 것은 중요합니다. 

객체를 생성하면 메모리에서 공간을 할당받아 객체가 생성됩니다. 그리고 객체를 사용하면 해당 객체에 대한 참조 카운트(`reference count`)가 증가합니다. 참조 카운트는 해당 객체를 참조하는 변수나 프로퍼티의 개수를 의미합니다.

객체를 더 이상 사용하지 않게 되면 참조 카운트가 감소하게 됩니다. 만약 참조 카운트가 0이 되면, 해당 객체는 메모리에서 해제되어 공간이 반환됩니다.

강한 참조(`strong reference`)는 해당 객체의 참조 카운트를 증가시키는 방식으로 동작합니다. 따라서, 해당 객체를 참조하고 있는 모든 변수나 프로퍼티가 해당 객체에 대한 강한 참조를 가지고 있다면, 해당 객체의 참조 카운트는 증가하여 메모리에서 해제되지 않습니다.

반면, 약한 참조(`weak reference`)는 해당 객체의 참조 카운트를 증가시키지 않습니다. 즉, 해당 객체를 참조하는 변수나 프로퍼티가 약한 참조를 가지고 있다면, 해당 객체의 참조 카운트는 증가하지 않습니다. 따라서, 해당 객체의 참조 카운트가 0이 되면, 해당 객체는 메모리에서 해제됩니다.

따라서, 객체의 수명을 고려하여 적절한 참조 방식을 선택하는 것이 중요합니다. 만약 객체가 다른 객체에 의존하고 있다면, 해당 객체에 대한 강한 참조를 유지해야 합니다. 그러나, 만약 객체가 다른 객체에 의존하지 않는다면, 해당 객체에 대한 약한 참조를 사용하여 메모리 누수를 방지할 수 있습니다. 

따라서, 적절한 참조 방식을 선택하여 객체들의 수명을 관리하면, 프로그램이 원활하게 동작하면서도 메모리 누수를 방지할 수 있습니다.

 

 

 

 

다음은 delegate 패턴에 대해서 공부해보겠다.

 

 

'🦜 Swift' 카테고리의 다른 글

[iOS] Navigation Controller 공부 기록 - 1  (0) 2023.05.13
[TIL] UIView, UIViewController, Delegate  (0) 2023.05.05
[Swift] 인스턴스의 생성과 소멸  (0) 2022.11.20
[Swift] 상속  (0) 2022.11.20
[Swift] 프로퍼티 감시자  (0) 2022.11.20