← 아카이브로 돌아가기

Development · Swift

if let과 guard let으로 옵셔널 안전하게 다루기

옵셔널 값을 안전하게 꺼내는 if let과 guard let의 제어 흐름과 사용 기준을 비교합니다.

Velog 원문 보기 ↗

Development 아카이브 표지

옵셔널을 꺼내는 두 문법은 결과만 보면 비슷하지만 이후 코드가 흐르는 방향은 정반대다. 조건 안에서 짧게 사용할지, 실패를 먼저 끝내고 정상 흐름을 이어갈지에 따라 선택이 달라진다.

if let

조건문 안의 옵셔널 값이 nil인지 체크하고, 각 경우에 대한 처리를 안전하게 수행한다. 보통 각 조건에 따른 처리를 위해 사용되지만, else문을 생략하고 사용할 수 있다. 옵셔널 바인딩 된 상수 if문 안에서만 사용할 수 있다.

struct UnwrapStudy: View {
    
    @State var currentUserID: String? = "Snack"
    @State var displayText: String? = nil
    @State var isLoading: Bool = false
    
    var body: some View {
        VStack {
        	// displayText가 nil이 아닌 경우
            if let text = displayText {
                Text(text)
                    .font(.title)
            }
            if isLoading {
                ProgressView()
            }
        }
        .onAppear {
            loadData()
        }
    }
    
    func loadData() {
		// currentUserID가 nil이 아닌 경우
        if let userID = currentUserID {
            isLoading = true
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                displayText = "The username is \(userID)."
                isLoading = false
            }
        // currentUserID가 nil인 경우
        } else {
            displayText = "There is no user data."
        }
    }
}

guard let

  • 블록 내부에서만 사용되며, 옵셔널 값을 체크하여 nil인 경우에 대한 처리를 guard 절 안에서 바로 수행한다.
  • return, break, continue, throw 등의 제어문 전환 명령어를 필수로 입력한다.
  • 옵셔널 바인딩 된 상수를 else문을 제외한 블록 내에서 사용할 수 있다.
  • 예외사항 처리를 먼저 수행하여 코드의 안정성과 가독성이 향상된다.
struct UnwrapStudy: View {
    
    @State var currentUserID: String? = "Snack"
    @State var displayText: String? = nil
    @State var isLoading: Bool = false
    
    var body: some View {
        VStack {
	        // displayText가 nil이 아닌 경우
            if let text = displayText {
                Text(text)
                    .font(.title)
            }
            if isLoading {
                ProgressView()
            }
        }
        .onAppear {
            loadData()
        }
    }
    
    func loadData() {
        guard let userID = currentUserID else {
        	// currentUserID가 nil인 경우
            displayText = "There is no user data."
            return // 함수 종료
        }
        // currentUserID가 nil이 아닌 경우
        isLoading = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            displayText = "The username is \(userID)."
            isLoading = false
        }
    }
}
← 아카이브로 돌아가기