본문 바로가기
iOS/Swift

[Swift] Strong (강한참조)

by Jiseong 2021. 5. 28.

평소처럼 공부하다 아웃렛 변수를 추가할 때 나타나는 팝업창의 Storage 항목에서 Strong, Weak가 궁금했다.

Storage

이 두가지는 메모리 회수 정책을 나타내는 키워드이다.

 

먼저 ARC란 것을 알아보자

 

ARC란?
Automatic Reference Counting 의 약자로 이름에서 알 수 있듯 자동으로 메모리를 관리해주는 방식이다. 
ARC는 더이상 필요하지 않은 클래스의 인스턴스를 메모리에서 해제하는 방식으로 동작한다.

참조 계수는 클래스의 인스턴스에만 적용되며, 구조체와 열거형은 값 타입이지 참조 타입이 아니며 참조를 저장하지 못하고 전달치 못한다.

 


How ARC Works

클래스의 새 인스턴스를 만들 때마다 ARC는 해당 인스턴스에 대한 정보를 저장하기위해 메모리 덩어리를 할당한다.

이 메모리는 해당 인스턴스의 저장 속성과 함께 인스턴스에 대한 정보를 보유한다.

 

또한 인스턴스가 더 이상 필요하지 않은 경우 ARC는 해당 인스턴스에 사용된 메모리를 할당 해제하여 메모리를 다른 용도에 사용 할 수 있게한다. (메모리 릭 방지) 이렇게 하면 클래스 인스턴스가 더 이상 필요하지 않을 때 메모리 공간을 차지하지 않는다.

 

그러나 ARC가 아직 사용중인 인스턴스의 메모리를 할당 해제하면 해당 인스턴스의 속성에 엑세스하거나 메소드를 호출할 수 없다.

사용중인 인스턴스의 메모리를 할당 해제한 후 인스턴스에 엑세스를 하려하면 앱은 죽을 수 있다. 

 

인스턴스가 필요한 상황에서 ARC는 인스턴스가 메모리에서 해제되지 않도록 인스턴스 참조 여부를 계속 추적한다.

다른 인스턴스의 프로퍼티나 변수, 상수 등 어느 한 곳에서 인스턴스를 참조한다면 ARC가 해당 인스턴스를 할당 해제하지 않고 유지해야한다.

 

이를 가능케하기 위해 프로퍼티, 변수, 상수에 클래스 인스턴스를 할당할 때마다 해당 프로퍼티, 변수, 상수는 인스턴스에 대한 강한 참조를 만든다. 강력한 참조가 유지되는 한 할당 해제를 허용하지 않기 때문에 강한 참조라고 한다.


ARC in Action

class Person {
    let name: String

    init() {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

 

Person 클래스에는 인스턴스의 이름 속성을 설정하고 초기화 진행중임을 나타내는 메세지를 출력하는 initializer가 있다.

또한 인스턴스가 할당 해제될 때 메시지를 출력하는 deinitializer도 있다.

 

다음은 Person 타입의 세 개 변수를 정의하여 다양한 참조를 설정 사용하는 예제이다.

var reference1: Person?
var reference2: Person?
var reference3: Person?

이제 새 Person 클래스 인스턴스를 만들고 세 변수중 하나에 할당할 수 있다.

reference1 = Person(name: "Jiseong")
//Jiseong is being initialized
//인스턴스 참조 횟수: 1

새 Person 인스턴스가 reference1 변수에 할당되었으므로 reference1에 새로운 Person 인스턴스가 강력참조로 된다.

ARC는 Person 인스턴스가 메모리에서 유지되고 할당 해제되지 않도록 한다.

 

같은 클래스 인스턴스를 나머지 두 변수에 할당하자

reference2 = reference1//인스턴스 참조 횟수: 2
reference3 = reference1//인스턴스 참조 횟수: 3

이제 하나의 Person 인스턴스에 3개의 강한참조가 있다.

 

만약 두개의 변수에 nil을 할당하여 강한참조가 깨져도 하나의 강한참조가 남아있기에  Person 인스턴스는 할당 해제되지 않는다.

reference3 = nil //인스턴스 참조 횟수: 2
reference2 = nil //인스턴스 참조 횟수: 1

ARC는 마지막 강한참조가 깨질 때까지 Person 인스턴스를 할당 해제하지않는다.

마지막 남은 강한참조를 해제해보자

reference1 = nil //인스턴스 참조 횟수: 0
//Jiseong is being deinitialized

마지막 남은 변수에  nil을 할당하여 강한참조가 깨지면 Person 인스턴스가 할당 해제되어  "Jiseong is being deinitialized" 가 출력되는 것을 볼 수 있다.

 

전체 코드

class Person {
    let name: String

    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}
var reference1: Person?
var reference2: Person?
var reference3: Person?

reference1 = Person(name: "Jiseong")
//Jiseong is being initialized
//인스턴스 참조 횟수: 1
reference2 = reference1//인스턴스 참조 횟수: 2
reference3 = reference1//인스턴스 참조 횟수: 3

reference3 = nil //인스턴스 참조 횟수: 2
reference2 = nil //인스턴스 참조 횟수: 1
reference1 = nil //인스턴스 참조 횟수: 0
//Jiseong is being deinitialized

 

 

https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html

 

Automatic Reference Counting — The Swift Programming Language (Swift 5.4)

Automatic Reference Counting Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you don’t need to think about memory management your

docs.swift.org

 

다음은 클래스 인스턴스간 강한 참조 순환을 알아보겠다.

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

MAC Xcode 신뢰할 수 없는 개발자 설정 방법  (0) 2021.06.04
[Swift] 컬렉션 타입 (Array)  (0) 2021.06.03
[Swift] Date Picker  (0) 2021.05.31
[Swift] Image View  (1) 2021.05.28
[Swift] Delegate Example  (2) 2021.05.19

댓글