[Swift] 옵셔널
개발🧑‍💻/Swift

[Swift] 옵셔널

* 이 글은 "스위프트 프로그래밍 (3판)" 및 야곰닷넷의 "스위프트 기초 강의", The Swift Programming (번역본)을 공부하며 정리한 내용입니다.

 

옵셔널(Optional) 이란?

 옵셔널은 nil의 가능성을 명시적으로 표현하는, 스위프트의 특징 중 하나인 안정성을 문법으로 담보하는 기능입니다.

단어 뜻 그대로 Optional, '선택적인' , '값이 있을 수도, 없을 수도 있음' 을 나타내는 표현입니다. 이 말인 즉슨, 변수나 상수에 값이 있다고 보장할 수 없다,혹은 변수나 상수의 값이 nil 일 수도 있다를 의미합니다.

 

 위 코드를 보면, convertedNumber에서 String 타입인 possibleNumber를 Int 타입으로 변환을 시도합니다. convertedNumber의 타입을 체크해보면, Optional<Int> 타입으로 리턴합니다. 이는 Int 타입으로 변환이 실패할 수도 있음으로, Int가 아닌 Optional<Int>로 나타내는 것입니다. 아래 경우는 Int타입으로 변환이 실패하여, anotherConvertedNumber가 nil이 된 경우를 보여줍니다. Optional<Int> 는 Int값이 있거나 없을수도 있다는 뜻으로 Int? 로 나타낼 수 있습니다. 

 

⚠️ Optional Type 이 아닌 상수나 변수에는 nil을 할당할 수 없습니다. 즉, nil은 옵셔널로 선언된 곳에서만 사용이 가능합니다. 아래는 예시입니다.

var string : String = nil // 'nil' cannot initialize specified type 'String'
var number : Int? = nil // O.K

 

옵셔널 추출

 옵셔널의 값을 옵셔널이 아닌 값으로 추출하는 방법은 크게 2가지가 있습니다.

강제 추출 (Forced Unwrapping)

 옵셔널 강제추출은 옵셔널에 값이 포함되어 있다고 확신하는 경우 사용합니다. 옵셔널인 상수나 변수 이름 맨 뒤에 느낌표(!)를 붙여 값을 추출합니다. 느낌표는 '이 옵셔널은 확실히 값이 있음으로 사용해도 괜찮습니다' 라는 의미입니다.

 

⚠️ 강제 추출하려는 변수 혹은 상수가 nil이라면 위처럼 에러가 발생합니다.

 

옵셔널 바인딩 (Optional Binding)

 옵셔널에 값이 있는지 확인할 때 사용합니다.

if let 구문을 이용하여 옵셔널에 값이 있는지 체크하고 상수나 변수로 추출 할 수 있다.

 if - let 구문을 사용하여 위에서 보았던 예제를 다시 만들어보면, Int(possibleNumber)의 값이 존재하기 때문에, 그 값을 realNumber로 추출한 것이고, 이 코드를 실행했을때 else 구문의 문장은 출력되지 않습니다. 추출된 realNumber는 상수임으로 첫번째 중괄호 {} 내에서 사용이 가능합니다.

 한 번에 하나의 변수/상수만을 Binding 하는것이 아니라, 쉼표(,)를 사용하여 여러 Optional 변수들을 한번에 Binding 할 수 있습니다.

 그러나 위에서 볼 수 있듯이 myName, yourName 모두에 값이 들어 있어야지만, if - let 구문이 실행됩니다. 첫번째 if - let 구문에서는 friend에 Binding 이 되지 않으므로 실행되지 않습니다.

 

※ 암시적 추출 옵셔널 (Implicitly Unwrapped Optionals)

 프로그램 구조에서 옵셔널의 값을 처음 설정한 후에는 항상 값을 갖는 것이 분명할 때가 있습니다. 이러한 경우에는 항상 값이 있다고 가정할 수 있으므로 접근할 때마다 옵셔널의 값을 확인하고 추출할 필요가 없어집니다. 혹은 때때로 nil을 할당하고 싶지만, Optional Binding으로 매번 값을 추출하기 귀찮거나 로직상 nil 때문에 런타임 오류가 발생하지 않는다는 확신이 들 때, 암시적 추출 옵셔널 (Implicitly Unwrapped Optionals) 을 사용할 수 있습니다. 우리는 위에서 옵셔널을 나타내기 위해 물음표(?) 를 사용했지만, 암시적 추출 옵셔널은 물음표 대신에 느낌표(!) 로 작성합니다. 예를 들어 보겠습니다.

 이처럼 타입에 느낌표(!) 를 붙여 암시적 추출 옵셔널로 지정한 타입은 일반 값처럼 사용할 수 있습니다. 그러나 여전히 Optional 이기 때문에 nil 도 할당해줄 수 있습니다. 

 또한 암시적 추출 옵셔널도 Optional이므로 당연히 Binding을 사용할 수 있습니다.

 

⚠️ 그러나 옵셔널을 사용할 때는 강제 추출 (Forced Unwrapping) 또는 암시적 추출 옵셔널 (Implicitly Unwrapped Optionals)을 사용하기보다는 옵셔널 바인딩, nil 병합 연산자를 비롯해 옵셔널 체이닝 등의 방법을 사용하는 편이 더욱 안전하고, 스위프트의 지향점에 부합한다고 합니다.