Swift Optionals and Error Handling

옵셔널 개념과 활용 (Optional Concept and Usage)

옵셔널 개념 (Understanding Optionals)

옵셔널은 값이 있을 수도 있고 없을 수도 있는 변수를 나타내는 Swift의 기능입니다. 옵셔널은 변수의 타입 뒤에 ?를 붙여 선언합니다.

var optionalString: String? = "Hello"
print(optionalString)  // Optional("Hello")

optionalString = nil
print(optionalString)  // nil

옵셔널 값의 활용 (Using Optional Values)

옵셔널 값에 접근하려면 강제 언래핑(!)을 사용하거나, 안전하게 접근하기 위해 옵셔널 바인딩을 사용합니다.

var optionalNumber: Int? = 42
if optionalNumber != nil {
    print("The number is \(optionalNumber!)")
} else {
    print("The number is nil")
}
// "The number is 42"

옵셔널 바인딩과 nil 병합 연산자 (Optional Binding and Nil-Coalescing Operator)

옵셔널 바인딩 (Optional Binding)

옵셔널 바인딩을 통해 안전하게 옵셔널 값을 추출할 수 있습니다. if let 또는 guard let을 사용합니다.

var optionalName: String? = "Alice"

if let name = optionalName {
    print("Hello, \(name)!")
} else {
    print("No name provided.")
}
// "Hello, Alice!"

guard let은 주로 함수 내부에서 early exit를 위해 사용됩니다.

func greet(_ name: String?) {
    guard let name = name else {
        print("No name provided.")
        return
    }
    print("Hello, \(name)!")
}

greet(optionalName)  // "Hello, Alice!"
greet(nil)           // "No name provided."

nil 병합 연산자 (Nil-Coalescing Operator)

nil 병합 연산자(??)를 사용하면 옵셔널 값이 nil일 때 기본 값을 제공할 수 있습니다.

let defaultName = "Guest"
var optionalUserName: String? = nil

let userName = optionalUserName ?? defaultName
print(userName)  // "Guest"

optionalUserName = "Bob"
let anotherUserName = optionalUserName ?? defaultName
print(anotherUserName)  // "Bob"

에러 처리 방법 (Error Handling Methods)

에러 처리 소개 (Introduction to Error Handling)

Swift에서는 에러를 던지고, 포착하고, 전파하여 에러를 처리할 수 있습니다. 에러는 Error 프로토콜을 준수하는 타입으로 표현됩니다.

enum FileError: Error {
    case fileNotFound
    case unreadable
    case encodingFailed
}

do-catch를 이용한 에러 처리 (Error Handling with do-catch)

do-catch 구문을 사용하여 에러를 처리할 수 있습니다.

func readFile(fileName: String) throws {
    if fileName.isEmpty {
        throw FileError.fileNotFound
    }
    // 파일 읽기 코드
    print("File read successfully.")
}

do {
    try readFile(fileName: "")
} catch FileError.fileNotFound {
    print("File not found.")
} catch {
    print("An unexpected error occurred: \(error).")
}
// "File not found."

try와 try? 그리고 try! (try, try?, and try!)

에러를 던지는 함수 호출에는 try 키워드를 사용합니다. try?를 사용하면 에러가 발생할 경우 nil을 반환하고, try!를 사용하면 에러를 무시하고 강제로 언래핑합니다.

func fetchDataFromServer() throws -> String {
    throw FileError.unreadable
}

// try?
let data = try? fetchDataFromServer()
print(data)  // nil

// try!
let forceData = try! fetchDataFromServer()
print(forceData)  // 런타임 에러 발생

에러 전파 (Propagating Errors)

에러를 호출자에게 전파하려면 throws 키워드를 사용합니다.

func processFile(fileName: String) throws {
    try readFile(fileName: fileName)
}

do {
    try processFile(fileName: "")
} catch {
    print("Failed to process file: \(error).")
}
// "Failed to process file: fileNotFound"

에러 처리 예제 (Error Handling Examples)

예제 1: 사용자 정의 에러와 에러 처리

enum NetworkError: Error {
    case invalidURL
    case noConnection
    case timeout
}

func fetchResource(from url: String) throws -> String {
    guard url == "https://valid.url" else {
        throw NetworkError.invalidURL
    }
    // 리소스 가져오기 코드
    return "Resource Data"
}

do {
    let data = try fetchResource(from: "https://invalid.url")
    print("Data received: \(data)")
} catch NetworkError.invalidURL {
    print("Invalid URL.")
} catch {
    print("An unexpected error occurred: \(error).")
}
// "Invalid URL."

예제 2: 옵셔널 바인딩과 에러 처리

func loadData(for userID: String) -> String? {
    guard userID == "validID" else {
        return nil
    }
    return "User Data"
}

func processData(for userID: String) {
    if let data = loadData(for: userID) {
        print("Data: \(data)")
    } else {
        print("No data available.")
    }
}

processData(for: "invalidID")  // "No data available."
processData(for: "validID")    // "Data: User Data"

이와 같이 Swift에서 옵셔널과 에러 처리의 개념과 활용, 옵셔널 바인딩과 nil 병합 연산자, 다양한 에러 처리 방법을 상세히 설명하고 다양한 예제를 제공했습니다.

Leave a Reply

Your email address will not be published. Required fields are marked *