[내일배움캠프] 251222 TIL

Bambu·2025년 12월 22일

내배캠 TIL

목록 보기
4/52

1. STEP 4(마스터). - 자료구조 / 메모리 구조 및 ARC

1) 자료구조

  • 배열(Array) : 빠른 조회(O(1)), 삽입/삭제 시 성능 저하(O(n))

2) 메모리 구조

  • Code : 실행 중인 코드 저장
  • Data : 전역 변수, 정적 변수 저장
  • Heap : 동적 메모리 할당, 참조 타입(클래스) 저장
  • Stack : 함수 호출, 지역 변수 저장

3) 직접 구현해보기

STEP 1: 자료구조 구현

가. 큐(Queue) 구현하기

struct Queue {
    var nums: [Int] = []
    
    // 데이터 삽입
    mutating func enqueue(_ num: Int) {
        nums.append(num) // 배열에 순서대로 삽입
    }
    
    // 데이터 제거
    mutating func dequeue() { 
        if !nums.isEmpty {
            nums.removeFirst() // 선입 선출로 제거
        }
    }
    
    // 현재 상태 출력
    func status() { 
        print(nums)
    }
}
var a = Queue()
a.enqueue(3)
a.enqueue(4)
a.status() // [3, 4] 출력

a.dequeue()
a.status() // [4] 출력

→ 정상 작동 확인

나. 스택(Stack) 구현하기

struct Stack {
    var stringArr: [String] = []
    
    // 데이터 삽입
    mutating func push(_ element: String) {
        stringArr.append(element) // 배열에 순서대로 삽입
    }
    
    // 데이터 제거
    mutating func pop() {
        stringArr.removeLast() // 후입 선출로 제거 (최상단 값이 제거되어야 하므로)
    }
    
    // 최상단 값 반환
    func peek() -> String {
        return stringArr.last ?? "" // stringArr.last는 옵셔널 값이므로 기본값 설정
    }
}
var stack = Stack()

stack.push("A")
stack.push("B")
print(stack.peek()) // "B" 출력

stack.pop()
print(stack.peek()) // "A" 출력

→ 정상 작동 확인

STEP 2: ARC와 순환 참조 해결

가. 순환 참조 문제 구현

class Person {
    var name: String
    var pet: Pet?
    
    init(name: String, pet: Pet? = nil) {
        self.name = name
        self.pet = pet
    }
    
    // 메모리에서 해제 시 출력
    deinit {
        print("\(name) 메모리에서 해제되었습니다.")
    }
}

class Pet {
    var name: String
    var owner: Person
    
    init(name: String, owner: Person) {
        self.name = name
        self.owner = owner
    }
    
    // 메모리에서 해제 시 출력
    deinit {
        print("\(name) 메모리에서 해제되었습니다.")
    }
}
var person: Person? = Person(name: "Bambu")
var cat: Pet? = Pet(name: "Duri", owner: person!)
    
person!.pet = cat

cat = nil
person = nil

personpet 속성으로 cat을 참조하고 있음
catowner 속성으로 person을 참조하고 있음

catnil로 할당하더라도 person은 여전히 pet 속성으로써 cat을 계속 참조하고 있으므로 cat 인스턴스는 메모리에서 해제되지 않음

→ 메모리에서 해제되지 않은 cat 인스턴스는 owner 속성으로써 person을 계속 참조하고 있으므로 personnil로 할당하더라도 메모리에서 해제되지 않음

⇒ 즉, 순환 참조 발생으로 두 인스턴스 모두 메모리에서 해제되지 않음

class Person {
    var name: String
    weak var pet: Pet? // 약한 참조로 변경
    
    init(name: String, pet: Pet? = nil) {
        self.name = name
        self.pet = pet
    }
    
    deinit {
        print("\(name) 메모리에서 해제되었습니다.")
    }
}

pet 프로퍼티를 약한 참조로 변경하여 참조 카운트가 되지 않도록 함

var person: Person? = Person(name: "Bambu")
var cat: Pet? = Pet(name: "Duri", owner: person!)
    
person!.pet = cat

cat = nil // Duri 메모리에서 해제되었습니다. 출력
person = nil // Bambu 메모리에서 해제되었습니다. 출력

catnil로 할당 시 personcat을 약한 참조하고 있으므로 참조 카운팅이 0인 cat 인스턴스는 메모리에서 해제됨

cat이 메모리에서 해제되었으므로 person을 참조하고 있는 인스턴스는 존재하지 않음 - personnil로 할당 시 메모리에서 해제됨

⇒ 순환 참조가 해소되어 두 인스턴스 모두 정상적으로 메모리에서 해제

2. 라이브 세션 - 간단한 앱 만들기

튜터님께서 랜덤 색상 변경 앱, 카운트 앱을 스토리보드, UIKit 코드, SwiftUI 3가지 방법으로 구현 시연

  • 💡 현업에서 스토리보드를 (거의) 사용하지 않는 이유?
    → 여러 화면 표시 - 느려짐
    협업 시 혼란을 줄 가능성이 매우 큼!
    : 모든 부분이 코드로 이루어져있지 않으므로 어떤 설정이 변하였는지 한번에 알기도 어렵고 커스텀 뷰를 재사용하기도 힘들다는 큰 단점이 있음

  • UIKit와 SwiftUI 서로 장단점이 있어 모두 사용하므로 둘다 알아야 함

profile
안녕하세요, iOS 개발을 공부하고 있는 Bambu입니다. (프로필: Swifticons)

0개의 댓글