스위프트에서의 핵심 개념이라고 하는 옵셔널에 대해서 공부해보았다.
다른 프로그래밍 언어에서는 찾아볼 수 없는 개념이기 때문에 다소 생소했다.
정확히 이해하고 다루는 데까지 시간이 좀 걸리지 않을까 생각한다.
1. Optional | 옵셔널
옵셔널, 그대로 해석해보면 '선택적인' 이라고 해석할 수 있다.
스위프트에서는 값이 '있을 수도, 없을 수도 있다' 는 것을 뜻한다.
옵셔널이 아닌 변수에 nil 값을 할당하려고 하면 아래와 같이 컴파일 오류가 발생한다.
그리고 옵셔널 타입을 사용하라고 "?"를 추가하라고 한다.
간단하게 생각해보면 옵셔널을 사용해서 값이 있는지 없는지 알 수 있다는 것이고
옵셔널이 아니라면 값이 꼭 있어야 한다는 것이다. 옵셔널이 없다면 확인해본 것과 같이 에러가 발생한다.
nil 의 값을 가지려면 옵셔널 타입을 추가해주어야 한다는 것.
(nil 은 다른 언어에서의 Null 과 같이 값이 없다는 것을 뜻한다.)
그리고 옵셔널의 기본 값은 nil 이다.
변수에 아무것도 없다면 nil을 반환해주게 되는데 nil 이 나오는 이유는 nil 도 메모리를 차지하고 있기 때문이라고 한다.
var opVal: Int?
print(opVal)
==================== 출력 결과 ====================
nil
2. 옵셔널을 쓰는 이유
그럼 옵셔널은 왜 필요한걸까?
1. 명시적 표현
- 옵셔널은 nil의 가능성을 명시적으로 표현
- nil 가능성을 문서화 하지 않아도 코드만으로 충분히 표현 가능
- 문서와 주석 작성 시간을 절약
옵셔널을 사용해야만 값이 없을 수도 있다는 사실을 알 수 있기 때문에
옵셔널을 사용하는 것만으로도 충분히 nil 에 대한 표현이 가능하다. 그래서 시간을 절약할 수 있다.
2. 안전한 사용
- 전달 받은 값이 옵셔널이 아니라면 nil 체크를 하지 않더라도 안심하고 사용
- 예외 상황을 최소화 하는 안전한 코딩
- 효율적인 코딩
옵셔널을 사용해야만 nil 을 표현할 수 있기 때문에 옵셔널이 아니라면 nil 체크를 하지 않고 사용해도 된다.
기본적인 변수들은 nil 의 값을 가질 수 없기 때문에 컴파일 에러에서 nil 의 예외적인 상황들에 대해 미리 예방할 수 있고
그렇기에 안전하고 효율적인 코딩이 가능해진다.
어느정도 이해는 가지만 참고해놓은 포스팅에서 더 자세하게 그리고 더 이해하기 쉽게 설명해주셨기 때문에
참고하면 좋을 것 같다.
3. 옵셔널 문법과 선언
옵셔널은 enum + generics 라고 열거형과 제네릭의 조합이라고 하는데 나중에 알아보기로 하자.
옵셔널은 다음과 같이 선언할 수 있다고 한다.
enum Optional<Wrapped>: ExpressibleByNilLiteral {
case none
case some(Wrapped)
}
// 완전한 문법
let optionalValue: Optional<Int> = nil
// 물음표로 표현 가능
let optionalValue: Int? = nil
완전한 문법으로 Optional<Int> 라고 선언할 수 있지만, 물음표 "?" 를 통해서 선언해줄 수 있다고 한다.
4. 옵셔널 표현 | 물음표(?) 와 느낌표(!)
옵셔널을 어떻게 표현할 수 있을까? 물음표(?) 와 느낌표(!) 를 통해서 표현할 수 있다고 한다.
느낌표 " ! ". 를 이용한 암시적 추출 옵셔널 | Implicitly Unwrapped Optional
var optionalValue: Int! = 100
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
==================== 출력 결과 ====================
Value is 100
느낌표를 사용한 옵셔널은 기존 변수처럼 사용이 가능하고 nil을 할당할 수 있다.
var optionalValue: Int! = 100
// 기존 변수처럼 사용 가능
optionalValue = optionalValue + 1
print(optionalValue)
// nil 할당 가능
optionalValue = nil
print(optionalValue)
// 잘못된 접근
optionalValue = optionalValue + 1
print(optionalValue)
==================== 출력 결과 ====================
Optional(101)
nil
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file study10.playground, line 46
nil 의 값에 1 을 더해줄 수 없기 때문에 런타임 오류가 발생한다.
물음표를 이용한 " ? " 일반적인 옵셔널 | Optional
var optionalValue: Int? = 100
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
==================== 출력 결과 ====================
Value is 100
물음표를 사용한 일반적인 옵셔널의 경우
nil 의 값을 할당할 수 있지만, 기존 변수처럼 사용할 수 없다고 한다.
var optionalValue: Int? = 100
// 기존 변수처럼 사용 불가
optionalValue = optionalValue + 1
print(optionalValue)
==================== 출력 결과 ====================
error: study10.playground:62:17: error: value of optional type 'Int?' must be unwrapped to a value of type 'Int'
optionalValue = optionalValue + 1
^
5. 정리
이렇게만 보면 옵셔널이 무엇인지 잘 이해가 되지 않는다.
물음표와 느낌표를 통해서 사용한다고 하는데 왜 물음표와 느낌표를 나누어서 사용하지? 라고 생각할 수 있다.
아래의 참고 사이트에 있는 Zedd 님이 너무 자세하고 친절하게 정리해주신 포스팅을 통해 직접 확인해면서 정리해보았다.
우선, 물음표를 통한 옵셔널 표현
옵셔널 타입을 정해주었으니 nil 의 값을 가지게 된다.
변수에 값이 있으면 값을 출력하게 되고 없으면 nil 을 출력하게 된다.
변수인 someOptional 을 물음표를 사용한 옵셔널로 선언하고 다른 하나의 변수인 Value를 선언해서 someOptionl 을 넣어주었다.
그런데 타입을 가지지 않는 변수는 옵셔널 타입의 변수가 되어 someOptional 의 값을 가지게 되었다.
Value 는 옵셔널 타입이 되었구나 확인할 수 있었다.
그리고 Int 타입의 Value2에도 someOptional 의 값을 넣어주었더니 에러가 발생했다.
Int 와 Int? 는 다른 타입이란 걸 직접 확인할 수 있었다.
다음으로는 느낌표를 통한 옵셔널 표현
언래핑? Unwrapping , 풀어준다는 뜻을 가지는데 옵셔널 타입의 변수에 들어있는 값을 풀어 가져온다는 것 같다.
위에서 예를 들었던 Value2 에 느낌표를 사용한 someOptional 의 값을 넣어주었더니 에러가 발생하지 않았다.
에러가 발생하지 않았다. 뭐지...?
값을 가져올 수 있었던 이유? 옵셔널 타입이었던 someOptional 이란 변수를 풀어서, Unwrapping 해서 값을 가져왔다는 말이다.
다행히 someOptional 은 Int 타입을 가지고 있었기 때문에 Value2 에는 someOptional 의 값이 들어가게 된다.
Unwrapping 해서 someNil 의 값을 가져오지만 someNil 의 값은 nil 이기 때문에
Int 타입의 Value3 는 nil의 값을 가질 수 없어 에러가 발생한다.
이러한 이유에서 느낌표를 사용할 때 조심해서 사용해야 한다고 한다.
그리고 옵셔널을 사용할 때에는 초기화를 해주지 않으면 nil 의 값을 가지기 때문에
느낌표를 사용할 때 옵셔널의 값이 nil 의 값이 아니라는 것이 확실해야 한다고 한다.
생각보다 어려운 내용이라 여기저기 찾아가며 공부해보았는데
어느 정도의 옵셔널에 대한 틀이 잡혔다고 생각한다. 직접 사용해보면서 익숙해져야 할 것 같다.
- 참고 사이트 -
www.edwith.org/boostcamp_ios/lecture/11240
monibu1548.github.io/2018/05/12/swift-optional/
'iOS > Swift' 카테고리의 다른 글
[Swift] 12. 구조체(struct) 기본 (0) | 2020.10.18 |
---|---|
[Swift] 11. 옵셔널 추출 (Optional Unwrapping) (0) | 2020.10.08 |
[Swift] 9. 반복문 (for-in, while, repeats-while) (0) | 2020.09.16 |
[Swift] 8. 조건문 (0) | 2020.09.16 |
[Swift] 7. 함수 고급 (0) | 2020.09.15 |