
Swift의 ~Copyable
Swift 6(및 Swift 5.9)부터 새롭게 등장한 ~Copyable 키워드는, Swift 개발자들에게 "값 타입도 이제 move-only(복사 금지, 이동 전용)로 만들 수 있다"는 혁신을 가져왔습니다.
1. ~Copyable, 왜 등장했을까?
기존 Swift는 struct와 enum의 값(인스턴스)을 아무 제약 없이 자유롭게 복사할 수 있었습니다. 대부분은 큰 문제가 없지만, 고유한 리소스(예: 파일 디스크립터, 보안 키 등)처럼 '정확히 하나'만 존재해야 하는 값 타입(struct, enum)으로 안전하게 관리하기란 어려웠죠.
Swift 6 이전에는 이런 리소스를 관리하려면 class와 deinit을 써야 했습니다. 하지만 class는 참조 카운팅에 의존하며, 값 타입의 효율이나 안전성(특히 스레드 안정성)을 온전히 얻지 못했습니다.
~Copyable은 struct와 enum에서 유니크한 리소스의 소유권을 코딩으로 명확하게 관리하자라는 취지에서 도입된 키워드입니다.
2. ~Copyable의 기본 개념
- ~Copyable은 "이 타입은 복사하지 마!"라는 약속입니다.
- 즉, 복사 없이 "이동(move)"만 가능합니다.
- move-only 타입으로 선언하면, 값을 변수에 대입하거나 함수에 넘기는 순간 소유권(ownership)이 통째로 넘어가고, 이전 변수는 더 이상 쓸 수 없습니다.
예) 은행 OTP 토큰처럼 하나만 존재해야 하고 복사되면 위험한 값
struct OneTimeToken: ~Copyable {
let value: String
consuming func use() {
print("토큰 사용: \(value)")
// 여기서 self는 완전히 소모됨
}
}
var token = OneTimeToken(Value: "SECRET")
token.use()
// token.use() // 컴파일 에러 발생함 -> token은 이미 소모 됐으므로
3. ~Copyable의 문법과 사용법
1) 선언 방법
struct MyResource: ~Copyable {
// ...
}
enum MyOption: ~Copyable {
// ...
}
struct, enum에만 사용 가능(class는 지원 X, class는 deinit으로 메모리/리소스 관리)
2) 소유권 이동 및 소비
- "이동(move)"하면 이전 변수는 더 이상 사용 불가
var a = MyResource()
var b = a // 소유권이 a에서 b로 이동
// print(a) // 에러 발생, a는 이미 이동 됐으므로
- 함수 인자로 사용할 때: 명확한 소유권 선언 필요
- consuming 파라미터: 소유권 가져가서 이전 변수는 못 씀
- inout: 소유권을 잠시 빌려썼다가 돌려줌
- borrowing: 값을 잠깐 빌려쓰지만 소유권 이동 X (읽기 전용)
func process(consuming resource: MyResource) {
// resource 사용하고 나서 resource 자체도 소모됨
}
var r = MyResource()
process(consuming: r) // r은 여기서 소모되어 이후 사용 불가
4. ~Copyable은 어떤 때 유용할까?
- 파일 디스크립터, 시스템 핸들 같은 고유 리소스를 값 타입으로 안전하게 관리하고 싶을 때
- 암호화 키 등 복사 금지가 중요한 데이터를 구조체로 만들고 싶을 때
- 데이터 경쟁이나 중복 없이, 구조체의 효율과 Swift의 안정성을 최대한 살릴 때
5. 실전 예제: FileDescriptor
struct FileDescriptor: ~Copyable {
private var fd: Int32
init(fd: Int32) {
self.fd = fd
}
func write(data: Data) {
data.withUnsafeBytes { buffer in
_ = Darwin.write(fd, buffer.baseAddress!, buffer.count)
}
}
deinit {
close(fd) // 소유권이 이동된 곳에서만 close 호출
}
}
func processFile(consuming fd: FileDescriptor) {
// fd를 안전하게 사용(소비 후 fd는 사라짐)
}
이렇게 하면 fd가 여러 군데서 close 되는 버그나, 시스템 리소스 누수 없이 오직 하나만 안전하게 관리됩니다.
6. ~Copyable 요약
| 특징 | 설명 |
| 대상 | struct, enum(class는 X) |
| 주요 효과 | 값 복사 금지, 이동만 가능(move-only) |
| 도입 목적 | 유니크 리소스 소유권, 값 타입 효율, 안정성 |
| 실제 사용 예 | 파일 디스크립터, 보안 키, 시스템 핸들 등 |
7. 참고하기 좋은 영상
https://developer.apple.com/videos/play/wwdc2024/10170/
Consume noncopyable types in Swift - WWDC24 - Videos - Apple Developer
Get started with noncopyable types in Swift. Discover what copying means in Swift, when you might want to use a noncopyable type, and how...
developer.apple.com
도움: Perflexity
'iOS > Common' 카테고리의 다른 글
| iOS 앱의 메모리 사용량 최적화 (0) | 2024.04.03 |
|---|---|
| iOS에서의 동시성 처리 방식 - GCD, Operation Queue 그리고 Actor (0) | 2024.04.02 |
| iOS 메모리 관리와 최적화 (0) | 2024.04.01 |
| Swift의 메모리 구조 (0) | 2024.03.29 |
| iOS 운영체제: 프로세스, 스레드, 메모리 관리, 샌드박스 이해하기 (0) | 2024.03.27 |