옵셔널 (Optional)

조정미·2024년 6월 6일

자습 일지

목록 보기
2/7

옵셔널의 개념이 이해는 되는데 이걸 어떻게 실전에 사용해야 하는지 또는 내가 직접 사용할 때 어떻게 코드를 짜야 하는지 모르겠어서 다시 공부를 시작한다.

옵셔널이란?

간단하게 말하자면, 값이 있을 수도 있고 없을 수도 있는 상태를 말한다.

예를 들어서 이런 변수를 선언하고...

var num1 :Int = 42
var num2 :Int? = 42

num1은 정숫값 42가 저장되어있지만, 변수명 + 타입 뒤에 ?를 붙여서 옵셔널화 해버리면 num2는 num1과 같은 정숫값을 담은 것이 아니게 된다.

즉, num1 == num2는 false인 것이다.

이유가 무엇이냐 함은, num1에는 확실한 정수 42가 담긴 반면에 num2는 말이 42지 이 값이 없을 수도 있고 있을 수도 있는 두 가지 상태를 가지게 되기 때문에 확실한 것을 좋아하는 컴퓨터는 같지 않다고 표현하는 것이다.

nil?

이때 값이 없을 수도 있다는 상태를 nil이라고 하는데 이것은 0도 아니고 아예 값이 없는 상태인데 그렇다고 오류가 나지는 않는다.

쉽게 예시를 들자면 옵셔널이라는 박스에 42가 담겨있는 상태인데 여기서 42가 없으면 빈 박스만 남아있는 것이다. 그래서 무언가가 아예 할당되지 않은 상태와는 다르기에 오류가 나질 않는다. (어쨌든 빈 박스가 자리를 차지하니까)

실제로 앱을 구동할 때는 값이 없으면 크래시... 그러니까 강종이 되기 때문에 값이 없어도 앱이 꺼지지 않고 계속 켜져있을 수 있도록 만들어 놓는 것이다.

옵셔널을 벗겨야 한다고요?

그런데 이 옵셔널은 꼭 벗겨야 하는 때가 찾아온다. 바로 연산이 필요할 때인데 옵셔널끼리는 연산이 불가능하기 때문에 옵셔널 추출이 필요하다.

당연함, 이 값이 있을 수도 있고 없을 수도 있는데 어떻게 연산을 함?

이럴 때는 다양한 방법을 시도할 수 있는데 대표적인 것을 알아보자

방법 1 : 강제 추출

var apple: String? = "사과"

이렇게 옵셔널 된 스트링 타입의 변수 apple이 있다고 치자.
여기서 변수명 뒤에 ! 기호만 붙이면 강제적으로 옵셔널을 추출해버린다.

apple!

그런데 이는 안정적인 방법이 아니기 때문에 그 뒤에 이어지는 안전한 방법을 권장하고 있다. 이 방법들은 우선 값에 nil이 있는지 없는지 판단 후에 옵셔널 추출을 진행하는 방식으로 이루어진다.

방법 2 : 옵셔널 바인딩

(1) if문으로 nil이 아니란 것을 확인하고 강제로 벗기기

if apple != nil {
print(apple)
}

위에서 선언한 apple이라는 변수가 nil과 같지 않다면 구문을 실행한다. 그럼 "사과"라는 문자열이 안전하게 결과값으로 나온다.

(2) if let

[ if 코드 구현부 내에서만 상수 사용 가능 (지역 변수)]

if let <상수 이름> = <옵셔널 > {
	구현 코드
}

let num :Int? = 3
if let number = num {
	print(number) // 출력값 3
}

이렇게 하면 옵셔널이 아닌 3이 출력된다.


직접 확인해 보면 이렇게 옵셔널 추출이 완료된 것을 볼 수 있다.

그리고 if let은 주로 함수 실행 중간에 쓰인다.

(3) guard let

[ guard문을 통과한 상수는 밖에서도 사용 가능 (전역 변수)]

guard let <조건문> {
	<return >
}

let x :Int? = 10
let y :Int? = nil

func opBindding() {
	guard let x = x else { return }
    print(x)
    
    guard let y = y else {return}
    print(y)
  
}

opBinding()

opBinding 함수를 실행하면 출력값은 10이 나온다.


실제로도 그렇게 구현이 되는 것을 확인할 수 있다.

guard let 에서의 조건문은 nil이 아닐 경우 언래핑하여 다시 할당하라는 뜻이고, 지금 x의 경우 10일 수도 있고 아닐 수도 있음 상태에 이미 10일 포함하고 있기 때문에 이를 확실하게 만든 것이다.

그렇기 때문에 이는 true로 판단이 되어서 else 구문을 실행하지 않기 때문에 바로 다음 구문으로 넘어가게 된다.

그 다음은 변수 y 부분인데 이곳에서의 조건문과 이미 위에서 선언된 내용을 보면 y는 nil이 확실하기 때문에 아무런 값이 없는 상태라서 할당을 하여도 값이 없음이 여전하여 false로 판단되어서 else 구문을 실행하고 return으로 아예 guard let 구문이 종료되기 때문에 다음 내용을 실행할 수 없게 된다.

(4) 닐 코어레싱 | nil coalescring 연산자

이 방법은 옵셔널 변수의 값이 nil일 때를 위해 기본값을 설정하는 것이며 닐 코어레싱 (??)이 사용되어 기본값을 부여한 변수는 옵셔널 타입이 아니다.

let(or var) a = b ?? c

닐 코어레싱 연산자는 기본적으로 이 형태로 진행된다.
b는 옵셔날 타입이고 이때 nil이라면 a에 cfmf e대입, nil이 아니라면 옵셔널 추출이 된 b값이 a에 대입된다.

var opNumber :Int? = 3

var  number = opNumber ?? 5
print(number)

opNumber에 nil 말고도 정수 3이 들어있으니 옵셔널 제거 후 number에 대입하기 때문에 number는 Int?가 아닌 Int 타입의 3이 나온다.

0개의 댓글