iOS/Swift이론

[iOS]Swift 개념! Optional이란?

Sweetft 2022. 1. 6. 13:51

한 학기 동안 스위프트 문법 공부 및 iOS 앱 만들기 실습을 하며 옵셔널을 많이 사용했다.

하지만 그럼에도 불구하고 아직까지 제대로 이해하지 못 했다고 판단해 다시 정리해보기로 했다.

 

 

스위프트에서는 안전한 코딩을 위해 옵셔널이 중요한 역할을 한다고 한다.

옵셔널 타입은 변수 또는 상수에 아무런 값이 할당되지 않는 상황을 안전하게 처리하기 위한 방법을 제공한다.

 

You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn’t a value at all.

The Swift Programming Language(Swift 5.5)에 따르면,

optionals는 값이 비어있을 수도 있는 상황에서 사용되고, 하나의 옵셔널은 두 개의 가능성을 나타낸다. - 언래핑을 해서 값에 접근 할 수 있는 그러한 값이 있거나, OR 값이 없거나. 


 

그리고 우리는 이 값이 없는 값을 nil이라고 한다.

If you define an optional variable without providing a default value, the variable is automatically set to nil for you

옵셔널 변수에 기본 값을 설정하지 않는다면, 그 변수에는 자동으로 nil 값이 설정된다.

 

스위프트에서 nil은 옵셔널에서만 허용된다.

즉, 옵셔널로 선언되지 않은 변수는 nil 값을 가질 수 없다! (optional 사용 이유)

 

옵셔널 변수 생성 방법은 간단하다. 변수 선언을 하며 물음표 ?만 붙여주면 된다.

var optionalTest : Int = nil
print(optionalTest)

스위프트에서는 이런 식으로 변수에 nil 값을 넣어주면 컴파일 에러가 발생한다.

에러문구 : add '?' to form the optional type 'Int?'

 

var optionalTest : Int? = nil
print(optionalTest)
//출력 결과 : nil

print(type(of:optionalTest))
//출력 결과 : Optional<Int>

optionalTest = 3
print(optionalTest)
//출력 결과  : Optional(3)

이런 식으로 타입 어노베이션 부분 뒤에 ?만 붙여주면 해결된다.

또한 위에서 언급했다시피, 옵셔널 변수의 기본값은 nil이므로 var optionalTest : Int?로 줄일 수 있다.

 

 

이렇게 만들어진 옵셔널 변수는 일반 변수와 달라서 그냥 사용할 수 없게 되는데,

이를 다시 사용하기 위해서는 옵셔널을 풀어주는 과정이 필요하다.

옵셔널 타입이라는 객체로 감싸진(wrapping) 변수를 다시 풀어주는(unwrapping) 것이다.

 

 

forced unwrapping

느낌표 !를 사용해서 아주 손쉽게 옵셔널을 풀어버릴 수 있는 방법이다.

하지만 변수에 nil 값이 저장되어 있다면 오류가 나기 때문에 주의해야 한다.

 

var optionalTest : Int? = 3
print(optionalTest) //출력 결과 : Optional(3)
print(optionalTest!) //출력 결과 : 3
print(type(of:optionalTest!)) //출력 결과 : Int

Optional(3)으로 출력되던 optionalTest가 느낌표 !를 사용해 언래핑하였더니 3으로 출력되며 타입 또한 Int로 나오는 것을 볼 수 있다.

 

optionalTest = nil
print(optionalTest!)

하지만 optionalTest가 현재 예시 처럼 nil 값일 경우에는 이렇게 강제 언래핑을 해주는 경우 오류가 발생한다.

 

optionalTest = nil
if optionalTest != nil {
  print(optionalTest!)
} else {
  print("nil")
}

 

optional binding

실제 값이 있든, nil 값이든 상관없이 더 안전하게 옵셔널 변수를 풀어주는 방법이다.

옵셔널에 할당된 값을 임시 변수 또는 상수에 할당한다.

var optionalPhone : String?
optionalPhone = "010-1234-5678"
if let phone = optionalPhone {
    //옵셔널 변수 optionalPhone에 값이 있으므로 언래핑해서 일반 상수 phone에 대입하고 if문을 실행한다.
    print("핸드폰 번호는 \(phone)") // Option(10) , 10
}
else {
    print("핸드폰 번호를 찾을 수 없습니다.")
}
//출력결과 : 핸드폰 번호는 010-1234-5678

if문을 활용한 옵셔널 바인딩의 예시이다.

optionalPhone이라는 변수를 옵셔널 바인딩 해주기 위해 새로운 상수 phone을 만들었다. 여기서 "phone"과 "optionalPhone" 즉, 일반 상수와 옵셔널 변수의 이름은 같아도 된다.

만약 optionalPhone에 아무런 값이 할당되지 않았다면 else문을 실행하는 더욱 안전한 코드이다.

 

var optionalPhone : String? = "010-1234-5678"
var optionalName : String? = "최자두"
if let phone = optionalPhone,
   let name = optionalName {
    //콤마를 이용해 여러 옵셔널 변수를 한 번에 언래핑할 수 있다. 
    //각 변수의 앞에 모두 let을 붙여야한다는 것에 주의하자.
    print("핸드폰 번호는 \(phone), 이름은 \(name)") // Option(10) , 10
}
else {
    print("핸드폰 번호, 이름을 찾을 수 없습니다.")
}
//출력결과 : 핸드폰 번호는 010-1234-5678, 이름은 최자두

위 코드와 같이, 여러 개의 옵셔널 변수들을 한 번에 바인딩 할 수 있다.

 

 

지금까지 물음표 ?를 통한 옵셔널만 봐왔는데 느낌표 !를 통한 옵셔널 표현도 가능하다.

이를 Implicitly Unwrapped Optional(암묵적으로 벗겨진 옵셔널)이라고 한다.

let a : Int! = 2
print("a=", a, type(of:a)) //a= Optional(2) Optional<Int>
let b : Int = a
print("b=", b, type(of:b)) //b= 2 Int
let c : Int = a!
print("c=", c, type(of:c)) //c= 2 Int
let d = a
print("d=", d, type(of:d)) //d= Optional(2) Optional<Int>
let e = a + 3
print("e=", e, type(of:e)) //e= 5 Int

위 코드를 보면 느낌표 !를 이용해 만든 옵셔널 변수 a를 그대로 출력하면 옵셔널 값이 나오는 것을 볼 수 있다.

하지만 코드의 마지막 부분을 보면, 이 옵셔널 변수 a+3을 계산하면, 오류가 나지 않고 문제없이 계산이 되는 것을 볼 수 있다.

이처럼 느낌표 !를 사용한 옵셔널은 기본 변수처럼 사용할 수 있으면서 nil 값 또한 할당이 가능하다.

(물론 nil 값이 할당되었을 때 값을 벗기려고 하면 오류가 난다.)

 

 

 

 

참고

https://yejprogramming.tistory.com/4

https://jaynamm.tistory.com/entry/Swift-10-%EC%98%B5%EC%85%94%EB%84%90-Optional

https://devxoul.gitbooks.io/ios-with-swift-in-40-hours/content/Chapter-2/optionals.html

https://medium.com/@codenamehong/swift-optional-1-54ae4d37ee09

https://jwonylee.tistory.com/entry/Swift-Optional%EA%B3%BC-Optional-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html