728x90
반응형

이전에 옵셔널 체이닝에 대해서 다루었던 것이 기억난다.
옵셔널 체이닝은 옵셔널 내부의 내부의 내부로 옵셔널이 연결되어 있을 때 유용하게 활용할 수 있다.
매번 nil 을 확인하지 않아도 최종적으로 원하는 값이 있는지 없는지 확인할 수 있다.
이렇게 말하면 이해가 잘 되지 않으니 예제를 통해 알아봐야겠다.

옵셔널 체이닝 | Optional Chaining

우선, 두 개의 클래스를 만들었다.

class Person {
    var name: String
    var job: String?
    var home: Apartment?
    
    init(name: String) {
        self.name = name
    }
}

class Apartment {
    var buildingNumber: String
    var roomNumber: String
    var `guard`: Person?
    var owner: Person?
    
    init(dong: String, ho: String) {
        buildingNumber = dong
        roomNumber = ho
    }
}

각 옵셔널 타입의 매개변수를 지정해주었고 옵셔널 타입이 아닌 변수는 인스턴스 생성과 동시에 초기값을 넣어주려고 한다.
각 클래스를 사용해서 인스턴스를 생성해보았다.

let jay: Person? = Person(name: "jay")
let apart: Apartment? = Apartment(dong: "36", ho: "48")
let superman: Person? = Person(name: "superman")

그럼 여기서 우리집의 경비원에 대해서 알고 싶다면
옵셔널 체이닝을 사용하지 않았을 때 다음과 같이 확인해볼 수 있다.

// 만약 우리집의 경비원이 궁금하다면???
// 옵셔널 체이닝을 사용하지 않을 경우
func guardJob(owner: Person?) {
    if let owner = owner {
        print("집주인은 \(owner.name) 입니다.")
        if let home = owner.home {
            print("집은 \(home) 입니다.")
            if let `guard` = home.guard {
                print("우리집 경비원은 \(`guard`) 입니다.")
                if let guardJob = `guard`.job {
                    print("우리집 경비원의 직업은 \(guardJob) 입니다.")
                } else {
                    print("우리집 경비원은 직업이 없습니다.")
                }
            } else {
                print("경비원이 없습니다.")
            }
        } else {
            print("집이 없습니다.")
        }
    } else {
        print("집주인이 없습니다.")
    }
}

========== 출력 결과 ==========
집주인은 jay 입니다.
집이 없습니다.

각각의 값을 조건문으로 비교해서 있는지 없는지 찾아야 한다.
결과를 보면 owner의 home 의 값이 없기 때문에 nil 을 반환하고 함수가 종료된 것을 확인할 수 있다.

이렇게 값의 여부를 확인하려면 각각의 값을 비교해야 한다.
하지만 옵셔널 체이닝을 사용하면 보다 쉽게 비교해 값을 가져올 수 있다.

옵셔널 체이닝을 사용해서 다음과 같이 확인해볼 수 있다.

// 옵셔널 체이닝을 사용했을 때
func guardJobWithOptionalChaining(owner: Person?) {
    if let guardJob = owner?.home?.guard?.job {
        print("우리집 경비원의 직업은 \(guardJob) 입니다.")
    } else {
        print("우리집 경비원은 직업이 없어요")
    }
}

guardJobWithOptionalChaining(owner: jay)

========== 출력 결과 ==========
우리집 경비원은 직업이 없어요

위와 같이 옵셔널 체이닝을 사용해서 앞에서부터 값을 비교해 나간다.
onwer 의 값이 있다면, onwer 내부의 home 의 값의 여부를 확인한다. 만약 없다면 nil 을 반환한다.
home 의 값이 있다면, home 내부의 guard의 값의 여부를 확인한다. 만약 없다면 nil 을 반환한다.
guard의 값이 있다면, guard 내부의 job의 값의 여부를 확인한다. 만약 없다면 nil 을 반환한다.

위에서 옵셔널 체이닝을 사용하지 않을 때와 같이 home 의 값이 없기 때문에 nil 을 반환하고 else 내부의 결과를 출력하게 된다.

확실히 옵셔널 체이닝을 사용할때와 아닐때의 소스 코드가 간결해진 것을 확인할 수 있다.
매 번 값을 확인하지 않고 한 번에 확인할 수 있다는 점이다.

옵셔널 체이닝을 통해 값을 확인하는 과정을 값을 할당하면서 확인해보았다.

jay?.home?.guard?.job // nil

jay?.home = apart
jay?.home // Optional(Apartment)

home 의 값이 nil 이었기 때문에 home 에 apart 라는 값을 할당해주었다.
그리고 nil 이 아닌 옵셔널 타입의 Apartment 의 값이 할당된 결과를 확인할 수 있었다.

jay?.home?.guard // nil

// 경비원 할당
jay?.home?.guard = superman
jay?.home?.guard // Optional(Person)

그 다음으로 guard 의 값이 nil 이므로 값을 할당해주었다.
superman 이라는 값을 할당해주었고 옵셔널 타입의 Person 의 값이 할당된 결과를 확인할 수 있었다.

jay?.home?.guard?.name // superman
jay?.home?.guard?.job // nil

jay?.home?.guard?.job = "경비원"
jay?.home?.guard?.job // 경비원

그래서 name의 값이 superman 으로 할당되었고 job 은 여전히 nil 값을 반환한다.
그래서 "경비원" 이라는 값을 할당해주었고 할당된 값을 확인했다.

nil 병합 연산자

그럼, nil 값을 반환할 때마다 매 번 값을 할당해줄 수는 없다.
그래서 nil 병합 연산자를 통해서 값을 할당해줄 수 있다.

nil 병합 연산자는 중위 연산자다.
?? , 물음표 두개를 사용해서 표현한다. 예) 옵셔널 ??  값
옵셔널 값이 nil 일 경우, 우측의 값을 반환한다.
그리고 띄어쓰기에 주의해야 한다.

그럼 nil 병합 연산자를 통해서 값을 할당해보자.

var guardJob: String
guardJob = jay?.home?.guard?.job ?? "슈퍼맨"

// nil 이 아니기 때문에 "경비원"의 값이 출력된다.
print(guardJob) // 경비원

?? 라는 연산자를 통해 nil 일 경우 "슈퍼맨" 이라는 값을 할당하도록 했다.
하지만 위에서 경비원의 직업에는 "경비원" 이라는 값을 할당해주었기 때문에
nil 의 값을 반환하지 않아 "슈퍼맨" 의 값이 할당되지 않고 "경비원" 이라는 값이 출력되었다.

그래서 해당 값을 nil 로 만들어 다시 확인해보았다.

jay?.home?.guard?.job = nil

guardJob = jay?.home?.guard?.job ?? "슈퍼맨"
// 경비원 직업은 nil 로 해주었기 때문에 "슈퍼맨"의 값이 할당된다.
print(guardJob) // 슈퍼맨

경비원의 직업을 nil 로 만든 후 nil 병합 연산자를 통해서 값을 할당해주었다.
job 이 nil 이므로 "슈퍼맨" 의 값이 할당된 것을 확인할 수 있었다.

 

 

- 참고 사이트 -

www.edwith.org/boostcamp_ios/lecture/11311/

 

[LECTURE] 23. 옵셔널 체이닝과 nil 병합 : edwith

:: 옵셔널 체이닝과 nil 병합 연산자 ::  1. 옵셔널 체이닝 옵셔널 체이닝은 옵셔널의 내부의 내부의 내부로 옵셔널이 연결되어 있을 때 유용하게 활용할 수 있습니다. 매번 n... - 부스트코스

www.edwith.org

 

728x90
반응형
복사했습니다!