본문 바로가기
Swift

[Swift] ARC (Auto Reference Counting)

by Sky Titan 2021. 5. 31.
728x90
스위프트 프로그래밍
국내도서
저자 : 야곰
출판 : 한빛미디어 2019.10.01
상세보기

ARC (Auto Reference Counting)

  • 매번 전달할 때 값을 복사해서 전달하는 값 타입(value type)과 달리 참조 타입(Reference Type)은 하나의 인스턴스가 참조를 통해 여러 곳에서 접근하기 때문에 언제 메모리에서 해제되는지 중요
  • Swift에서는 메모리 사용을 관리기법인 ARC 사용
    • ARC는 값 타입인 class의 인스턴스만 적용
    • enum, struct는 value 타입이므로 무관
    • Objective-C에서도 사용

 

ARC vs Garbage Collection

기법 ARC Garbage Collection
Reference Counting 시점 컴파일 시 프로그램 동작 중 (런타임 시)
장점 - 컴파일 시 메모리 해제 시점이 정해져 있어서 언제 해제 될지 예측 가능

- 해제 시점이 정해져 있어서 메모리 관리를 위한 추가 시스템 자원 필요 x
- 상호 참조 (Mutual Reference) 등의 상황에서도 인스턴스를 해제할 수 있는 가능성이 더 높음

- 규칙 신경 쓸 필요 없음
단점 - ARC 작동 규칙을 모르면 영원히 인스턴스가 메모리 해제되지 않을 수 있음 - 프로그램 동작 외에 메모리 관리를 위한 추가 시스템 자원 필요

- 메모리 해제 시점 예측 어려움

 

강한 참조 (Strong Reference)

  • 특정 instance를 다른 instance의 프로퍼티, 변수, 상수 등에 할당할 때 강한 참조를 사용하면 참조 횟수가 1 증가
  • 강한 참조를 사용 중인 프로퍼티, 변수, 상수에 nil 할당 시 참조 횟수 1 감소
  • 인스턴스가 계속해서 메모리에 남아있게 함
  • 참조 횟수가 0이 되는 순간 메모리에서 해제
  • default 참조 방식
import Foundation

class Human {
    var name: String
    init (_ name: String) {
        self.name = name
    }
}

var human1: Human? = Human("Park")//참조 횟수 1
var human2: Human? = human1 //참조 횟수 2
var human3: Human? = human2//참조 횟수 3

human1 = nil //참조 횟수 2
human2 = nil //참조 횟수 1
human3 = nil //참조 횟수 0

 

강한참조 순환 문제 (Strong Reference Cycle)

  • 서로가 서로를 강한 참조할 때 발생하는 문제
  • delegate 패턴 사용 시, closure 주의해야할 사항
import Foundation

class Human {
    var name: String
    var pet: Dog?

    init (_ name: String) {
        self.name = name
    }
}

class Dog {
    var name: String
    var host: Human?

    init (_ name: String) {
        self.name = name
    }
}

var host: Human? = Human("Park")//host 참조 횟수 1
var pet: Dog? = Dog("Happy")//pet 참조 횟수 1

host?.pet = pet //pet 참조 횟수 2
pet?.host = host//host 참조 횟수 2

host = nil //host 참조 횟수 1
pet = nil //pet 참조 횟수 1

//host 인스턴스 참조 불가 - 계속 잔존
//pet 인스턴스 참조 불가 - 계속 잔존

 

강함참조 순환 문제 해결법

import Foundation

class Human {
    var name: String
    var pet: Dog?

    init (_ name: String) {
        self.name = name
    }
}

class Dog {
    var name: String
    var host: Human?

    init (_ name: String) {
        self.name = name
    }
}

var host: Human? = Human("Park")//host 참조 횟수 1
var pet: Dog? = Dog("Happy")//pet 참조 횟수 1

host?.pet = pet //pet 참조 횟수 2
pet?.host = host//host 참조 횟수 2

//수동 해결법
host?.pet = nil//pet 참조 횟수 1
pet?.host = nil//host 참조 횟수 1

host = nil //host 참조 횟수 0
pet = nil //pet 참조 횟수 0

 

약한 참조 (Weak Reference)

  • 강함참조와 달리 자신이 참조하는 인스턴스의 참조횟수를 증가시키지 않는다.
  • 프로퍼티, 변수 선언 앞에 weak 키워드 사용
  • 약한 참조는 항상 nil이 할당될 수 있어야 하기에 optional 타입의 변수여야 한다.
import Foundation

class Human {
    var name: String
    weak var pet: Dog?

    init (_ name: String) {
        self.name = name
    }
}

class Dog {
    var name: String
    weak var host: Human?

    init (_ name: String) {
        self.name = name
    }
}

//weak 사용
var host: Human? = Human("Park")//host 참조 횟수 1
var pet: Dog? = Dog("Happy")//pet 참조 횟수 1

host?.pet = pet //pet 참조 횟수 증가 x
pet?.host = host//host 참조 횟수 증가 x

host = nil //host 참조 횟수 0
pet = nil //pet 참조 횟수 0

 

미소유참조 (Unowned Reference)

  • 약한 참조처럼 참조 횟수를 증가시키지 않는다.
  • 약한 참조와는 다르게 참조하는 인스턴스가 항상 메모리에 존재할 것이라는 전제를 기반으로 동작
    • 자신이 참조하는 인스턴스가 메모리에서 해제되더라도 nil을 할당해주지 않는다.
    • optional이나 변수일 필요 없음
  • 미소유참조 중에 메모리에서 해제된 인스턴스에 접근 시도시 런타임 오류 발생
    • 따라서 해당 인스턴스가 메모리에서 해제되지 않는다는 확신이 있을 때만 사용
import Foundation

class Human {
    var name: String
    unowned let pet: Dog

    init (_ name: String,_ pet: Dog) {
        self.name = name
        self.pet = pet
    }
}

class Dog {
    var name: String

    init (_ name: String) {
        self.name = name
    }
}

var dog: Dog = Dog("Happy")//참조 횟수 1
var human: Human
human = Human("Park", dog) //참조 횟수 증가 x

print(human.pet.name) // Happy

dog = Dog("Sad") //기존 인스턴스 참조 횟수 0

print(human.pet.name) // 런타임 에러 발생

 

728x90

'Swift' 카테고리의 다른 글

[Swift] 가변매개변수 (Variadic Parameters)  (0) 2021.06.13
[Swift] class 키워드 vs static 키워드  (0) 2021.06.02
[Swift] where절  (0) 2021.05.31
[Swift] inout 파라미터  (0) 2021.05.28
[Swift] 제네릭 (Generics)  (0) 2021.05.28

댓글