Swift 기본문법

이재원·2024년 6월 23일
0

Swift

목록 보기
1/13
post-thumbnail
post-custom-banner

기본(The basics)

타입 세이프티와 타입 추론

Swift는 타입 세이프(type-safe)한 언어예요. 그래서 컴파일할 때 코드에서 타입이 맞지 않으면 오류를 내줍니다. 또한, Swift는 타입을 추론할 수 있어서 모든 상수와 변수에 타입을 일일이 지정할 필요는 없어요. 예를 들어, 정수와 부동소수점을 함께 사용하면 Swift는 자동으로 Double 타입으로 추론합니다.

타입 별칭(Type Aliases)

타입 별칭은 기존의 타입에 새로운 이름을 붙여주는 기능입니다. 예를 들어볼까요?

typealias AudioSample = String

var audioName: AudioSample = "audio"

이렇게 하면 AudioSample이라는 이름으로 String 타입을 사용할 수 있어요. 이후에 AudioSample이 마치 새로운 타입인 것처럼 사용할 수 있는 거죠.

튜플(Tuples)

튜플은 여러 값을 하나로 묶을 때 사용합니다. 각각의 값이 어떤 타입이든 상관없고, 같은 타입일 필요도 없어요.

let http404Error = (404, "Not Found")

이렇게 HTTP 상태 코드와 메시지를 하나로 묶어서 사용할 수 있죠. 또, 튜플을 분해해서 사용할 수도 있어요

let (statusCode, statusMessage) = http404Error

print("The status code is \(statusCode)")
print("The status message is \(statusMessage)")

이런 식으로 튜플의 값을 쉽게 분해해서 사용할 수 있답니다. 튜플의 요소에 이름을 붙여 더 편하게 접근할 수도 있어요

let http200Status = (statusCode: 200, description: "OK")

print("The status code is \(http200Status.statusCode)")
print("The status message is \(http200Status.description)")

튜플은 간단한 데이터 묶음을 표현할 때 유용하지만, 복잡한 구조를 나타낼 때는 클래스나 구조체를 사용하는 게 더 좋습니다.

옵셔널(Optionals)

옵셔널은 값이 있을 수도, 없을 수도 있음을 나타내는 타입입니다. 값이 없으면 nil로 표현하죠.

let possibleNumber: String = "123"
let convertedNumber: Int? = Int(possibleNumber)

여기서 Int?는 옵셔널 타입을 나타내며, possibleNumber가 숫자 문자열이면 Int로 변환하고, 그렇지 않으면 nil을 반환합니다.

nil

옵셔널 변수는 nil을 가질 수 있어요. 이 말은, 변수에 값이 없음을 나타낼 때 nil을 사용할 수 있다는 뜻입니다.

var serverResponseCode: Int? = 404
serverResponseCode = nil

이렇게 옵셔널로 선언한 변수는 값을 넣거나 nil로 비울 수 있어요.

옵셔널 바인딩(Optional Binding)

옵셔널 바인딩은 옵셔널에 값이 있는지 확인하고, 그 값을 안전하게 꺼내 사용할 수 있게 해줍니다.

if let actualNumber = convertedNumber {
    print("The string \"\(convertedNumber)\" has an integer value of \(actualNumber)")
} else {
    print("The string \"\(convertedNumber)\" could not be converted to an integer")
}

이 코드에서는 convertedNumber에 값이 있는지 확인하고, 값이 있으면 actualNumber에 할당해서 사용하는 방법입니다. 이런 과정을 옵셔널 바인딩이라고 해요.

대체값 제공(Providing a Fallback Value)

옵셔널 값이 없을 때 기본값을 제공하고 싶다면, nil-결합 연산자(??)를 사용하면 됩니다

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

여기서는 namenil이면 "friend"라는 기본값이 사용됩니다.

강제 언래핑(Force Unwrapping)

강제 언래핑은 옵셔널을 강제로 풀어주는 방법이에요. 변수 뒤에 느낌표(!)를 붙이면 되는데, nil일 경우 런타임 에러가 발생할 수 있으니 주의해야 해요.

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

let number = convertedNumber!
print("number: \(number)")
// Prints number: 123

강제 언래핑은 nil이 아닌 경우에만 안전하게 사용할 수 있습니다. nil일 가능성이 있다면 옵셔널 바인딩이나 nil 결합 연산자를 사용하는 게 더 안전해요.

암시적으로 언래핑된 옵셔널(Implicitly Unwrapped Optionals)

때로는 옵셔널 값을 항상 갖고 있다고 확신할 수 있을 때, 일일이 언래핑하지 않고 자동으로 언래핑되게 할 수 있습니다. 이걸 암시적으로 언래핑된 옵셔널이라고 해요.

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // Unwrapped automatically

하지만 조심해야 해요. 만약 assumedStringnil이라면 접근할 때 에러가 발생할 수 있거든요.

에러 처리(Error Handling)

Swift에서는 에러가 발생할 수 있는 상황을 처리할 수 있도록 에러 핸들링 기능을 제공해요. throws 키워드를 사용해 에러를 던질 수 있고, do-try-catch 구문을 사용해 그 에러를 처리할 수 있습니다.

func makeASandwich() throws {
    // this function may or may not throw an error
}

