[Swift 정면돌파] 04. 옵셔널
본 시리즈는 아래 강의자료를 기반으로 작성되었습니다.
https://www.boostcourse.org/mo122/joinLectures/38564
오늘은 옵셔널에 관련하여 공부해보았다. Kotlin 의 Nullable 개념과 매우 흡사하며, Syntax 조차 별로 다를 바 없어 보였다. Null-Safety 의 편리함을 진작 깨달은 필자의 입장에서, 옵셔널 역시 유용하게 사용되겠구나 하는 생각을 해볼 수 있었다.
특히 앱 개발을 할 때, 미리 대응하지 못한 NPE 로 인한 ANL 발생을 막기 위한 수단으로 Null-Safety 특성이 큰 힘을 발휘한 통계자료가 있다. (Java → Kotlin 으로 공식 언어를 변경한 뒤 구글에서 ANL 횟수가 현저히 감소했다고 함) 따라서 iOS 앱 개발 시에도 이를 유용하게 사용해볼 수 있을 것 같다.
옵셔널 개념
→ 코틀린과 유사하게,스위프트 역시 기본적으로 nil
을 허용하지 않는다. 이는 Null-Safety 를 보장하기 위한 특성 중 하나이다. 개발자의 실수로 발생하는 NPE 를 방지해주는 엄청 편리한 특성이다. 따라서 스위프트에서 어떤 변수의 값이 nil
일 수도 있는 경우, 별도의 구분을 해주게 되는데 이것이 바로 '옵셔널' 이다. 옵셔널은, 값이 있을수도 있고 없을 수도 있는 변수를 의미한다. 별도로 nil
이 담길 가능성을 문서화 하지 않아도 사람이 읽기에 '아 이 변수는 nil
을 갖고 있을 수도 있겠구나' 하는 생각을 할 수 있다. 또한, 옵셔널 변수가 아닌 경우 예외처리를 하지 않아도 해당 변수가 nil
이 담길 가능성이 없는 것이기 때문에 안심하고 사용을 할 수 있다
func someFunction(someOptionalParam: Int?)
func someFunction(someParam: Int)
someFunction(someOptionalParam: nil)
someFunction(someParam: nil) // 컴파일 오류 발생
옵셔널은 일반 변수들과 달리, Optional 이라는 enum 클래스로 래핑돼있는 형태이기 때문에 일반 변수처럼 사용할 수 없다. 갖고 있는 값에 대한 연산이 불가능하다.
var optionalValue: Int? = 100
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// nil 할당 가능
optionalValue = nil
// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로 연산불가
//optionalValue = optionalValue + 1
따라서, 언젠가 nil 이 들어갈 수 있는 녀석이지만 자유롭게 일반 값 처럼 활용하고 싶다면 '암시적 추출 옵셔널' 이라는 구문을 사용하면 된다. 일반적인 옵셔널과 다르게, 데이터 타입 뒤에 !
를 붙여 표현한다.
하지만, 암시적 추출 옵셔널 변수에 nil
을 넣으면 런타임 오류가 발생하므로 유의해야 한다.
var implicitlyUnwrappedOptionalValue: Int! = 100
switch implicitlyUnwrappedOptionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// 기존 변수처럼 사용 가능
implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
// nil 할당 가능
implicitlyUnwrappedOptionalValue = nil
// 잘못된 접근으로 인한 런타임 에러 발생
//implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
그렇다면, 일반 옵셔널 같은 경우 변수의 값을 어떻게 사용할 수 있을까?
이에 대한 개념이 바로 '옵셔널 바인딩 (옵셔널 값 추출)' 이다.
옵셔널 값 추출
조금 번거롭지만, 아래 처럼 옵셔널 변수의 값을 추출하여 nil
여부를 판단할 수 있고, 만약 nil
이 아니라면 원하는 동작을 수행하도록 코드를 짤 수 있다. 대신, if-let
스코프 내에서만 추출한 값을 사용할 수 있다.
func printName(_ name: String) {
print(name)
}
var myName: String? = nil
// printName(myName)
// 전달되는 값의 타입이 다르기 때문에 컴파일 오류발생
if let name: String = myName {
printName(name)
} else {
print("myName == nil")
}
var yourName: String! = nil
if let name: String = yourName {
printName(name)
} else {
print("yourName == nil")
}
// name 상수는 if-let 구문 내에서만 사용 가능
// 상수 사용 범위를 벗어났기 때문에 컴파일 오류 발생
// printName(name)
// ,를 사용해 한 번에 여러 옵셔널을 바인딩 할 수 있음
// 모든 옵셔널에 값이 있을 때만 동작 (&& 동작)
myName = "H43RO"
yourName = nil
// yourName이 nil이기 때문에 출력 구문이 실행되지 않음
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
yourName = "LULU"
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
// H43RO and LULU
하지만, if-let
구문을 사용하지 않고 다소 위험한 방식으로 옵셔널 내부의 값을 추출하는 방법도 있다. 바로 강제 추출
기법인데, 만약 옵셔널 변수가 nil
을 담고 있었다면 이를 사용할 시 런타임 에러를 뿜는다.
printName(myName!) // H43RI
myName = nil
// print(myName!)
// 강제추출시 값이 없으므로 런타임 에러 발생
yourName = nil
//printName(yourName)
// nil 값이 전달되기 때문에 런타임 에러 발생
따라서 필자는 강제 추출 기법같은 경우 디버깅 목적으로 사용하는 경향이 있다. 놓치는 예외처리가 없는지 점검할 때 이 강제 추출 기법을 사용하게 되면, 어떤 시점에서 nil
을 핸들링하는지 쉽게 알 수 있기 때문에 편리하다.
Author And Source
이 문제에 관하여([Swift 정면돌파] 04. 옵셔널), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@haero_kim/Swift-정면돌파-04저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)