Weekoding
[Swift] 옵셔널(Optional) 본문
옵셔널에 대해 좀 더 명확한 개념을 갖고자 이 글을 쓰기로 계획했다.
< 목차 >
1. 옵셔널이란?
2. 옵셔널 사용
3. 옵셔널 추출(Optional Unwrapping)
- 강제 추출(Forced Unwrapping)
- 옵셔널 바인딩(Optional Binding)
- 암시적 추출 옵셔널(Implicitly Unwrapped Optional)
4. 심화 - 옵셔널 뜯어보기
1. 옵셔널이란?
옵셔널(Optional): '선택적인' 이라는 뜻을 가진 단어. Swift에서 값이 있을수도, 없을수도 있음을 나타내는 표현이다.
즉, 변수/상수에 값이 nil일 수도 있다(=값이 있는 것을 보장할 수 없다) 라는 의미이다.
Swift의 특징 중 하나인 '안전성'을 문법으로 담보하는 기능이다.
옵셔널 변수 또는 상수가 아니면 nil을 할당할 수가 없다.(할당 시에는 런타임 오류가 발생한다.)
2. 옵셔널 사용
옵셔널 상수나 변수는 데이터 타입 뒤에 물음표(?)를 붙여 표현할 수 있다.
옵셔널을 사용하는 이유는, 예를 들자면
ex1) 내가 만든 함수에 전달되는 전달인자의 값이 잘못된 경우, 처리하지 못했음을 런타임 에러가 아닌 간단히 nil로 반환하여 표현할 때
ex2) 매개변수를 굳이 넘기지 않아도 된다는 뜻을 표현하고 싶을 때
정도가 있을 것이다.
물음표 하나만으로 값이 없어도 되는, 혹은 없을 수도 있다는 커뮤니케이션이 가능한 것이다.
//데이터타입(String)뒤에 물음표를 붙여 옵셔널 변수를 선언한다.
var dog: String? = "pitbull"
print(dogName)
//Optional("pitbull")
//특징으로는 그냥 "pitbull"이 아닌, Optinal()로 감싸져서 값이 출력되는 것
//이는 추후 서술되는 옵셔널 추출을 통해 벗겨낼 수 있다.
//추가) nil을 할당하면, print함수 사용시 'nil'이 출력된다
3. 옵셔널 추출(Optional Unwrapping)
옵셔널이 아닌 변수에는 옵셔널 값이 들어갈 수 없다.
따라서 옵셔널이 아닌 값으로 추출해서(Optional() 껍데기를 벗겨내는 작업) 할당해주어야 한다.
- 강제 추출(Forced Unwrapping)
가장 간단한 방법이면서, 가장 위험한 방법이다.
옵셔널 값의 뒤에 느낌표(!)를 붙여주면 값을 강제로 추출하여 반환받을 수 있다.
❗️: 강제 추출시 옵셔널에 값이 없다면(nil이면), 런타임 오류가 발생한다.
따라서 런타임 오류가 일어날 가능성이 가장 높고, 런타임 오류의 가능성을 항상 내포하기 때문에 강제 추출은 지양해야 한다.
var dog: String? = "pitbull"
var puppy: String = "Husky"
dog = nil
puppy = dog! //runtime Error
- 옵셔널 바인딩(Optional Binding)
옵셔널에 값이 있는지 확인할 때 사용
옵셔널에서 추출한 값을 일정 블록 안에서 사용할 수 있는 상수나 변수로 할당해서 사용할 수 있게 해준다.
또한, if 혹은 while문과 결합하여 사용할 수 있다.
var dog: String? = "pitbull"
//옵셔널 바인딩을 통한 임시 상수 할당.(nil이 아니면 true)
it let puppy = dog{
print("dog is \(puppy)")
}else{
print("dog is nil")
}
// dog is puppy
//puppy라는 임시 상수는, if블록 내에서만 사용할 수 있다.
//따라서 별도로 사용하는 것도 가능하다.
//한번에 여러 옵셔널 값을 추출할 때는 쉼표(,)를 이용한다.
var cat: String? = "persian"
var kitty: String? = nil
if let myCat = cat, let myKitty = kitty{
print("they are my \(cat) and \(kitty)")
}
//kitty가 nil을 할당받아 바인딩이 되지 않았으므로 실행되지 않는다.
- 암시적 추출 옵셔널(Implicity Unwrapped Optionals)
타입 뒤에 느낌표(!)를 사용해주면 된다.
지정된 타입은 일반 값처럼 사용할 수 있으나, 옵셔널이기 때문에 nil을 할당해줄 수 있다.
→ 그러나, nil이 할당되어 있을 때 접근을 시도하면 런타임 오류가 발생한다.
//타입 뒤에 느낌표를 붙여 암시적 추출 옵셔널을 한다.
var cat: String! = "russianBlue"
//옵셔널이기 때문에 nil할당이 가능하다.(바인딩도 사용 가능)
cat = nil
//nil이 할당되어 있을 때 사용하면 오류가 발생한다
print(cat.count) //Error
📌 옵셔널을 사용할 때는,
강제추출 / 암시적 추출 옵셔널 사용을 지양하고,
옵셔널 바인딩, 옵셔널 체이닝 등의 방법을 사용하는 것이 훨씬 안전하며, Swift의 지향점과도 부합한다고 볼 수 있다.
4. 심화 - 옵셔널 뜯어보기
옵셔널은 제네릭이 적용된 열거형이라고 한다. 옵셔널의 정의를 보자.
public enum Optional<Wrapped>: ExpressibleByNilLiteral{
case none
case some
public init(_ some: Wrapped)
//중략...
}
주목해야 할 점은, none과 some이다.
값이 nil이면 none이고, 값이 있으면 some이다.
이 때 옵셔널에 값이 있으면, some의 연관 값인 Wrapped에 값이 할당된다고 한다.
즉 값이 옵셔널이라는 열거형에 Wrapping되어있는 것이다.
옵셔널이 열거형이라 switch구문을 통해서도 값을 확인할 수 있다!
switch optionalValue{
case .none:
print("Optional is nil")
case .some(let value):
print("Optional is \(value)")
}
옵셔널 마다 일일이 switch를 적용하는 것은 비효율적이므로 위에서 서술한 옵셔널 바인딩 등의 값 추출 방법을 이용하는 것이다.
오류 및 지적사항은 댓글로 남겨주시면 감사하겠습니다!
참고 : 스위프트 프로그래밍 3판(한빛미디어)
'공부 노트(Swift)' 카테고리의 다른 글
[Swift]DispatchQueue와 스레드의 개념 (3) | 2022.04.25 |
---|---|
[Swift] 네트워크 통신(RESTful API, JSON, URLSession) (0) | 2022.04.20 |
[Swift] Closure의 단축 인자($0, $1....) (0) | 2022.04.11 |
[Swift] 다크모드와 가로모드(디바이스 방향)에 대한 설정 (0) | 2022.04.04 |
[Swift] Xcode 프로젝트에 파일, 폴더 추가하기(groups, folder references) (0) | 2022.03.25 |