brunch

You can make anything
by writing

C.S.Lewis

by Robin Kang May 17. 2016

[Swift]guard 문

Swift에는 나로써 생소한 guard 라는 문법이 있다.

함수의 시작부분에 써서 반드시 가져가야할 조건들을 검사하는 파트라고 볼 수 있다.

if 문의 subset 개념이므로 if 문으로 완벽히 대체할 수 있다.

그럼에도 guard를 쓰는 이유는 가독성 때문이라고 본다. 함수 진입점에 if 를 나열하는 것보다 guard로 꼭 필요한 조건들을 걸러내면 함수를 분석하는 사람 입장에서도 더 이해하기 쉬울 것 같다.


예) Int 타입을 쓰긴 했지만 음수를 받으면 안되는 함수인 경우


- if 문으로 짰던 경우

func elapsedTime( A:Int, B:Int ) throws -> Int {

  if A < 0 || B < 0 {

    throw someError

  }


  let dt = B - A

  return dt

}


- guard 문으로 짠다면

func elapsedTime( A:Int, B:Int ) throws -> Int {

  guard A >= 0 && B >= 0 else {

    throw someError

  }


  let dt = B - A

  return dt

}


보는대로 문법은 이렇다.


guard 조건 else { 조건이 false인경우 수행되는 구문 }


조건이 true 이면 guard 문은 그냥 지나가고, false 이면 else 구문을 수행한 뒤 함수를 바로 종료한다.

이 때, 암묵적인 종료가 아니라 명시적인 종료이므로 return 이나 throw 등 종료하는 명령이 존재해야하며, 없으면 알아서 컴파일 에러가 난다.


함수만 빠져나가는게 아니라 프로그램을 끝내버린다는 차이만 빼면 assert 랑 비슷하다.


위의 예에서는 guard 라고 명시해서 가독성을 준 것 말고는 별 의미가 없다.

실질적으로 코딩이 좀 편해지는 경우는 let 으로 할당했을 때 느낄 수 있다.


예) nil이 아닌 변수를 사용하려는 경우


- if 문 1

func getLoginUserName() -> String {

  if loginMgr.myInfo == nil {

    return “X"

  }


  // something, loginMgr.myInfo!.something


  return “\(loginMgr.myInfo!.userName) 님"

}


- if 문 2

func getLoginUserName() -> String {

  if let myInfo = loginMgr.myInfo {


    // something, myInfo.something


    return “\(myInfo.userName) 님"

  }

  else {

    return “X"

  }

}


- if 문 3

func getLoginUserName() -> String {

  let myInfo:String

  if loginMgr.myInfo != nil {

    myInfo = loginMgr.myInfo!

  }

  else {

    return “X"

  }


  // something, myInfo.something


  return “\(myInfo.userName) 님"

}


- guard 문

func getLoginUserName() -> String {

  guard let myInfo = loginMgr.myInfo else {

    return “X"

  }


  // something, myInfo.something


  return “\(myInfo.userName) 님"

}


이렇다. 요지는 if 문을 쓰면 nil 체크 후에 unwrap을 위해 ! 를 붙여서 써야하거나,

let 으로 받아서 쓰려면 if 문의 블럭 안에서 써야 하거나,

타입과 함께 포워드선언한 뒤에 if 문 안에서 대입하고 나중에 사용해야 한다.

하지만 guard 문을 쓰면 let 으로 받으면서 nil 체크를 하는 동시에 그 값을 guard 문 아래에서 계속 사용할 수 있다.

예가 좀 짧아서 그렇지만 좀 복잡한 곳에서는 그 이점이 더 잘 드러난다.


암튼 guard 는 안써도 로직 구현에는 전혀 문제가 없다.

가독성과 편의성을 위해서 사용하면 될 것 같다.






브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari