새소식

인기 검색어

iOS/Swift

[Swift] Swift에서의 메모리 관리

  • -

Swift에서의 메모리 관리


Swift에서는 ARC(Automatic Reference Counting)를 사용하여 자동으로 할당/해제를 해준다.

BoostCamper 클래스가 있을 때 Swift에서 힙에 메모리를 어떻게 할당하고 해제하는지 알아보자.

class BoostCamper {
  let	id: String
	let name: String
}

var boostcamper1: BoostCamper? = BoostCamper(id: "S029", name: "이준복")
var boostcamper2: BoostCamper? = boostcamper1

boostcamper2 = nil
boostcamper1 = nil

 

var boostcamper1: BoostCamper? = BoostCamper(id: "S029", name: "이준복")
var boostcamper2: BoostCamper? = boostcamper1
boostcamper2 = nil
boostcamper1 = nil
heap에 할당된 boostcamper가 해제된 모습

 

이처럼 Swift는 rc가 0이 되면 자동으로 힙에 할당한 메모리를 해제 해주게 된다.

ARC 덕분에 Swift에서는 메모리를 신경쓰지 않아도 되는것처럼 느껴지지만 그렇지 않다.

 

인스턴스간 강한 참조 순환


Swift에서 메모리에 문제가 발생하는 경우를 알아보자.

swift는 변수를 선언할 때 디폴트로 강한 참조(Strong)를 하는데 이 때 강한 순환 참조 문제가 발생한다.

아래 예시를 보자.

class BoostCamper {
  	let id: String
	var boostCamp: BoostCamp?
}

class BoostCamp {
	let part: String
	var boostCamper: BoostCamper?
}
var boostcamper: BoostCamper? = BoostCamper(id: "S029")
var boostcamp: BoostCamp? = BoostCamp(part: "iOS")

boostcamper.boostcamp = boostcamp
boostcamp.boostcamper = boostcamper

boostcamper = nil
boostcamp = nil

boostcamper.boostcamp = boostcamp / boostcamp.boostcamper = boostcamper

 

boostcamper = nil
boostcamp = nil

 

코드에선 boostcamper와 boostcamp가 nil이 되었지만 내부에서

서로를 순환해서 참조(Strong Reference Cycle)하고 있기 때문에 힙에서 메모리가 해제되지 않아

메모리 누수(Memory Leak)가 발생한다.

swift는 이와 같은 Strong Reference Cycle을 방지해주기 두 가지 방법을 제공해준다.

 

 

 

Weak ReferenceUnowned Reference


weak와 unowned 키워드는 둘 다 가르키는 인스턴스의 RC를 올라가지 않게 한다.

 

Weak Reference (약한 참조)

  • 변수 선언시 옵셔널 타입만 가능
  • 참조하고 있던 인스턴스가 해제되면 nil을 자동 할당
// 옵셔널만 가능
class BoostCamper {
  let	id: String
	weak var boostCamp: BoostCamp?
}

class BoostCamp {
		let part: String
		weak var boostCamper: BoostCamper?
}

 

Unowned Reference (약한 참조)

  • 변수 선언시 옵셔널과 논 옵셔널 타입 둘 다 가능
  • 참조하고 있던 인스턴스가 해제되면 nil을 자동할당 하지 않음
  • 논 옵셔널일 때도 가르키는 곳의 RC가 안올라기 때문에 가르키는 곳이 비어 있다면 에러 발생
// 옵셔널 논옵셔널 둘 다 가능
class BoostCamper {
  let	id: String
// unowned var boostCamp: BoostCamp
	unowned var boostCamp: BoostCamp?
}

class BoostCamp {
		let part: String
//		unowned var boostCamper: BoostCamper
		unowned var boostCamper: BoostCamper?
}

 

약한 참조로 선언한뒤 실행코드를 똑같이 돌려보면 메모리 구조는 아래와 같다.

 

 

boostcamper.boostcamp = boostcamp / boostcamp.boostcamper = boostcamper
boostcamper = nil
boostcamp = nil

 

둘다 RC가 올라가지 않기 때문에 순환참조가 발생하지 않아 힙에서 메모리가 해제되는 것을 볼 수 있다.

 

 

최종 정리


 

 

참고자료


[Swift] Value, Reference type에 관해 알아야 할 10가지

스위프트 타입별 메모리 분석 실험

[iOS] Swift의 Type과 메모리 저장 공간

iOS) 메모리 구조 (Code, Data, Stack, Heap)

iOS) 메모리 관리 (1/3) - ARC(Automatic Reference Counting)

Swift ) (1) Understanding Swift Performance (Swift성능 이해하기)

Swift Memory Management #1 기초 개념

자동 참조 카운트 (Automatic Reference Counting)

'iOS > Swift' 카테고리의 다른 글

[Swift] RxSwift, Combine 원리 이해하기  (0) 2024.01.20
[Swift] 정규표현식  (1) 2024.01.12
[Swift] Copy-on-Write  (1) 2023.12.28
[Swift] Swift에서의 Value Type, Reference Type  (0) 2023.12.28
[Swift] Swift Package 만들기  (0) 2023.12.12
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.