내배캠 iOS 마스터 6기

[ 사전캠프 2일차 ] 자료구조/ 메모리 구조 및 ARC

Sheep1sik 2025. 2. 4. 20:45
반응형

1. 자료구조

배열(Array)

  • 데이터를 순차적으로 저장하는 자료구조
  • 인덱스를 사용해 특정 요소에 접근
  • 특징: 빠른 조회(O(1)), 삽입/삭제 시 성능 저하(O(n))
var numbers = [1, 2, 3, 4, 5]
numbers.append(6)
print(numbers) // [1, 2, 3, 4, 5, 6]

 

 


큐(Queue)

  • 선입선출(FIFO, First In First Out) 구조
  • 데이터를 한쪽에서 삽입하고, 반대쪽에서 제거
  • 사용 사례: 프린터 작업 대기열, BFS 탐색
struct Queue<T> {
    private var elements: [T] = []
    
    mutating func enqueue(_ element: T) {
        elements.append(element)
    }
    
    mutating func dequeue() -> T? {
        return elements.isEmpty ? nil : elements.removeFirst()
    }
}

 

 

궁금한점 🔎

mutating 이란 무엇인가?

 

[ Swift ] mutating

사전캠프 과제를 통해 한 번도 사용해보지 않은 mutating 키워드에 대해 다시 한 번 깊이 알아보자.  Swift에서 mutating 키워드는 구조체(struct) 또는 열거형(enum) 내부에서 인스턴스의 속성을 변경할

sheep1sik.tistory.com

 


스택(Stack)

  • 후입선출(LIFO, Last In First Out) 구조
  • 데이터를 한쪽에서 삽입하고 제거
  • 사용 사례: 함수 호출 스택, 괄호 검사
struct Stack<T> {
    private var elements: [T] = []
    
    mutating func push(_ element: T) {
        elements.append(element)
    }
    
    mutating func pop() -> T? {
        return elements.popLast()
    }
}

2. 메모리 구조 및 ARC 

  1. 메모리 구조
    • Stack: 함수 호출, 지역 변수 저장
    • Heap: 동적 메모리 할당, 참조 타입(클래스) 저장
    • Code: 실행 중인 코드 저장
    • Data: 전역 변수, 정적 변수 저장
  2. ARC(Automatic Reference Counting)
    • Swift의 메모리 관리 방식
    • 클래스 인스턴스의 참조 횟수를 추적하여 필요하지 않은 인스턴스를 메모리에서 해제
    • 순환 참조(Circular Reference)
      • 두 개 이상의 객체가 서로를 참조하면서 메모리에서 해제되지 않는 상황
  • 해결 방법
    • weak 또는 unowned 키워드 사용

🛠 순환 참조 해결 예제

class Person {
    var name: String
    var pet: Pet?

    init(name: String) {
        self.name = name
    }
}

class Pet {
    var owner: Person?
}

let person = Person(name: "Alice")
let pet = Pet()

person.pet = pet
pet.owner = person // 순환 참조 발생

 

해결 방법: weak 키워드


💡 직접 구현해보기

Step 1: 자료구조 구현

  1. 큐(Queue) 구현하기:
    • 정수를 저장하는 Queue 구조체를 구현하세요.
    • enqueue()로 데이터를 삽입하고, dequeue()로 데이터를 제거합니다.
    • 큐의 현재 상태를 출력하는 메서드를 추가하세요.
  2. 스택(Stack) 구현하기:
    • 문자열을 저장하는 Stack 구조체를 구현하세요.
    • push()로 데이터를 삽입하고, pop()으로 데이터를 제거합니다.
    • 스택의 최상단 값을 반환하는 메서드를 추가하세요.
import UIKit


// 큐 ( 선입 선출, FIFO )
struct Queue {
    private var elements : [Int] = []
    
    mutating func enqueue(_ element: Int) {
        elements.append(element)
    }
    
    mutating func dequeue() -> Int? {
        // elements 배열이 비어있다면 nil 반환 , 비어있지 않다면 배열 제일 앞 숫자 제거
        return elements.isEmpty ? nil : elements.removeFirst()
    }
    
    func printQueue() {
        print("Queue : ", elements)
    }
}

// 스택 ( 후입선출, LIFO )
struct Stack {
    private var elements: [String] = []
    
    mutating func push(_ element: String) {
        elements.append(element)
    }
    
    mutating func pop() -> String? {
        // elements 배열의 가장 마지막 제거
        return elements.popLast()
    }
    
    func top() -> String? {
        // elements 마지막 반환
        return elements.last
    }
    
    func printStack() {
        print("Stack : ", elements)
    }
}

var queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
queue.printQueue()
print("Dequeued:", queue.dequeue() ?? "nil")
queue.printQueue()

var stack = Stack()
stack.push("A")
stack.push("B")
stack.push("C")
stack.printStack()
print("Top Element:", stack.top() ?? "nil")
print("Popped:", stack.pop() ?? "nil")
stack.printStack()

 


Step 2: ARC와 순환 참조 해결

  1. 순환 참조 문제 구현:
    • 두 클래스를 생성하세요:
      • Person 클래스: 이름을 저장하는 속성(name)과 애완동물(pet) 속성을 가짐.
      • Pet 클래스: 주인(owner) 속성을 가짐.
    • 서로를 참조하는 인스턴스를 생성하고 순환 참조 문제를 확인하세요.
  2. 순환 참조 해결:
    • weak 키워드를 사용해 순환 참조 문제를 해결하세요.
    • 해결 후, 두 인스턴스가 정상적으로 메모리에서 해제되는지 확인하세요.
import UIKit

class Person {
    var name: String
    var pet: Pet?
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) deinit")
    }
}

class Pet {
    var name: String
    weak var owner: Person?
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) deinit")
    }
    
}

// 순환 참조 확인
var person: Person? = Person(name: "양원식")
var pet_1: Pet? = Pet(name: "뭉치")
var pet_2: Pet? = Pet(name: "큐티")


person?.pet = pet_1
pet_1?.owner = person
pet_2?.owner = person


// 인스턴스 해제
person = nil
pet_1 = nil
pet_2 = nil

 

반응형