오늘은 iOS 앱을 실행시켰을 때, 실제로 소스 코드가 메모리의 어느 영역에 적재되는지 알아보도록 하겠습니다. 이 후에는 iOS에서 메모리를 관리해주는 ARC(Auto Reference Counting)에 대해서도 다룰 예정입니다.
프로세스는 실행 중인 프로그램을 말합니다. 그렇다면, iOS에서는 실행 중인 프로그램 즉, 실행 중인 앱을 뜻합니다.
앱이 실행되어 프로세스가 메모리에 적재되고, 프로세스는 다음과 같이 사용자 영역에 코드, 데이터, 힙, 스택 영역으로 나뉘어 저장됩니다.
코드 영역은 말 그대로 실행할 수 있는 코드, 즉 기계어로 이루어진 명령어가 저장됩니다.
코드 영역에는 데이터가 아닌 CPU가 실행할 명령어가 담겨 있기 때문에 쓰기가 금지되어 있습니다.
즉, read-only(읽기 전용) 공간 입니다.
데이터 영역은 프로그램이 실행되는 동안 유지할 데이터가 저장되는 공간입니다.
struct Constants {
static let BASE_URL = "https://naver.com" // 전역 변수 - 스택 영역에 할당
}
데이터 영역에 저장되는 대표적인 데이터로 전역변수가 있습니다.
힙 영역은 개발자가 직접 할당할 수 있는 저장 공간입니다.
개발자는 힙 영역에 메모리 공간을 할당했다면, 언젠가는 메모리 해제를 해줘야합니다. 그렇지 않으면 메모리 누수(memory leak)이 발생합니다.
힙 영역은 메모리 영역 중에 가장 중요한 영역입니다. 개발자가 직접 공간을 할당할 수 있고, 할당했으면 해제를 해줘야하는데 그렇지 않으면 문제가 발생하겠죠? 힙 영역은 앱의 성능, 안정성과도 직결되어 있는 부분이기 때문에 잘 알고 사용하는 것이 중요합니다.
우리가 직접 할당할 수 있는 공간이라고 하는데 대체 어떻게 할당해서 사용할 수 있을까요?
사실 우리는 너무나도 당연하게 힙 영역을 할당해서 사용하고 있었습니다.
클래스 인스턴스(Class Instance), 클로저와 같은 참조 타입의 값
// 클래스, 클로저와 같은 참조 타입의 데이터는 힙 영역에 할당
class Object {
var move: ()->Void = {}
}
let object = Object() // 클래스 인스턴스는 힙 영역에 저장
object.move = {
// 클로저는 힙 영역에 저장
}
클래스 인스턴스, 클로저 같은 참조 타입의 값은 모두 힙에 자동 할당됩니다.
또한, 힙 영역에 할당했으면 반드시 메모리 해제를 해줘야한다고 했죠?
근데, 우리는 Swift를 사용하면서 메모리 해제를 해주는 작업을 한적이 없습니다.
참조 타입의 데이터를 모두 사용한 후에 realease와 같은 처리를 해준적이 없으니까 그럼 우리는 힙 영역을 계속 낭비하고 있었던걸까요?
보통의 경우에는 그렇지 않습니다!!
왜냐하면 Swift는 ARC(Auto Reference Counting)을 통해 힙에 할당된 메모리가 더 이상 사용되지 않으면(참조되지 않으면) 자동으로 해제해주기 때문입니다
하지만, 개발자의 실수로 인해 순환 참조 라는 것이 발생하면, ARC도 그 메모리를 해제하지 못하고, 결과적으로 메모리 누수로 이어질 수 있습니다.
ARC와 순환 참조에 대해서는 나중에 다루도록 하겠습니다
스택 영역은 데이터를 일시적으로 저장하는 공간입니다.
// 함수의 파라미터, 지역 변수와 같이 일시적으로 사용하는 데이터는 스택 영역에 할당된다.
func calculate(a: Int, b: Int) -> Int { // a와 b는 함수의 파라미터로 스택 영역에 할당
let result = a + b // result는 지역변수로 스택 영역에 할당
return result
}
데이터 영역에 담기는 값과는 달리 잠깐 쓰다가 말 값들이 저장되는 공간입니다.
예를들어, 지역변수, 함수의 파라미터가 있습니다.