Swift Type System
Swift 메타타입 완벽 정리
self, Self, .Type, .self의 차이와 실전 활용법
학습 날짜
2026-07-07
1. 핵심 개념 한눈에 보기
| 표현 | 이것은 | 용도 | 예시 |
|---|---|---|---|
self (소문자) |
현재 인스턴스 | 인스턴스 메서드 내부에서 자기 자신 참조 | self.name |
Self (대문자) |
현재 타입 | 프로토콜/클래스 내부에서 타입 자체 참조 | Self.defaultValue |
Dog.Type |
메타타입 (타입) | 타입 선언에 사용 ("Dog 타입 자체를 담는 타입") | let t: Dog.Type |
Dog.self |
메타타입 값 | 대입/비교에 사용 ("Dog 타입 자체"를 값으로) | t = Dog.self |
핵심 구분
DogvsDog.Type→ 둘 다 타입 (선언용)Dog()vsDog.self→ 둘 다 값 (대입/비교용)
2. self vs Self
class Dog {
var name = "멍멍이"
func printSelf() {
print(self) // 👈 소문자: 현재 "인스턴스"
print(self.name) // "멍멍이"
}
static func printSelfType() {
print(Self.self) // 👈 대문자: 현재 "타입" 자체
}
}
let dog = Dog()
dog.printSelf() // Dog 인스턴스 출력
Dog.printSelfType() // "Dog" 타입 출력
self (소문자)
- 현재 인스턴스를 가리킴
- 인스턴스 메서드 내부에서 사용
self.property,self.method()
Self (대문자)
- 현재 타입을 가리킴
- 프로토콜, 클래스 내부에서 사용
- 상속 시 실제 타입으로 바뀜
3. .Type vs .self
// 일반적인 경우
let dog: Dog = Dog() // dog은 Dog의 "인스턴스"
let dogType: Dog.Type = Dog.self // dogType은 Dog "타입 자체"를 담는 변수
print(type(of: dog)) // Dog
print(type(of: dogType)) // Dog.Type
비유로 이해하기
Dog |
"강아지"라는 개념 (타입 어노테이션용) |
Dog.Type |
"강아지라는 개념을 담는 상자"의 타입 |
Dog.self |
"강아지라는 개념"을 상자에 넣은 실제 값 |
Dog() |
실제 강아지 한 마리 (인스턴스) |
올바른 사용
// 왼쪽은 타입, 오른쪽은 값
let instance: Dog = Dog() // ✅
let metatype: Dog.Type = Dog.self // ✅
잘못된 사용
let wrong1: Dog = Dog.self // ❌ 값 타입 불일치
let wrong2: Dog.Type = Dog() // ❌ 값 타입 불일치
4. 인스턴스에서 .self와 .Type
let a = Dog()
a.self // ✅ 가능 - 그냥 a 자신을 반환 (의미 없음)
a.Type // ❌ 불가능 - 문법 에러!
| 표현 | 가능? | 결과 |
|---|---|---|
Dog.self |
✅ | Dog.Type 값 (타입 자체) |
Dog.Type |
✅ | 메타타입 (타입 선언용) |
a.self |
✅ | a 자신 (의미 없음) |
a.Type |
❌ | 문법 에러 |
type(of: a) |
✅ | Dog.Type 값 (= Dog.self) |
인스턴스의 타입을 알고 싶으면?
type(of: a) // Dog.Type 값 반환 (= Dog.self와 동일)
5. 메타타입 비교
let a = Dog()
type(of: a) == Dog.self // ✅ 비교 가능 → true
type(of: a) == Dog.Type // ❌ 컴파일 에러!
| 표현 | 이것은 | 비교 가능? |
|---|---|---|
type(of: a) |
값 | ✅ |
Dog.self |
값 | ✅ |
Dog.Type |
타입 | ❌ |
왜?
값끼리만 == 비교 가능. 타입은 비교 대상이 아님.
// 비유:
"철수" == "철수" // ✅ 값 == 값
"철수" == String // ❌ 값 == 타입 (말이 안 됨)
6. 메타타입 실전 활용
6.1 타입을 파라미터로 전달
func createAnimal<T: Animal>(type: T.Type) -> T {
return type.init()
}
let dog = createAnimal(type: Dog.self) // ✅ Dog.self를 파라미터로 전달
let cat = createAnimal(type: Cat.self)
// ❌ 잘못된 호출
let wrong = createAnimal(type: Dog.Type) // 컴파일 에러! 타입을 값으로 전달 불가
6.2 JSON 디코딩
func decode<T: Decodable>(_ type: T.Type, from data: Data) -> T? {
return try? JSONDecoder().decode(type, from: data)
}
let user = decode(User.self, from: jsonData)
6.3 셀 등록 (UITableView)
tableView.register(MyCell.self, forCellReuseIdentifier: "cell")
// ^^^^^^^^^ 타입 자체를 전달
7. 실전 예제: 네임스페이스 패턴
카카오페이의 멀티 프레임워크 리소스 관리에서 사용한 패턴:
// 프로토콜 정의
public protocol PayResourceSupports {}
public struct PayResource<Base> {
public let base: Base
public init(_ base: Base) { self.base = base }
}
public extension PayResourceSupports {
// 1번: 타입에서 호출 (static)
static var pay: PayResource<Self>.Type { PayResource<Self>.self }
// 2번: 인스턴스에서 호출
var pay: PayResource<Self> { PayResource(self) }
}
왜 메타타입을 반환하나?
extension PayResource where Base == UIImage {
// static 프로퍼티!
public static var ic_core_message: UIImage {
UIImage(named: "ic_core_message", in: .resourceBundle, compatibleWith: nil)!
}
}
// 사용
imageView.image = .pay.ic_core_message
흐름 분석
UIImage.pay
│
│ static var pay: PayResource<Self>.Type { PayResource<Self>.self }
│ ───────────────────── ─────────────────────────
│ 반환 타입: 메타타입 반환 값: 메타타입 값
│
▼
PayResource<UIImage>.self (= PayResource<UIImage> 타입 자체)
│
│ 타입에서 static 프로퍼티 접근 가능!
│
▼
.ic_core_message → UIImage 인스턴스 반환
인스턴스 반환 vs 메타타입 반환
// 인스턴스를 반환하면:
UIImage.pay // → PayResource<UIImage>() 인스턴스
UIImage.pay.ic_core_message // ❌ static 프로퍼티 접근 불가
// 메타타입을 반환하면:
UIImage.pay // → PayResource<UIImage>.self (타입 자체)
UIImage.pay.ic_core_message // ✅ static 프로퍼티 접근 가능!
8. Q&A
Q:
let dog: Dog = Dog.self 해도 돼?
A: ❌ 안 됩니다. Dog.self는 Dog.Type 타입이고, Dog()는 Dog 타입입니다. 타입이 다릅니다.
Q:
Dog.self가 Dog()랑 같아?
A: ❌ 완전히 다릅니다.
Dog() = 강아지 한 마리 (인스턴스)
Dog.self = "강아지"라는 종 자체 (타입)
Q:
Dog과 Dog.Type은 같아?
A: ❌ 다릅니다.
Dog = 인스턴스의 타입
Dog.Type = 메타타입 (타입 자체를 담는 타입)
Q:
type(of: a) == Dog.Type?
A: ❌ 컴파일 에러. Dog.Type은 타입이라 비교 불가.
✅ type(of: a) == Dog.self 사용 (값 비교)
9. 최종 정리표
| 표현 | 카테고리 | 용도 |
|---|---|---|
self |
값 | 현재 인스턴스 참조 |
Self |
타입 | 현재 타입 참조 (프로토콜/클래스 내부) |
Dog |
타입 | 인스턴스 타입 선언 |
Dog.Type |
타입 | 메타타입 선언 |
Dog() |
값 | 인스턴스 생성 |
Dog.self |
값 | 타입 자체를 값으로 |
type(of: a) |
값 | 인스턴스의 타입을 값으로 |
기억법
- .Type → 타입 (선언용) → 콜론(
:) 왼쪽에 올 수 있음 - .self → 값 (대입/비교용) → 등호(
=) 오른쪽에 올 수 있음