[Swift] Optional(옵셔널) 정의

어흥·2024년 5월 4일

Swift

목록 보기
4/28

안녕하세요! 오늘은 Optionals 포스팅으로 돌아왔습니다.
개발할 때 가장 많이 발생하는 예외 중 하나가 NullPointerException입니다. 접근하는 변수의 값이 nil이어서 발생하는 것입니다.

var yourName: String        // 선언
//yourName = "어흥"           // 값을 저장하지 않는다면..

print(yourName)   // (만약 저장과정이 없다면) 메모리에 저장된 값이 없는데 접근 ===> 🔸"에러"

위처럼 변수를 선언했지만 값을 저장하지 않은 변수에 접근하면 에러가 발생합니다. 앱 실행 중에 해당 에러가 발생하면 바로 앱이 중단됩니다.

이 때문에 Optional 개념을 도입한 것이라고 할 수 있습니다.

Optional

Swift는 안전한 코딩을 할 수 있게 해주는 언어라고 알려져 있습니다. 그리고 이 안전성의 기본 바탕에 있는 중요한 요소 중 하나가 바로 Optional이라는 개념입니다.

위 그림처럼 기존 non-optional type 값과 nil을 포함한 타입이 optional type이라고 생각하면 됩니다.

Optional은 nil을 사용할 수 있는 타입과 없는 타입을 구분하기 위함이며, nil을 사용할 수 있는 Type을 Optional Type이라 부릅니다. (nil - 값이 없음을 나타내는 키워드)

이처럼 에러가 나지 않도록 임시적인 타입을 담아두는 개념이라고 생각하시면 됩니다.

그럼 optional 은 어떻게 구현되어 있을까요?

optional 타입 내부

옵셔널은 제네릭 Enum(열거형)으로 구현되어 있습니다.

enum Optional<Wrapped> {
  case none // nil
  case some(Wrapped) // optional value
}
  • some의 케이스인 경우 연관값을 저장합니다.
  • none 케이스는 구체적인 정보에 값이 없음을 나타냅니다. (none 케이스와 nil은 동일합니다.)

따라서 nil은 실제 값이 없는 것이 아니라 값이 없음을 나타내는 키워드인 것을 알 수 있습니다.

var num: Int? = 3 // optional type
var noneNum: Int? = nil 

위 코드를 예시로 들면 각각의 변수는 다음과 같이 표현할 수 있습니다.

  • num은 Optional.some(3)
  • noneNum은 Optional.none

옵셔널 사용

모든 타입의 뒤에 '?' (물음표)를 붙이면 옵셔널 타입이 됩니다.

var num: Int? = 3
var yourAge: Int? = nil
var yourGrade: Double? = nil
var name1: String? = "Jobs"

num = nil
name1 = nil

옵셔널 타입 선언의 기본 규칙

  • 1) nil 대입 가능
  • 2) 자동 초기화 (값을 넣지 않을 시에 nil로 초기화) ⭐️

옵셔널은 2가지로 표현할 수 있지만 주로 간편표기 방식을 많이 사용합니다.
일반 타입과는 다르게 옵셔널 타입은 타입 추론 방식을 사용할 수 없습니다. -> nil 값으로 초기화될 때 어떤 타입인지 추론하기 어렵기 때문입니다.

따라서 type annotation을 사용해서 초기화해야합니다.

let num1: Int? = 2             // 간편표기
let num2: Optional<Int> = 0    // 정식문법

//var optionalNum = nil         // 불가능한 형태

그렇다면 optional type에 non-optional type 값을 담으면 어떻게 될까요?
optional 타입인 b에 non-optional 타입인 c를 할당해도 non-optional 타입이 Optional 타입으로 바꿔서 담기는 걸 확인할 수 있습니다.

var a: Int? = 7  // 옵셔널 인트
var b = a        // 값을 복사해서 담는 다면 타입은?

print(b) //Optional(7)

var c: Int = 5
b = c     // Int를 Int?타입에 담을 수는 있다. (어쨌든 타입이 Int? 타입으로 바뀌어서 담김)

print(b)  // Optional(5)

optional 타입끼리 계산할 수 없습니다. 계산하기 위해서 unwrapping을 진행해야 합니다.

unwrapping에 대해서는 다음 포스팅에 이어 작성하도록 하겠습니다!

0개의 댓글