Swift 옵셔널 체이닝과 nil 병합 연산자
Swift를 공부하다 보면 옵셔널(Optional)이라는 개념을 꼭 마주하게 된다. 옵셔널은 "값이 있을 수도 있고, 없을 수도 있는 변수"를 뜻한다.
Swift는 안전한 언어이기 때문에, 값이 없을 수 있는 상황에서는 반드시 옵셔널로 처리해야 한다.
하지만 이 옵셔널을 다루다 보면 종종 코드가 복잡해지고, 옵셔널 안의 옵셔널을 꺼내야 할 때마다 여러 번 if let을 중첩해서 써야 해서 불편함이 생긴다.
이럴 때 옵셔널 체이닝(Optional Chaining)과 nil 병합 연산자(nil coalescing operator) 를 사용하면 깔끔하게 처리할 수 있다(:
1. 옵셔널 체이닝이란?
옵셔널 체이닝은 ?. 연산자를 이용해 옵셔널 내부에 또 다른 옵셔널이 있을 때 안전하게 접근하는 방법이다.
중간에 하나라도 nil이 있으면 전체 결과는 nil이 되고, 에러 없이 멈춘다.
예제 구조
class Person {
var name: String
var job: String?
var home: Apartment?
init(name: String) {
self.name = name
}
}
class Apartment {
var buildingNumber: String
var roomNumber: String
var `guard`: Person?
init(dong: String, ho: String) {
buildingNumber = dong
roomNumber = ho
}
}
여기에서 Person이 살고 있는 home이 있고, 그 집의 guard가 또 하나의 Person인 구조이다.
옵셔널 체이닝 사용 예시
let yagom = Person(name: "yagom")
let home = Apartment(dong: "101", ho: "202")
let guardman = Person(name: "슈퍼맨")
guardman.job = "경비원"
home.guard = guardman
yagom.home = home
let job = yagom.home?.guard?.job
print(job) // Optional("경비원")
여기서 yagom.home?.guard?.job은 다음과 같은 뜻이다:
- yagom이라는 사람이 있고
- 그 사람이 사는 home이 존재하고
- 그 home에 guard라는 사람이 있고
- 그 guard의 job이 있다면 → 그 값을 가져온다.
중간에 하나라도 없으면(nil), 전체는 nil이 되고,
Swift는 아무 에러도 발생시키지 않고 그냥 nil을 반환한다.
2. 옵셔널 체이닝이 에러를 내지 않는 이유
많은 초보자가 헷갈리는 부분 중 하나는 이 부분이다:
"옵셔널 체이닝 중간에 nil이 되면 멈춘다는데,
그럼 앱은 에러가 나야 하는 것 아닌가?"
그렇지 않다.
Swift의 옵셔널 체이닝은 "안전한 접근"을 전제로 한다.
즉, 중간에 nil이 되면 아예 실행을 멈추고 결과값을 nil로 돌려준다.
강제로 꺼내는(!) 것이 아니기 때문에 앱이 절대 터지지 않는다.
3. nil 병합 연산자 (??)
옵셔널 체이닝의 결과가 nil일 경우,
기본값을 지정하고 싶을 때 사용하는 것이 nil 병합 연산자이다.
형식은 다음과 같다:
옵셔널값 ?? 기본값
예를 들어:
let job = yagom.home?.guard?.job ?? "슈퍼맨"
print(job) // 경비원
위 코드는 이렇게 읽을 수 있다:
- job이 있으면 → 그 값을 사용하고
- 없다면(nil) → "슈퍼맨"이라는 기본값을 사용한다.
4. if let vs guard let (복습용 🥰)
옵셔널 체이닝만으로는 처리가 어려운 경우,
if let 또는 guard let을 통해 옵셔널을 안전하게 꺼내서 사용할 수 있다.
if let
if let job = yagom.home?.guard?.job {
print("경비원의 직업은 \(job)")
} else {
print("경비원의 직업이 없습니다")
}
조건이 만족되면 job을 안전하게 꺼내서 사용하고,
nil일 경우 else 블록이 실행된다.
guard let
func printGuardJob(owner: Person?) {
guard let job = owner?.home?.guard?.job else {
print("경비원의 직업이 없습니다")
return
}
print("경비원의 직업은 \(job)입니다")
}
- 조건이 불충족되면 즉시 함수 종료
- 이후 코드는 조건이 만족되었을 때만 실행됨
Swift에서는 guard let을 사용하여 조건을 초반에 정리하고 깔끔하게 흐름 제어하는 것을 추천한다.
5. 변수명이 guard인데 왜 백틱(`)을 써야 할까? (요것도 복습! ㅎㅎ)
Swift에서 guard는 예약어이다.
예약어란 이미 문법적으로 의미가 정해진 단어를 말한다.
(예: if, else, return, guard, for 등)
따라서 이를 변수명으로 쓰려면 백틱으로 감싸야 한다:
var `guard`: Person?
하지만 실제 코드에서는 securityGuard, gatekeeper처럼 다른 이름을 쓰는 것이 좋다.
✅ 핵심 요약
문법 | 의미 | 사용 예시 |
?. | 옵셔널 체이닝 | person?.home?.guard?.job |
?? | nil 병합 | job ?? "기본값" |
if let | 옵셔널 안전 추출 | if let job = ... {} |
guard let | 조건 불충족 시 빠른 탈출 | guard let job = ... else { return } |
백틱(`) | 예약어 변수명 허용 | var `guard`: Person |
옵셔널 체이닝과 nil 병합 연산자는 Swift의 안정성과 가독성을 높여주는 필수 문법이다. 처음에는 어렵게 느껴질 수 있지만, 왜 이런 문법이 존재하고, 어떤 상황에서 유용한지를 이해하면 오히려 코드가 훨씬 간결하고 안전해진다.
Swift는 "안전하게 프로그래밍하자"는 철학을 가진 언어다.
그 철학을 가장 잘 보여주는 문법이 바로 옵셔널과 옵셔널 체이닝이라는 것!🖤
'IT' 카테고리의 다른 글
Swift : assert, guard, 그리고 제어 흐름 제어문 (0) | 2025.05.11 |
---|---|
Swift에서 is와 as로 배우는 타입 확인과 변환의 핵심 (0) | 2025.05.11 |
Swift 클래스, 인스턴스, 그리고 메모리 관리: init과 deinit의 역할 (0) | 2025.05.10 |
Swift 클래스 상속 제대로 알기: 프로토콜과 final, override (0) | 2025.05.09 |
Swift 프로퍼티 감시자: willSet과 didSet 완벽 이해하기 (1) | 2025.05.05 |
댓글
이 글 공유하기
다른 글
-
Swift : assert, guard, 그리고 제어 흐름 제어문
Swift : assert, guard, 그리고 제어 흐름 제어문
2025.05.11 -
Swift에서 is와 as로 배우는 타입 확인과 변환의 핵심
Swift에서 is와 as로 배우는 타입 확인과 변환의 핵심
2025.05.11 -
Swift 클래스, 인스턴스, 그리고 메모리 관리: init과 deinit의 역할
Swift 클래스, 인스턴스, 그리고 메모리 관리: init과 deinit의 역할
2025.05.10 -
Swift 클래스 상속 제대로 알기: 프로토콜과 final, override
Swift 클래스 상속 제대로 알기: 프로토콜과 final, override
2025.05.09