Typealias는 Swift에서 새로운 타입을 정의하지 않고 기존 타입에 대한 대체 이름을 생성하는 선언입니다. 별칭은 컴파일 타임에 원래 타입과 완전히 동일합니다 — 컴파일러는 typealias가 사용된 모든 곳에서 원래 타입을 대체합니다. Swift Language Guide(2025)에 따르면, typealias는 긴 시그니처를 단축하고, 프로토콜에서 associatedtype을 통해 내부 타입을 추상화하며, 복잡한 제네릭 매개변수를 단순화하는 데 사용됩니다. 타입 래퍼와 달리, typealias는 타입 안전성을 추가하지 않습니다 — 타입 시스템이 구분하지 않는 단순한 별칭일 뿐입니다.
핵심 사항
typealias NewName = ExistingType — 모든 수준에서 선언 가능 (전역, 로컬, 타입 내부)typealias Result = Swift.Result<Data, Error>typealias Handler = (Int) -> VoidTypealias는 Swift에서 기존 타입에 대한 대체 이름을 도입하는 선언입니다. typealias를 선언한 후에는 원래 타입이 예상되는 모든 곳에서 새 이름을 사용할 수 있습니다 — 컴파일러는 이들을 동일하게 취급합니다. Typealias는 의미론적 격리를 추가하지 않습니다: UserID 타입(String의 typealias)의 값은 오류 없이 String을 기대하는 함수에 전달될 수 있습니다.
Typealias의 주요 목적은 긴 이름 단축, 타입의 목적 문서화, 구체적 구현 추상화입니다. 예를 들어, typealias JSON = [String: Any]는 딕셔너리가 JSON 구조로 사용됨을 명시적으로 나타내고, typealias Completion = (Result<Data, Error>) -> Void는 복잡한 클로저 시그니처를 읽기 쉬운 타입으로 변환합니다.
Swift.org(2025)에 따르면, typealias는 표준 라이브러리에서 널리 사용됩니다. 예를 들어, String은 String의 typealias입니다(특화된 Array<Character>). 최신 Swift 버전에서는 이 구현이 숨겨져 있습니다. Void는 빈 튜플 ()의 typealias로, 함수 시그니처를 더 읽기 쉽게 만듭니다.
타입의 의미론을 문서화하기 위해 typealias를 사용하세요. 하지만 동일한 기본 타입의 다른 개념이 혼합되는 것을 방지하지는 않는다는 점을 기억하세요. 타입 안전한 분리를 위해 래퍼(struct wrapper)를 사용하세요.
Typealias는 키워드 typealias로 선언되며, 그 뒤에 새 이름, 등호, 기존 타입이 옵니다. 기본 형태:
typealias Name = ExistingType
typealias UserID = Int
typealias JSONDictionary = [String: Any]
Typealias의 범위는 선언된 위치에 따라 결정됩니다:
| 수준 | 예시 | 가시성 |
|---|---|---|
| 전역 | typealias Name = String | 전체 모듈 (액세스 제어 적용) |
| 타입 내부 | struct User { typealias ID = Int } | User.ID — 타입을 통해 접근 가능 |
| 함수 내부 | func f() { typealias Local = Int } | 함수 내부에서만 |
| 프로토콜 내부 | protocol P { associatedtype T } | 채택 시 지정 |
타입 내부의 Typealias(예: User.ID)는 관련 별칭을 그룹화하는 일반적인 패턴입니다. 이는 네임스페이싱을 개선합니다: Order.ID와 User.ID는 모두 Int이지만 다른 개념으로 읽힙니다. 중첩된 typealias에 대한 접근은 User.ID를 통해 또는 타입이 알려진 경우 점 표기법을 통해 이루어집니다.
Typealias의 가장 일반적인 용도 중 하나는 클로저 시그니처를 단순화하는 것입니다. Swift의 클로저 타입은 특히 Optional 및 제네릭 매개변수와 함께 사용될 때 번거로울 수 있습니다. Typealias는 (Data?, Error?) -> Void를 읽기 쉬운 FetchResultHandler로 변환합니다:
typealias FetchResultHandler = (Data?, Error?) -> Void
func fetchUser(id: Int, completion: FetchResultHandler) {
// network request
completion(data, nil)
}
Ray Wenderlich Style Guide에 따르면, 클로저용 typealias는 메서드 시그니처의 가독성을 향상시킵니다. 특히 위임 프로토콜 및 콜백 패턴에서 유용합니다. 그러나 과도한 별칭은 피하세요 — 클로저가 한 곳에서만 사용되는 경우 인라인으로 선언할 수 있습니다.
Swift 표준 라이브러리는 이 접근 방식을 적극적으로 사용합니다. 예를 들어, DispatchQueue.WorkItem은 DispatchWorkItem의 typealias이지만, 외부에서는 별도의 타입처럼 보입니다. 클로저용 Typealias는 가독성 도구입니다 — 남용하지 마세요: 모듈당 3~5개의 클로저 별칭이 합리적인 한계입니다.
Typealias는 제네릭 매개변수를 포함할 수 있어, 제네릭 타입의 특화된 버전을 만듭니다. 이는 Result, Publisher 및 표준 라이브러리와 Combine의 다른 제네릭 타입을 다룰 때 특히 유용합니다:
typealias FetchResult = Result<Data, Error>
typealias AnyPublisherOfData = AnyPublisher<Data, Error>
func loadData() -> FetchResult {
// data loading
}
원래 타입으로 전달되는 사용자 정의 제네릭 매개변수가 있는 typealias를 만들 수도 있습니다:
typealias NetworkResult<T> = Result<T, NetworkError>
func fetchUser() -> NetworkResult<User> {
// ...
}
중요한 규칙: typealias는 새로운 제네릭 제약 조건(where 절)을 추가할 수 없습니다 — 매개변수를 원래 타입으로 전달만 합니다. 추가 제약 조건이 필요한 경우 제네릭 struct 또는 class를 만드세요. Swift by Sundell(2024)에 따르면, 제네릭이 있는 typealias는 Combine, Result 및 async/await를 많이 사용하는 프로젝트에서 반복적인 시그니처를 단축하는 이상적인 방법입니다.
Associatedtype은 프로토콜 내부에 선언된 typealias로, 연관 타입을 정의합니다. 일반 typealias와 달리, associatedtype은 선언 시점에 특정 타입에 바인딩되지 않습니다 — 프로토콜을 채택하는 각 타입에 의해 지정됩니다:
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
}
struct IntBox: Container {
typealias Item = Int
// implementation
}
struct StringBox: Container {
typealias Item = String
// implementation
}
Associatedtype은 선언 지점에 구체적인 타입을 지정하지 않고 프로토콜에 제네릭 타입의 유연성을 제공합니다. 이는 많은 Swift 패턴의 기초입니다: Collection(Element), IteratorProtocol(Element), Identifiable(ID). 컴파일러는 구현에서 associatedtype을 자동으로 추론할 수 있으므로, 명시적인 typealias Item = Int는 종종 생략됩니다 — Swift는 메서드 append의 매개변수에서 Item을 Int로 추론합니다.
Swift Evolution SE-0195(2022)에 따르면, associatedtype을 포함하는 프로토콜을 다루기 위해 불투명 결과 타입(some Container)이 도입되었습니다 — 이는 이러한 프로토콜을 변수 타입으로 사용하지 못하게 했던 PAT(연관 타입이 있는 프로토콜) 문제를 해결했습니다.
핵심 차이점: Typealias는 기존 타입의 다른 이름일 뿐인 반면, 래퍼(wrapper)는 원본과 의미론적으로 격리된 새로운 타입입니다. typealias UserID = Int를 선언하면 UserID와 Int는 상호 교환 가능합니다 — Int를 기대하는 함수가 오류 없이 UserID를 받아들입니다.
래퍼는 struct를 통해 생성되며 진정한 타입 안전성을 제공합니다:
struct UserID: RawRepresentable {
let rawValue: Int
}
struct OrderID: RawRepresentable {
let rawValue: Int
}
// Compilation error: cannot pass OrderID where UserID is expected
Point-Free(2025)에 따르면, 다른 개념이 동일한 기본 타입(UserID vs OrderID)으로 표현될 때 래퍼가 선호됩니다. Typealias는 격리 없이 가독성을 목표로 할 때 정당화됩니다: 긴 이름 단축, 의미론 문서화, associatedtype을 통한 구현 추상화. 가독성을 위해 typealias를, 타입 안전성을 위해 래퍼를 선택하세요.
자주 묻는 질문
Typealias는 특정 기존 타입의 별칭입니다. Associatedtype은 프로토콜 내부에 선언되며 프로토콜을 채택하는 각 타입에 의해 지정됩니다 — 다른 타입이 동일한 프로토콜에 대해 다른 associatedtype을 사용할 수 있습니다.
아니요, typealias는 단지 대체 이름일 뿐입니다. 컴파일러는 컴파일 타임에 이를 원래 타입으로 대체합니다. 새롭고 의미론적으로 격리된 타입을 만들려면 struct 래퍼 또는 rawValue가 있는 enum을 사용하세요.
네, typealias는 제네릭 매개변수를 포함할 수 있습니다: typealias Result<T> = Swift.Result<T, Error>. 제네릭 매개변수는 원래 타입으로 전달됩니다. Where 제약 조건은 추가할 수 없습니다 — 이를 위해서는 제네릭 struct를 사용하세요.
모든 수준에서 가능합니다: 전역(파일 내), 타입 내부(struct/class/enum), 함수 내부, 프로토콜 내부(associatedtype으로). 범위는 선언 위치에 의해 결정됩니다 — 전역 typealias는 전체 모듈에 표시되고, 로컬 typealias는 해당 범위 내에서만 표시됩니다.
원래 타입과의 상호 교환성이 안전한 경우, 긴 이름 단축 및 의미론 문서화를 위해 typealias를 선택하세요. 동일한 기본 타입(UserID vs ProductID)의 다른 개념이 실수로 혼합되는 것을 방지해야 하는 경우 래퍼(struct)를 선택하세요.
요약
typealias NewName = ExistingType, 범위 — 전역, 타입 내부, 함수 내부typealias Handler = (Int) -> Void턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.