[Swift]ARC_강한참조

나는 사과·2021년 3월 23일
0

TIL

목록 보기
10/17

강한참조 = 인스턴스가 메모리에 계속 남아있어야하는 명분을 만들어 주는 것
지난 예제처럼 인스턴스를 다른 인스턴스의 프로퍼티나 변수, 상수에 할당할 때 참조 횟수가 1이 증가하고 nil을 할당하면 1이 감소한다.
기본적으로 참조는 강한참조여서 별도의 식별자를 명시하지 않아도 강한참조를 하게 된다.

하지만, 인스턴스끼리 서로 강한참조할 때 문제가 발생하는데 이를 강한참조 순환이라고 한다.

강한참조 순환의 예를 먼저 보면 다음과 같다.

class Car {
	let company: String
    var owner: Person?
    
    init(company: String){
    	self.company = company
        print("\(company)가 생성되었습니다.")
	}
    deinit{
    	print("\(company)가 해제되었습니다.")
    }
}
class Person{
	let name: String
    var car: Car?
    
    init(name: String){
    	self.name = name
        print("\(name)이 생성되었습니다.")
    }
    
    deinit{
    	print("\(name)이 해제되었습니다.")
    }
}

var tesla: Car? = Car(company: "tesla")
// tesla가 생성되었습니다.
// Car 인스턴스 참조 횟수 = 1
var chang: Person? = Person(name: "chang")
// chang이 생성되었습니다.
// Person 인스턴스 참조 횟수 = 1

tesla?.owner = chang
// Person 인스턴스 참조 횟수 = 2
chang?.car = tesla
// Car 인스턴스 참조 횟수 = 2

tesla = nil
// Car 인스턴스 참조 횟수 = 1
chang = nil
// Person 인스턴스 참조 횟수 = 1


위 코드를 실행하면 생성자만 실행이 되고 Car클래스와 Person 클래스의 인스턴스 참조 횟수가 1씩 남아있어서 소멸자가 실행되지 않는다. 하지만 이미 각각의 인스턴스를 참조하던 변수에 nil을 할당해서 더 이상 참조할 방법이 없다. 바로 이것이 강한참조 순환 문제이다. 참조횟수는 0이 아니여서 소멸자가 실행되지 않았지만 인스턴스에 더 이상 접근하지 못하는 문제다.

이렇게 되면 메모리에는 각각의 인스턴스가 차지하는 공간이 계속 발생하고 메모리 누수가 발생하게 된다. 그래서 이 문제를 해결하기 위해서는 어떻게 해야 할까?

먼저 무식한 방법이다.
바로 nil을 할당해 메모를 해제할 때 아래 코드처럼 서로 연관되어있는 것 먼저 해제를 한 다음 인스턴스에 nil을 할당하는 방법이다.

tesla?.owner = nil
// Person 인스턴스 참조 횟수 : 1
chang?.car = nil
// Car 인스턴스 참조 횟수 = 1

tesla = nil
// Car 인스턴스 참조 횟수 = 0
chang = nil
// Person 인스턴스 참조 횟수 = 0

이렇게 한 다음 실행을 시키게 되면 생성자부터 소멸자까지 실행이 된다.

하지만 이 방법은 조금 불편하다. 지금처럼 짧은 코드에서는 쉽게 할 수 있지만 코드가 길어지고 인스턴스가 많아지게 된다면 어쩌면 까먹을 수도 있고 너무 많아서 도저히 엄두가 안 날수도 있다. 이럴때에는 약한참조나 미소유참조를 이용해서 조금 더 깔끔하게 해결할 수 있다고 한다.

0개의 댓글