[iOS_Swift] 옵셔널(Optional), 옵셔널 바인딩(Optional Binding), 옵셔널 체이닝(Optional Chaining)

2021. 10. 14. 01:31Programming/iOS_Swift

옵셔널(Optional)

옵셔널이란 간단하게 생각하면 어떤 상수나 변수로 선언된 타입(String, Int...)에 nil값이 있을 수도 있다는 조심스러운 기능이다. 조심스러움을 알 수 있는 한 예로 타입의 뒤에 ?를 넣어서 표현해준다.

 

var nickname: String?

var age: Int?

 

조금 더 명확하게 써주려면 var nickname: Optional<String> 도 가능하다. 그러나 ? 하나만 써주는게 간단하고 편하다.

 

그러면 이런 옵셔널을 우리는 왜 굳이 사용해야 할까? 변수나 상수에 꼭 nil이 있을거라고 가정해야할 필요가 있을까. 그 이유는 다음과 같은 예로 생각하면 쉬울 것 같다. 가령 우리가 어떤 함수를 만들었다고 가정해보자. 해당 함수에는 매개변수가 있을 것이고 매개변수를 통해 우리는 외부로부터 어떤 값을 전달 받게 될 것이다.(전달인자) 그런데 전달받은 값이 만약에 잘못된 값이라면 우리는 해당부분에 대한 처리가 필요하다. 그럴 때, 우리는 nil값을 반환함으로써 해당 값에 문제가 있음을 간단하게 알릴 수 있다.

 

위의 예를 통해 살펴보면 상수 case1과 2의 타입은 UserMissionStatus? 임을 알 수 있다. 즉 nil값이 있을 수도 있다고 가정하고 있는 타입이다. 상수 case1의 경우 올바른 원시값을 넣어줬으므로 case에 해당하는 missionFailed를 반환했으나 case2의 경우 잘못된 원시값이므로 nil을 반환했음을 알 수 있다.

 

옵셔널 추출

옵셔널은 안전하고 좋은 기능이지만 필요에 의해 옵셔널을 뜯어내야할 때가 자주 있다. 그런 경우 우리는 Unwrapping한다고 하는데 가장 간단하고 쉬운 방법은 옵셔널 강제추출(Forced Unwrapping)이다. 이는 간단한만큼 위험한 방법으로 해당 타입에는 절대로 nil값이 안들어갈 것이라고 가정하는 것이다. 사용법은 확실히 강하게 나가는 느낌이 들게 타입 뒤에 ! 를 붙여주면 된다.

 

var nickname: String!

var age: Int!

 

그러나 이 방법은 가급적 사용을 하면 안되는 방법으로 정말 nil값이 들어갈 가능성이 없을 때만 사용해야 한다. 만약에라도 해당 변수나 상수에 nil값이 들어간다면 바로 런타임 오류를 일으키기 때문이다.

 

옵셔널 바인딩(Optional Binding)

강제 추출의 위험성을 보완한 방법이 옵셔널 바인딩이다. if 구문을 통해 해당 변수나 상수가 nil인지 아닌지 검사를 하는 것이다.

 

변수 myName: String? 의 값이 nil이 아니므로 정상적으로 name을 출력한 걸 확인할 수 있다. 여기서 상수 name의 타입을 확인해보면 정상적으로 옵셔널이 언래핑된 상태인 String임을 확인할 수 있다.

 

 

반대로 myName의 값이 nil이라면 위 예시처럼 값 없음을 출력한 걸 확인할 수 있다.

 

옵셔널 체이닝(Optional Chaining)

또 다른 방법은 옵셔널 체이닝이다. 옵셔널 체이닝은 구조체나 클래스 안에 또 다른 클래스나 구조체의 인스턴스가 있고 그 안에 또다른 클래스나 구조체의 인스턴스가 있을 때 유용한 방법이다. 예시를 통해 보자.

 

 

 

위 예시를 보면 구조체 안에 또 다른 구조체의 인스턴스가 옵셔널 타입으로 설정되어 있다. 이 때 옵셔널 바인딩을 한다면 조건문이 생각보다 길어지게 되는 문제가 발생한다. 이러한 단점을 보완해주기 위해 옵셔널 체이닝을 해준다. 좀 더 자세히 살펴보자. 아래의 조건문을 보면, 만약 cloth?에 값이 없다면 뒤의 shoes?.nike는 보지도 않고 바로 nil값을 뱉어낸다. 따라서 해당되는 프로퍼티에 값이 없다면 바로 nil값을 뱉어내게 된다.

모든 프로퍼티에 정상적으로 값을 준다면 옵셔널이 성공적으로 해제 된다!