Swift

2023년 9월 19일 수정

Swift Programming Language

Swift(스위프트)는 애플 주도로 개발된 프로그래밍 언어로 정적 타이핑(Static Typing)을 특징으로 하는 바이너리 컴파일이 가능한 언어다. 이를 돌려서 타입 안전성(Type Safety)을 고려하는 언어 라고도 하는데, 빌드 타임에 타입이 확정되지 않으면 무조건 에러로 간주하는 단순하면서도 문제를 미연에 방지하기에 합리적인 시스템이기도 하다.

그 밖에 스위프트의 가장 큰 특징으로는 값 타입(Value Type)을 지원한다는 점이 있다. 값 타입의 지원은 완벽한 Immutable 변수를 지원하기 때문에 레퍼런스 공유로 발생하게 되는 다양한 부작용을 해소하면서도 동시에 성능 또한 잡아낸 설계이기도 하다.

Swift는 macOS, iOS, watchOS, tvOS를 위한 강력하고 직관적인 프로그래밍 언어입니다. Swift 코드 작성은 대화식으로 재미있고, 구문은 간결하면서도 표현력이 풍부하며, Swift에는 개발자들이 좋아하는 첨단 기능이 포함되어 있습니다. Swift 코드는 안전하게 설계되었으며 빛의 속도로 빠르게 실행되는 소프트웨어도 제작할 수 있습니다.

애플 공식 스위프트 홈페이지에서는 위와 같이 설명하고 있긴 한데, 오픈소스라서 굳이 플랫폼이나 앱 타입에 구애는 받지 않는 언어라고 봐도 될 것 같다. 그리고 빛의 속도는 좀 오버고, 네이티브 바이너리로 빌드가 되기 때문에 빠르긴 빠르지만 아무래도 최적화된 C 코드에 비하기는 힘들 것이다.

대신 Objective-C와 같이 쓰기에 상당히 편한 언어이기에 C 나 C++ 코드를 함께 쓰기도 어렵지 않다. 따라서 최적화도 굉장히 손쉬운 편에 속한다.

개념 메모

메서드 디스패치(Method Dispatch)

상속 관계의 메서드 디스패치는 OOP에 상식적이다.

class P {
    func foo() { ... }
}

class C: P {
    override func foo() { ... }
}

let obj1 = C()
obj1.foo()   // C.foo()

let obj2: P = C()
obj2.foo()   // C.foo()

뭐 그다지 어려울 것도 없고 OOP에 익숙하다면 당연한 결과다.

프로토콜의 경우는 상속과는 좀 다른 면이 있다.

protocol P {
    func foo()
}

extension P {
    func foo() { ... }
    func bar() { ... }
}

struct A: P {
    func foo() { ... }
    func bar() { ... }
}

let a = A()
a.foo()   // A.foo()
a.bar()   // A.bar()

let p: P = A()
p.foo()   // A.foo()
p.bar()   // P.bar()

여기서는 프로토콜의 extension으로 정의된 기본 구현체가 이 프로토콜을 따르는 구조체의 동일한 이름의 구현체보다 높은 우선순위를 가지고 있다는 것을 알 수 있다. 다르게 말하자면 extension의 디스패치 테이블이 A 구조체의 테이블보다 우선 검색된다는 말이 된다. 이 부분은 아무래도 클래스 상속과는 다르기 때문에 주의가 필요할 것 같다.

아래는 메서드 디스패치 관련 지시어다:

final
클래스의 경우 이 final 이 붙게 되면 더 이상 상속이 되지 않는다. 다르게 말해서 final class는 동적 디스패치 기능을 없애버린 것과 비슷하다.
dynamic
final 과 반대되는 것 같은 dynamic 은 정말 반대되는 의미다. 다이내믹인 경우 Swift 인스턴스가 아니게 된다. NSObject 를 상속 받은 것과 비슷한 상태가 되기 때문이다. 덕분에 무거워진다. 하지만 메시지 디스패치를 사용할 수 있어서 KVO(Key-Value Observing)가 가능해지게 된다.
@objc
@objcObjective-C 네임스페이스에 등록 시켜서 메시지 디스패치가 가능하게 해 준다. 반대로 @noobjc 는 메시지 디스패치를 못 하게 막아버린다.
@inline
인라인(inline)은 말 그대로 호출을 하지 않고 컴파일 타임에 아예 구현체를 그대로 넣어버리는 무시무시한(?) 다이렉트 디스패치와 비슷한 것이다.

그 외의 사소한 팁

큰 숫자 표현하기

밑줄(underscore)을 이용하면 큰 숫자의 가독성을 좋게 만들 수 있다.

let krw = 2_9000_0500  // 2억 9천 5백만
let usd = 1_135_010    // 1 million 135 thousand 10

일부만 Import 하기

import struct SwiftUI.Image
import class UIKit.UIImage
import class AppKit.NSImage

그냥 할 수도 있다는 거지 굳이 이렇게 쓸 필요는 없을지도 모른다.😏

외부 링크

종합 가이드

써드파티 모듈

  • Alamofire: HTTP 요청이 필요할 때 사용하는 유명한 모듈이다.
  • Kingfisher: 이미지 캐시
  • KeychainAccess: 이름 처럼 키체인에 뭔가를 저장하거나 불러오는 기능을 제공한다.