[Swift 기본 문법] 옵셔널 추출 (Optional Unwrapping)

Ryan (Geonhee) Son·2021년 3월 12일
0
post-thumbnail

본 Lecture Note는 yagom.net의 '스위프트 기초' 강의를 수강하고 작성하였습니다.

옵셔널 타입으로 Wrapped 처리된 값을 어떻게 꺼내어 사용할 수 있을까요? 옵셔널의 추출 방법에 대해 알아보겠습니다.

옵셔널을 꺼내는 방법은 무엇이 있나요?

옵셔널은 아래 두 가지 방식으로 추출할 수 있습니다.

옵셔널 추출 방식

  • 옵셔널 바인딩 (Optional Binding)
  • 무조건 추출 (Unconditional Unwrapping)

    Note: 무조건 추출 방식을 이전에는 강제 추출 (Forced Unwrapping)이라고 표현하였습니다.

옵셔널 바인딩 (Optional Binding)

옵셔널의 값을 꺼내오는 방식 중 하나로, nil 체크와 동시에 안전하게 값을 추출할 수 있는 방식입니다. 옵셔널 타입이 적용된 값은 옵셔널이라는 상자에 들어있는 상태로 메모리에 저장된 값임을 상상하실 수 있으실 것입니다. 값이 nil이라면 상자 안에 아무 것도 없는 상태이겠죠. 이는 일반형, 암시적 추출형과 관계없이 동일합니다. 옵셔널 바인딩은 상자에 물어보고 값을 가져오는 방식입니다. 상자에 값이 있는지를 물어보고 있으면 가져오고, 없으면 지나치는 것이죠.

func printName(_ name: String) {
  print(name)
}

var myName: String? = nil

printName(myName)	// 에러 발생!
// 전달되는 값의 타입이 다르기 때문에 컴파일 에러가 발생합니다. 
// 옵셔널 타입은 일반 String 타입과 다른 타입이기 때문입니다.

위의 예시에서는 옵셔널이 적용되지 않은 순수 String 타입을 매개변수로 받을 수 있는 함수 printName(_:)이 정의되어 있습니다. 이 함수의 매개변수에 nil이 할당된 String? 타입인 myName 변수를 준다면 컴파일 에러가 발생하겠죠. 이제 옵셔널 바인딩을 통해 옵셔널을 추출해봅시다.

if-let

func printName(_ name: String) {
  print(name)
}

var myName: String! = nil

if let name: String = myName {
  printName(name)
} else {
  print("myName == nil")
}

printName(name)	// 에러 발생! if-let 구문을 벗어났기 때문에 옵셔널 추출이 되지 않은 상태입니다.

if let 키워드로 정의된 상수는 옵셔널이 해제된 순수한 타입을 가집니다. 선언한 이후 나오는 중괄호 묶음(코드블럭)에는 옵셔널 타입 안에 값이 있었을 때 실행할 구문이, else 코드블럭에는 옵셔널 타입 안에 값이 없었을 때(nil) 실행할 구문이 들어갑니다.
한 가지 유의해야할 점은, if-let 방식으로 정의된 상수는 if-let 구문 내에서만 사용 가능하다는 것입니다.
한 번에 하나씩만 바인딩 할 수 있는 것이 아니라 여러 옵셔널 변수들을 함께 바인딩할 수 있습니다. 쉼표를 통해 말이죠. 아래 예시를 보실까요?

var myName: String? = "Ryan"
var yourName: String? = nil

if let name = myName, let friend = yourName {
  print("\(name) and \(friend)")
}
// yourName 이 nil이기 때문에 실행되지 않습니다.

yourName = "KangKyung"

if let name = myName, let friend = yourName {
  print("\(name) and \(friend)")
}
// Ryan and KangKyung

무조건 추출 (Unconditional Unwrapping)

옵셔널의 값을 강제로 추출하는 방식입니다. if, switch, guard와 같은 조건문을 이용하지 않고 옵셔널 값을 추출하는 방식이기에 이러한 이름을 지어주었다고 판단됩니다. 노크해서 정중하게 값을 가져오는 방식과는 다르게 옵셔널 상자를 강제로 뜯어서 가져옵니다. 동일한 예시를 가져왔습니다.

func printName(_ name: String) {
  print(name)
}

printName(myName!)	// Ryan

myName = nil

print(myName!)	// 강제 추출 시 값이 없으므로 런타임 에러가 발생합니다.

var yourName: String! = nil	// 암시적 추출 형식은 처음 변수를 선언할 때부터 무조건 추출을 가정한 것입니다.

printName(yourName)	// nil 값이 전달되기 때문에 런타임 에러가 발생합니다.

위의 예시와 같이 무조건 추출 방식은 예기치 못한 에러를 일으킬 가능성이 크기 때문에 그다지 추천되는 방식은 아닙니다. 안전하게 값을 사용하기 위해서는 옵셔널 바인딩을 활용하는 것이 좋습니다.

profile
합리적인 해법 찾기를 좋아합니다.

0개의 댓글