상세 컨텐츠

본문 제목

함수의 생명주기와 참조 카운트의 연관성(feat. chat GPT)

Swift&SwiftUI

by (방울)도마토 2024. 9. 8. 20:21

본문

함수의 생명주기참조 카운트는 객체의 메모리 관리와 밀접하게 관련이 있습니다. 이를 쉽게 설명하기 위해, 먼저 각각의 개념을 간단히 설명한 후 둘의 연관성을 설명하겠습니다.

참조 카운트 (Reference Counting)
Swift는 ARC(Automatic Reference Counting)라는 메모리 관리 방식을 사용합니다. 이는 객체가 메모리에 얼마나 오래 남아 있어야 하는지를 결정하는 방식입니다. 

- 참조 카운트란, 객체가 몇 번 참조되고 있는지 숫자로 추적하는 방식입니다.
- 객체를 참조할 때마다 참조 카운트가 1 증가하고, 참조가 없어질 때마다 1 감소합니다.
- 참조 카운트가 0이 되면, 더 이상 그 객체는 필요하지 않다는 뜻이므로 메모리에서 해제됩니다.

함수의 생명주기
함수는 호출되면 작업을 수행하고, 작업이 끝나면 자동으로 종료됩니다. 하지만 함수 내부에서 사용하는 클로저(closure)나 객체는 함수가 끝난 후에도 특정 조건에서 메모리에 남아 있을 수 있습니다. 이때 참조 카운트가 중요한 역할을 합니다.

함수와 참조 카운트의 연관성
1. 함수 내에서 객체를 참조할 때:
- 함수가 호출되면 그 내부에서 사용하는 객체의 참조 카운트가 증가합니다. 함수가 종료되면 그 객체에 대한 참조가 없어지므로 참조 카운트가 감소합니다.
   

func someFunction() {
   let object = SomeClass() // 객체 생성, 참조 카운트: 1
   // 함수가 종료되면 object 참조가 사라져 참조 카운트: 0, 메모리 해제
}


- `someFunction`이 호출될 때 `object`는 참조 카운트가 1이 됩니다. 함수가 끝나면 `object`에 대한 참조가 사라져 참조 카운트가 0이 되고, 메모리에서 해제됩니다.

 


2. 클로저와 참조 카운트  

- 클로저는 함수의 외부 변수객체를 캡처(참조)할 수 있습니다. 이때 캡처된 객체의 참조 카운트가 증가하며, 클로저가 메모리에서 해제되지 않는 한 그 객체도 메모리에서 해제되지 않습니다.
  

func outerFunction() -> () -> Void {
    let object = SomeClass() // 참조 카운트: 1
       
    let closure = {
        print(object) // 클로저가 object를 참조하여 참조 카운트: 2
    }
       
    return closure // 클로저가 반환되면서 object는 여전히 참조됨
}
   
let returnedClosure = outerFunction()
// outerFunction이 끝났지만 returnedClosure가 object를 참조 중이므로 메모리 해제 안 됨


- 여기서 `outerFunction`이 끝난 후에도 클로저 `returnedClosure`는 `object`를 참조하고 있으므로, 그 객체는 여전히 메모리에 남아 있습니다. 이때 참조 카운트가 2가 되어, 클로저가 사라질 때까지 메모리가 해제되지 않습니다.

 


3. 강한 참조 순환 (Strong Reference Cycle)
- 객체 A와 객체 B가 서로를 강하게 참조하면, 두 객체가 서로의 참조 카운트를 유지해 참조 카운트가 0이 되지 않아 메모리가 해제되지 않는 문제가 발생할 수 있습니다. 이를 강한 참조 순환 또는 메모리 누수라고 합니다.
- 이를 해결하기 위해 Swift에서는 weak 또는 unowned 참조를 사용해 참조 카운트가 증가하지 않도록 만듭니다.

class A {
    var b: B?
}

class B {
    weak var a: A? // weak로 설정하여 강한 참조 순환 방지
}

 


결론
- 함수 내에서 생성된 객체는 함수가 끝나면 참조 카운트가 0이 되어 메모리에서 해제됩니다.
- 하지만 클로저가 함수 내의 객체를 참조하는 경우, 클로저가 메모리에서 사라지기 전까지 해당 객체는 참조 카운트가 증가한 상태로 유지되어 메모리에서 해제되지 않습니다.
- 참조 카운트를 관리하는 방식인 ARC는 Swift에서 메모리 관리의 핵심이며, 이를 통해 함수의 생명주기와 객체의 메모리 해제 시점을 자동으로 관리합니다.

관련글 더보기

댓글 영역