Optional

추니·2022년 3월 21일
0

Optional이란 무엇인가?

  • 값이 존재할 수도 있고, 없을 수도 있는 경우를 표현하기 위해 Swift에서 제공하는 문법이다.

Optional이 왜 필요할까?

프로그래밍을 하다보면 많은 에러를 마주한다. Optional은 발생할 수 있는 에러를 최소화하기 위해 존재한다. 어떤 상황에서든 값이 있다, 없다를 나눠서 많은 에러들을 안전하게 처리하기 위해 사용한다.

예를 들면, 어떤 데이터가 값이 없는 경우가 생길 수 있고 프로그램 상에서 그 데이터에 접근하게 되면 에러가 발생하게 된다. 이 에러를 미연에 방지하고자 만들어 둔 문법이라 할 수 있다.

"데이터 값을 Optional이라는 베일에 감싸둔다" 라는 표현이 괜찮을 것 같다.

데이터가 값을 가지고 있는지 값이 없는지 Optional 베일에 싸다보니 결과적으로 우리가 실제 데이터를 활용하기 위해서는 감싸진 값을 꺼내서 활용해야한다.

이 때 감싸진 값을 접근하는 방법에는 4가지 방법이 있다.

옵셔널 바인딩, 옵셔널 체이닝, 강제추출, nil 병합 연산자

Optional Binding

if let 구문을 통해 optional을 벗길 값이 nil일 경우 구문 안 블록을 실행할 수 있고, nil일 경우 else 구문 또는 if let 블록 외부의 코드가 실행된다.

guard let 구문은 if let구문과 반대로, optional을 벗길 값이 nil이면 else구문의 블록을 실행하고, nil이 아니라면 다음 코드가 실행된다.

그럼 언제 if let을 쓰고, 언제 guard let을 쓰냐?

if let구문과 guard let의 가장 큰 차이점은 if let구문을 통해 optional을 벗긴 값은 if let 블록 내부에서만 사용가능하다.
하지만 guard let의 경우, 이후 코드라인에서도 사용가능하다.

func optionalBinding() {
	if let optional을 벗긴 값 = optional을 벗길 값 {
    	// "optional을 벗길 값"이 nil이 아니라면
        // 여기서 "optional을 벗긴 값"을 사용할 수 있다.
	}
    // 근데 여기서는 "optional을 벗긴 값"을 사용할 수 없다!
    
    guard let optional을 벗긴 값 = optional을 벗길 값 else {
    	// "optional을 벗길 값"이 nil일 경우 이 블록이 실행된다.
        return
	}
    // "optional을 벗길 값"이 nil이 아닐 경우 이후 코드에서 "optional을 벗긴 값"을 사용할 수 있다.
}

Optional Chaining

Optional Chaining은 계층적으로 깊이 있는 Optional 타입에서 활용하는 경우, 특히 메소드를 사용하는 경우 많이 사용한다.

struct Person {
	var name: string
    var home: String?
}

let chuuuny: Person? = Person(name: "chuuuny", home: "서울")

func optionalBinding() {
	guard let chuuuny = chuuuny, let home = chuuuny.home else {
    	return
	}
}

func optionalChaining() {
	guard let home = chuuuny?.home else {
    	return
	}
}

Optional Binding을 통해 추니가 어디에 살고 있는지 알아내기 위해서는 추니의 집이 있는지, 집이 있다면 어떤 집인지를 해야한다. (optionalBinding 메소드)
하지만 위와 같이 2개 이상의 Optional Binding은 Optional Chaining을 통해 깔끔하게 처리할 수 있다.

Nil Coalescing Operator

Nil Coalescing Operator는 왼쪽의 옵셔널 값이 nil일 경우 대체값을 정해줄 수 있는 연산자이다.

func nilCoalescingOperator() {
    // chuuny가 nil이라면 Person 객채를 새로 생성한다.
	let chuuny = chuuny ?? Person(name: "chuuny", home: "경기도")
    
    // chuuny의 home이 nil이라면 chuuuny의 home을 "경기도" 으로 대체한다.
    let home = chuuny.home ?? "경기도"
}

Forced Unwrapping

말 그대로 Optional로 감싸진 값이 있는지 nil인지 확인도 하지 않고 벗겨버리는 방식이다.

당장은 빠르고 쉽게 값을 추출할 순 있지만, 벗길 값이 nil일 경우 런타임 에러가 발생한다.

func forcedUnwrapping() {
	let chuuuny = chuuuny!
    let home = chuuuny.home!
}

Forced Unwrapping은 왠만하면 쓰지마세요!!!

Optional 비교하기

옵셔널 공부하다가 새롭고 흥미로운 것을 찾았다.

let a: Int? = Optional(10)
let b: Int = 10

print(a == b) // true

실제로 위와 같이 true가 나온다!

Optional로 감싸진 값과 그냥 값이 어떻게 비교 가능할까?

이는 Swift Github의 Optional 구현 코드를 보면 알 수 있다.
Swift Github

간단하게 설명하자면 Optional이 아닌 값이 비교될 때 Optional 값으로 감싸진 후 비교를 한다!

@inlinable
  public static func ==(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
  	switch (lhs, rhs) {
    case let (l?, r?):
    	return l == r
    case (nil, nil):
    	// 둘다 nil인데 값이 true? 이건 좀 신기하네용 ㅋㅋ
      	return true
    default:
      	return false
	}
}
profile
iOS 개발자가 되고싶어요

0개의 댓글