[iOS Swift] RC, ARC 와 MRC 란? 그리고 Strong, Weak, Unowned 는? 간단하게 적어봤습니다.

요즘에도 MRC 기반으로 개발 하는 곳이 있을 지 궁금하군요.

옛날?에 Objective-C(Objc) 개발할 때.. 처음에는 MRC로 개발 했었습니다.

RC

Reference Counting 입니다.

애플에서 메모리를 관리 하는 방법이죠.

참조 해서 사용할 때 카운트를 해서 메모리를 관리 하겠다는 거에요.

메모리를 할당하거나, 메모리 포인터를 참조 할 때 레퍼런스 카운트를 증가 시키고, 사용을 완료 하면 레퍼런스 카운트를 감소 시키지요.

Objective-C 로 개발하던 시기에는 개발자가 직접 참조 관리를 했었죠.

그걸 MRC 라고 합니다.

MRC

MRC는 Manual Reference Counting의 약어 입니다.

Cocoa Framework 에서 레퍼런스 증가는

alloc, new, copy, mutableCopy, retain 등을 사용했고,

레퍼런스 감소는 release 등을 사용했죠.

가물가물 하지만… 대충 이런 느낌입니다. (이해할 필요없는 내용이에요.)

// Objective-C 언어로 작성해봤습니다.
- (void)showSampleController:(id)sender {
SampleController *controller = nil
    // controller 는 nil
// controller 는 메모리 주소가 생성되기 전이고, 레퍼런스 카운트는 당연히 적용 전이죠.
    controller = [[SampleController alloc] initWithNibName:@"SampleController" bundle:nil];
    // controller alloc 하면서 메모리 주소가 할당 되고
// controller init 하는 과정을 통해 레퍼런스 카운트 1
    [self.navigationController pushViewController:controller animated:YES];
    // controller 레퍼런스 카운트 2  
    [controller release];
    // release가 호출 됬으니!! controller 레퍼런스 카운트 1
    // (.. controller .. 의 사용을 다하고 뒤로가기 같은 버튼을 눌렀다면)
    // 그리고 SampleController의 오브젝트인 controller의 사용을 종료할때
// 레퍼런스 카운트가 0이 되면서 dealloc ..소멸하겟죠?
// 살짝 가물가물하지만 비슷할 거에요.
}

그리고 Objective-C 개발하던 과거!!

iOS 4 이상 부터 ARC라고 자동으로 레퍼런스 카운트를 관리해 주는 기능이 생겼습니다. 참 옛날 이야기 이군요.

2018년 지금 iOS 12 이니.. 오래 전이야기 입니다.

저는 iOS5? 6? 쯤 부터 사용했던 것 같은데.. 기억은 안나네요.

한번 사용해 보니 너무 좋았던 .. 😍 그 뒤로 부터는 MRC를 사용하지 않았습니다.

아 .. 가끔 레거시 소스 건드릴 때는 .. 😭😭😭😭

Objective-C 이야기는 이제 그만해도 되겠지요.

요즘은 Swift 시대이니깐요.


ARC, GC

아참!! 처음 ARC가 도입할 때는 가비지 컬렉션과 비교를 많이 하며 이야기 했었지요.

Compile, Linking, Runtime (linking) 이렇게 3단계를 거쳐 Application 이 빌드되고 만들어져서 실행되는 것은 아시지용?😀

ARC는 컴파일 타임(compile time) 에 기존 MRC 때 개발자가 직접 코드를 작성해야 되던 부분을 자동으로 구문을 분석해서 적절하게 레퍼런스 감소 코드삽입해 주어, 실행 중에 별도의 메모리 관리가 이루어 지지 않습니다.

가비지 컬렉션( GC, Garbage Collection)은 프로그램 실행 중(Runtime)에 동적으로 감시하고 있다가, 더 이상 사용할 필요가 없다고 여겨지는 것을 소멸(해제) 시켜 버리죠.

어느쪽이 더 효율적일까요? ☺☺☺️


ARC

ARC는 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 do not need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.

