Optional은 아래와 같이 enum으로 구현되어 있습니다.

enum Optional<T> {
	case none
  case some(<T>)
}

optional의 타입은 generic이라 Int, String 등 어떤 타입도 들어갈 수 있습니다.

optional에는 두가지 경우가 있는데, none은 아직 설정되지 않은 경우이고 some은 그 타입의 값을 가지고 있다는 의미입니다.

optionalenum이지만 enum으로 사용하지 않는 이유는 optional을 사용할 때마다 switch문을 사용하여 값을 얻어야 합니다. 그러면 코드도 길어지고 복잡해 질 것입니다. 그래서 ?, !, ??, if 등으로 쉽게 표기하게 만들고 내부적으로는 enum으로 작성된 optional 코드가 실행되는 것입니다.

var hello: String?            // var hello: Optional<String> = .none
var hello: String? = "hello"  // var hello: Optional<String> = some("hello")
var hello: String? = nil      // var hello: Optional<String> = .none

optional은 항상 nil로 시작합니다.

아래는 optionalunwrapping하는 방법을 보여주는 예제입니다.

enum Optional<T> {
	case none
  case some(<T>)
}

let hello: String? = "hello"
print(hello!)

switch hello {
	case .none:  // error 발생
	case .some(let data): print(data)
}
enum Optional<T> {
	case none
  case some(<T>)
}

if let greeting = hello {
	print(greeting)
} else {
	// do someting...
}

switch hello {
	case .none:  // do something...
	case .some(let data): print(data)
}
enum Optional<T> {
	case none
  case some(<T>)
}

let hello: String? = "hello"
let greeting = hello ?? "bye"

switch hello {
	case .none: greeting = "bye"
	case .some(let data): greeting = data
}

nil 병합 연산자는 ??로 표현되고 optional의 값이 있으면 some의 경우인 ??의 왼쪽 값을 사용하고, 값이 없으면 none의 경우인 ??의 오른쪽 값을 사용하는 것이다.

아래는 옵셔널 체인을 보여주는 예제입니다.

enum Optional<T> {
	case none
  case some(<T>)
}

let x: String? = ...
let y = x?.foo()?.bar?.z

switch x {
	case .none: y = nil
	case .some(let data1):
		switch data1.foo() {
			case .none: y = nil
			case .some(let data2):
				switch data2.bar {
					case .none: y = nil
					case .some(let data3): y = data3.z
				}
		} 
}