TIL: 소멸자(Deinitialization)

Royce·2025년 3월 23일

Swift 문법

목록 보기
39/63

소멸자(Deinitialization)

  • 소멸자는 클래스 인스턴스가 메모리에서 제거되기 직전에 실행되는 코드 블록을 의미한다
  • 소멸자를 정의하여 인스턴스가 사라지기 전에 필요한 정리 작업을 수행할 수 있다
  • Swift는 자동 참조 카운팅(ARC)을 사용하여 메모리를 관리하기 때문에 대부분의 경우 소멸자를 사용하지 않아도 된다
  • 그러나, 파일을 닫거나 네트워크 연결을 해제하는 등 특정 작업의 정리가 필요한 경우 소멸자를 사용한다

소멸자의 특징

  • 클래스에만 존재하며, 구조체와 열거형에는 사용할 수 없다
  • 클래스마다 하나의 소멸자만 정의할 수 있다 (deinit 키워드를 사용)
  • 소멸자는 파라미터를 사용하지 않으며, 반환 값도 없다
  • 인스턴스가 메모리에서 제거되기 직전에 자동으로 호출된다
  • 소멸자는 명시적으로 호출할 수 없다 (자동으로 호출됨)
  • 상속 관계가 있는 경우, 하위 클래스의 소멸자가 호출된 후 상위 클래스의 소멸자가 자동으로 호출된다

소멸자 기본 사용 방법

  • 소멸자는 클래스 인스턴스가 더 이상 필요 없거나 강한 참조가 모두 제거될 때 자동으로 호출된다
  • 기본 사용 방법으로는 인스턴스를 nil로 설정하여 메모리에서 제거되도록 하는 방식이 있다
  • 인스턴스의 소멸 여부는 ARC(Automatic Reference Counting)에 의해 결정된다

소멸자 기본 사용 예시

// 클래스 정의 (Logger)
class Logger {
    var message: String

    init(message: String) {         // 초기화 메서드
        self.message = message
        print("Logger 생성: \(message)")  // 인스턴스 생성 시 메시지 출력
    }
    
    // 소멸자 정의
    deinit {
        // 인스턴스가 제거되기 직전에 실행되는 코드
        print("Logger 소멸: \(message)")
    }
}

// 인스턴스 생성
var logger: Logger? = Logger(message: "파일 기록 중...")

// 인스턴스를 nil로 설정하여 소멸자를 호출
logger = nil  // Logger 소멸: 파일 기록 중...
  • 이 예제는 가장 기본적인 소멸자 사용 예시이다
  • Logger 클래스는 message라는 저장 속성을 가진다
  • init() 메서드는 인스턴스가 생성될 때 메시지를 출력한다
  • 소멸자 deinit은 인스턴스가 메모리에서 제거되기 직전에 메시지를 출력한다
  • logger = nil을 설정하면 소멸자가 자동으로 호출된다

소멸자의 일반적인 사용 예시 (특별한 작업 수행 시 필요)

  • 인스턴스가 사라질 때 특별한 정리 작업이 필요할 경우 소멸자를 사용한다
  • 예를 들어, 파일을 열고 데이터를 쓰는 경우 파일을 닫아야 파일이 손상되지 않는다
  • 네트워크 연결이 유지되는 경우, 인스턴스가 사라지기 전에 연결을 종료해야 할 수도 있다

파일 처리 예제

// 클래스 정의 (FileWriter)
class FileWriter {
    var fileName: String         // 파일 이름 저장
    var isFileOpen: Bool = false  // 파일 열림 상태를 저장하는 변수
    
    init(fileName: String) {
        self.fileName = fileName
        openFile()               // 인스턴스 생성 시 파일 열기
    }
    
    // 파일 열기 메서드
    func openFile() {
        isFileOpen = true
        print("\(fileName) 파일을 열었습니다.")
    }
    
    // 파일 닫기 메서드
    func closeFile() {
        isFileOpen = false
        print("\(fileName) 파일을 닫았습니다.")
    }
    
    // 소멸자 정의
    deinit {
        if isFileOpen {     // 파일이 열린 상태일 경우
            closeFile()      // 파일을 닫는 작업 수행
        }
    }
}

// 인스턴스 생성
var writer: FileWriter? = FileWriter(fileName: "Data.txt")

// 인스턴스를 nil로 설정하여 소멸자를 호출
writer = nil  // Data.txt 파일을 닫았습니다.
  • FileWriter 클래스는 fileNameisFileOpen이라는 저장 속성을 가진다
  • 인스턴스가 생성되면 파일이 자동으로 열리며 (openFile() 메서드 호출), 상태는 isFileOpen = true가 된다
  • 소멸자 deinit은 파일이 열린 상태일 때(isFileOpen == true), 파일을 닫는 메서드(closeFile())를 호출한다
  • 인스턴스를 nil로 설정하면 소멸자가 호출되며 열린 파일이 닫힌다
  • 파일을 안전하게 닫도록 보장하는 방식이다

소멸자와 상속 관계 (상속이 있는 경우의 소멸자 호출 규칙)

  • 상위 클래스의 소멸자는 하위 클래스의 소멸자가 호출된 후에 자동으로 호출된다
  • 하위 클래스가 자체적인 소멸자를 제공하지 않더라도 상위 클래스의 소멸자는 항상 호출된다
  • 이 과정은 상위 클래스의 모든 정리 작업이 완료되도록 보장한다

상속 관계에서의 소멸자 예시

// 상위 클래스 정의 (NetworkManager)
class NetworkManager {
    var connectionName: String

    init(connectionName: String) {
        self.connectionName = connectionName
        print("\(connectionName) 연결을 시작합니다.")
    }

    deinit {
        print("\(connectionName) 연결이 종료되었습니다.")
    }
}

// 하위 클래스 정의 (WebSocketManager)
class WebSocketManager: NetworkManager {
    var socketID: String

    init(connectionName: String, socketID: String) {
        self.socketID = socketID
        super.init(connectionName: connectionName)
        print("웹소켓 연결 설정됨. Socket ID: \(socketID)")
    }

    deinit {
        print("웹소켓 연결 해제됨. Socket ID: \(socketID)")
    }
}

// 인스턴스 생성
var manager: WebSocketManager? = WebSocketManager(connectionName: "Main Server", socketID: "ABC123")

// 인스턴스를 nil로 설정하여 소멸자를 호출
manager = nil  
  • NetworkManager는 네트워크 연결을 관리하며, 소멸자가 연결 종료 메시지를 출력한다
  • WebSocketManagerNetworkManager를 상속하여 웹소켓 연결을 추가로 관리한다
  • 인스턴스를 nil로 설정하면 하위 클래스의 소멸자가 호출된 후 상위 클래스의 소멸자가 호출된다

요약

  • 소멸자는 인스턴스가 메모리에서 제거되기 직전에 자동으로 호출되는 메서드이다
  • deinit 키워드를 사용하여 정의하며, 클래스마다 하나만 존재할 수 있다
  • 소멸자는 파일 닫기, 네트워크 연결 해제 등 중요한 정리 작업을 수행하는 데 사용된다
profile
iOS 개발자 지망생

0개의 댓글