이번 시간에는 Swift언어의 Type Safety에 대해서 간단히 살펴보고 Swift의 옵셔널의 개념과 예시에 대해서 알아보도록 하겠습니다. 이미 옵셔널에 대해서 다룬 글이 있긴 하지만 Swift 언어에서는 옵셔널이 중요한 개념이기도 하고 몇 가지 추가할 내용이 있기도 해서 겸사겸사 글을 더 적어보려고 합니다!
Type Safety
"Type Safety"는 프로그래밍 언어의 중요한 특징 중 하나로, 타입 안전성이라고도 번역됩니다. 타입 안전성은 프로그램이 실행되는 동안 데이터가 항상 명시적으로 선언된 타입을 유지하도록 하는 속성입니다.
타입 안전한 언어에서는, 예를 들어 정수를 문자열에 할당하려고 시도하면 컴파일러 또는 런타임 시스템에서 오류를 발생시킵니다. 이런 방식으로, 개발자가 실수로 잘못된 타입의 데이터를 사용하는 것을 방지할 수 있습니다.
Swift, Java 등의 언어는 강력한 타입 검사 기능을 가진 타입 안전 언어입니다. 이들 언어에서 변수나 객체의 타입은 선언 시점에 결정되며, 이후에 변경할 수 없습니다. 따라서 해당 변수나 객체가 지원하지 않는 연산을 수행하려고 하면 컴파일 에러 또는 런타임 에러가 발생합니다.
타입 안전성은 코드의 품질과 신뢰성을 향상시키며 버그 발생 가능성을 줄여줍니다. 그러나 모든 상황에서 최선의 선택은 아닐 수 있으며 때때로 동적인 유형 시스템이 필요한 경우도 있습니다.
옵셔널 타입
이제 본격적으로 옵셔널에 대해서 살펴보겠습니다.
옵셔널 타입은 값을 반환할 때 오류가 발생할 가능성이 있는 값은 옵셔널 타입이라는 객체로 감싸서 반환하는 것입니다.
코드를 살펴보면서 설명하도록 하겠습니다.
Int("123")
print(Int("123"))
첫 번째 줄에서 Int("123")은 123이 아닌 Optional(123)을 리턴하게 됩니다. 실제로 Optional(123)을 리턴하는지 확인하고 싶다면 위에 코드처럼 print(Int("123"))으로 출력해서 확인해보면 됩니다.
Int("Hi")
위 코드와 같은 경우에는 정수 값을 반환할 수 없기 때문에 아무런 값도 반환할 수 없다는 의미로 nil을 반환하게 됩니다.
Swift에서 기본 자료형은 nil값을 저장할 수 없습니다. 만약 nil을 저장하려면 옵셔널 타입으로 선언해야 합니다.
옵셔널 타입은 변수 또는 상수에 아무런 값이 할당되지 않는 상황을 안전하게 처리하기 위해 사용하는 타입입니다. 옵셔널 타입 변수를 선언하기 위해서는 타입 선언부 뒤에 "?"를 사용합니다. 만약 index라는 이름의 옵셔널 Int 변수를 선언하려면
var index: Int? //index 변수는 정수 값을 갖거나 아무 값도 갖지 않을 수 있음
이렇게 사용하면 됩니다. 간단하죠?
옵셔널 타입 강제 언래핑 1
다음으로 방금 배운 옵셔널 타입을 강제 언래핑 하는 방법에 대해서 살펴보도록 하겠습니다.
옵셔널 변수에 값이 있으면 옵셔널로 래핑 되었다 라고 표현합니다. 옵셔널에 래핑된 값은 강제 언래핑으로 풀어줄 수 있습니다.
옵셔널 언래핑을 사용하는 방법은 변수명 뒤에 "!"를 붙여주면 됩니다. 소스 코드를 보면서 살펴보겠습니다.
var x : Int? //옵셔널 정수형 변수 x 선언
var y : Int = 0
x = 10
print(x) // Optional(10)
print(x!) // forced unwrapping해서 10이 나옴
print(y)
/*
실행 결과
Optional(10)
10
0
*/
x는 옵셔널 타입으로 선언되어 있으므로, 값을 가질 수도 있고 값이 없을 수도 있는 상태입니다. 따라서 x에 값을 할당할 때에는 Optional(...) 형태로 출력되게 됩니다. 따라서 print(x)는 Optional(10)을 출력하게 됩니다.
! 기호를 사용하여 x!와 같이 강제 언래핑(force unwrapping)을 수행하면, 옵셔널에서 실제 값을 추출할 수 있습니다. 이 경우, x!는 옵셔널 내부의 값인 10을 반환합니다. 즉, 강제 언래핑된 결과인 실제 값인 10이 출력되고 마지막 줄은 일반 정수형이므로 변수 y의 값 0이 출력됩니다.
만약 값이 nil일 때 강제 언래핑을 하게 되면 없는 값을 강제로 언래핑 하기 때문에 앱에서 크래쉬(crash)가 발생하게 되니 값이 nil이 아닐 때만 언래핑을 하도록 주의해야 합니다.
var x : Int?
x = 10
if x ! = nil { //주의 : if x!=nil 이라고 쓰면 안 됨
print(x!)
}
else {
print("nil")
}
var x1 : Int?
if x1 != nil {
print(x1!)
}
else {
print("nil")
}
위 소스 코드를 살펴보면 먼저, x라는 옵셔널 변수를 선언하고 값 10을 할당합니다. 그 다음, if문을 사용하여 x가 nil이 아닌지 확인합니다. 만약 x가 nil이 아니라면, 즉 값이 있다면 해당 값을 강제 언래핑(!)하여 출력합니다. 그렇지 않은 경우에는 "nil"을 출력합니다.
다음으로, x1라는 또 다른 옵셔널 변수를 선언하고 초기값은 할당하지 않습니다. 마찬가지로 if문으로 x1이 nil인지 확인하고, 값을 가지고 있다면 강제 언래핑 후 값을 출력하고, 그렇지 않으면 "nil"을 출력합니다.
결과적으로 위의 코드를 실행하면 다음과 같은 결과가 나타납니다.
첫 번째 if문에서는 x에 값 10이 있으므로 해당 값을 강제 언래핑한 후 출력됩니다. 두 번째 if문에서는 x1에 초기값이 없기 때문에 "nil"이 직접적으로 출력됩니다.
*강제 추출 연산자 !는 피연산자와 꽉 묶이는(tightly associates) 높은 우선순위를 가진다. 즉, 대부분의 다른 연산자보다 먼저 계산되며, 다른 연산자와 함께 사용되는 표현식에서는 피연산자에 밀접하게(bind tightly) 결합되어, 표현식에서 다른 연산자와는 무관하게 즉시 적용된다. 예를 들어, let x = optionalValue! + 5 표현식에서 강제 추출 연산자 !는 덧셈 연산자 +보다 높은 우선순위를 가지므로, 옵셔널 값이 5에 더해지기 전에 먼저 추출된다. 그러나 옵셔널 값이 nil인 경우 런타임 오류가 발생할 수 있으므로, 가능한한 강제 추출 대신 옵셔널 바인딩 또는 옵셔널 체인을 사용하는 것이 좋다. 이렇게 하면 코드를 보다 견고하게 만들어 crash를 피할 수 있다. |
옵셔널 타입 강제 언래핑 2 : Optional binding
옵셔널 바인딩은 강제 언래핑하는 또 다른 방법으로, 옵셔널 바인딩을 이용하여 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당할 수 있습니다.
if let constantname = optionalName {
//옵셔널 변수가 값이 있다면 언래핑해서 일반 상수 constantname에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
if var variablename = optionalName {
//옵셔널 변수가 값이 있다면 언래핑해서 일반 변수 variblename에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
옵셔널 바인딩을 사용하는 방법은 3가지가 존재합니다. 각각의 방법을 아래 소스 코드를 통해 살펴보겠습니다.
첫 번째 방법
var x : Int?
x = 10
if let xx = x { //옵셔널 변수 x가 값(10)이 있으므로 언래핑해서 일반 상수 xx에 대입하고 if문 실행
print(x, xx)
}
else {
print("nil")
}
var x1 : Int?
if let xx = x1 { //옵셔널 변수 x1이 값이 없어서 if문의 조건이 거짓이 되어 if문 실행하지 않고 else로 감
print(xx)
}
else {
print("nil")
}
두 번째 방법
var x : Int?
x = 10
if let x = x { //옵셔널 변수 x가 값(10)이 있으므로 언래핑해서 일반 상수 xx에 대입하고 if문 실행
print(x)
}
else {
print("nil")
}
var x1 : Int?
if let xx = x1 { //옵셔널 변수 x1이 값이 없어서 if문의 조건이 거짓이 되어 if문 실행하지 않고 else로 감
print(xx)
}
else {
print("nil")
}
세 번째 방법
var x : Int?
x = 10
if let x { //옵셔널 변수 x가 값(10)이 있으므로 언래핑해서 일반 상수 xx에 대입하고 if문 실행
print(x)
}
else {
print("nil")
}
var x1 : Int?
if let xx = x1 { //옵셔널 변수 x1이 값이 없어서 if문의 조건이 거짓이 되어 if문 실행하지 않고 else로 감
print(xx)
}
else {
print("nil")
}
이번 시간에는 옵셔널의 개념과 예시에 대해서 글을 다뤄 봤습니다. 최대한 한 게시글 안에 내용을 다 담아보려 했는데 워낙 중요한 내용이라 글이 길어지는 관계로 나머지 내용은 정리해서 따로 올리도록 하겠습니다!
감사합니다.
틀린 부분이 있거나 더 좋은 내용 훈수 환영합니다!
공감과 댓글 부탁드립니다.
'Apple > Swift' 카테고리의 다른 글
[Swift] 업캐스팅과 다운캐스팅, Swift와 Kotlin 옵셔널의 차이 (0) | 2023.09.25 |
---|---|
[Swift] 옵셔널과 Nil합병 연산자 (0) | 2023.09.23 |
[Swift] 데이터 타입, 상수, 변수의 개념과 예시 (0) | 2023.09.12 |
[Swift] for문을 이용한 특정 키워드 반복 출력 (2) | 2023.09.05 |
[Swift] 클래스 인스턴스의 소멸 (0) | 2023.08.21 |