프로그래밍iOS 개발자

Swift에서 defer의 작동 메커니즘에 대해 설명하고 주의해야 할 경계 사례와 특징은 무엇입니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

defer는 Swift의 특별한 구성으로, 함수의 범위에서 나가기 직전에 특정 코드 블록을 실행할 수 있도록 하며, 일반적인 return이나 오류(throw)로 인해 나가는 경우와 관계없이 작동합니다. defer는 리소스를 해제하거나 변경을 취소 할 때 или 작업을 마무리할 때 유용하게 사용할 수 있습니다.

작동의 특징:

  • 함수에 여러 defer가 있을 경우, 이들은 역순으로 실행됩니다 (LIFO 구조 — last in, first out).
  • defer는 오류(throw)가 발생하거나 함수에서 return을 하더라도 실행됩니다.
  • closure 내에서는 defer가 closure의 본체에 포함되며, closure 호출 지점에 포함되지 않습니다.

예제:

func testDefer() { print("시작") defer { print("첫 번째 defer") } defer { print("두 번째 defer") } print("종료") } // 출력: // 시작 // 종료 // 두 번째 defer // 첫 번째 defer

경계 사례:

  • defer는 defer가 나타날 당시 변수가 가지는 값을 캡처합니다: defer closure에서 변수를 사용할 경우, defer가 실행되는 시점에서의 변경 사항이 보입니다.
  • 만약 함수가 fatalError로 종료된다면, defer는 호출되지 않습니다.

함정 질문.

함수 내에서 fatalError가 호출되면 모든 defer 블록이 실행되나요?

답변: 아니요, 함수에서 fatalError(또는 유사한 제어 불가능한 크래시)가 호출되면, 모든 defer 블록이 실행되지 않습니다. defer는 애플리케이션이 비정상적으로 종료되는 경우 코드가 호출될 것이라는 보장을 제공하지 않습니다.

예제:

func foo() { defer { print("Defer 1") } fatalError("어이구") defer { print("Defer 2") } } foo() // 아무것도 출력되지 않으며 크래시가 발생합니다.

이 주제에 대한 전문 지식 부족으로 인한 실제 오류 사례.


이야기

프로젝트에서 파일 디스크립터를 닫기 위해 defer를 사용했습니다. 오류가 발생했을 때 fatalError를 사용했으며, 이는 리소스가 누출되는 결과를 초래했습니다. 왜냐하면 크래시 시 defer가 실행되지 않았기 때문입니다.


이야기

하나의 함수에서 여러 defer가 있었으며, 그 중 일부는 지역 변수의 상태에 의존했습니다. 개발자는 변수가 특정 값일 것이라고 예상했으나, defer에서 이 값이 다른 코드 섹션에 의해 변경되었고, defer 실행 시 актуальное 값이 사용되었으며, 그 결과 필요하지 않은 ID로 트랜잭션 취소 버그가 발생했습니다.


이야기

중첩된 closure에서 defer 블록을 작성했으며, 그것이 외부 함수에서 나갈 때 실행될 것이라고 생각했습니다. 결과적으로 이 defer는 closure에서 나갈 때 실행되었고, 전체 함수에서 나가는 것이 아니라 리소스가 너무 일찍 해제되었습니다.