본문 바로가기

iOS (스파르타)/앱 개발 숙련

메모리 관리 이해

메모리와 디스크의 차이를 생각해보고 어떤 데이터를 어디에 저장하는게 나을지 생각

 

 

Garbage Collector (GC)

  • Garbage Collector 는 메모리 관리를 돕는 시스템 중 하나. 대표적으로 Java 에서 GC 를 사용한다.

메모리에서 필요없는 것들을 정리해주는 역할을 한다. 좋은 개발자는 메모리 관리를 신경써서 잘 할 줄 알아야 한다.

개발자라면 필수 교양으로 알아야하는 내용.

 

 

Reference Counting (RC)

 

메모리를 할당 받은 객체를 인스턴스라고 한다.

예를들어 아래 코드에서 myClass 는 인스턴스가 된 것이다.

class MyClass {}

// 메모리를 할당받음. 인스턴스.
let myClass = MyClass()

 

인스턴스는 하나 이상의 참조자(소유자 = owner) 가 있어야 메모리에 유지가 된다. 소유자가 없다면 즉시 메모리에서 제거가 되고 이때 인스턴스를 참조하고 있는 소유자의 개수를 reference count라고 한다.

reference count > 0 이면 메모리에 살아있고, reference count = 0 이면 메모리에서 삭제된다.

더 이상 사용하지 않을 인스턴스의 reference count 가 0보다 크지 않도록 주의를 해야 한다.

클래스의 deinit 소멸자 메서드는 메모리에서 해제될때 호출됩니다.

 

 

ARC 와 MRC

  • ARC = Automatic Reference Counting
  • MRC = Manual Reference Counting
  • ARC
    • ARC 는 Swift 의 메모리 관리 시스템. Java 에 GC 가 있다면 Swift 에는 ARC 가 있음.
    • Reference Count 를 자동으로 계산. (Automatic)
      • 객체가 생성될 때 RC 가 1 로 설정
      • 객체가 다른 변수나 속성에 할당되어 참조될때마다 RC 가 1 씩 증가
      • 객체에 대한 참조가 해제될때마다 RC 가 감소
      • RC 0 이 되면 더 이상 사용되지 않는 것으로 간주되어 메모리에서 해제.
  • MRC
    • MRC 는 Objective-C 에서 사용하는 메모리 관리 시스템.
    • Reference Count 를 개발자가 코드로 직접 계산. (Manual)
      • 객체가 생성될때 개발자가 명시적으로 메모리 할당
      • 객체를 다른 변수나 속성에 할당되어 참조될때마다 개발자가 명시적으로 RC 증가
      • 객체에 대한 참조가 해제될때마다 개발자가 명시적으로 RC 감소
      • RC 가 0 이되면 개발자가 명시적으로 메모리에서 해제.

ARC 자동으로 RC 카운트를 해서 메모리 관리를 해주는 좋은 시스템이나, ARC 로 잡아내지 못하는 메모리 누수 상황이 발생할 수 있기 때문에, 개발자는 메모리 관리 방법을 반드시 알아야 한다.

 

 

약참조와 강참조

  • 약참조
    • Reference Count 를 증가시키지 않으면서 참조하는 것.
    • weak 키워드를 붙여서 약참조를 할 수 있다.
  • 강참조
    • Reference Count 를 증가시키면서 참조하는 것.
    • 일반적인 참조 방식을 말한다.

 

클로저의 캡처링 개념

Swift 의 클로저 안에서 값을 사용하는 방법 중에는 캡처링 이 있습니다.

printMbti 라는 클로저를 선언했고, 클로저 내부에서 클로저 외부의 adam 이라는 객체를 가져다 쓰고 싶으면 값을 캡처 해야합니다. 이때 [ ] 로 감싸면 값을 캡처링해서 클로저 내부에서 사용할 수 있게 됩니다.

🌟 클로저 내부에서 클래스의 값을 캡처하면, Reference Count 가 증가합니다.

위 예시를 따라해보면 adam  deinit 소멸자가 호출되지 않습니다. 클로저에서 값을 캡처해 rc 가 증가했기 때문입니다.

위 코드를 개선해서, 메모리 누수가 발생하지 않는 상황을 만들려면 다음과 같이 코드를 작성해야 합니다.

위 코드를 따라서 실행해보면, 메모리가 해제되고 deinit ”클래스 소멸” 이 호출되는 것을 확인할 수 있습니다.

 

 

순환 참조 (Circular Reference)

 

A 가 B 를 참조하고 (A→B),

B 가 A 를 참조해서 (B→A), 서로가 서로를 참조하는 상황을 순환 참조라고합니다.

일반적으로 순환 참조는 메모리 누수를 발생시키는 대표적인 사례입니다.

일반적인 개발론에서 피해야 함