본문 바로가기
etc/Swift

assert와 guard

by IT learning 2021. 5. 28.
728x90

 

오늘은 동작을 중지시킬 수 있는 키워드인 assert와 guard를 배워보았다.

두 키워드는 애플리케이션 동작 도중에 생성하는 다양한 결과값을 동적으로 확인하고 안전하게 처리할 수 있도록 확인하고 빠르게 처리할 수 있다. 그래서 많이 사용할 듯 싶다

 

Assertion

var someInt: Int = 0

assert(someInt == 0, "someInt != 0")

someInt = 1
// assert(someInt == 0) // 동작 중지, 검증 실패
// assert(someInt == 0, "someInt != 0") // 동작 중지, 검증 실패
// assertion failed: someInt != 0: file guard_assert.swift, line 26

func functionWithAssert(age: Int?) {
    assert(age != nil, "age == nil")
    
    assert((age! >= 0) && (age! <= 130), "나이값 입력이 잘못되었습니다")
    print("당신의 나이는 \(age!)세 입니다")
}

functionWithAssert(age: 50)
// functionWithAssert(age: -1) // 동작 중지, 검증 실패
// functionWithAssert(age: nil) // 동작 중지, 검증 실패

assert 함수는 디버깅 모드에서만 동작한다. 배포할때의 애플리케이션에서는 제외된다. 주로 디버깅 중 조건의 검증을 위하여 사용한다.

 

위 코드를 보자. someInt = 1로 되어있다. 그리고 assert로 숫자가 0이 아닐 경우 동작을 멈추는 코드를 주석으로 달았다. 실제로 우리는 1을 넣었기 때문에 주석을 풀면 에러가 난다. 이렇게 코드의 조건에 문제가 있는지 없는지를 판단하게 도움을 준다.

 

함수의 코드도 보자. 함수의 매개변수는 age라는 이름의 Int 형 옵셔널 이다. 만일 age 가 nil일 경우 assert가 발동해 즉시 프로그램을 종료시킴과 동시에 어디가 잘못됐는지를 알려준다. 그 아래 int의 범위또한 맞지 않으면 즉시 종료시킨다. 그거 아닐경우 마지막에 나이가 나온다.

 

 

Early Exit

func functionWithGuard(age: Int?) {
    
    guard let unwrappedAge = age, //age가 nil일 경우 그냥 return
        unwrappedAge < 130,
    unwrappedAge >= 0 else {
        print("나이값 입력이 잘못되었습니다.")
        return
    }
    
    print("당신의 나이는 \(unwrappedAge)세입니다")
}

var count = 1

while true {
    guard count < 3 else {
        break
    }
    print(count)
    count += 1
}

// 1
// 2

이번에는 guard를 이용하여 코드의 문제점을 파악하게 된다.

guard를 사용하여 잘못된 값의 전달 시 특정 실행구문을 빠르게 종료한다.

디버깅 모드 뿐만 아니라 어떤 조건에서도 동작한다. guard의 else 블럭 내부에는 특정 코드블럭을 종료하는 지시어(return, break 등) 가 꼭 있어야만 한다. 타입 캐스팅, 옵셔널과도 자주 사용된다. 그 외 단순 조건 판단 후 빠르게 종료할 때도 용이하다.

 

코드를 보면, guard 에 쓰인 코드에 age가 보이고, 만일 age가 nil일 경우에는 바로 return 을 거친다. 이외에도 각 조건들이 부합하지 않으면 return 을 거친다.

 

다음 코드를 보면 카운트가 1로 설정되어있고, while문을 돌때, guard를 만나게 되고, 3을 만나기 전까지는 아래의 출력문이 계속 된다.

이후에 3을 만나면 break를 거치고 종료하게 된다.

 

이외의 코드

func someFunction(info: [String: Any]) {
    guard let name = info["name"] as? String else {
        return
    }
    
    guard let age = info["age"] as? Int, age >= 0 else {
        return
    }
    
    print("\(name): \(age)")
}

someFunction(info: ["name": "jenny", "age": "10"]) // 나이가 String 타입
someFunction(info: ["name": "mike"]) // 아얘 나이가 없다
someFunction(info: ["name": "it", "age": 10]) // it: 10

위의 코드를 보자. 딕셔너리도 사용이 가능하다. 딕셔너리의 name이 없을 경우에 바로 return을 하게 되고, age가 없을때도 return을 하게 된다.

 

마지막 3줄 코드를 보면, 첫 코드는 나이가 String 타입이라 리턴을 뱉어내고, 두 번째 코드도 아얘 나이가 없기때문에 return 을 반환하게 된다. 마지막 줄 코드는 정상적이라 print 를 하게 된다.

728x90

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

익스텐션(Extension)  (0) 2021.05.28
프로토콜(Protocol)  (0) 2021.05.28
타입 캐스팅(Type Casting)  (0) 2021.05.28
옵셔널 체이닝(부제 - 갈고리 살인마)  (0) 2021.05.28
인스턴스 생성과 소멸  (0) 2021.05.28

댓글

IT_learning's Commit