defer 구문 알아보기


swieeft | 2020. 02. 26. 18:10

안녕하세요. 오늘은 defer 구문을 알아보려고 합니다.

defer는 제가 면접을 보러 다니면서 자주 접했던 Swift 문법 질문으로, 내용은 쉽지만 우리가 놓치고 넘어가기 쉬운 문법 중 하나 입니다.

실제로 실무에서도 잘 사용하지 않는 문법이기도 하지만 그래도 필요할 때 적절히 사용하면 좋은 문법이기 때문에 이런게 있다는 것만 알아두시면 좋을 것 같습니다.

defer란 무엇인가?


defer란, 현재 코드 블록을 나가기 전에 꼭 실행해야 되는 코드를 작성하여 코드가 블록을 어떻게 빠져 나가든 꼭 마무리해야 되는 작업을 할 수 있게 도와줍니다.

  • 예제 코드

  • 실행 결과

    defer1.png

    실행 결과에서 보듯이 defer 안에 있는 “test function end”가 먼저 선언되어 있지만 아래에 있는 “Hello world”가 먼저 print 되고 함수가 종료 되면서 “test function end”가 print 되는 것을 확인할 수 있습니다.

defer의 실행 순서


defer가 헷갈리는 부분 중에 하나가 defer의 실행 순서인데, defer는 선언 된 역순으로 실행됩니다. 잘 이해가 안 가실 수 있지만 예제 코드를 보시고 한번 따라서 해보시면 금방 이해하실 수 있습니다.

  • 예제 코드

  • 실행 결과

    defer2.png

    실행 순서가 역순이기 때문에 선언된 순서의 반대로 print 되고 있는 것을 확인 할 수 있습니다.

중첩 코드 블록에서의 defer 실행 순서


defer는 현재 코드 블록을 빠져 나가기 전에 실행된다고 하였습니다. 그렇다면 중첩 작성 된 코드 블록에서는 어떻게 동작 하는지 알아보겠습니다.

  • 예제 코드

  • 실행되는 순서 설명

    예제 코드가 많이 복잡해 보이지만 두 가지만 기억하면 실행 순서를 유추하는데 큰 어려움은 없습니다.

    • defer는 역순으로 실행된다.
    • defer가 선언 된 코드 블록을 빠져나가기 직전에 실행 된다.

    위 두 가지를 생각하면서 하나씩 보도록 하겠습니다.

    1. test 함수를 실행 했을 때 처음 선언 된 defer로 제일 마지막에 출력 됩니다.

    2. do문은 바로 실행 되기 때문에 “test 3”이 첫번째로 print 되며, 현재 코드 블록을 빠져나가기 직전에 defer가 호출 되므로 “test2가 두번째로 print 됩니다.

    3. 0을 2로 나누었을 때 나머지가 0이므로 if문의 코드 블록이 먼저 실행 됩니다. if문 코드 블록 안 “test 6”가 세번째로 print 되고, if문 코드 블록을 나가면서 “test 5”가 네번째로 print됩니다.

      for 문 코드 블록 안에 있는 defer는 한번의 루프가 끝날 때마다 호출 되므로 “test 4”가 다섯번째로 print 되며, 1은 나머지가 0이 안 되므로 if문을 타지 않고 “test 4”가 한번 더 print 된 후 for문이 종료됩니다.

    4. for문 밑에 있는 defer는 아래 있는 “test 8”이 print 된 후 print가 되게 되며, 그 후에 “test 1”이 마지막으로 print 되면서 함수가 종료되게 됩니다.

  • 실행 결과

    defer3.png

defer가 호출되지 않는 경우


defer는 코드 블록을 빠져 나가기 직전에 호출 된다고 알고 있습니다. 그렇다고 무조건 defer를 선언한다고 100% 호출을 보장하지는 않습니다. 아래 세 가지의 경우는 defer가 호출되지 않고 끝나기 때문에 개발 시 유의해야 합니다.

  1. throw를 이용해서 오류를 던질 경우

    • 예제 코드

    • 실행 결과

      defer4.png

      중간에 throw가 발생해서 함수가 종료 될 경우 아래 선언 된 defer에 도달하지 못해 함수가 종료 되어도 defer가 호출되지 않습니다.

      간단하게 생각하면 defer도 하나의 실행 코드이기 때문에 defer가 작성된 곳에 도달하지 못하고 함수가 종료되면 defer가 호출되지 않는 것입니다.

  2. guard 문을 사용하여 중간에 함수를 종료하는 경우

    • 예제 코드

    • 실행 결과

      defer5.png

      guard문을 이용했을 경우에도 위의 throw를 이용해서 오류를 던질 경우와 마찬가지로 guard문 이후에 나오는 defer에 도달하기 전에 함수가 종료되어 호출 되지 않습니다.

  3. 리턴값이 Never(비반환함수)인 경우

    • 예제 코드

    • 실행 결과

      에러가 발생하면서 함수를 반환하지 않고 실행을 종료하기 때문에 defer가 호출되지 않습니다.

마무리


지금까지 defer에 대해 알아보았습니다. 실무를 하면서 많이 사용되지는 않겠지만 어느 순간 필요로 하는 곳이 있기 때문에 defer가 만들어졌다고 생각합니다.

작업을 하면서 적재적소에 잘 사용한다면 중복되는 코드를 제거할 수 있고, 놓치는 부분을 최소화 할 수 있기 때문에 잘 쓰이지 않는다고 그냥 넘어가지 마시고 한번은 이해하고 나중에 필요할 때 유용하게 사용하시면 좋겠습니다.

면접 때도 허를 찌르는 질문으로 많이 등장하기 때문에 이직을 준비하시는 분들이라면 제대로 이해하고 계시면 좋겠네요.

그럼 달콤한 개발 되세요!

참고자료