[swift] 옵셔널

이은수, Lee EunSoo·2024년 9월 21일
0

Swift Basic

목록 보기
1/24
post-thumbnail

개요

옵셔널이란? 다른 언어들에서 사용하는 null이나 nil을 이야기 하는것이다.

java의 경우 일반 변수나 배열에다 = null으로 null을 지정해 줄 수 있지만

swift의 경우 nil이 허용되는 데이터는 따로 명시를 해주고 사용해야 하며 이러한 것을 옵셔널타입이라고 한다.

이러한 옵셔널은 옵셔널이 아닌 요소들처럼 바로 사용하는것은 불가능하고 따로 처리를 해 주어야 사용이 가능하다( 이를 옵셔널 바인딩이라고 함)

형태

var someData: String?
var someData2: String? = nil
var someData3: String = nil // 에러 발생

변수 이름뒤에, 타입이 지정되어 있다면 타입 뒤에 ?물음표를 붙이는것으로 옵셔널임을 나타낼 수 있다.

옵셔널이 아닌 데이터에 nil을 대입하는것은 불가능

옵셔널의 비교

옵셔널은 == 으로 nil과 비교할 수 있다
당연히 ><을 이용한 크기 비교는 안되고 == nil 혹은 != nil 같은 값이 존재하는지에 대한 비교연산만 가능하다

var someData: String?

if someData != nil{
	print("someData is not empty")
}else{
	print("someData is empty")
}

//결과....."someData is empty"

옵셔널 바인딩

var someData: String? = nil

print(someData) // 오류발생

옵셔널 데이터의 경우 그냥 사용할 수 없다.

swift의 경우 옵셔널(null데이터)을 엄격하게 관리하는 편이기 때문에 옵셔널데이터를 추출하는 별도의 과정이 필요하다.

if-let

if let 상수 이름 = 추출하고자 하는 옵셔널 변수/상수{
   print(상수 이름)
}else {
    print("데이터가 비었습니다.")
}

위와 같은 형태로 데이터를 추출해서 사용하는것이 제일 안전하다.

let myNumber? = 123

if let myNumber = myNumber {
    print("My number is \(myNumber)")
}
//결과....."My number is 123"

따로 값에 접근한 후에 기존 옵셔널 상수 또는 변수를 참조할 필요가 없다면 같은 이름으로 새로운 상수 또는 변수를 사용할 수 있다

if-let 축약형

let myNumber? = 123

if let myNumber{
    print("My number is \(myNumber)")
}
//결과....."My number is 123"

이전의 코드처럼 변수/상수의 이름이 다르게 설정할 필요가 없는경우 이렇게 생략해서 사용하는것도 가능하다.

여러개를 바인딩

let myNumber1? = 123
let myNumber2? = 456
let myNumber3? = 789

if let myNumber1, let myNumber2, let myNumber3{
    print("My number is \(myNumber1), \(myNumber2), \(myNumber3)")
}
//결과....."My number is 123, 456, 789"

,로 구분해서 여러개의 데이터를 바인딩하는것이 가능하다.

guard-let

옵셔널 바인딩의 경우 if-let이 아니라 guard-let을 사용할 수 있다.

guard란 함수에서 조기종료를 위해 사용하는 if문 이라고 생각하면 된다.

guard를 만족하지 못하면 바로 else에서 오류를 발생시키거나 함수를 종료하는 코드를 작성하는 형태라고 생각하면 된다.

guard let의 경우 if let과는 다르게 조건문 외부에서도 사용이 가능하다.

var opt:Stirng? = "hello"

if let hello = opt else{
    	print("opt is empty")
}
print(hello) // 에러

if let의 경우 if문 밖에서 사용하는것이 불가능 하다.

var opt:Stirng? = "hello"
var hello: String

if let opt{
	hello = opt
}else{
    print("opt is empty")
}

print(hello)

//결과.....hello

if let으로 바인딩한 데이터를 if외부에서 사용하려면 별도의 변수나 상수에 대입을 한 다음에 사용해야 한다.

하지만 guard let은 다르다

var opt:Stirng? = "hello"

func someFunction(){
	guard let hello = name else{
    	return nil
    }
    print(hello)

}

someFunction()

//결과.....hello

이처럼 guard let으로 바인딩 한 데이터는 그 이름 그대로 함수 내부에서 사용이 가능하다.

이것이 if-let과의 큰 차이점이다.

if-var & guard-var

if-let 또는 guard-let의 형태로 옵셔널 바인딩을 했지만 if-var, guard-var의 형태로 옵셔널 바인딩하는것도 가능하다.

