프로그래밍iOS 개발자

Swift에서 ARC란 무엇인가요? 클로저 및 위임과 함께 작업할 때 retain cycle을 피하는 방법은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

ARC(Automatic Reference Counting)는 Swift의 자동 메모리 관리 시스템입니다. 객체에 새 강한 참조가 생성될 때 카운터가 증가하고, 제거될 때는 감소합니다. 카운터가 0이 되면 객체가 해제됩니다.

Retain cycle(유지 사이클)은 객체가 서로 강한 참조로 참조하여 절대 해제되지 않는 상황입니다.

피하는 방법:

  • 위임 객체의 경우 약한 참조를 사용하세요:
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
  • 클로저의 경우 [weak self] 또는 [unowned self]를 사용하세요:
class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }

함정 질문입니다.

클로저 내부에서 [weak self][unowned self]의 차이는 무엇인가요? 어떤 종류의 참조를 사용하고 언제 사용해야 하나요?

답변:

  • [weak self]는 선택적 참조를 생성합니다; self는 nil일 수 있으므로 일반적으로 안전한 언래핑 self?를 사용합니다.
  • [unowned self]는 비선택적 참조를 생성하고 카운터를 증가시키지 않습니다; 객체가 이미 해제되었고 접근하는 경우 크래시가 발생합니다.
  • 선택은 비즈니스 로직에 따라 다릅니다: 클로저가 self보다 보장된 생명 주기를 가지면 [unowned self]를 사용할 수 있습니다.

예시:

someClosure = { [weak self] in self?.doTask() } // 또는 (self가 100% 클로저보다 오래 살아남을 경우): someClosure = { [unowned self] in doTask() }

주제에 대한 미숙지로 인한 실제 오류 사례.


이야기

프로젝트에서 ViewController와 버튼 클릭 처리에 바인딩된 클로저 간의 retain cycle 상황이 발생했습니다. ViewController는 클로저를 참조했으며, 클로저는 self를 강한 참조로 캡처했습니다. 이로 인해 컨트롤러와 모든 데이터가 화면을 닫아도 해제되지 않았습니다. 문제는 클로저에 [weak self]를 도입하여 해결되었습니다.


이야기

두 개체 간의 델리게이트 패턴 구현. Delegate는 강한(strong) 속성으로 선언되었습니다. 그 결과 메인 객체를 메모리에서 제거하려 할 때 해제되지 않아 메모리 누수로 이어졌습니다. Delegate를 weak으로 변경한 후 문제는 사라졌습니다.


이야기

애니메이션을 위해 UIView 내부에서 클로저가 사용되었습니다. 클로저는 [unowned self]를 사용하여 self를 캡처했습니다. 애니메이션이 완료되기 전에 뷰가 제거되었을 때, 이미 해제된 self에 접근하려 하여 애플리케이션이 크래시되었습니다. 해결책은 [weak self]를 사용하고 클로저 내부에서 non-nil self를 반드시 체크하는 것입니다.