이번 포스팅에서는 ARC의 Counting 방식으로 인해 생기는 Strong Reference Cycle에 대해 알아보겠습니다!
Strong Reference(강한 참조)란?
변수, 상수 등으로 클래스 인스턴스에 할당할 때를 의미합니다.
var strongRefernece = ChangbroClass()
해당 Refernece가 남아있는 한, 메모리에서 해제되지 않고 계속 메모리에 남아 있습니다. 이럴 때 Memory Leak이 발생합니다.
그럼 이제 Strong Reference Cycle이 일어나는 예제를 확인해 보겠습니다.
두 개의 클래스 객체가 서로 강한 참조를 하고 있고, 서로의 참조를 떼어놓지 못하고 있는 코드입니다.
class Job {
var name: Name?
deinit{
print("Job 메모리 해제")
}
}
class Name {
var job: Job?
deinit {
print("Name 메모리 해제")
}
}
var a: Job? = Job()
var b: Name? = Name()
a?.name = b
b?.job = a
a 변수는 Job의 객체를 갖고, b는 Name의 객체를 가지고 있습니다.
또한 a의 Job객체 내부에서는 b를 가지고 있습니다. b 또한 마찬가지로 객체 내부에서는 a가 가지고 있는 Job객체를 가지고 있습니다.
근데 이게 왜 Strong Reference Cycle이라는 거죠? nil로 초기화하면 되는 것 아닌가요?
이런 의문이 들 수 도있습니다.
아래 예시를 보시죠
원래라면 deinit이 실행되어서 print가 보여야 할 텐데 실행이 되지 않는 것을 볼 수 있습니다.
왜 이런 현상이 일어날까요?? 🤬
이전 포스팅에서 하나의 객체를 참조하는 변수들에 따라서 Reference Count가 올라간다고 설명드렸습니다.
a와 b에 nil을 할당하기 전 위 코드의 count를 확인해 보겠습니다.
그림에서 보시다시피 각각 a, b가 class를 참조할 때 count가 하나씩 올라가고 서로 내부에서 또 참조를 했을 때 하나씩 올라가 총 count는 2가 된 것을 확인할 수 있습니다!
nil을 할당한 직후 count를 그림으로 확인해 보겠습니다.
이러한 이유로 nil을 할당해도 count가 1이 되어 메모리에서 해제되지 못하고 있는 것이었습니다. 😶
앞에서 말씀드린 것처럼 이러한 경우는 Memory Leak의 주범이기 때문에 꼭 해결을 해야 합니다.
그럼 어떻게 해야 할까요?🤥
1. a와 b를 nil처리 하기 전 Job 인스턴스와 Name 인스턴스가 서로 참조하고 있는 구조를 해제시킵니다.
2. Job객체와 Name객체가 서로 참조할 때 Reference Count를 증가시키지 않도록 합니다.
하나 하나씩 알아보죠!!
1. Job 인스턴스와 Name 인스턴스의 서로 참조를 해제
a.name과 b.job도 nil을 할당해주며 count를 0으로 만들어 deinit이 실행되어 print문이 찍히는 것을 확인 할 수 있습니다!
2. Reference Count를 증가시키지 않는 법 (weak, unowned 사용)
Job 인스턴스와 Name 인스턴스의 서로를 참조 해제를 하지 않아도 메모리가 해제되며 print문이 찍히는 것을 확인할 수 있습니다!
weak이나 unowned를 사용하면 count를 증가시키지 않고 사용할 수 있습니다🤗
그럼 weak이랑 unowned는 뭐가 다른거죠???
다음 포스팅에서 알아보겠습니다!
수고하셨습니다👏
'Swift Study' 카테고리의 다른 글
Error Handling (0) | 2024.02.23 |
---|---|
Optional (0) | 2024.02.21 |
weak, unowned (0) | 2024.02.20 |
ARC (0) | 2024.02.20 |
Class vs Struct (0) | 2024.02.19 |