아래의 표가 주니어 개발자로서 알고 있어야 할 개발에 대한 기본 지식이라고 한다.
위에서부터 순서대로 공부해보자.
| 분야 | 상세지식 |
|---|---|
| 자료구조 | 스택, 힙 |
| 알고리즘 | 회귀호출, 인덱스, 정렬, 이진 검색 |
| 운영체제 | 프로세스, 스레드, 뮤텍스, 세마포어 |
| 디자인패턴 | MVC 아키텍처 |
| 프로그래밍 언어 | 네이티브 코드, 콜 바이 밸류, 콜 바이 레퍼런스 |
| 경험 | 간단한 텍스트 기반의 게임 만들어보기 |
스택은 이름 그대로 물건을 차곡차곡 쌓아 올리는 것과 비슷한 방식으로 데이터를 관리한다.
스택은 후입선출 (LIFO, Last In First Out) 구조를 따르는데, 이는 마지막에 추가된 데이터가 가장 먼저 처리된다는 뜻이다. '선입선출은 알았는데 후입선출은 꽤나 낯설다.'
메모리에서의 사용 : 스택은 정적인 메모리 영역에 할당되어 프로그램 실행 중에 크기가 고정되는 것이다.
속도 : 매우 빠르게 접근할 수 있다. 함수 호출 시 자동으로 메모리에서 관리되기 때문에 효율적이다.
주 사용처 : 함수 호출 시 사용된다. 함수가 호출될 때마다 지역 변수나 매개변수가 스택에 쌓이고, 함수가 끝나면 해당 데이터는 스택에서 제거된다.
func example() {
let x = 10
let y = 20
}
여기서 x와 y는 스택에 저장되고 함수가 호출되면 스택에 x와 y가 추가된다. 함수가 종료되면 이 값들은 스택에서 제거된다.
장점은 데이터 접근 속도가 빠르며 메모리 할당과 해제가 자동으로 이루어진다는 것.
단점으로는 스택 크기가 제한적이며 데이터를 스택에 저장하려면 문제가 발생할 수 있다는 점.
특징에 나와있는 내용 중 '주 사용처에서 함수가 호출 될 때마다 지역 변수나 매개변수가 스택에 쌓이고 함수가 끝나면 해당 데이터는 스택에서 제거 된다' 는 말이 이해되지 않았다.
좀 더 풀어서 설명을 듣고 싶어 알아보니, 함수 호출 시 스택의 동작 과정에 대해 알 수 있었는데,
프로그램이 실행될 때, 함수는 여러 번 호출되고 종료되며 이 과정에서 지역 변수와 매개변수를 저장하고 관리를 해야한다고 한다. 이때 사용하는 것이 스택이다.
함수가 호출되면 그 함수만을 위한 스택 프레임이라는 공간이 스택에 쌓이게 되는데 이 스택 프레임에는 그 함수에서 사용하는 지역 변수와 매개변수가 저장되고, 함수가 끝나면 스택 프레임 자체가 스택에서 사라진다.
이렇게 함으로써 프로그램이 여러 함수를 호출할 때, 함수가 사용할 데이터를 효율적으로 관리할 수 있다고 한다.
예시를 통해 알아보자
func multiply(a: Int, b: Int) -> Int {
let result = a * b
return result
}
let product = multiply(a: 3, b: 4)
이 코드는 두 개의 매개변수 a와 b를 받아서 곱한 값을 result에 저장한 후, 결과를 반환하는 함수이다. 이 코드가 실행될 때 스택에서 어떤 일이 일어나는지 살펴보자면,
아직 함수가 호출되지 않았으므로, product는 아직 값을 가지지 않았다.
스택에는 이 함수와 관련된 정보가 없다.
multiply(a: 3, b: 4) 함수가 호출되면, 스택에 이 함수에 대한 스택 프레임이 추가된다.
이 스택 프레임에는 함수의 매개변수 a(값: 3)와 b(값: 4), 그리고 함수 내에서 사용하는 지역 변수 result가 저장된다.
함수가 실행되면서 result에 3 * 4 = 12가 저장되고, 이 모든 데이터 (a, b, result)는 스택에 있는 스택 프레임에 저장돼 있다.
함수가 return result를 실행하면서 result 값 12를 반환한다.
함수가 끝나면, 이 함수에 해당하는 스택 프레임(즉, a, b, result가 저장된 공간)은 스택에서 자동으로 제거되는 것이다.
이제 스택에는 더 이상 이 함수와 관련된 데이터가 남아있지 않는다.
product 변수는 반환된 값인 12를 가지게 된다.
이를 통해 함수마다 독립된 데이터 공간을 유지하면서도, 효율적으로 메모리를 관리할 수 있다.
힙은 프로그램 실행 중에 필요한 만큼 메모리를 할당하고, 필요 없으면 해제하는 방식이다. 스택과 달리 힙은 동적 메모리 할당을 지원하며, 크기가 고정되어 있지 않다.
메모리에서의 사용 : 힙은 크기가 고정되어 있지 않기 때문에 프로그램 실행 중에 메모리의 어느 부분이든 동적으로 할당된다.
속도 : 스택보다 메모리 접근 속도가 느리기 때문에 동적으로 할당된 메모리를 관리해야 하므로 스택에 비해 시간이 더 걸린다.
주 사용처 : 대용량 데이터나 객체를 사용할 때 힙을 사용한다. 예를 들어, Swift에서는 클래스 인스턴스가 힙에 저장된다.
class MyClass {
var name: String
init(name: String) {
self.name = name
}
}
let myObject = MyClass(name: "Swift")
myObject는 힙에 저장된다. 클래스는 주로 힙에 할당되고, 프로그래머가 명시적으로 관리해야 한다고 한다.
장점은 큰 데이터를 유연하게 관리할 수 있고 스택보다 크기에 대한 제약이 적다는 것.
단점으로는 메모리 관리가 복잡할 수 있으며, 메모리 누수(Memory Leak) 같은 문제가 발생할 수 있다는 점.
스택 : 작은 데이터(지역 변수 등), 빠른 접근, 후입선출, 정적 할당.
힙 : 동적 메모리 할당, 객체나 큰 데이터 관리, 비교적 느린 접근.
쉽게 보면 뭔가 스택은 상수이고 힙은 변수인 느낌이다.