옵셔널 추출

CHOI·2021년 5월 25일
0

Swift

목록 보기
10/10
post-thumbnail

옵셔널 추출(Optional Unwrapping)이란 옵셔널의 값을 사용하기 위해서 꺼내오는 것이다.

이떄 옵셔널 추출법은 크게 두가지로 나뉠 수있다.

1. Optional Binding - 옵셔널 바인딩

옵셔널 바인딩은 옵셔널 값을 꺼내오는 방법중 하나이다.

옵셔널 바인딩은 nil 체크를 하는 동시에 안전하게 값을 추출할 수 있는 방식이다.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/87fdc47e-0808-4b87-8311-7325da8873e5/Untitled.png

옵셔널을 생각할 때 위 그림처럼 생각하면 이해하기 편하다.

어떠한 메모리안에 공간에 42라는 값이 들어 있다고 생각하면 옵셔널은 값들을 보호해주는 보호막이 하나 씩 있다고 생각하면 된다. 옵셔널 타입과 암시적 추출 옵셔널 둘다 옵셔널 타입이기 때문에 둘다 열거형 타입으로 박스가 하나 쌓여져 있다고 생각하면 된다.

가운데 박스 안에는 42라는 값이 있고 오른쪽 박스는 nil 즉 값이 없는 상태를 표현한다고 상상해보자.

옵셔널 바인딩 방법은 이때 상자에다가 물어보는 것이다.

우리가 상자에다가 "값이 들어 있습니까? 안에 들어 있습니까?" 하고 물어보는 것이다.

만약 안에 값이 있으면 그 값을 꺼내오고 없으면 값을 꺼내지 않고 그냥 지나친다.

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

var myName: String? = nil

printName(myName) // 오류발생

printName 함수를 위와 같이 정의해두고 옵셔널 타입이 아닌 String 타입을 전달 받게 만들어 놨다.

그러나 myName 라는 변수는 옵셔널 타입이다.

만약 이 옵셔널 타입을 가지고 함수로 전달하게 되면 옵셔널 타입은 일반 String 타입과 다른 타입이기 때문에 컴파일 오류가 발생하게 된다.

그래서 이때 우리는 if - let 방식으로 옵셔널 바인딩을 해줄 수 있다.

func printName(_ name: String) {
    print(name)
}
var yourName: String! = nil

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

위 코드에서 yourName 는 암시적 추출 옵셔널이기 때문에 값을 if let name: String = yourName

이런식으로 값을 꺼내올 수 있다.

그런데 name 이라는 상수는 if - let 구문 안에서만 사용이 가능하다.

myName = "yagom"
yourName = nil

if let name = myName, let friend = yourName {
    print("\(name) and \(friend)")
}
//>> 실행결과 없음

또한 위 코드처럼 한번에 하나씩만 바인딩 할 수 있는 것이 아니라 한번에 여러 옵셔널 변수들를 바인딩 할 수 있다.

그러나 위 코드는 myName yourName 둘다 모두 값이 있어야 실행되게 되는데 yourName 의 값이 nil이기 때문에 if - let 구문이 실행되지 않는다.

2. Force Wrapping - 옵셔널 강제추출

또 다른 방법으로 Force Wrapping 방법이 있다.

이 방식은 강제로 옵셔널 값을 추출하는 방식이다.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2f959bc2-3209-4710-b7b3-52159f8e9911/Untitled.png

옵셔널 바인딩에서는 정중하게 값을 꺼내오는 방식과는 다르게 여기서는 옵셔널 보호막을 강제로

망치로 깨부신 다음에 가져온다고 상상하면 된다.

func printName(_ name: String) {
    print(name)
}
var myName: String? = "CHOI"
printName(myName!) // CHOI

앞서 사용했었던 함수를 가지고 위 코드를 확인해보면 printName(myName!) 과 같이 myName 에 느낌표를 붙임으로써 옵셔널의 값을 강제로 꺼내와서 전달하게 되고 myName 변수의 옵셔널 물음표가 벗겨지게 되면서 안에 있었던 "CHOI" 라는 값이 전달되게 된다.

그래서 옵셔널 타입이 아닌 String 타입으로 값을 전달할 수 있게 된다.

이렇게 변수뒤에 느낌표를 붙이게 되면 옵셔널 타입을 안에 값을 강제로 추출한다고 생각하면 된다.

myName = nil
print(myName!) // 런타임 오류 발생

그러나 위와 같이 nil 값을 할당하게 되면 강제 추출 할 때 값이 들어있지 않기 때문에 런타임 오류가 발생한다.

func printName(_ name: String) {
    print(name)
}
var yourName: String! = nil

printName(yourName) // 런타임 오류 발생

여기서 암시적 추출 방식 처음에 선언할 때 부터 앞선 과정을 가정하고 선언한다고 생각하면 된다.

그래서 뒤에 느낌표를 붙이지 않았지만 printName(yourName) 를 하여도 전달하는 과정에 알아서 느낌표를 붙여준거와 같은 효과를 보여주게 된다.

위 코드는 nil 값을 전달하기 때문에 런타임 오류가 발생하게 된다.

결론적으로 옵셔널 강제추출 방식은 그다지 추천되는 방법은 아니고 조금더 안전하게 값을 추출하기 위해서

옵셔널 바인딩이 추천된다.

profile
벨로그보단 티스토리를 사용합니다! https://flight-developer-stroy.tistory.com/

0개의 댓글

관련 채용 정보