[iOS / Swift] Optional 개념과 Unwrapping 정리
iOS 개발하면서 Optional 개념은 필수로 알아야 함. Swift에서 값이 없을 수도 있다는 걸 표현하려면 Optional을 써야 함. 이번 포스팅에서는 Optional 기본 개념, Unwrapping, Optional Binding에 대해서 정리해볼 것임.
1. Optional 이란? 🤔
let num: Int? = nil // 값이 없음
let name: String? = "Doseo" // 값이 있음
Optional 타입 변수는 값이 없을 때 nil을 저장할 수 있음. 반면, Non-Optioanl(일반 타입) 타입 변수는 무조건 값을 가짐.
2. Optional 값 사용하기: Unwrapping 🫢
Optional 값을 사용하려면 Unwrapping이 필요함.
(1) 강제 Unwrapping
: !를 붙여서 값을 강제로 꺼낼 수 있음.
let optionalNum: Int? = 123
print(optionalNum!) // 123
하지만, Optional 값이 nil일 경우 강제 Unwrapping하면 런타임 에러가 발생함.
let optionalNum: Int? = nil
print(optionalNum!) // 런타임 에러 🚨
(2) Optional Binding
: 강제 Unwrapping 대신 Optional Binding을 써서 안전하게 값을 꺼내는 방법임.
if let str = str {
if let num = Int(str) {
print(num) // 123
} else {
print("타입 변환 실패")
}
} else {
print("옵셔널 바인딩 실패")
}
3. 자주쓰는 Optional 패턴 👍
Optional을 사용할 때 자주 쓰는 패턴을 몇가지 정리해봄
(1) guard let을 활용한 Unwrapping
: guard let은 조건이 맞지 않으면 초기 단계에서 바로 빠져나감.
func processString(_ input: String?) {
guard let unwrapped = input else {
print("입력값이 nil임")
return
}
print("입력값은 \(unwrapped)임")
}
(2) 기본값 제공 (?? 연산자)
: Optional 값이 nil이면 기본값을 설정할 수 있음.
let optionalName: String? = nil
let name = optionalName ?? "Default Name"
print(name) // "Default Name"
4. Optional 관련 주의할 점 🚨
- 강제 Unwrapping은 필요한 경우에만 하셈. 값이 nil일 때 앱이 크래시 날 수 있음
- Optional Binding을 자주 쓰셈. if let, guard let 등을 쓰면 안전하게 코드 작성 가능
- Optioan과 Non-Optional의 차이점을 알아두셈. Optional 타입은 Non-Optional 타입과 호환 안 됨. 따라서 적절한 Unwrapping이 필요함.
5. 결론 ✍️
Swift에서 Optional은 처음엔 어렵게 느껴질 수 있지만, 익숙해지면 코드 안정성을 높여주는 좋은 도구임. 강제 Unwrapping보다는 Optional Binding과 guard let을 자주 쓰는 게 좋음.
아래는 내가 공부하면서 정리한 전체 코드랑 코드 파일임. 필요하면 참고하셈.
import UIKit
// Non-Optional, Non-Optional Type
//let num: Int
//num = 123
//
//print(num)
// Optional로 선언
//let num1: Int? // 뒤에 물음표를 붙임
//num1 = nil // null, 값을 nil로 저장하면 값을 저장하지 않는다 라고 생각하면 됨
//
//let attendeeCount: Int? = nil
//
//let name: String? = ""
//let num = 123
//
//print(num)
// Unwrapping, 추출
// 강제 언래핑을할거면 뒤에 !를 붙이면 됨
let optionalNum: Int? = 123
//print(optionalNum) 이렇게하면 값이 들어있는 것
print(optionalNum!) // 이렇게하면 강제 언래핑
//let optionalNum1: Int? = nil
//print(optionalNum1!) 이렇게하면 옵셔널 값이 없는데 강제 언래핑해서 값이 nil이라 추출할 값이 없기 때문에 오류 발생
let a = optionalNum
print(type(of: a))
let b = optionalNum! // 이건 강제 언래핑을한 상태이므로 옵셔널 Int가 아닌 그냥 Int타입
//let str = "123"
//let num1 = Int(str)
//print(type(of: num1)) // 이렇게하면 Optional<Int>로 저장됨 형변환에 실패할 수 있기 때문
let str: String? = "123"
let num = Int(str!)
//let str: String? = "123"
//let num = Int(str) 옵셔널 값을 전달할 수 없음 str뒤에 !를 붙이면 가능. but, 값이 nil이 아닐때 가능
// optional binding 하는 방법. 중요함!!
// if let name : Type = OptionalExpreesion {
// statements
// }
//
// while let name : Type = OptionalExpreesion {
// statements
// }
//
// guard let name : Type = OptionalExpression else {
// statements
// }
if let str = str { // = str은 생략해도 되긴 함
if let num = Int(str) { // 지금 if에서 선언한 str을 말하는 것임 위에 있는 str이 아님
print(num)
} else {
print("타입 변환 실패")
}
} else {
print("옵셔널 바인딩 실패")
}
// 위 경우 let str: String? = "123"인 경우는 123이출력
// let str: String? = nil인 경우는 옵셔널 바인딩 실패 출력
// let str: String? = "nil"인 경우는 타입 변환 실패 출력