차이점으로는 바인딩한 데이터가 변수가 되어 수정하는것이 가능해 진다.

//if-var 예시
var optionalNumber: Int? = 10

if var number = optionalNumber {
    number += 5
    optionalNumber = number
}


//guard-var 예시
func updateName(name: String?) {
    guard var validName = name else {
        print("이름이 없습니다.")
        return
    }
    
    // 변수 값 수정
    validName = validName.uppercased()
    print("업데이트된 이름: \(validName)")
}

let으로 바인딩 하게 되면 위와 같은 형태는 불가능하다.

?? 대체값 사용

옵셔널 바인딩이 많이 쓰이는 형대이고 if-else로 데이터를 경우에 따라 상세하게 처리하기 때문에 옵셔널 바인딩이 좋은 방법이긴 하지만

간단하게 사용하고 싶을땐 코드길이가 길어서 조금 불편할 수 있다 그럴땐 대체값을 지정하는 키워드를 사용하면 된다.

?? 키워드

let name: String? = nil
let greeting = "Hello, " + (name ?? "friend") + "!"

print(greeting)

//결과.....Hello, friend!

이처럼 옵셔널데이터 ?? 대체값 의 형태로 작성하면 nil이 아닌경우 그대로 옵셔널데이터를 사용 할 수 있고 내부에 데이터가 없는 nil인 경우 대체값을 반환하게 된다.

! 강제 언래핑

언래핑이란 말그대로 un wrapping 무언가를 열다 라는 뜻으로 해석된다.

앞서 if-let이나 ?? 으로 옵셔널 데이터를 처리한것을 말한다. 이 경우 데이터가 nil인 경우를 확실히 처리한다.

강제 언래핑의 경우 nil인 경우를 따로 처리하지 않고 옵셔널 데이터를 처리하는 방식을 말한다.(말그대로 강제로 사용하는 것)

만약 nil인 데이터를 강제 언래핑 하는경우 컴파일 단계에서는 오류가 없지만 런타임 단계에서 오류가 발생한다.

사용 방법

그냥 옵셔널 타입의 데이터 이름뒤에 !느낌표를 붙여서 사용하면 된다.

let name: String? = "gil-dong"
let oname: String? = nil

print(name!)
print(oname!) // 런타임 에러

사용하기 간편하지만 앞서 말했던 것처럼 nil인 데이터를 강제 언래핑 하는것은 위험하다.

왠만하면 사용하면 안된다 진짜 nil이 안들어 갈 데이터라는 확신이 있거나 급하게 구현만 하는게 필요한 경우가 아니라면 사용하지 않는것을 권장한다.

암시적으로 언래핑된 옵셔널

프로그램을 작성하다 보면, 옵셔널이 한 번 값이 설정된 이후에는 계속해서 값이 존재할 것이라고 확신할 수 있는 경우가 있다.

이런 상황에서는 매번 옵셔널을 확인하고 언래핑(Unwrapping)하는 과정이 번거로울 수 있다.

이를 해결하기 위해 암시적으로 언래핑된 옵셔널을 사용할 수 있다. 옵셔널이지만, 사용 시에 자동으로 언래핑되어 일반 값처럼 사용할 수 있는 옵셔널이다.

사용방법

var someName: String! = "gildong"

옵셔널을 선언할때 ?를 사용하던 곳에 !느낌표를 작성해주면 된다.

이렇게 암시적으로 언래핑된 옵셔널은 별도의 바인딩없이 일반 변수처럼 사용이 가능하다.

하지만 다른 옵셔널과 마찬가지로 nil이 들어있는경우 데이터를 사용하려고 하면 런타임 단계에서 오류가 발생한다.

물론 위에서 했던 것처럼 if-let을 이용한 옵셔널 바인딩이나 ??을 이용한 대체값을 이용한 안전한 언래핑도 가능하다.

정리

  • 옵셔널타입은 기본적으로 사용할때 변수이름뒤 혹은 타입뒤에 ?물음표를 붙여서 선언한다
  • 옵셔널은 nil을 포함할 수 있는 타입이다.
  • 옵셔널데이터를 사용하기 위해선 옵셔널 바인딩을 통해서 가능하다
  • !키워드를 이용해서 강제로 언래핑해서 데이터 접근이 가능하다.
  • 옵셔널 선언부에서 !를 사용해서 선언하면 바인딩 없이도 데이터 접근이 가능하다.
  • 런타임에러가 발생 할 수 있으니 옵셔널의 접근은 반드시 안전하게 해야한다!!!
profile
iOS 개발자 취준생, 천 리 길도 한 걸음부터

0개의 댓글