[Swift] ARC 뿌시기

ARC.. 들어는 봤습니다만?ㅎ

naljin
10 min readMay 31, 2020

들어가기 전에

자자 오늘은 ARC와 함께 돌아왔습니다요. Auto Reference Counting 은 iOS 공부하신 분들이라면 개념은 잘 몰라도 한번쯤 들어보셨을거예요!

ARC에 관한 저의 얕은 지식은 이렇습니다.

ARC란

  • 자동으로 메모리 관리해주는 좋은 친구
  • 객체에 대한 참조 카운트를 관리하고 0이 되면 자동으로 메모리 해제
  • run time에 계속 실행되는게 아니라 complie time(build 할 때)에 실행
  • 하지만 retain cycle에는 유의해야한다
  • 옛날 옛적 Objective-C에서는 MRC, 즉 수동으로 메모리 관리 했다

이 정도인데… 흠.. 위의 정보를 알고 있다고 가정하고 글을 쓸거예요! 이게 대체 뭔 소린데!!! 하면 좋은 글들이 많으니 구글링하고 오십셔!

그럼 오늘 할 것은 뭐냐~~~~ 바로 바로 ARC에 대해 더 깊게 파헤쳐볼겁니다! 니킥 뿌셔🦵🏻 팝핀 뿌셔🕺🏻 ARC 뿌셔!!!!👊🏻 알아들으셨다면 당신은 제 동년배!😉

쓰게 된 이유는

‘ARC가 compile time에 실행되는데 어떻게 동적으로 실행되는 것들의 reference count를 세고 메모리 관리를 할 수 있냐

라는 질문을 받았기 때문! 오잉 그러게 말이져 ㅎ? 지금부터 알아보도록 합시다 ㅎㅎ

앗..시작하기 전에 obj-c 코드도 잠깐 등장할 수 있으니 마음의 준비 단단히 하십쇼…(스스로에게 하는 소리)

입벌려 옵젝씨 들어간다

MRC 메모리 관리

자 옛날 옛적 Obj-C는 retain, release, autorelease 등을 통해 수동으로 메모리 관리를 해왔나봐여~~(MRC. Manual Reference Counting)

자 옵젝씨 코드를 봅시다

- (void)setName:(NSString *)newName {
[newName retain];
[name release];
name = newName;
}

retainrelease가 보이시나요? 원래는 이런식으로 메모리 관리를 해주고 그랬나 봐요!

여기서 retainrelease 를 잠깐 짚고 넘어가 봅시다.

  • retain : retain count(= reference count) 증가를 통해 현재 Scope에서 객체가 유지되는것을 보장
  • release : retain count(= reference count)를 감소시킴. retain 후에 필요 없을 때 release

하지만 딱 봐도 쉽지 않아보이네요. 이런 개발자들의 어려움을 알았던건지 WWDC 2011 에 ARC가 뚜둔- 등장하게 됩니다.

ARC 등장하다..!

그리고 Swift는 무조건 ARC를 통해 메모리 관리를 하게 되죠! 참고로 Obj-C는 ARC 여부를 선택할 수 있습니다. Xcode 5 이후부터 default로 설정되어있긴 하지만요.

ARC 메모리 관리

ARC가 어떻게 기존 메모리 관리를 쉽게 바꿔주었냐! 하면

compile time에 자동으로 retain, release를 적절한 위치에 삽입하는 방식

으로 라고 말씀드릴 수 있어요.

ARC에서 reference count 를 통해 메모리 관리를 한다고 할 때, 대체 어떻게 reference count를 증가/감소 시키는거지..? 했는데 retain, release를 삽입하고 있던거였네요! 아까 위에서 봤듯 retainrelease 는 각각 reference count 를 증감시키는 애들이니까요!

어쨌든 수동으로 작성하던걸 자동으로 작성해주다니! 훨씬 메모리 관리가 쉬워졌겠죠? MRC에서 ARC로 왔을때 코드도 훨씬 짧아집니다.

이렇게 ARC는 자동으로 retain, release를 삽입해서 retainCount 를 관리하고, 0이 될때 deinit을 호출해서 메모리 해제를 시킨답니다!

족굼만 더 깊이 들어가봅시다! 과연 referenceCount는 어디서 관리하고 있는걸까요!

여러분 지금 저희가 하고 있는건 뭐죠? 메모리 관리입니다! 지금까지 주구장창 ARC가 referenceCount를 통해 메모리를 관리한다! 라고 말해왔어요. 그리고 메모리 관리는 Data, Heap, Stack, Code 이렇게 4가지 가상 메모리 영역 중 Heap 영역과 관련되어 있습니다. Heap 은 class, closure 등의 참조형(reference) 자료 들이 머무는 공간이자, 개발자가 동적으로 할당하는 메모리 공간이기 때문에 관리가 필요하기 때문이죠.

관리를 위해서는 Heap 영역참조형 자료들이 얼마나 참조되고 있는지 카운팅하고 이에 따라 메모리 할당 및 제거하면 됩니다. 그리고 이것을 자동으로 해주는 것이 바로 ARC 입니다.

ARC의 메커니즘은 Swift Runtime 이라는 library에 구현되어있습니다. Swift Runtime은 동적 할당되는 모든 object를 HeapObject 라는 struct로 표현합니다. HeapObject에서는 Swift에서 객체를 구성하는 모든 데이터, 즉 reference count와 type meta data를 포함하고 있습니다.

자 실제로 HeapObject.h를 들어가보면 RefCount.h 를 import 하고 있는걸 볼 수 있죠. (RefCount.h 들어가보면getWeakRefCount()getUnownedRefCount() 같은 함수가 정의되어있어요..! 신기..!!!)

//HeapObject.h#include "RefCount.h"

자 정보를 종합해보자면

  1. 동적 할당으로 object가 생성되면 해당 정보는 HeapObject라는 struct로 관리됨
  2. HeapObject 안에는 reference count도 포함됨
  3. 따라서 class에 대한 HeapObject를 통해 reference count 관리 가능

마무리

이제 처음의 질문에 대해 답변할 수 있을 것 같아요. 자 질문이 뭐였죠?

ARC가 compile time에 실행되는데 어떻게 동적으로 실행되는 것들의 reference count를 세고 메모리 관리를 할 수 있냐

제 대답은 이렇습니다!

  1. compile time에 코드 분석을 통해 적절한 위치에 retain, release 등의 코드를 삽입해 줌
  2. 삽입된 코드는 run time에 실행됨
  3. retain, release를 통해 referenceCount를 증감시키다가 count 가 0이 되면 deinit 을 통해 해제 시킴
  4. referenceCount 는 동적 할당된 object를 표현하는 HeapObject struct에서 접근 가능

어떤가요! 여러분도 이해..?공감..?이 되시나요?!

사실 retain, release 하고 reference count가 0이 되었을때 deinit하는 구현부를 찾아보고 싶었지만 잘 못찾겠네여 ㅎ 더 깊게 들어가진 않았지만 이 정도로 만족하고 필요하면 그때 또 공부해보는걸로합시다!

만약 틀렸거나 보충해주실 내용 있다면 제발베라제발제발제발!!! 댓글 남겨주세요!!!!!! 저는 선생님덜의 댓글을 먹고 성장하겠슴둥👩🏻‍💻 (이미 한번 잘못된 정보 남기고 부랴부랴 고쳤슴다 ㅎ)

그럼 20000!

+) 추가로 WWDC21 에 ARC 동작에 관한 좋은 세션이 나왔길래 첨부합니당

참고 사이트

--

--