iOS

iOS) Memory Management - ARC

kangwook 2022. 8. 27. 23:16

iOS에는 독특한 메모리 관리 방식이 있다.

원래 Objective-C는 MRC라고 수동적으로 레퍼런스 카운트를 증가시키는 방식을 해왔었다.

retain, release 등을 사용해서 메모리를 관리해 왔다고 한다.

근데 Swift부터는 ARC라고해서 자동으로 레퍼런스 카운트를 증가시키는 메모리 관리 방식을 채택했다.

이 ARC는 참조 타입에만 적용이 되고(클래스 등) 값타입에는 적용이 안된다.

compile time에 실행되고, retain cycle에 유의해야 한다.

이 retain cycle이 뭐냐면 어떤 두 레퍼런스가 서로를 참조하고 있을 경우 발생하는 거라고 할 수 있겠다.

예를 한 번 들어보자

class A {
	var some: A?
}
var a = A()
var b = A()

a.some = b
b.some = a

출처 : https://fomaios.tistory.com

그럼 위 그림과 같은 모양이 된다고 할 수 있겠다.

그런데 여기서 만약 인스턴스들이 nil이 된다면 프로퍼티인 some만 남게되는데, 

이 프로퍼티들이 서로 연결되 있기 때문에 해제되지 않고 남아있어 버리게 된다.

이렇게 되면 메모리 릭이 발생하고 이러한 것을 순환참조, retain cycle이라고 한다.

 

이제 이런 retain cycle을 해결할 수 있는 방법은 뭘까.

객체를 참조하는 방식에는 weak, unowned, strong이 있는데 일반적으로 선언한 객체는 strong이다.

strong은 말그대로 강하게 참조하고 있기 때문에 메모리에 할당되어 있는 상태이고 그로 인해 위와 같은 retain cycle이 발생하는 것이라고 할 수 있겠다.

그래서 우리는 weak와 unowned를 통해 해결할 거다.

weak 참조는 참조하는 인스턴스가 메모리에서 해제되면 ARC는 weak reference를 자동으로 nil로 설정한다.

그래서 weak는 언제든지 nil로 변경될 수 있는 참조 방식이라고 알면 되겠다.

unowned는 사실상 weak랑 거의 비슷하다. 하지만 메모리에서 해제될 때 unowned는 nil로 설정되지 않고(항상 값을 가지고 있는 것으로 간주) 이 인스턴스를 메모리 해제 이후 접근하면 crash가 발생하게 된다.

그래서 사실 주로 위와 같은 상황에서 weak를 많이 쓰고 unowned를 쓸 땐 굉장히 신중하게 써야한다.

나중에 기회가 되면 메모리 관리 하는 방식, 참조 방식 등에 대해 더 자세히 다뤄볼 예정이다.