본문 바로가기
iOS/Swift

[iOS] ARC

by 안녕주 2022. 2. 20.

ARC가 관리해주는 참조 횟수 계산은 참조 타입인 클래스의 인스턴스에만 적용됩니다. 구조체나 열거형은 값 타입이므로 참조 횟수 계산과 무관합니다. 즉, 구조체나열걸형은 다른 곳에서 참조하지 않기 때문에 ARC로 관리할 필요가 없습니다.

 

 

ARC란

ARC( Automatic Reference Counting)는 자동으로 메모리를 관리해주는 방식입니다. 더이상 필요하지 않은 클래스의 인스턴스를 메모리에서 해제하는 방식으로 동작합니다.

 

ARC와 자바의 메모리 관리 기법인 가비지 컬렉션기법과는 어떤 차이가 있을까요?

메모리 관리 기법 ARC 가비지 컬렉션
장점 - 컴파일 당시 이미 인스턴스의 해제 시점이 정해져 있어서 인스턴스가 언제 메모리에서 해제될지 예측할 수 있습니다.

- 컴파일 당시 이미 인스턴스의 해제 시점이 정해져 있어서 메모리 관리를 위한 시스템 자원을 추가할 필요가 없습니다.

- 상호 참조 상황 등의 복잡한 상황에서도 인스턴스 해제할 수 있는 가능성이 더 높습니다.

- 특별히 규칙에 신경 쓸 필요가 없습니다. 
단점 - ARC의 작동 규칙을 모르고 사용하면 인스턴스가 메모리에서 영원히 해제되지 않을 가능성이 있습니다.  - 프로그램 동작 외에 메모리 감시를 위한 추가 자원이 필요하므로 한정적인 자원 환경에서는 성능 저하가 발생할 수 있습니다.

- 명확한 규칙이 없기 때문에 인스턴스가 정확히 언제 메모리에서 해제될지 예측하기 어렵습니다.

 

클래스의 인스턴스를 생성할 때마다 ARC는 그 인스턴스에 대한 정보를 저장하기 위한 메모리 공간을 따로 할당합니다. 그 메모리 공간에는 인스턴스의 타입 정보와 함께 그 인스턴스와 관련된 저장 프로퍼티의 값 들을 저장합니다. 그 후에 인스턴스가 더 이상 필요없는 상태가 되면 인스턴스가 차지하던 메모리 공간을 다른 용도로 활용할 수 있도록 ARC가 메모리에서 인스턴스를 없앱니다.

 

그런데 만약 아직 더 사용해야하는 인스턴스를 메모리에서 해제시킨다면 인스턴스와 관련된 프로퍼티에 접근하거나 인스턴스의 메서드를 호출할 수 없습니다. 그래서 인스턴스가 언제 메모리에서 해제될지 예측할 수 있도록 ARC에 적용되는 규칙이 있습니다.

 

 

 

강한참조

인스턴스가 계속해서 메모리에 남아있어야하는 명분을 만들어 주는 것. 인스턴스 참조 횟수가 0이 되는 순간 메모리에서 해제되는데, 강한참조를 사용하면 참조횟수가 +1됩니다.

 

강한참조는 참조의 기본형이므로, 별도의 식별자를 명시하지 않으면 강한 참조를 합니다. 강한 참조를 사용하는 곳에 nil을 할당해주면 원래 자신에게 할당되어 있던 인스턴스의 참조 횟수가 -1됩니다.

 

지역변수의 경우 사용된 범위의 코드 실행이 종료되면 그 지역변수가 참조하던 인스턴스의 참조횟수가 -1되면서 메모리에서 해제됩니다.

 

강한참조 순환문제

인스턴스끼리 서로가 서로를 강한참조를 할 때를 강한참조 순환이라고 합니다.

var yagom: Person? = Person(name: "yagom") // Person 인스턴스의 참조횟수 : 1
var room: Room? = Room(number: "505") // Room 인스턴스의 참조 횟수 : 1

room?.host = yagom // Person 인스턴스의 참조횟수 : 2
yagom?.room = room // Room 인스턴스의 참조 횟수 : 2

yagom = nil // Person 인스턴스의 참조횟수 : 1
room = nil // Room 인스턴스의 참조 횟수 : 1

// Person 인스턴스를 참조할 방법 상실 - 메모리에 잔존
// Room 인스턴스를 참조할 방법 상실 - 메모리에 잔존

위의 코드를 그림으로 설명

따라서 수동으로 아래의 작업들을 추가로 해줘야합니다.

room?.host = nil // Person 인스턴스의 참조 횟수 : 0 -> deinitialized
yagom?.room = nil // Room 인스턴스의 참조 횟수 : 0 -> deinitialized

만약 해제해야 할 프로퍼티가 너무 많게되면 귀찮아 지겠죠? 해결책으로는 약한참조와 미소유참조가 있습니다.

 

약한 참조

약한참조는 강한참조와 달리 자신이 참조하는 인스턴스의 참조 횟수를 증가시키지 않습니다. 참조타입의 프로퍼티나 변수의 선언 앞에 weak 키워드를 써주면 그 프로퍼티나 변수는 자신이 참조하는 인스턴스를 약한참조합니다.

 

약한참조는 nil이 할당될 수 있도록 해야하기 때문에 상수에서 쓰일수 없고, 항상 옵셔널 변수여야합니다.

 

인스턴스가 메모리에서 해제될 때, 즉 yagom = nil 을 하면서 Person 인스턴스의 참조횟수가 0이 되면서, Person이 메모리에서 해제

-> Person의 프로퍼티인 room이 메모리에서 해제되면서, room이 강한참조 하던 Room인스턴스의 참조횟수도 -1된다.

Class Room {
	let number : String

	init....

	weak var host: Person?
	
	deinit ...
}

var yagom: Person? = Person(name: "yagom") // Person 인스턴스의 참조횟수 : 1
var room: Room? = Room(number: "505") // Room 인스턴스의 참조 횟수 : 1

room?.host = yagom // Person 인스턴스의 참조횟수 : 1
yagom?.room = room // Room 인스턴스의 참조 횟수 : 2

yagom = nil // Person 인스턴스의 참조횟수 :0, Room 인스턴스의 참조 횟수 : 1
//yagom -> deinitialized

print(room?.host) //nil

room = nil // Room 인스턴스의 참조 횟수 : 0
//room -> deinitialized

오른쪽의 참조 해제의 경우는 room = nil 하기 전까지의 그림

 

미소유 참조

라는 것도 있답니다..! 추후 업데이트 하겠습니다..!

 

 

 

 

[참고 사이트 및 공부하면 좋을 사이트들]

https://ahyeonlog.tistory.com/3

https://jusung.gitbook.io/the-swift-language-guide/language-guide/23-automatic-reference-counting

https://fomaios.tistory.com/entry/리테인-사이클

https://sujinnaljin.medium.com/ios-arc-뿌시기-9b3e5dc23814

[WWDC21에서 ARC 동작 관련 세션] https://developer.apple.com/videos/play/wwdc2021/10216/

'iOS > Swift' 카테고리의 다른 글

[iOS] 화면 전환 방식 push vs present  (3) 2022.04.15
[iOS] Any, AnyObject, nil  (0) 2022.03.07
[iOS] SOLID 원칙 in Swift  (0) 2022.02.19
[iOS] 의존성 주입 DI  (2) 2022.02.19
[iOS] Data Binding in MVVM  (0) 2022.02.19

댓글