Swift는 ARC를 사용하니 메모리 관리를 생각할 필요 없다. 라는 것 같아요.

그런데 몰라도 된다는 것은 아니고 메모리 참조 순환에 대해 기본적인 것은 알고 사용해야 됩니다.

흐음… 🤔🤔🤔🤔

바로 위 링크의 docs.swift.org의 내용 중

조금 더 아래로 스크롤 해보면..

Strong, Weak, Unowned Reference Cycles정도를 가볍게 알고 있으면 좋치 않을까요?

한국어로 말을 바꿔서.. 강한 순환 참조, 약한 순환 참조, …unowned 는 뭐라 해야되지 비소유? or 미소유? 순환 참조 정도 입니다.

Strong

Swift 에서 Strong은 어떠한 설정도 없을 때의 기본값입니다. 별도의 지시자를 기술하지 않았을 때의 디폴트 값이죠.

  • 해당 레퍼런스에 대해 강한 참조(strong reference)를 유지 하겠다는 뜻이죠
  • 해당 키워드는 레퍼런스 카운트를 증가시키죠.
힙 안에 있는 것 들을 힙 안에 머무르게 합니다.
Strong은 힙에 머물도록 강제한다고 생각하면 됩니다.
그 포인트가 더 이상 가리키지 않을 때 까지 입니다.
그래서 Strong 포인트는 힙 안에서 강하게 붙들고 있는 역활을 합니다.
예를 들어 포인터를 만들었는 데 그것이 모두 Strong 이라면,
깨끗이 청소하기 위해서는 모든 포인트를 지워야 합니다.

그런데 강한 순환 참조는 클로저 캡처링이나 객체간 서로 참조 등등의 경우 RC가 0이 되지 않는 상황이 있을 수 있고, 이럴 때 메모리 누수 (Memory Leak)가 발생할 수 있죠.

그래서 아래의 WeakUnowned도 알아야 됩니다.

Weak, Unowned

Weak와 Unowned는 대상 객체에 대해 레퍼런스 카운트를 변화시키지 않습니다. 같은 말로 “레퍼런스 카운트를 증가시키지 않는 다.” 입니다.

Weak와 Unowned는 힙에 있는 것에 아무도 관심이 없다면, 너희는 힙에서 제거할 수 있다..

그런데 이 둘은 중요한 차이점이 있습니다.

Weak

Weak는 해당 객체가 nil (NULL)일 수 있습니다.

weak는 객체가 옵셔널이라 해당 객체가 해제 되어 버린 상태에서 참조하게 되면, Application이 강제 종료되는 상황을 맞이하겠죠?

대신, weak는 언래핑 하는 과정을 통해 안전하게 사용할 수 있습니다.

weak는 반드시 Optional 입니다. 객체 참조형 변수에 nil(Null)이 할당 될 수 있어야 합니다.

weak는 힙에서 어떤 메모리를 가리키고는 있지만!! 
그 안에 들었는 것에는 그만큼 관심이 없어서사라져 버리면
그대로 nil로 설정하겠다는 것 입니다.

Unowned

unowned는 해당 객체는 절대 nil(Null) 일 수 없다. “Optional 객체가 아니다” 입니다.

매우 위험한 방법입니다.

보통의 경우에는 사용할 일이 없을 것입니다. weak 를 사용하시면 됩니다.

사용 되는 것을 예로 들어보면, 
메모리간에 순환 참조가 일어나는 데, 직접/간접 적으로 서로를 가리키게 되는 데,
메모리 안에 둘다 보관되는 경우? unowned로 그런 연결을 깰 수 있다고 합니다.
그리고 절대로 해지될리 없는 장소? 😓😓😓
보통은 필요하다면 Weak로 할 거에욧!!

개발하면서 갑작스래 물어보면, 잘 설명이 안되는 내용인 것 같습니다.

전 긴장을 매우 잘하는 타입이라 …..

한 번 정리해 보면 오래 기억할 수 있을까? 싶은 기대감에 작성해 봤습니다.

읽어주셔서 감사합니다.

즐거운 하루 되세요 :) 🙇‍