[SwiftUI] 옵셔널

3 분 소요

문제

스위프트를 빠르게 배워서 쓰다보니까 아무래도 스위프트에만 있는 옵셔널이라는 개념이 익숙치가 않아서
뭔지도 모르고 그냥 !를 사용해 강제 언래핑을 해서 코딩을 하고 있었다. 이렇게 하다보니 서버에서 정보를 잠깐만 못불러와도 nil 값이 되어
앱이 자주 튕기는 현상이 발생해서, 이번 기회에 옵셔널에 대해 제대로 짚고 다시 코딩하기 위해서 옵셔널에 대해 적어보려한다.

옵셔널이란?

스위프트를 쓰다보면 변수에 ?,! 이러한 기호를 사용하는 것을 볼 수 있는데, 이 기호는 옵셔널 기호로 다른 언어에는 없는 스위프트의 특이한
기호이다. non-optional이 기본값이며, non-optional은 nil값을 가질 수 없는 변수이기때문에 반드시 값을 가져야한다. 이렇게 함으로써 nil에 대해서
강제적인 예외처리가 요구되고, 이는 개발 과정에 있어서 nil로 인한 여러가지 문제들을 컴파일 단계에서 예방이 가능해진다. 또한, 이 변수가 nil값을 가질수도
있는 변수인지 아닌지를 명확하게 표기하기 때문에 다른 개발자와 협업에 있어서도 좀 더 의도를 쉽게 전달 할 수 있다.

옵셔널 사용법

옵셔널 변수는 ? 기호를 이용하여 선언한다.

1
2
var name: String?
 

이렇게 하면 방금 선언한 name 변수는 nil을 가질 수 있게 되고, 따라서 다른 값을 할당하지 않아도 컴파일 에러가 나지 않는다. 만약 옵셔널 기호인 ?가 없는
non-optional 값으로 변수를 선언한다면,

1
2
var name : String
 

위의 코드는 non-optional 값에 nil이 들어갔으므로 컴파일 에러가 뜨게 된다.

## 옵셔널 변수 사용법
옵셔널 변수는 nil을 가질 수 있는 변수이기 때문에 이를 통해 연산을 하거나 직접 사용을 하려면 이러한 optional을 해제해주는 과정이 필요하다.

1
2
3
4
5
var num1 : Int? = 20
var num2 : Int = 10

num1 + num2

만약 위처럼 non-optional인 변수와 optional인 변수의 연산을 시도하게 되면, 컴파일 단계에서 Int? optional 변수가 unwrap 되어있다는 에러가
발생하게 된다. nil값과 정수의 합은 존재 하지 않기 때문에, nil값을 가질 수 있는 optional 변수 그 자체로는 연산을 할 수 없는 것이다.

따라서 이러한 값을 사용할 수 있도록 unwrappiing 또는 binding 과정이 필요하다.

Optional Unwrapping

Optional Unwrapping은 Optional 변수에서 Optional을 벗겨내는 작업이다. 위에서 다룬 두수를 연산하는 상황으로 예를 들면,

1
2
3
4
5
6
 var num1 : Int? = 20
 var num2 : Int = 10
 
 if num1 {
  let sum = num1! + num2
}

if문을 사용해서 Optional 변수의 값이 nil인지 아닌지 판별 후에 ! 를 이용하여 값을 꺼내온다.
여기서 !는 unwrapping 기호로, 강제로 Optional을 벗기는 기호이다. 따라서 무분별하게 Optional 변수에 !를 사용하여 강제 unwrapping을 하게되면
Optional 변수가 nil인 경우에 에러가 발생할 수 있다. 위 코드의 경우에는 if를 통해 먼저 num1이라는 Optional 변수가 nil값인지 아닌지 확인 후 !를 통해
unwrapping 했기 때문에 nil값으로 인한 에러를 방지하게 된다.

Optional Binding

1
2
3
4
5
6
var num1 : Int? = 20
var num2 : Int = 10

if let nonOptionalNum1 = num1{
    let sum = nonOptionalNum1 + num2
}

위의 Optional Unwrapping 과 비슷하지만, 새로운 상수로 num1을 받고 이렇게 받은 nonOptional을 사용한다는 차이가 있다.
새롭게 선언된 nonOptionalNum1은 non-Optional인 변수이므로, ! 기호 없이 사용할 수 있다.

### Optional Chaining
위처럼 Optional 변수를 연산할 때 Optional Binding을 사용해야 한다는 것을 알게되었다. 하지만 만약 여러개의 Optional 변수를 한번에 연산해야 한다면
모든 변수마다 Optional Binding을 해주는 것은 너무 복잡하고 가독성도 떨어질 것이다. 따라서 Optional Chaining을 사용하면 좀 더 간단하게 Optional 예외
처리가 가능하다.

1
2
3
4
5
6
class A{
    var b: B?
}
class B{
    var c:String?
}

위 코드의 경우는 A의 프로퍼티 b의 c에 접근할 때, b에대한 옵셔널, c에대한 옵셔널 이렇게 두번의 바인딩이 필요할 것이다.
따라서 이 경우에 Optional Chaining을 이용해 옵셔널 연쇄적으로 옵셔널 바인딩을 해줄 수 있다.

1
2
3
4
5
var a: A = A()

if a.b?.c{

}

이렇게 a.b?.c를 통해 b,c의 옵셔널 바인딩을 모두 처리 가능하다.

default 값 설정해주기

??를 사용하면 optional 값이 nil일때의 default값을 설정해 줄 수 있다.

1
2
3
4
 var num1 : Int? = nil
 var num2 : Int = 10
 
 print(num1 ?? 10 + num2)

위처럼 Optional 기호 자리에 ??를 사용해주면 optional 값이 nil일 때 뒤에 적어준 defualt 값을 넣어서 연산해준다.
따라서 위 코드의 경우는 20이 출력되게 된다.

## 마치며…
사실 Optional 이란게 있다는 것도 알고 언젠가는 공부해야지 하면서 넘겼는데, 진작 공부하고 코딩했으면 이럴일이 없었겠다는 생각을 했다…
너무 기본적인 것 같아보여서 넘긴 감이 있는데, 코드에서는 가장 기본적인 것이 잘못되면 와르르 무너질 수 밖에 없다는 생각이 들었다.
얼른 가서 !로 강제 언래핑 해놓은 코드들을 고치러 가야겠다… 이제는 앱 안튕기겠지

카테고리:

업데이트:

댓글남기기