[Swift] Optional 이란?

정환우·2020년 12월 24일
1

iOS

목록 보기
2/24
post-thumbnail

요즘 유튜브를 통해 iOS 어플 만들기에 도전하고 있는데, 코딩을 하다보면 생소한 것들이 있다. 대표적으로 변수 뒤에 ?!가 붙는 경우가 있는데, 이게 무엇인지 궁금했다. 이것들은 Optional 이라고 정의하는 개념이다.

Optional 이란?

Optional은 Type Casting이나 nil value 체크 등에 있어서 중요한 역할을 한다. Optional은 ?을 통해 표현되는데, 그 의미는 다음과 같다.

이 변수에는 값이 들어갈 수도 있고, 아닐 수도 있다.(nil)

일단 여기 nil value 라는 개념이 생소하기 때문에, 이것을 먼저 알아보자.

nil 에 대해서

nil은 c에서 흔히 쓰던 NULL과 비슷하지만 조금 다르다.

  1. C에서 NULL은?
// c-pointer의 부재 및 c나 c++의 변수 및 객체에 사용한다.
int *intPtr = NULL;
  1. Swift에서 nil은?
var optionalString: String?
var optionalString2: String? = nil
// 두 값 모두 nil이다.

nil은 Swift에서 value가 없는 것을 의미한다.
그리고 optional 변수 이외에서 사용 불가. 그리고 따로 초기화하지 않아도 기본으로 설정된다.

다시 본론으로

Optional의 기본적인 형태는 다음과 같다.

let myFirstOpVar : Int?

위처럼 변수 타입의 뒤에 ?를 붙여주면 해당 변수는 Optional 변수가 된다. Swift에서는 기본적으로 변수 선언시에 nil 값이 들어가는 걸 허용하지 않는다고 한다. (심지어 런타임 에러가 아니라 아예 컴파일 에러를 내버린다.)

var OpString: String = nil	// 컴파일 에러
var OpString2: String? = nil	// Optional이므로 정상

다음 예시는 String -> Int로 Type Casting 하는 경우이다.

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

print(convertedNumber)
>>> Optional(123)

let convertedNumber = Int(possibleNumber)!
print(convertedNumber)
>>> 123

첫 번째 경우, "123"은 String 이기 때문에 Int(possibleNumber) 초기화에 실패한다. 이 경우 바로 에러가 나오는게 아니라 Optional Int형으로 선언한다.(Int는 아님) 그래서 두번째 경우처럼 뒤에 !를 붙여서 unwrap(뒤에나올 내용)을 해주면 Int로 형 변환이 된다.

Wrapping

Optional과 뗄 수 없는 관계가 Wrapping 이라는 개념이다.
Optional타입은 기본적으로 wrap되어 있는 상태이다. 즉, Optional 변수들은 현재 값이 존재하는 것인지, nil은 것인지 wrap되어 있어서 모른다고 보면 된다. 그렇기 때문에 wrap 된 상태에서는 value값이 있는지 없는지에 관계 없이 바로 value가 출력되지 않는다.

var opString : String? = "Hello"
print(opString)	// opString은 optional 이다.
>>> Optional("Hello")

Forced Unwrapping

우리는 변수들을 출력할 때 앞의 경우처럼 Optional("Hello") 이렇게 나오는 것을 대부분 바라지 않는다. 이 때 올바른 출력을 위해 사용하는 것이 !이다. Optional로 선언했지만, 변수에 value가 있는 상황이 보장된 경우 !를 사용하면 우리가 원하는 출력값을 얻을 수 있다.

var opString : String? = "Hello"
print(opString!)
>>> Hello

즉, wrap되어 있는 Optional 변수를 unwrap 한다고 할 수 있다. 우리가 원하는 출력값은 unwrap 되어 있는 상태에서만 얻을 수 있는 것이다.
주의해야 할 점은, 변수에 값이 있다고 확신한 상태에서만 unwrap을 할 것.(그렇지 않으면 런타임 에러가 발생한다.)
따라서 보통은 unwrap하기 전에 nil인 경우를 체크하고 unwrap 한다.

let value2: String? = nil
if value2 != nil {	// nil 체크.
  print(value2)!
}

Optional Binding

Optional Binding은 Optional 타입으로 선언된 변수에 값이 있는지 없는지를 확인할 수 있도록 해주는 기능이다. Optional Binding을 사용하면 느낌표 없이 Optional 타입의 변수 값을 출력할 수 있어서 좀 더 안전한 형태로 값을 얻을 수 있다. 기본적인 형태는 다음과 같다.

if let 변수명 = Optional 변수 {
 // 임시 변수에 Optional 변수의 value값이 할당된다다.
}

형태만 봐서는 잘 이해가 되지 않으므로 예제를 봐보자.

// Optional type으로 선언한 myNumber
let myNumber: Int? = 1234
if let actualNumber = myNumber {
 print(“\(myNumber)은 실제로 \(actualNumber)입니다.)
} else {
 print(“\(myNumber)는 변환될 수 없습니다.)
}
// 출력 결과 : Optional(1234)은 실제로 1234입니다.
print(actualNumber) // error

여기서 myNumber 변수는 Optional 타입으로 선언되어 있는데, Optional Binding은 이 변수의 값이 있는 지 없는 지 판단하고, 값이 있는 경우 if let 조건문을 실행한다고 생각하면 된다.
actualNumbermyNumber 값을 할당하고, 값이 있다면 바로 실제값으로 사용할 수 있도록 해준다. 추가적으로, actualNumber는 if문 안에서만 사용 가능하고, 밖에서는 사용 불가능하다!

nil 체크 + nil이 아닌 경우에 새로운 변수로 바꿔주는 기능을 if let 한줄에 할 수 있게 해주는 굉장히 유용한 기능이다.

출처 : Swift Optional(1)

profile
Hongik CE

0개의 댓글