오늘 공부할 주제는 옵셔널!
단어가 주는 느낌은 무언가 선택이 가능한 것 같은 느낌이다.

우선 공식문서의 상단을 보자.

열거형으로 정의가 되어있고, 이름은 Optional인 타입이다.
A type that represents either a wrapped value or the absence of a value.
'wrapped value' 또는 'the absence of a value'를 나타내는 타입이다.
값이 있거나 없거나라는 의미의 옵셔널인 것인데,
우리에게 친숙한 배열을 생각해보면 first나 last등의 프로퍼티가 옵셔널이다.
배열의 경우 비어있을 수도 있으니 만약 비어있다면 first나 last는 있을 수가 없다.
또 비어있지 않더라도 first(where:) 등의 메서드를 통해 특정 조건을 만족하는 첫 번째 요소를 요구할 수도 있다.

하지만 그 조건에 부합하는 요소가 단 하나도 없을 수 있다.

그럴 경우 '없거나' 즉 nil이 된다.
이러한 타입이 있으면 있을지 없을지 모르는 값에 대해 개발자가 더 편하게 처리할 수 있게 된다.
타입 어노테이션에서 타입 뒤에 물음표를 붙이는 것으로 간단히 사용할 수 있다.
var serverResponseCode: Int? = 404
열거형이므로 당연히 다르게 표현할 수 있다.
var serverResponseCode: Optional<Int> = 404
열거형이라면 보통 여러 케이스를 묶어주기 위한 타입의 종류인데 과연 옵셔널은 어떨까?
case none
case some(Wrapped)
옵셔널에는 두 가지 케이스가 있다. none과 some. 그야말로 없거나 있거나.
앞서 공식문서 상단에서 본 정의의 Wrapped라는 제네릭 타입을 통해 모든 타입에 갖다 쓸 수 있게 한 모습이다.
하는 사람도 있을 것이다. 왜냐하면 Swift에서는 옵셔널을 굳이 열거형 문법으로 쓰지 않더라도 적절하게 값이 할당된다.
아래의 예시는 모두 같다.
let optionalNumber: Int? = 10
let otherOptionalNumber: Int? = Optional.some(10)
let anotherOptionalNumber: Int? = Optional(10)
이는 물론 nil일 경우도 마찬가지다.
let optionalNumber: Int? = nil
let otherOptionalNumber: Int? = Optional.none
let anotherOptionalNumber: Int? = Optional(nilLiteral: ())
그래서 우리는 아주 편하게 옵셔널 변수에 옵셔널이 아닌 것처럼 값을 할당할 수가 있다.

map과 flatMap을 옵셔널에서도 사용할 수가 있다.

두 메서드 모두 설명이 같은데,
Evaluates the given closure when this Optional instance is not nil, passing the unwrapped value as a parameter.
즉 nil이 아닐 때만 클로저가 평가 된다는 것이다.
다른 말로 하면 값이 있다면 전달된 클로저를 통해 값을 바꿔서 반환한다고 이해할 수 있겠다.
let optionalNumber: Int? = 10
let mappedNumber = optionalNumber.map { Double($0) }
print(mappedNumber) // "Optional(10.0)" 출력

nil일 경우 그대로 nil이 될테니 옵셔널일 수 밖에 없다.
옵셔널은 쉽게 생각하면 슈뢰딩거의 고양이라서 까보기 전엔 값이 있는 상태와 없는 상태가 공존한다.

아무튼 이 포장된 값을 옵셔널이 아닌 값으로서 사용하려면 즐거운 언박싱을 해줘야 하는데 여기에는 다양한 방법이 있다.
옵셔널을 처리하는 안전한 방법이다.
if, guard, while 등을 사용해 값이 있을 경우 할당될 상수를 정의한다.
let optionalNumber: Int? = 10
if let number = optionalNumber { // optionalNumber에 값이 있다면 다음 코드블록을 실행
// number라는 상수를 이 코드블록 내부에서 사용할 수 있다.
}
while let number = optionalNumber { // optionalNumber에 값이 있는 동안 다음 코드블록을 반복 실행
// 마찬가지로 number라는 상수를 이 코드블록 내부에서 사용할 수 있다.
}
guard let number = optionalNumber else { // optionalNumber에 값이 없다면 다음 코드블록을 넘어가지 못한다.
}
// 이후 number라는 상수를 사용할 수 있다.
느낌표를 붙이는 것만으로 강제 추출을 할 수 있다. 하지만 nil일 경우 런타임 에러가 발생한다.
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
let number = convertedNumber!
여기서 강제 추출을 사용한다는 것은 다음 표현과 같다.
guard let number = convertedNumber else {
fatalError("The number was invalid")
}
강제 추출을 다른 방법을 통해 표현하면 아래와 같이 작성할 수 있다.
let number = convertedNumber.unsafelyUnwrapped
unsafelyUnwrapped 프로퍼티의 설명을 보면
The wrapped value of this instance, unwrapped without checking whether the instance is nil.

nil인지 아닌지 묻지도 따지지도 않고 가져다 쓰겠다는 말이다.
Force Unwrapping과 비슷한 경우라고 볼 수 있다.
다만 다른 점은 암시적 추출 옵셔널은 타입 어노테이션에 느낌표가 붙는다는 점이다.
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // Requires explicit unwrapping
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // Unwrapped automatically
공식문서에는 다음과 같은 설명이 덧붙여져 있다.
If an implicitly unwrapped optional is nil and you try to access its wrapped value, you’ll trigger a runtime error.
nil일 때 접근하려고 하면 펑! 하고 런타임 에러를 낼 것이라고.
닐 병합 연산자 ??를 사용할 수도 있다.
let name: String? = nil
let greeting = "Hello, " + (name ?? "friend") + "!"
print(greeting)
// Prints "Hello, friend!"
의미는 '왼쪽 값이 만약 nil이면 뒤의 값을 사용해줘'라고 이해하면 되겠다.

재미있는 점은 비단 뒤에 오는 것이 옵셔널이 아닌 값이어야 하는 것은 아니라는 것이다.
조건에 따라 참이면 왼쪽 값을, 거짓이면 오른쪽 값을 취하는 삼항 연산자를 사용해볼 수도 있다.
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
let number = convertedNumber != nil ? convertedNumber! : 0
nil이 아니면 그냥 쓰고 nil이라면 0을 사용하겠다.

그런데 이것 닐 병합 연산자와 비슷하지 않은가?

The nil-coalescing operator is shorthand for the code below:
그렇다 닐 병합 연산자는 삼항연산자 표현의 축약표현이었던 것이다.

값이 있을 수도 없을 수도 있는 경우에 사용하기 좋은 옵셔널을 알아보았다.

까보기 전에는 모르는 것이 도박과도 같은 타입이었다.
이 밖에도 더 Optional 타입에 대해 궁금한 것이 더 있다면 아래의 공식문서들을 참조할 것.
https://developer.apple.com/documentation/swift/optional
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Optionals