본문 바로가기

Mobile/iOS

[iOS] defer 블록

반응형


defer 블록은 함수나 메소드에서 코드의 흐름과 상관없이 가장 마지막에 실행되는 블록입니다. 지연블록이라고 부르기도 하는데, 이 블록에 작성된 구문은 항상 함수의 종료 직전에 실행되기 때문에 종료 시점에 맞추어 처리해야 할 구문이 있다면 우리는 어디에 작성해야 할지 고민하지 않고 defer 블록에 넣어두기만 하면 됩니다.

특징

  1. defer 블록은 작성된 위치와 순서에 상관없이 함수가 종료되기 직전에 실행된다.
  2. defer 블록을 읽기 전에 함수의 실행이 종료될 경우 defer 블록은 실행되지 않는다.
  3. 하나의 함수나 메소드 내에서 defer 블록을 여러 번 사용할 수 있다. 이때에는 가장 마지막에 작성된 defer 블록부터 역순으로 실행된다.
  4. defer 블록을 중첩해서 사용할 수 있다. 이때에는 바깥쪽 defer 블록부터 실행되며 가장 안쪽에 있는 defer 블록은 가장 마지막에 실행된다.

아래와 같이 코드 예시가 있다고 가정하고, 결과가 어떻게 나오는지 확인해보도록 하겠습니다.

func numberFunc(num: Int) {
    print(" 1 ")
    
    guard num > 1 else {
        print(" num < 1 ")
        return
    }
    
    defer {
        print("first defer")
    }
    
    print(" 2 ")
    
    var num2: Int = 900 + num
    
    guard num2 > 999 else {
        print(" num2 < 999 ")
        return
    }
    
    defer {
        print("second defer")
        print(num2)
    }
    
    print(" 3 ")
}

1. 변수 num이 0인 경우

이 경우는 첫 번째 guard 조건에서 걸리는 경우입니다.

결과는 1과 num < 1 이 출력되었습니다. 첫번째 defer 구문은 실행되지 않습니다.

2. 변수 num이 2인 경우

이 경우는 두 번째 guard 조건에서 걸리는 경우입니다. num의 값이 2로 첫 번째 guard 구문은 통과되었지만 num2의 값이 902가 되어 999보다 크다는 조건을 충족하지 못해 두 번째 guard 에서 걸리게 됩니다.

어떻게 출력되었는지 보시죠. 첫 프린트인 1이 출력되고, 두 번째 프린트인 2까지 출력되었습니다. 다음으로 두 번째 guard 구문에 있는 프린트가 출력되었습니다. 마지막으로 첫 번째 defer 구문이 출력되었습니다.

3. 변수 num이 100인 경우

이번 경우는 모든 guard 구문이 통과된 다음 실행되는 경우입니다. 

첫 번째, 두 번째, 세 번째 프린트가 차례대로 출력되고 defer 구문이 역으로 출력되는 모습입니다. defer 구문에서는 순서대로 출력됩니다.


그럼 defer 구문 안에 defer 구문이 있으면 어떻게 출력이 될까요? 두 번째 defer 구문을 변경해보도록 하겠습니다.

    defer {
        print("second defer")
        
        defer {
            print("추가된 defer 구문입니다.")
        }
        
        print(num2)
    }

이제 다시 num 값을 100으로 두고 출력해보겠습니다.

1, 2, 3 을 차례로 출력하고 두 번째 defer 구문을 출력한 뒤 두 번째 defer 구문 안에 있는 중첩된 구문을 출력합니다.

defer 블록은 정확하게 return 되기 직전에 실행됩니다. 실제로 이 블록은 함수에서 사용된 각종 리소스의 처리나 해제, 연결 종료 등의 구문을 처리하는 용도로 유용하게 사용됩니다.

반응형