안녕하세요! 피피아노입니다🎵
이번 포스팅에서는 Implicitly Unwrapped Optional과 Optional Chaining에 대해서 다뤄보려고 합니다.
편의상 Implicitly Unwrapped Optional은 줄여서 IUO라고 표현하겠습니다. 이 점 유의해서 봐주시기 바랍니다.
그럼 바로 시작하겠습니다!
IUO(Implicitly Unwrapped Optional)란?
우선 옵셔널에 대해서 간단하게 살펴보고 가자면, Swift 언어에서 Optional은 값이 있을 수도 있고, 없을 수도 있는 변수나 상수를 선언할 때 사용합니다.
이게 무슨 소리야?? 라고 생각하시는 분들을 위해 예를 들어서 설명해보자면!
우리가 앱을 이용하면서 앱을 만든 개발자들은 사용자로부터 입력 받은 데이터를 항상 예측 가능하지 않습니다. 예를 들어, 양식에 정보를 입력할 때 필수적인 정보가 누락되었거나, 올바르지 않은 형식으로 입력된 경우가 있을 수 있습니다. 이럴 때 Optional을 사용하면, 이러한 입력 값의 존재 여부를 검사하고, 올바르게 처리할 수 있습니다.
그렇기 때문에 옵셔널을 사용한다고 생각하시면 됩니다!
자 아무튼!! 다시 본론으로 돌아와서
Optional 변수는 실제 값 또는 'nil'을 가질 수 있습니다. 여기서 IUO는 특별한 형태의 Optional로, Optional 변수임에도 불구하고 값을 사용할 때 마다 Unwrapping(강제 추출)하지 않아도 되는 특성을 가집니다.
선언 방법
암시적으로 추출된 옵셔널은 변수나 상수를 선언할 때 타입 뒤에 !를 붙여서 선언합니다. 예를 들어, String? 대신 String!을 사용합니다.
var possibleString: String! = "An optional string."
소스코드와 함께 살펴보자면
class SampleClass {
var mustHaveValue: Int!
}
let sample = SampleClass()
sample.mustHaveValue = 10
print(sample.mustHaveValue) // 10 출력, 별도의 unwrapping 없이 사용 가능
위 코드에서 mustHaveValue는 IUO로 선언되었습니다. 이 변수는 나중에 값이 할당되는 것이 보장되지만, 초기화 시점에서는 값이 없습니다. 따라서 IUO를 사용하여 나중에 값에 접근할 때 마다 강제 unwrapping을 하지 않아도 됩니다.
사용 사례
암시적으로 추출된 옵셔널은 주로 두 가지 상황에서 유용하게 사용됩니다.
- 초기화 이후 값이 반드시 설정되는 경우: 클래스나 구조체의 속성으로 사용될 때, 초기화 과정에서는 값이 설정되지 않지만, 초기화 이후에는 반드시 값이 존재하는 경우에 유용합니다. 예를 들어, UI 컨트롤러의 아웃렛이 로드되는 시점에는 값이 없지만, 뷰가 로드된 이후에는 항상 값이 존재한다고 가정할 수 있습니다.
- Objective-C와의 상호 운용성: Swift 코드가 Objective-C API와 상호 작용할 때, Objective-C의 nil 반환 가능성이 있는 메서드나 프로퍼티를 Swift에서 사용하려 할 때 유용합니다. Objective-C에는 Swift의 옵셔널 타입에 해당하는 개념이 없기 때문에, Swift로 가져올 때 암시적으로 추출된 옵셔널로 처리되는 경우가 많습니다.
주의사항
암시적으로 추출된 옵셔널은 사용 시 주의가 필요합니다.
왜 그러냐면!
이 타입의 변수나 상수에 접근할 때, 만약 값이 nil이라면 런타임 오류가 발생하여 애플리케이션이 강제 종료될 수 있습니다. 따라서, 이러한 옵셔널을 사용할 때는 해당 값이 항상 존재한다는 확신이 있을 때만 사용해야 하며, 가능하면 일반 옵셔널을 사용하고 안전하게 값을 추출하는 방법을 선호하는 것이 좋습니다!!
암시적으로 추출된 옵셔널은 편리함을 제공하지만, 오용될 경우 앱의 안정성을 해칠 수 있습니다. 따라서, 이를 사용할 때는 항상 주의를 기울이고, 필요한 경우에만 제한적으로 사용하는 것이 가장 좋답니다!
자 이제 다음으로는 Optional Chaining(옵셔널 체이닝)에 대해서 알아보겠습니다!
옵셔널 체이닝은 옵셔널이 포함된 여러 연산을 연결해서 하나의 연산처럼 처리할 수 있는 기법입니다. 이는 옵셔널이 nil을 포함할 가능성이 있는 경우, 간결하고 안전하게 코드를 작성할 수 있게 해줍니다.
아래에서 좀 더 자세하게 살펴보겠습니다.
옵셔널 체이닝이란?
옵셔널 체이닝은 옵셔널 값을 포함하는 프로퍼티, 메소드, 서브스크립션 등에 접근할 때 사용할 수 있습니다. 이 기법을 사용하면, 옵셔널의 값을 강제로 추출하지 않고도 해당 값에 접근할 수 있습니다. 만약 옵셔널 체인의 어느 한 부분이 nil이라면, 전체 표현식은 즉시 nil을 반환합니다. 이는 코드의 안전성을 크게 향상시킵니다.
사용 방법
옵셔널 체이닝은 옵셔널 값 뒤에 물음표(?)를 붙여서 사용합니다. 이는 해당 옵셔널이 nil인지 아닌지를 체크하고, nil이 아니라면 다음 연산을 계속 진행합니다.
코드도 함께 살펴보겠습니다!
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
print("John의 집에는 \(roomCount)개의 방이 있습니다.")
} else {
print("John의 집에 대한 정보를 알 수 없습니다.")
}
위 코드에서, john.residence는 nil입니다. 따라서 john.residence?.numberOfRooms는 nil을 반환하고, "John의 집에 대한 정보를 알 수 없습니다."가 출력됩니다.
앱 개발에서 옵셔널 체이닝의 사용 예시
1. 모델 객체 접근: 앱 내에서 복잡한 데이터 구조를 다룰 때, 모델 객체의 중첩된 프로퍼티에 접근해야 하는 경우가 많습니다. 이때, 어느 한 단계에서라도 값이 nil일 수 있으므로, 옵셔널 체이닝을 사용해 안전하게 접근할 수 있습니다.
class User {
var account: Account?
}
class Account {
var profile: Profile?
}
class Profile {
var username: String?
}
let user = User()
if let username = user.account?.profile?.username {
print("사용자 이름은 \(username)입니다.")
} else {
print("사용자 이름을 찾을 수 없습니다.")
}
2. UI 업데이트: 앱의 UI 컴포넌트를 업데이트할 때, 해당 컴포넌트가 아직 완전히 초기화되지 않았을 수 있습니다. 이 경우, 옵셔널 체이닝을 사용하여 안전하게 UI 컴포넌트의 속성을 업데이트할 수 있습니다.
textView?.text = "새로운 텍스트"
3. 델리게이트 메소드 호출: 앱에서 델리게이트 패턴을 사용하는 경우, 델리게이트 객체가 실제로 메소드를 구현하고 있는지 확실하지 않을 수 있습니다. 옵셔널 체이닝을 사용하면, 델리게이트가 해당 메소드를 구현하고 있다면 호출하고, 그렇지 않다면 무시합니다.
protocol SomeDelegate {
func didUpdateData(_ data: Data)
}
class SomeClass {
var delegate: SomeDelegate?
}
let someClass = SomeClass()
someClass.delegate?.didUpdateData(newData)
4. 옵셔널 반환값 처리: 함수나 메소드가 옵셔널 값을 반환할 때, 이를 처리하는 과정에서도 옵셔널 체이닝을 활용할 수 있습니다. 이를 통해 반환값이 nil일 경우의 로직을 간결하게 처리할 수 있습니다.
func fetchDocument(id: String) -> Document? {
// 문서를 찾아 반환하거나, 찾지 못했으면 nil을 반환
}
if let document = fetchDocument(id: "123")?.printDocument() {
print("문서 출력 성공")
} else {
print("문서 출력 실패")
}
이렇게 Implicitly Unwrapped Optional과 Optional Chaining에 대해서 살펴보았는데 혹시 내용 중에 잘못된 점 있다면 댓글 부탁드립니다.
감사합니다!
잘못된 내용이 있거나 더 좋은 내용 피드백은 언제나 환영합니다!
궁금하신 부분은 댓글로 질문 부탁드립니다!
'Apple > Swift' 카테고리의 다른 글
[Swift] 동시성(Concurrency) 톺아보기 (1/2) (0) | 2024.07.23 |
---|---|
[Swift] 고차함수(Higher-order function) 이해하기 (2) | 2024.06.27 |
[Swift] 배열(Array) (0) | 2024.03.13 |
[Swift] 초기화(Initializers) 알아보기 (6) - Failable Initalizers (0) | 2024.02.22 |
[Swift] 초기화(Initializers) 알아보기 (5) - 요구 이니셜라이저 (0) | 2024.02.16 |