본문 바로가기
iOS/Swift

[Swift] defer

by Jiseong 2022. 6. 10.

음... 잠이 안와서.. 간단히 defer..

defer가 무엇이냐?

함수가 종료되기 전에 실행되야 할 코드를 작성하는 블럭을 의미한다.

 

예를 들면..

func config() {
    // config code..
    
    // after complete config code..
    defer {
    	print("complete!")
    }
}

이런 식이다.

 

이리 간단해보이는 defer는 중첩이 가능한데 이 때 defer 블럭 실행 순서가 중요하다.

 

defer는 Stack 방식으로 동작하여(LIFO) 선언된 역순으로 호출된다.

 

func test() {
    defer {
        print("test 1")
    }

    do {
        defer {
            print("test 2")
        }

        print("test 3")
    }

    for i in 0..<2 {
        defer {
            print("test 4")
        }

        if i % 2 == 0 {
            defer {
                print("test 5")
            }

            print("test 6")
        }
    }

    defer {
        print("test 7")
    }

    print("test 8")
}

이런 코드가 있다고 생각해보자

 

출력 순서를 살펴보면, do 구문 또한 하나의 코드 블럭이므로 먼저 호출이 되고, 블럭 내부 실행이 종료되면 do 구문 내부에 위치한 defer가 호출된다.

 

그러니 3 -> 2

 

그리고 다음 블럭인 for문으로 가서 두번 반복을 하겠지?

 

내부 조건문의 조건인 i % 2 == 0은 i가 0일 때만 조건에 부합하기때문에 한번만 탄다.

 

한번 반복을 할 때(i = 0) 조건에 부합하므로 6이 호출되고, if 구문이 종료되기에 5가 출력된다.

 

그리고 for문 또한 한번 종료되고 다시 반복하기에 defer가 호출되어 4가 출력된다.

 

두번째로 반복을 할 때 (i = 1) 조건문에 부합하지 않으므로 if 구문 내부로 타지 않으므로 아무 동작도 하지않고 반복문이 종료되므로 다시 defer가 호출되어 4가 출력된다.

 

그리고 8이 호출된다. 7하고 1은 함수 내부에 위치한 defer 구문이기 때문에 함수 종료시 호출이 되겠지?

 

같은 선상에 위치한 defer (1, 7)는 선언된 역순으로 호출되기때문에 7 -> 1 순으로 호출된다.

 

결과적으로 출력 순서는 3 -> 2 -> 6 -> 5 -> 4 -> 4 -> 8 -> 7 -> 1 이 된다.

 

그렇다면 defer가 호출되지 않는 경우는 무엇이 있을까?

defer는 throwguard를 사용하여 함수를 도중에 탈출해버리는 경우엔 탈출문 이후에 있는 defer는 호출되지 않으며, 오류가 발생하면 함수를 반환하지 않고 프로그램을 종료시키는 비반환함수 또한 defer가 호출되지 않는다.

 

언제 사용할까?

나도 그닥 사용해본 적은 없지만, 언제 사용할지.. 생각해보면 함수 내부 로직상에서 특정 thread를 lock해버린 경우에 함수가 종료될 때 unlock을 진행시킬 수 도 있을 것 같고, 뭐... nil을 할당하여 사용한 특정 인스턴스를 메모리에서 내리는 작업도 할 수 있을 것 같다.

 

아무래도 후처리 작업을 위해 사용하는 구문이니까 그렇겠지

'iOS > Swift' 카테고리의 다른 글

[iOS] View Drawing Cycle (Layout까지 작성함)  (0) 2022.08.07
[Xcode] 단축키 좀 써주세요...  (0) 2022.08.06
[Swift] mutating  (2) 2022.05.08
[Swift] Hashable  (0) 2022.05.02
[Swift] Increasing Performance by Reducing Dynamic Dispatch  (0) 2022.04.22

댓글