do {
    try makeASandwich()
    eatASandwich() // 에러가 없을 경우 실행
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

이처럼 에러가 발생할 수 있는 코드를 try로 감싸고, 에러가 발생하면 catch 블록에서 처리합니다.

에러 처리의 다양한 방법

Swift에서는 에러를 처리하는 다양한 방법이 있어요

  1. try?: 에러가 발생하면 nil을 반환해요. 간단하게 결과만 필요할 때 유용합니다.

    let result = try? someThrowingFunction()
  2. try!: 에러가 발생하지 않음을 확신할 때 사용해요. 에러가 발생하면 프로그램이 크래시할 수 있으니 주의해야 해요.

    let result = try! someThrowingFunction()
  3. rethrows: 함수 자체는 에러를 던지지 않지만, 전달받은 클로저가 에러를 던질 수 있을 때 사용해요. 예를 들어, 고차 함수가 클로저를 파라미터로 받을 때 rethrows를 사용합니다.

    func someFunction(callback: () throws -> Void) rethrows {
        try callback()
    }

역설과 전제조건(Assertions and Preconditions)

코드가 올바르게 작동하는지 확인하기 위해 AssertionsPreconditions를 사용할 수 있어요. 이 두 가지는 코드가 예상치 못한 상황에서 어떻게 반응할지 확인하는 데 유용해요.

Assertions

Assertions는 주로 개발 중에 잘못된 상태를 감지하는 데 사용돼요. 예를 들어, 나이가 음수가 될 수는 없겠죠? 이럴 때 assert로 조건을 걸어두는 겁니다.

let age = -3
assert(age >= 0, "A person's age can't be less than zero.")
// 이 Assertion은 -3이 0보다 크지 않기 때문에 실패합니다.

이렇게 하면 디버깅할 때 논리적인 오류를 쉽게 발견할 수 있어요.

Preconditions

PreconditionsAssertions와 달리 프로덕션 코드에서도 반드시 지켜져야 하는 조건을 검사해요. 예를 들어, 배열의 인덱스가 범위를 벗어나면 안 되겠죠?

// 배열의 인덱스를 접근하기 전에 반드시 인덱스가 유효한지 검사
precondition(index >= 0 && index < array.count, "Index out of bounds")

이렇게 해서 잘못된 인덱스 접근을 방지할 수 있답니다.

Assertions과 Preconditions의 차이

  • Assertions: 디버그 빌드에서만 실행돼요. 주로 개발 중에 예상치 못한 상황이나 논리 오류를 감지할 때 사용합니다. 프로덕션 빌드에서는 무시돼요.
  • Preconditions: 디버그 빌드와 프로덕션 빌드 모두에서 실행돼요. 실제 프로그램이 작동할 때 반드시 충족되어야 하는 조건을 확인합니다.

정리하자면, Assertions는 개발 중 논리 오류를 조기에 발견하기 위해 사용하고, Preconditions는 프로덕션 코드의 안전성을 보장하기 위해 필수 조건을 확인할 때 사용해요. 각각의 목적에 맞게 잘 활용하면 코드를 더 안전하게 만들 수 있습니다.

Swift 기본 개념 요약

  1. 타입 세이프티와 타입 추론

    • Swift는 타입 세이프(type-safe)한 언어로, 컴파일 시 타입 오류를 잡아줌.
    • 타입 추론 기능이 있어, 모든 변수나 상수에 타입을 명시할 필요 없음.
  2. 타입 별칭(Type Aliases)

    • typealias 키워드를 사용해 기존 타입에 새 이름을 부여할 수 있음.
  3. 튜플(Tuples)

    • 서로 다른 타입의 여러 값을 하나로 묶어 그룹화.
    • 튜플의 각 요소에 이름을 부여해 쉽게 접근 가능.
  4. 옵셔널(Optionals)

    • 값이 있을 수도, 없을 수도 있음을 나타내는 타입으로, 값이 없을 때 nil로 표현.
    • 옵셔널 바인딩을 통해 안전하게 값을 언래핑 가능.
  5. nil

    • 옵셔널 변수에 값을 넣지 않은 상태를 나타내며, nil로 표현.
  6. 강제 언래핑(Force Unwrapping)

    • 옵셔널 값 뒤에 !를 붙여 강제로 값을 언래핑. nil일 경우 런타임 에러 발생 가능.
  7. 암시적으로 언래핑된 옵셔널(Implicitly Unwrapped Optionals)

    • 옵셔널 값을 항상 갖고 있다고 확신할 때, 자동으로 언래핑됨. 하지만 nil일 경우 에러 발생.
  8. 에러 처리(Error Handling)

    • throws 키워드를 사용해 에러를 던지고, do-try-catch 구문으로 처리.
    • try?, try!, rethrows를 사용해 다양한 에러 처리 방법 제공.
  9. Assertions

    • 디버그 빌드에서 잘못된 상태를 감지하기 위해 사용. 조건이 충족되지 않으면 프로그램 종료.
  10. Preconditions

    • 프로덕션 코드에서 반드시 지켜져야 하는 조건을 검사. 디버그와 프로덕션 빌드에서 모두 사용.
  11. Assertions과 Preconditions의 차이

    • Assertions: 디버그 빌드에서만 사용, 논리 오류 감지.
    • Preconditions: 디버그 및 프로덕션 빌드 모두에서 사용, 필수 조건 검증.

출처
이 글은 swift 공식문서를 읽고 정리한 내용입니다.
https://bbiguduk.gitbook.io/swift/language-guide-1/the-basics

profile
20학번 새내기^^(였음..)
post-custom-banner

0개의 댓글