iOS/Swift - ARC에 대해 (1)
ARC에 대한 개념을 다시 확실하게 잡고 싶어 공식 문서를 보고 정리한 내용을 공유한다.
공식문서 링크 : https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html
- Swift는 기본적으로 ARC를 통해서 앱의 메모리 사용량을 관리해주는 역할을 한다.
웬만해서는 개발자가 크게 신경 안 써도 잘 작동한다. 자동적으로 클래스 인스턴스 가 필요 없을 때 메모리에서 잘 해제해준다.
그런데 ARC가 이걸 다 해주진 못하고, 앱의 효율적인 메모리 관리를 위해 개발자가 객체와 객체 사이의 관계를 조금 더 명확히 작성해줘야 ARC가 이걸 파악해서 메모리를 해제해야 할 때 해제해준다.
✻ Reference Counting은 클래스 인스턴스에게만 일어난다. 구조체나 enum은 Value Type이기 때문에 주소값, 즉 참조에 대한 정보가 저장되거나 왔다갔다 하지 않는다.
ARC 작동 방식
한 클래스 인스턴스를 생성할 때, ARC는 메모리에 해당 클래스에 대한 참조 정보를 할당한다.
→ 인스턴스의 타입, 가지고 있는 프로퍼티 등을 저장한다.
그리고 해당 객체가 더 이상 쓰일 필요가 없을 때 ARC는 이 객체를 메모리에서 해제한다.
ARC가 해당 객체를 메모리에서 해제할지 말지는 해당 객체에 대한 참조 횟수가 0이냐 아니냐에 달려있다. 참조 횟수가 1이상이면 메모리에서 해제하지 않는다.
→ 특정 클래스 인스턴스를 어떤 변수나 상수에 할당을 하면 해당 클래스에 대한 strong reference를 만드는 것이다. strong reference가 있는 한 메모리에서 해제되지 않는다.
ARC 예시
reference1 = Person(name: "Kevin")
reference2 = reference1
reference3 = reference1
✻ Person 인스턴스에 대한 strong reference가 3개 있음.
reference1 = nil
reference2 = nil
→ 참조 횟수 - 2 → 아직 1개가 남아있기 때문에 Person 인스턴스는 메모리에서 해제되지 않고, 그에 따라 deinit { } 메서드는 호출되지 않음.
reference3 = nil
→ 비로소 deinit { } 메서드가 호출되면서 메모리에서 해제
클래스 인스턴스 사이의 Strong Reference Cycle
위 예시 같은 경우에는 ARC가 참조 횟수를 추적하면서 그 횟수가 0에 도달했을 때 알아서 잘 메모리에서 해제해준다.
다만, 어떤 경우에는 클래스 참조 횟수가 0에 절대 도달하지 않는 경우 가 있다.
✻ 언제? → 2개의 클래스 인스턴스가 서로에 대한 “강한 참조”를 가지고 있으면 strong reference cycle이 일어나면서 메모리에서 절대 해제가 되지 않는다.
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
var john = Person(name: "John Appleseed")
var unit4A = Apartment(unit: "4A")
두 개의 인스턴스를 생성하면 strong reference는 아래와 같은 형태가 된다.
john 변수는 Person 인스턴스에 대한 강한 참조가 1개 있고, unit4A 변수는 Apartment 인스턴스에 대한 강한 참조가 1개 있다. 각각 1개씩이다.
john.apartment = unit4A
// Person 인스턴스가 Apartment 인스턴스에 대한 strong reference가 1 증가했다
unit4A.tenant = john
// Apartment 인스턴스가 Person 인스턴스에 대한 strong reference가 1 증가했다
→ 이제 총 2개씩의 strong reference를 가지고 있음.
john = nil
unit4A = nil
이렇게 해도 메모리에서 해제가 되지 않는다.
→ 해제를 해도 아래와 같이 강한 참조가 남아있음
✻ 그런데 john 가 unit4A를 해제했기 때문에, 이제 그 안에 있는 apartment랑 tenant 프로퍼티에 접근할 수 있는 법이 사라진거임. 접근이 불가능해서 결국 memory leak 발생
Author And Source
이 문제에 관하여(iOS/Swift - ARC에 대해 (1)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kevinkim2586/iOSSwift-ARC에-대해-1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)