본문 바로가기

UIKit

[UIKit] LSP 위반 케이스 (Forced Unwrapping의 위험성)

반응형

설명하기 앞서, 다음 함수에서 Crash가 발생할 수 있는 케이스가 있을까요?

 

setDelegate(to:) 함수 내에서는 Crash가 발생되지 않는다는 가정을 하겠습니다.

 

 

 

 

. . .

 

 

 

 

정답은 Crash가 발생할 수 있는 케이스가 있습니다.

 

Crash가 발생한다면, 강제 언랩핑 부분에서 발생할 것이라는 게, 합리적인 생각일 텐데...

 

근데 왜? 이상하죠, UITableViewDelegate 타입인, tableView의 delegate가 nil이 아닌데 강제 언랩핑한다고 Crash 발생한다니요.

 

 

 

어떤 케이스에서 Crash가 발생할까요?

 

예를 들어 setDelegate function 이 다음과 같이 구현되어 있을 경우 Crash가 발생합니다.

 

 

분리해서 본다면, 각 function은 문제 될 것이 없어 보입니다.

 

하지만 문제는 상속관계에 있는데도 불구하고, 동일 프로퍼티의 타입이 다르다는 것입니다.

 

  • UIScrollView - delegate: UIScrollViewDelegate
  • UITableView - delegate: UITableViewDelegate

 

사실상 TableView이지만, 부모 클래스인 ScrollView로 캐스팅된 상황에서,

 

UIScrollViewDelegate만을 채택한 객체가 delegate로 설정될 수 있기 때문입니다.

 

따라서, TableView 입장에서는 delegate는 존재하지만, delegate 타입인 UITableViewDelegate 타입으로 존재하지 않은 아이러니한 상황이 발생하면서 Crash가 나는 것이죠.

 

동일 타입 강제 언랭핑이라 영향이 없지만? Crash 나는 상황

 

delegate의 일관성을 잃으면서, LSP 위반된 케이스라고 볼 수 있습니다.

 

UIScrollView의 delegate는 UIScrollViewDelegate만 채택해도 가능한 객체이다.

> UITableView의 delegate는 UIScrollViewDelegate만 채택해도 가능한 객체이다. (X)

 

하지만 이것이 UIKit을 사용하는 데 있어서 큰 불편함을 주지 않을뿐더러 개발자는 이미 경험을 통해 익숙하기 때문에?

 

치명적인 문제가 되지는 않는다고 생각합니다.

 

그리고 Swift는 Stored Property override는 못하도록 설계되어 있기에, 동일 케이스는 발생하지 않겠지만

 

그래도, 언제 어떤 잠재적인 상황이 발생할지 모르기에, 강제 언랩핑은 위험하다는 것을 또 한 번 느끼게 되었습니다.

 

반응형