티스토리 뷰

728x90
반응형

Swift Docs > The Basics > Assertions and Preconditions 에 있는 내용을 토대로 한 글입니다! 

 

# Assertions 과 preconditions  용도 

Assertions 와 preconditions 은 런타임에  체크됩니다. 

futher code 를 실행시키기 전에 essential condition 을 만족시켰는 지 검증하는 용도로 사용할 수 있습니다. 

 

assertion  또는 precondition 의 조건이 true 면 코드는 계속 실행되고

false 면 현재 프로그램 상태가 invalid 하다고 판단되어서 코드 실행이 멈추고 앱이 종료됩니다.

 
Assertion은 개발 중에 실수나 잘못된 가정을 찾는 데 도움이 되고

preconditions는 production에서 이슈를 발견하는 데 도움이 됩니다. 

 

Error Handling 과 달리 assertions 과 preconditions 은  복구가능한 에러 또는 예상되는 오류를 위해 사용되는 것이 아닙니다.

실패한 assertion 또는 precondition은  invalid  프로그램 상태를 나타내므로 failed assertion을 catch 할 방법이 없습니다.

 

assertions와 preconditions 사용은 invalid state가 발생하면 앱이 종료되므로 문제를 파악하기 더 쉽습니다. 

또한  invalid state 에서 실행을 중지하는 것은 잘못된 상태로 인해 발생할 수 있는 damage를 제한하는 데도 도움이 됩니다. 

 

# Debugging with Assertions

assert(_:_:file:line:) 에 조건과 조건의 결과가 false 일 경우 표시할 메세지를 넘길 수 있습니다. 

아래 예제에서는  age가 음수라면 assertion이 실패하고 앱이 종료됩니다. 

let age = -3
assert(age >= 0, "A person's age can't be less than zero.")
// This assertion fails because -3 isn't >= 0.

 

 

만약 코드가 이미 조건을 체크하고 있다면 assertionFailure(_:file:line:) 을 사용할 수 도 있습니다.

if age > 10 {
    print("You can ride the roller-coaster or the ferris wheel.")
} else if age >= 0 {
    print("You can ride the ferris wheel.")
} else {
    assertionFailure("A person's age can't be less than zero.")
}

 

 

# Enforcing Preconditions

조건 (condition) 이  false일 가능성이 있을 때마다 precondition을 사용할 수 있고 다음 코드를 실행하려면 조건은 반드시 true 여야합니다. 예를들어 subscript가 범위를 벗어나지 않았는 지, function이 valid value 를 전달받았는 지 확인할 때 쓸 수 있습니다. 

 

 precondition(_:_:file:line:) 에  조건과 조건의 결과가 false 일 경우 표시할 메세지를 넘길 수 있습니다. 

// In the implementation of a subscript...
precondition(index > 0, "Index must be greater than zero.")

 

 

preconditionFailure(_:file:line:) function 을 호출해서 failure이 발생했음을 나타낼 수 도 있습니다.

 

#  Assertions 과 preconditions  차이 

assertion과 precondition의 차이는 언제 체크되냐에 있습니다.

assertion은 오직 debug build 에서만 체크됩니다.

precondition은 debug build와 production build 에서 모두 체크됩니다. 

 

즉 production build 에서 assertion 안에 있는 condition은 평가되지 않습니다.

이는 프로덕션 성능에 영향을 주지 않으면서 개발 과정 중, 많은 assertions 을 사용할 수 있다는 것을 의미합니다. 

 

 

💬💬💬

문서에는 이렇게 간단히 말하지만,,,

production build 라면 무조건 assertion 체크안하는게 아니라 빌드세팅에 따라 체크여부가 다릅니다 

즉 production에서 빌드세팅을 default 로 설정되있는 것에서  -Onone으로 바꿨다,,, 이러면 해당되지 않는 것입니다.  

 

 

https://developer.apple.com/documentation/swift/1541112-assert

 

그리고 assertFailure 은 assert 랑 조건이 좀 다른 것도 유의해야합니다. 

 

https://developer.apple.com/documentation/swift/1539616-assertionfailure

 

 

# Preconditions Unchecked 모드

unchecked mode (-Ounchecked) 로 컴파일하면 preconditions이 체크되지 않습니다. 

컴파일러는 preconditions 이 항상 true 라고 가정하고, 그에 따라 코드를 최적화합니다.

 

 

 

💬💬💬

 

assertion 과 마찬가지로 precondition과 preconditionfailure 도 조건이 좀 다르므로 유의해줘야합니다.

아래의 precondition, preconditionfailure 문서를 들어가보면 unchecked 모드는 precondition만 해당되는 것을 알 수 있습니다. 

 

https://developer.apple.com/documentation/swift/1540960-precondition

 

https://developer.apple.com/documentation/swift/1539374-preconditionfailure

 

 

참고로 Optimization Level 에서 -Ounchekced 가 없어서 (XCode 12.5 기준) 

 

 

 

Other을 선택하고 직접 입력해줬습니다 동작 잘하더라구요!

 

 

 

 

# fatalError

하지만  fatalError(_:file:line:)  function은 위와 같은 optimization settings 에 상관없이 항상 실행을 중단합니다. 

프로토타이핑 또는 초기 개발 중에 fatalError를 사용해서 아직 구현되지 않은 기능에 대한 stub 을 생성할 수 있습니다. 

예를들어 stub 구현으로  fatalError("Unimplemented")  를 작성해줄 수 있겠습니다. 

 

 

# 정리

문서가 너무 헷갈려서 테스트해봤습니다. 

하나씩 주석을 풀어가며 앱이 종료안되는가 (즉 체크를 안하는가) 를 봤습니다. 

 

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        assert(1==2)
        //assertionFailure()
        
        //precondition(1==2)
        //preconditionFailure()
      }
}

 

 

1. Optimization Level 이 -Oneone 일 때  (Debug 빌드의 디폴트 값) 

 

assertion  = 체크함 

assertionFailure = 체크함

precondition = 체크함 

preconditionFailure = 체크함 

 

 

2. Optimization Level 이 -O 일 때  (Release 빌드의 디폴트 값) 

 

assertion  = 체크안함

assertionFailure = 체크안함

precondition = 체크함

preconditionFailure = 체크함 

 

 

3. Optimization Level 이 -Osize 일 때 

 

assertion  = 체크안함

assertionFailure = 체크안함

precondition = 체크함

preconditionFailure = 체크함 

 

 

4. Optimization Level 이  -Ounchekced  일 때

 

assertion  = 체크안함

assertionFailure = 체크함

precondition = 체크안함

preconditionFailure = 체크함 

 

 

참고로 fatalError는 Optiomization Level 과 상관없이 항상 체크합니다. 

 

 

# 첨언 

위의 variation들을 다 기억할 수 있을까요...?

릴리즈 빌드에서는 실행되면 안된다!! 할 때 그냥 이렇게 하는 게 더 편하고 확실할 것 같네요

 

#if !RELEASE
...
#endif

 

 

 

 

 

 

반응형

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

[Swift] Substring  (0) 2021.12.12
Swift, Dart, Python % Operator 비교  (0) 2021.12.07
[Swift] Self Type  (0) 2021.11.22
[Swift Algorithms] chunks(ofCount:)  (0) 2021.09.28
[Swift] async / await 사용사례  (0) 2021.07.06
댓글