Programming/Swift

[Swift] Optional의 정의

JunsuKim 2026. 1. 3.
728x90

Swift 언어를 공부하기 위해 프로그래머스에서 문제를 풀어보고 있다.

이때 에러로 자주 만나는 것이 Optional이었다.

때문에 OPtional이란 무엇인가에 대해 알아볼 겸 정리를 해보려 한다.

Optional이란?

코틀린을 공부할 때도 nullable, non null로 구분이 되었었다.

이때 자료형 뒤에?를 붙여 이 변수가 nullable인지 아닌지 여부를 알 수 있었다.

Swift에서는 이 값이 nullable인지 아닌지를 Optional로 나타내는 것으로 이해된다.

조금 다른 점으로는 Swift에서는 null이라 하지 않고 nil이라고 하더라 정도?

즉, Optional Type이라면 nil을 가질 수 있다는 의미이다.

 

간단한 예제를 통해 예제를 만들어보자.

 

Dictionary를 생성하여 특정 값을 가져오고자 할 때 Exprssion implicitly coerced from 'Int?' to 'Any'라는 warning이 뜨며 출력값으로 Optional(1)이 뜨는 것을 확인할 수 있었다.

 

아래처럼 없는 key값을 통해 접근을 하게 되면 nil이 출력되는 것을 확인할 수 있다.

 

그렇다면, Optional Type과 Non-Optional Type은 어떤 자료형에서 사용되는가?

일반적으로 선언과 동시에 초기화를 하던가, 타입을 Non-Optional로 선언했다면 이들은 모두 Non-Optional Type이다.

Non-Option Case

Non-Option Type의 특징은 무조건 값을 가져야 한다는 것이다.

만약 case2에서 city = "Seoul"를 제한 후 출력하고자 하면 에러를 볼 수 있게 된다.

값을 가져야 한다?

그렇다면 nil이라는 값을 저장할 수는 없을까?

당연히 저장할 수 없다.

위에서 말했듯이 nil은 오직 Optional Type만이 가질 수 있기 때문이다.

 

그럼 nil 값을 저장하기 위해 Optional은 어떻게 설정할까?

이 부분은 코틀린과 같다.

자료형의 뒤에 ?를 붙여 변수를 선언해주면 그 변수는 Optional이 되며 nil 값을 가질 수 있게 된다.

제일 위에서 처음 예제로 보였던 Dictionary의 출력값에서도 Optional을 확인할 수 있었다.

Dictionary로 들어가보면 Value?를 반환하는 것을 알 수 있게 된다.

 

이처럼 우리가 이미 자주 사용하고 있는 자료형들에서도 Optional을 반환하는 경우가 많기에 미리 알고 있어야 에러가 발생하는 것을 방지할 수 있을 것 같다.

 

추가로 Dictionary에서 반환된 Optional(1)은 Int형이 아니다.

Optional(1), Optional("1") 등을 Int, String으로 사용하기 위해서는 Optional을 벗겨내야 한다.

 

Optional을 벗겨내는 방법으로는 아래의 방법들이 있다.

  1. 강제 추출(Forced Unwarpping)
  2. 옵셔널 바인딩(Optional Binding)
  3. nil 결합 연산자(nil coalescing operator)
  4. 옵셔널 체이닝(Optional Chaning)

강제 추출(Forces Unwarpping)

Optional 값을 벗기고자 하는 변수 뒤에 느낌표(!)를 붙여주면 강제로 값을 추출하여 반환할 수 있다.

var fruits: String? = "apple"
print(fruits)    //Optional("apple")
print(fruits!)   // apple

만약 !를 붙여 강제 추출을 하고자 하는 값이 nil이라면 에러가 발생하게 된다.

옵셔널 바인딩(Optional Binding)

옵셔널 값이 nil인지 아닌지를 판단하여 안전하게 추출하기 위해 사용된다.

옵셔널 값이 nil이 아니라면 추출한 값을 상수 혹은 변수에 할당하여 사용할 수 있으며, nil이라면 상황에 맞는 동작을 수행하게 할 수 있다.

if let, guard let 구문을 사용하는데, guard let의 경우 반드시 return 혹은 throw와 같이 메서드를 종료시키는 코드가 포함되야 한다.

var fruits: String? = "apple"

if let fruit = fruits {
    // nil이 아닐 때
    print(fruit)
} else {
    // nil일 때
    print("doesnt fruit")
}

func caseGuard() {
    guard let fruit = fruits else {
        // nil일 떄
        print("doesnt fruit")
        return
    }
    
    // nil이 아닐 때
    print(fruit)
}

nil 결합 연산자

옵셔널 바인딩은 딱 보기에도 코드가 길다.

이를 간단하게 할 수 있는 것이 nil 결합 연산자이다.

단순히 ?? 연산자를 통해 표현할 수 있다.

var fruits: String? = "apple"
let fruitName = fruits ?? "banana"

이렇게 변수에 할당을 해줄 때 nil일 때와 아닐 때의 자료형이 같아야만 한다.

만약 둘의 자료형이 다르다면 에러가 발생하게 된다.

옵셔널 체이닝(Optional Chaining)

class Person {
    var residence: Residence?
}

class Residence {
    var city: String = "gyeonggi"
}

var junsu = Person()
let city = junsu.residence?.city

코드에서처럼 dot(.)을 사용해 내부 프로퍼티나 메서드에 접근할 때 옵셔널 값이 포함되어 있다면 이는 옵셔널 체이닝이다.

이때 Optional 값이 nil이라면 nil이 반환된다.

728x90

댓글