본문 바로가기
iOS/Swift

힙 메모리 관리 - ARC 정리

by 나리._. 2022. 1. 13.

힙 메모리를 왜 관리해야할까?

 

스위프트에서 값 형식은 스택에 저장이 되고

 스택의 스코프가 종료되면 메모리에서 자동으로 제거되기 때문에 메모리 관리를 할 필요가 없다 !

 

그에 반해, 참조형식은 힙 영역에 저장이 되고 힙은 동적할당을 하기 때문에 우리는 메모리 관리를 해야한다.

 

여기서 동적할당은? 🧐

힙이라는 공간은 저장할 공간이 정해져있지않고

스캔을 해서 비어있는 공간에 할당을 한다는 개념!

 

힙에 할당되는 데이터를 관리를 하지 않는다면 (데이터가 필요 없음에도 할당이 해제되지 않는다면)

메모리 누수 (Memory Leak) 현상이 발생한다!

(메모리가 쌓이기만 하고 지워지지 않으면 메모리가 많은 공간을 차지하고 앱이 꺼지는 현상이 발생할 수 있음)

 

 

그럼 힙 영역의 메모리를 관리를 어떻게 해야할까?!

 

일단 Java에서는 GC(Garbage Collector)라는 메모리 관리 모델이 있다.

이름 그대로 쓰레기를 모으는 것인데, 여기서 쓰레기는 당연히 사용 안하는 데이터를 말하는 것이다. Java에서 GC는 자동으로 알아서 하기 때문에 개발자가 신경쓸 일이 없다.

하지만 힙 영역을 한번씩 스캔해야한다는 치명적인 단점이 있다. (느림)

 

Obj-C나 Swift에서는 RC(Reference Counting)을 이용한다.

나의 메모리 주소를 가르키는 숫자를 세서 (Reference Counting) 이 숫자가 0이면 메모리에서 없애는 것이다!

 

Obj-C에서는 MRC(Manual RC), ARC(Automatic RC)가 있고

Swift에서는 ARC(Automatic RC)가 있다.

 

이름에서도 알 수 있듯이 

MRC(Manual RC), ARC(Automatic RC)

둘의 메커니즘은 같고 수동으로 하냐 자동으로 하냐의 차이이다.

수동으로 하게되면 개발자가 이 관리 코드를 작성해야하고 

자동으로 하게되면 Xcode가 알아서 관리 코드를 작성해준다고 생각하면 된다.

 

Obj-C가 처음 나왔을때는 MRC(Manual RC)만 가능했지만

개발자는 실제 로직 구현 포함, 메모리 관리에 대한 부담이 있었고

메모리 해제하는 것을 까먹고 실수하는 경우가 많았다고 한다.

따라서, 현대적 언어들은 대부분 자동 메모리 관리 모델(ARC)을 사용한다.

 

Xcode가 자동으로 관리코드를 작성해주는데 왜 개발자가 ARC에 대해 알아야할까?

Xcode에서 메모리 관리를 자동으로 해주는 것이 아니라 RC(참조 숫자)를 자동으로 세주는 것이기 때문에 

개발자가 이 개념을 모른채로 코드를 잘못 작성하면 Xcode가 이 참조 숫자(RC) 세는 것을 잘못 인식할 수 있다.

 

이제 MRC, ARC모델에 대해 자세히 알아보자!

 

이와 관련된 WWDC의 코드를 보면

 

개발자가 작성한 코드

 

위의 코드를 돌리면 힙 영역에 Point 인스턴스가 하나 들어갈 것이고

point1, point2가 그것을 가리킬것이다.

 

위의 코드를 실제로 돌리면 Swift 내부에서 아래와 같은 일이 일어난다고 한다.

컴파일 된 코드 (MRC 모델이라고 생각해도 된다.)

 

클래스를 만들때 refCount(참조변수)라는 변수를 하나 더 만들고

인스턴스를 찍어낼때 이 변수에 +1을 한다는 것이다.

 

또 point1을 point2에다 담을때 (메모리 주소 복사)

Swift에서 자동으로 retain(point2)이라는 코드를 심어주는데 이것은 point2가 가르키는 애의 refCount에 +1을 하는것이다.

그럼 여기서 RC는 2가 된것이다 !!!

생성자 코드를 작성할때도 이 retain 함수가 숨어있다고 생각하면 된다.

 

스코프가 종료되면 release 코드가 심어지는데 이것은 refCount에 -1을 하는 것이다.

여기서는 point1,2가 같은 것을 가르키기 때문에 RC가 0이 됨을 알 수 있다.

이때(RC가 0이 되었을때) 힙에서 해당 인스턴스가 사라진다.

 

즉 스위프트의 경우, 컴파일러가 실제로

retain() 할당 ---> release() 해제 코드를 삽입한다고 보면 되는 것!!

 

컴파일러가 메모리 관리코드를 자동으로 추가해 줌으로써, 프로그램의 메모리 관리에 대한 안정성이 증가한다.

 

 [ARC모델의 기반: 소유정책과 참조카운팅]

   1.소유정책 - 인스턴스는 하나이상의 소유자가 있는 경우 메모리에 유지됨

             (소유자가 없으면, 메모리에서 제거)

   2.참조카운팅 - 인스턴스(나)를 가르키는 소유자수를 카운팅

 

정리하면,

인스턴스를 가르키고 있는 RC 1이상이면 메모리에 유지되고, 0이되면 메모리에서 제거된다는 것이다.