옵셔널은 값이 있을 수도 있고, 없을 수도(nil 값이 없음) 있는 상태를 말한다. 기존 타입 뒤에 ?를 사용하여 옵셔널 타입으로 선언하고, 그 값에 접근하면 Optional로 감싸진 값이 반환된다. 비교 연산자만 사용 가능하므로 기본 타입과 연산할 경우, 언래핑 작업을 통해 기본 타입으로 변환한 후에 사용해야 한다.
var hello: String? = "안녕"
// Optional로 래핑된 값 출력
print(hello) // Optional("안녕")
옵셔널 값의 속성/메서드 등에 접근할 때, 값이 nil이면 그냥 nil을 반환하고, nil이 아니면 정상적으로 작동하게 만드는 기능이다. 즉, 중간에 하나라도 nil이면 전체 표현식은 nil이 되고, 모두 nil이 아니라면 Optional로 래핑된 값을 반환한다. 이로 인해 크래시 없이 안전하게 처리가 가능하다.
let length = name?.count // name이 nil이면 length는 nil
name이 "Luna"면 → length = 4name이 nil이면 → length = nil옵셔널로 래핑된 값에서 실제 값을 꺼내는 과정으로, 여러 방법이 있다.
옵셔널 값에 !를 붙인다. 값이 절대 nil이 아님을 확신할 때 사용한다. 잘못 쓰면 런타임 에러가 발생하므로, 지양하는 것이 좋다.
let name: String? = "Luna"
print(name!) // "Luna"
❗️name이 nil이면 → 런타임 에러 발생!
조건문 if , guard을 사용하여 안전하게 값을 변환한다.
let name: String? = "Luna"
// 1. if let
if let actualName = name { // 옵셔널 값이 있다면 actualName에 저장하고 블록 실행
print(actualName)
} else { // nil이면 else 블록 실행
print("이름이 없습니다.")
}
// 2. guard let
func greet(_ name: String?) {
// 값이 없으면 일찍 빠져나오고, 있으면 이후 코드에서 안전하게 사용 가능
guard let name = name else {
print("이름이 없습니다.")
return
}
print("안녕하세요, \(name)님!")
}
옵셔널 값이 nil일 경우 기본값을 제공할 때 사용한다.
let name: String? = nil
let displayName = name ?? "이름 없음" // name이 nil이면 "이름 없음"을 기본값으로 사용
print(displayName) // → "이름 없음"
옵셔널이지만, 사용할 때 자동으로 언래핑된다. 값이 nil 일 때 접근하면 런타임 오류가 발생하므로, 값이 있다고 확신이 들 때 사용해야 한다.
var name: String! = "Luna"
| 구분 | 설명 | 사용 예 |
|---|---|---|
Optional | 값이 nil일 수도 있는 타입 | var name: String? |
| 옵셔널 체이닝 | nil이면 중단하고 nil 반환 | user?.name?.count |
강제 언래핑(!) | 확실할 때만 강제 꺼내기 | print(name!) |
if let | 값이 있으면 꺼내서 사용 | if let name = name { ... } |
guard let | 함수 초기에 체크 후 처리 | guard let name = name else { return } |
?? | nil 병합 (기본값 제공) | let name = name ?? "익명" |
| 묵시적 언래핑 | 자동으로 언래핑 | var name: String! = "Luna" |
💡 필요한 경우에만 옵셔널을 사용하고, 옵셔널을 피할 수 있다면 피하는 것이 코드의 안정성과 가독성을 높이는 방법!