본문 바로가기
Swift Deeep Dive

[Swift] ARC에 관한 문제 해결하기(클래스에 관하여)

by shinhyogeun 2020. 7. 19.

저번 글에서는 ARC과정에서 생길 수 있는 문제점에 대해서 보았다. 대표적인 문제점은 바로 메모리 낭비가 일어난다는 것이었고 오늘은 어떻게하면 그 메모리 낭비를 하지 않을 수 있는지 그 해결책에 관해서 알아보려 한다.

 

1. 약한 참조를 이용하기(ex. weak var)

 참조의 갯수를 파악에 대상이 되는 것은 강한 참조이다. 즉 강한 참조를 한다면 ARC가 그것을 알아차리고 클래스 인스턴스에 대한 참조의 수를 1증가시킬 것이다. 하지만 이렇게 1을 증가 시키지 않을 수 있는데 대표적으로는 약한 참조를 이용하는 것이다. 

 

 평소에 우리가 선언하는 변수나 상수는 자동으로 강한 참조를 하게 되어있다. 여기서 우리가 약한 참조로 바꾸기 위해서는 var 이나 let 앞에  weak이라는 것을 같이 선언해주면 그것은 더 이상 ARC에 의해 계산되지 않는 참조가 된다.

 

저번 시간에 들었던 예를 약한 참조로 다시 바꾼 예를 보자.

Apratment 클래스 안에 tenant라는 변수 앞에 weak이라는 것이 같이 적혀있는 것이 보인다.

그러면 어떤 것이 달라질까??

다음과 같이 변수를 선언하고 클래스를 참조하게 만든다.(이 과정은 전 시간에 보았던 것과 같다.)

이것은 참조 현황을 표현한 그림이다.

중요한 것은 tenant 변수가 Person(name: "John Appleseed")라는 클래스 인스턴스를 약한 참조 하고 있다는 것이다.

과연 이렇게 약한참조를 하면 john과 unit4A 변수에 nil을 할당해도 메모리 낭비가 일어나지 않을까??

 

과정은 다음과 같다.

 

(현재 Person instance 참조 수 : 1 )

(현재 Apartment instance 참조 수 : 2)

 

john 에 nil를 할당하면 

(현재 Person instance 참조 수 : 0)

(현재 Apartment instance 참조 수 : 1)

 

unit4A에 nil를 할당하면

(현재 Person instance 참조 수 : 0)

(현재 Apartment instance 참조 수 : 0)

 

결국 모두 메모리에서 해제되어 메모리 낭비가 일어나지 않게된다.

혹시 john에 nil를 할당해서 Person instance 참조 수가 1 감소되는 것은 이해가 되지만 왜 갑자기 Apartment instance의 참조 수가 1줄어드는 지 궁금하다면 그것은 Person instance 참조 수가 0이 되는 순간 더 이상 메모리에 존재하지 않게되면서 그 인스턴스가 사라지고 그 인스턴스가 Apartment 인스턴스를 참조하고 있었기에 그것도 같이 없어지기 때문이다.

 

또한 매우 중요하게 tenant 변수에는 nil값이 배정되게 된다!!!(그래서 처음부터 var tenant : Person?으로 optional로 정의한다.)

 

하지만 메모리 낭비를 막을 수 있는 방법에 약한참조만 있는 것은 아니다. 

 

2. 미소유 참조 이용하기(ex. unowned var)

미소유 참조는 자신이 참조하는 인스턴스가 메모리에서 해제되어도 스스로에게 nil값을 배정하지 않는다. 그래서 nil값을 배정해야 할 때 오류가 나게되는 위험한 느낌이다. 따라서 미소유참조는 참조하는 동안 해당 인스턴스가 메모리에서 해제되지 않으리라는 확신이 었을 때만 사용해한다. 일단은 예시를 보자.

손님과 신용카드에 관한 클래스 정의로 손님이 신용카드가 없을 수는 있지만 신용카드가 주인이 없을 수는 없기에 

CreditCard 클래스 안에 unowned let customer : Customer 로 ?가 없는 것을 볼 수 있다.

 

여기에

 

var john : Customer?

john = Customer(name : "John Appleseed")

john.card = CreditCard(number : 1234_5678_9012_3456, customer:john!) 

이렇게 실행하면 부디 다음과같은 그림이 머리속에 그려져야 한다.. (이제 자세한 설명은 생략할게요..ㅎㅎ)

과정은 다음과 같다.

 

(현재 Customer instance 참조 수 : 1 )

(현재 CreditCard instance 참조 수 : 1)

 

john 에 nil를 할당하면 

(현재 Person instance 참조 수 : 0)

(현재 Apartment instance 참조 수 : 0)

 

 과정을 디테일하게 보면 john에 nil을 할당하면 Customer instance에 대한 참조가 0이되어서 메모리에서 해제되고 동시에 card라는 속성이 CreditCard instance를 참조하는 것이 사라지므로 CreditCard instance에 대한 참조도 0이된다. 그래서 CreditCard도 메모리에서 해제된다. 우리가 customer 속성에 nil를 줘야할 순간은 없다. 그래서 이럴 경우는 미소유 참조를 사용해야한다.

 

오늘은 class속에서 어떻게 메모리 낭비를 막을 수 있는지 ARC와 관련되어서 알아보았다. 다음 글에서는 클로져에서도 메모리 낭비를 막을 수 있는데 그 과정이 어떤지 알아보겠다!!

 

 

-------감사합니다~!!-------