ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ARC 심화
    Swift 2021. 2. 17. 12:12

    안녕하세요. 그린입니다!

    이번 포스팅에서는 ARC에 대해 심화적으로 알아보겠습니다.

     

    • ARC란?
       : Automatic Reference Counting (자동참조계수)를 뜻한다.
       : 다른 언어에는 없는 독창적인 것으로 자바의 가비지 컬렉션 기법과는 다름 (메모리 해제 시점에 관한 이해가 필요)
    • 자동참조계수란?
      : 앱의 메모리 사용을 추적하고 관리해준다.
      : 인스턴스가 더이상 필요하지 않을때 클래스 인스턴스에 사용된 메모리를 자동으로 해제해준다. (참조 타입의 할당 / 해제 시점을 자동 관리)
      : 클래스의 인스턴스(참조 타입)에만 적용 (구조체/열거형 등 값 타입에는 적용되지 않는다)
    • ARC 특징
      1) 하나의 활성화 참조가 있다면 인스턴스는 할당 해제되지 않고 계속 존재
      2) 강한참조의 할당을 nil로 정리해준다면 할당 해제된다.
      3) 객체 생성 및 공유 시 마다 카운터(참조횟수)를 업데이트 해준다.
    • ARC 사용

    =

    : 이 부분에서 참조된 2개에 강한참조로 인스턴스가 메모리에 할당된다.

    -> 만약 1/2를 nil로 할당하면 강한 참조는 깨지고 마지막 3의 강한참조만 남고 Person 인스턴스는 할당 해제되지 않는다.

    : 마지막 남은 강한 참조를 nil로 깨주면 Person 인스턴스가 할당 해제된다.

    • ARC의 여러 참조 종류
      1) 강한참조
       : 프로퍼티, 변수, 상수에 대해 기본값으로 설정되어 있는 참조 옵션
       : 참조횟수가 0일시 해제되고 디이니셜라이저가 호출됨 (자동)
       : 여러개의 인스턴스가 서로 참조할 시 강한 참조 순환 문제 발생 가능성 농후
       : 메모리 해제 시점 이해없이 사용 시 인스턴스가 영원히 메모리에서 해제되지 않는 메모리 누수가 일어남
         (약한참조 / 미소유참조로 해결 가능)
      2) 약한참조
       : weak 옵션 키워드를 붙여 생성
       : 자신이 참조하는 인스턴스의 참조횟수를 증가시키지 않음
       : 항상 옵셔널로 사용
      3) 미소유참조
       : unowned 옵션 키워드 붙여 생성
       : 참조하는 인스턴스가 항상 메모리에 존재할거라는 기반을 가지고 사용
    • 강력참조순환
      : 클래스 인스턴스 사이의 강력참조순환의 문제가 발생할 수 있다.
      : 두 클래스 인스턴스가 서로 강력 참조를 하고 있을때 각 인스턴스의 참조를 깨줘도 계속 살아 유지되어 메모리 누수를 야기하게되는것

    : 서로 클래스가 참조하고 있다.


    : 이럴 시 해당 두 클래스 인스턴스는 서로 강력참조순환을 한다. (아래 그림과 같은 형태이다)

    : 해당 인스턴스들의 할당을 깨줘도 서로 강력참조순환은 남아있다.

    • 강력참조순환 해결방안
      -> 약한참조와 미소유 참조가 있다. 참조 순환 안에 있는 인스턴스가 다른 인스턴스에 강한 참조를 유지할 필요없이 참조
           (즉, 각각 강력 참조 순환을 만들지 않고 서로 참조 할 수 있음)
      1) 약한참조
      : 객체가 옵셔널이라 해당 객체가 해제되었는데 참조하게되면 앱이 강제종료된다. (언래핑을 통해 안전하게 사용 필요)

    : weak를 붙여 약한 참조

    : 강력 순환 참조가 깨짐

    : 강한 참조를 깨서 남아있지 않게됨

    : 이후 number73 = nil로 주면 디이니셜라이저가 할당 해제됨을 알린다. (강한 순환 참조가 깨진 증거)

          2) 미소유 참조
    : 약한 참조와 비슷하지만 항상 값이 있음을 가정한다. (옵셔널이 아닌 타입으로 정의됨)

    : 옵셔널이 아님으로 사용 시 언래핑할 필요가 없음 (항상 직접 접근이 가능)

            : 인스턴스 할당 해제 시 참조를 nil로 설정할 수 없음 (옵셔널이 아닌 타입 변수는 nil로 설정될 수 없기에)
            : 절대 nil일 수 없다!!! (옵셔널 객체가 아니다) -> 매우 위험한 방법으로 대부분 weak 사용

    : 이후 할당 해제되면 해제된다 (강력 참조 순환이 없기에)

    • 클로저의 강한 참조 순환 -> 문제 발생 시 획득목록을 통해 해결 (강한획득, 약한획득, 미소유획득)
      -> Capture list: 대괄호로 넣어 표현하며 외부에서 발생하는 변화에 반응하지 않음
    • ARC 이전 메모리 관리는 어떻게?
      : MRC(Manual Reference Counting), MRR등 개발자가 수동으로 직접 메모리 관리
      -> alloc, new, copy, mutableCopy, retain 등을 사용하여 레퍼런스 증가
      -> release를 사용하여 레퍼런스 감소
    • 레퍼런스 카운팅을 하는 이유?
      : 참조의 시점을 알기 위해서
    • 애플리케이션이 빌드되는 단계
      1) Compile (ARC가 이뤄지는 단계)
      2) Linking
      3) Runtime (가비지 컬렉션, GC는 이 단계에서 동적으로 감시하다가 필요 없을 시 해제됨)
    • weak unowned 차이
      1) 사용되는 시점
       : unowned는 다른 인스턴스의 생명주기 같거나 더 긴 경우
       : weak는 다른 인스턴스의 생명주기 짧은 경우
      2) 객체가 사라지면 nil로 바뀌는 weak에 반면 unowned는 객체가 사라지면 댕글로 포인터가 남음
           : 댕글러포인터? 원래 바라보던 객체가 해제되면서 할당되지 않는 공간을 바라보는 포인터

    [참고자료]

    http://minsone.github.io/mac/ios/swift-automatic-reference-counting-summary

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

    https://shark-sea.kr/entry/iOS-ARC-strong-weak-unowned

    야곰의 스위프트 프로그래밍(3판)

     

    'Swift' 카테고리의 다른 글

    lazy var  (0) 2021.03.17
    Swift Performance  (0) 2021.03.01
    Type Casting  (0) 2021.01.29
    Protocol Oriented Programming  (0) 2021.01.28
    타입 메서드  (0) 2021.01.27
Designed by Tistory.