Swift

[Swift] Optional

thoonk: 2021. 5. 22. 00:23
반응형

Swift의 특징 중 하나인 안정성의 중요한 요소인 Optional에 대한 내용을 기록합니다. 

 

Optional (옵셔널) 

값이 있을 수도 없을 수도 있음을 나타내는 표현이다.

nil로 반환해서 오류가 있음을 알리거나 매개변수를 굳이 넘기지 않아도 된다는 뜻으로 매개변수의 타입을 옵셔널로 정의할 수 있다. 

nil은 옵셔널로 선언된 곳에서만 사용할 수 있다.

-> 옵셔널이 선언된 변수와 아닌 변수를 아예 다른 타입으로 인식해서 옵셔널이 아닌 변수에 nil이 할당되면 컴파일할 때 바로 오류가 발생한다. 

 

옵셔널은 제네릭이 적용된 열거형으로 구현되어 있다.

public enum Optional<Wrapped>: ExpressibleByNilLiteral {
	case none
	case some(Wrapped)

	@_transparent
	public init(_ some: Wrapped) { self = .some(some) }
	. . . 
}

위 코드를 보면 옵셔널이 가질 수 있는 경우는 값을 가지는 케이스와 갖지 못하는 케이스로 나뉘는 것을 볼 수 있다. 

nil일 때는 none 케이스이고 값이 있을 때는 some 케이스이고 연관 값(Associated Value)으로 Wrapped가 있다. 

옵셔널에 값이 있으면 Wrapped에 값이 할당되고 그 말은 값이 Wrapping 되어 있는 것으로 볼 수 있다.

 

 

let str = "123"
let n = Int(str)
print(n) // Optional(123)

위의 코드처럼 String을 Int로 캐스팅했을 때 값이 Wrapping 되어 있는 것을 볼 수 있다.

이는 캐스팅에 실패하면 nil이 될 수 있어 캐스팅의 결과는 Optional타입이다.


Opational UnWrapping (옵셔널 추출)

옵셔널은 기본적으로 Wrapping되어 있는 상태이다. 

그러므로 옵셔널이 아닌 변수에는 옵셔널 값이 들어갈 수 없으므로 추출해서 할당해주어야 한다. 

 

Forced Unwrapping(강제 추출)

런타임 오류가 날 가능성이 제일 높은 방법이고 강제 추출 시 nil이라면 런타임 오류가 발생한다.

그러므로 옵셔널 강제 추출 사용은 지양해야 한다. 

let n = Int("123")! 
print(n) // 123

위 코드처럼 !(느낌표)를 사용하여 옵셔널의 값을 강제로 추출한다.

 

Optional Binding(옵셔널 바인딩)

옵셔널에 값이 있는지 확인할 때 사용한다. (nil 체크)

만약 옵셔널에 값이 있다면 옵셔널에서 추출한 값을 상수나 변수로 할당해서 사용할 수 있도록 해준다.

옵셔널 바인딩은 if 또는 while 구문 등과 같이 사용할 수 있다.

let str = "123"
if let n = Int(str) {
    print(n) // 123
} else {
    print("casting failed")
}

위 코드와 같이 n에 값이 있다면 123을 출력할 것이다.

하지만 str의 값이 "ㅁㄴㅇㄹ"와 같이 캐스팅할 수 없는 값이라면 "casting failed"가 출력된다. 

 

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

옵셔널 바인딩으로 매번 값을 추출하기 귀찮거나 로직상 nil로 인해 오류가 발생하지 않을 것 같다는 확신이 있을 때

nil을 할당해 줄 수 있는 옵셔널이 아닌 변수나 상수를 사용할 때 사용한다.

일반 값처럼 사용할 수 있으나, nil도 할당할 수 있다. 

nil이 할당되어 있을 때 접근을 시도하면 런타임 오류가 발생한다.

 

var str: String! = "ㅁㄴㅇㄹ"
print(str) // Optioanl(ㅁㄴㅇㄹ)
str = nil 
print(str.count) // Fatal Error 

위 코드처럼 타입 뒤에 !을 붙여서 암시적 추출 옵셔널을 사용한다.

str에 nil을 할당하고 접근하면 오류가 발생한 것을 볼 수 있다.

 

 

이와 같이 Optinal은 Swift의 안전성을 담당하는 중요한 요소이며 함수형 프로그래밍 패러다임에서의 모나드 개념과 같은 맥락이다.

 

부족한 점은 피드백해주시면 감사합니다!

 

참고: 

https://github.com/apple/swift/blob/main/stdlib/public/core/Optional.swift

반응형