질문에 대한 배경:
defer는 코드 블록이 끝난 후에 리소스를 보다 편리하게 관리하고 작업을 수행하기 위해 Swift에 도입되었습니다. 이는 다른 언어의 finally와 유사합니다. 이러한 구조는 리소스를 정리하거나 작업을 종료하는 단계를 명확하게 보여주는 데 도움이 됩니다.
문제:
많은 초보자들은 defer가 즉시 중첩된 코드를 실행한다고 생각하지만, 항상 트리거되는 순간을 정확히 이해하지는 못합니다. 또한 여러 defer 블록이 있을 경우 LIFO(Last In, First Out) 규칙을 모르면 이해하기 힘든 경우도 있습니다. try/catch 및 조기 종료와 관련된 어려움이 있을 수 있습니다.
해결책:
defer는 현재 함수 블록을 빠져나가기 직전에 범위 내에서 중첩된 코드를 실행합니다. 함수에서의 조기 종료(예: return, throw, break 등)가 일어나더라도 실행됩니다. 여러 defer는 등장 순서의 역순으로 실행됩니다.
코드 예:
func readFile() { print("파일 열기") defer { print("파일 닫기") } print("1번째 줄 읽기") if Bool.random() { print("조기 반환!") return } print("2번째 줄 읽기") } readFile() // 콘솔에는 항상: 파일 열기, ..., 파일 닫기 (마지막에)
주요 특징:
defer를 함수 외부에서 사용할 수 있나요?
아니요, defer는 함수, 메서드, 초기화자 및 디초기화자 내부에서만 허용됩니다. 예를 들어, 파일의 전역 영역이나 함수 외부의 코드 블록 내부에 배치할 수 없습니다.
블록 내에서 예외(throw)가 발생하면 defer는 어떻게 되나요?
defer는 그래도 실행됩니다. 이것이 그의 장점 중 하나로, 오류(throw)가 발생하더라도 리소스가 보장되게 해방됩니다. 안전한 리소스 해방 패턴이 구현됩니다.
여러 defer의 실행 순서는 어떻게 되나요?
그들은 역순으로 실행됩니다(LIFO): 나중에 선언된 defer가 먼저 실행됩니다.
코드 예:
func test() { defer { print("첫 번째") } defer { print("두 번째") } print("내부") } test() // 출력: "내부", "두 번째", "첫 번째"
여러 개의 비일관적으로 배치된 defer가 있는 함수; 일부 리소스의 해제를 잊고 함수에서 다양한 위치로 돌아갑니다. 이는 리소스 누수 및 동작 디버깅의 어려움을 초래합니다.
장점: 코드의 일관성, 정리 작업이 한 곳에 "모여" 있습니다.
단점: 무슨 일이 일어나고 어떤 순서로 실행되는지 추적하기 어렵습니다; 논리 오류로 인한 누수 가능성이 있습니다.
중요한 각 단계에 대한 하나의 defer가 있으며, 리소스가 초기화되는 곳에 배치되고 주석이 추가됩니다. 코드 리뷰에서 확인됩니다.
장점: 리소스의 보장된 해제, 행동 순서에 대한 명확한 이해.
단점: 새로운 리소스 및 정리 블록을 추가할 때 규율과 주의가 필요합니다.