Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
Tags
- Observable
- 클로드코드
- ios
- uiscrollview
- MVVM
- Xcode
- swiftUI
- 스위프트
- claude code
- UICollectionView
- HIG
- combine
- 리펙토링
- UITextView
- 클린 코드
- uitableview
- RxCocoa
- Human interface guide
- map
- Protocol
- clean architecture
- tableView
- Clean Code
- 리팩토링
- swift documentation
- collectionview
- SWIFT
- Refactoring
- 애니메이션
- rxswift
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS] Swift6 개념 (옵트인, 데이터 레이스 안정성, Default Actor Isolation, Approachable Concurrency) 본문
iOS 응용 (SwiftUI)
[iOS] Swift6 개념 (옵트인, 데이터 레이스 안정성, Default Actor Isolation, Approachable Concurrency)
jake-kim 2026. 9. 14. 00:21swift6 세팅
- swift6는 xcode16부터 지원
- Xcode > targets > Build Settings > swift compiler - Language에서 swift6 선택

swfit6는 옵트인 모드
- 패키지/모듈 단위로 swift6를 적용할 수 있음
- 아래처럼 swiftLanguageMode(.v6)으로 적용 가능
- 모듈별 점진적 마이그레이션이 설계 의도
// Package.swift
.target(name: "MyLib", swiftSettings: [.swiftLanguageMode(.v6)])
데이터 레이스란?
- 두 개 이상의 스레드가 동시에 동일한 메모리 공간에 접근할 때 발생하며, 다음 조건이 모두 충족되는 상태를 의미
- 동시성: 둘 이상의 스레드가 동시에 메모리에 접근
- 동일 메모리: 최소 하나의 작업이 해당 메모리에 값을 쓰는(Write) 작업을 수행
- 동기화 부재: 뮤텍스(Mutex), 락(Lock), 또는 원자적 연산(Atomic) 같은 동기화 메커니즘이 전혀 없음
- Swift5에서는 데이터 레이스 위험이 있음
Default Actor Isolation 옵션
- swift 6.2에서 추가된 기능
- 코드 대부분이 어차피 메인 스레드에서 돌기 때문에, 타입/함수마다 @MainActor를 일일이 붙여야만 했었음
- 아래 사진처럼 `MainActor`로 작성하면 @MainActor를 따로 붙이지 않아도 타입/함수/변수가 자동으로 @MainActor인 것처럼 취급됨
- swift 6에서부터는 데이터레이스를 해치는 코드가 발견되면 Sendable을 붙이라는 컴파일 에러가 나기 때문에 이렇게 설정해준것 (이미 진행중인 프로젝트에 swift6 마이그레이션을 쉽게해주기 위함)

ex)
// Default Actor Isolation = MainActor 일 때
class Counter { // 암묵적으로 @MainActor
var n = 0
func bump() { n += 1 }
}
func test() { // 암묵적으로 @MainActor
let c = Counter()
Task { c.bump() } // 메인 액터 상속 → 안전, 에러 없음
}
- @MainActor라는 것은 동시성을 안쓴다는 의미이고, 만약 동시성이 필요하면 @concurrent를 명시적으로 붙여서 사용
@concurrent로 명시적으로 벗어남
@concurrent
func heavyWork() async {
// 여기는 메인 액터가 아님, 백그라운드에서 돎
}
Approachable Concurrency 옵션
- Swift 6.2에서 "6.0이 너무 빡빡하다"는 피드백에 대응해, 관련된 여러 개선(SE-0461 등)을 정식 Swift 7 도입 전에 조기 체험할 수 있게 묶어놓은 것
Approachable Concurrency (Yes) ← 상위 스위치, 여러 기능의 묶음
├─ Default Actor Isolation 선택 가능해짐 ← 그 중 하나
├─ nonisolated async 함수가 호출자 격리 상속 (SE-0461)

- Approachable Concurrency = "이 묶음 기능들을 쓸지 말지" (on/off 스위치, 선택 항목을 노출시키는 게이트)
- Default Actor Isolation = "그 안에서, 기본 격리값을 뭘로 할지" (MainActor / nonisolated 중 선택)
swfit6 제대로 알아가기
- swift6는 데이터 레이스 안정성을 위해 컴파일 에러를 활용하는데, 이건 default actor isolation을 nonisolated로 하여, 어떤것들이 컴파일 에러가 나고, 데이터 레이스 안정성을 위해 어떤 코드를 추가해야하는지 알아볼 것
- Default Actor Isolation을 nonisolated로 설정
- 아래처럼 코드를 작성하면 컴파일 에러 발생

에러 내용
Sending value of non-Sendable type '() async -> ()' risks causing data races

class Counter {
var n = 0
func bump() { n += 1 }
}
let c = Counter()
Task { c.bump() } // 스레드 A
Task { c.bump() } // 스레드 B
- 에러가나는 이유?
- n += 1은 사실 세 단계: 읽기 → 더하기 → 쓰기.
- 두 스레드가 동시에 실행하면:
A: n 읽음 (0)
B: n 읽음 (0) ← A가 아직 안 썼음
A: 1 씀
B: 1 씀 ← A의 작업이 사라짐
- 결과는 2가 아니라 1. 이게 데이터 레이스
- 100번 중 99번은 잘 돌고, 하필 사용자 기기에서만 터지며, Swift 5에서는 컴파일러가 이걸 전혀 막아주지 않았음
- Swift 6는 위 코드를 아예 컴파일 에러로 만들어서 해결
- 핵심 아이디어: `isolation` (격리 구역)
- main actor 구역을 만들고, actor 하나당 하나씩만 접근하게 만듦 (그 외 아무데도 속하지 않는 코드는 nonisolated라고 표현)
- actor 구역 내부는 안전하며, 구역 경계를 넘어갈 때문 위험하니, 넘어가는 값이 안전한지 검사하는 것이 Swift6의 핵심
- 이걸 위한 키워드: Sendable / actor / @MainActror
Sendable, actor @MainActor에 관한 글은 다음 포스팅 글에서 계속..
'iOS 응용 (SwiftUI)' 카테고리의 다른 글
| [iOS] Swift6 개념 (actor, Sendable, @MainActor, @unchecked Sendable) (1) | 2026.09.23 |
|---|---|
| [iOS - SwiftUI] 앱 아이콘과 리퀴드글래스 (#Icon Composer, foreground layer, background layer, .icon) (0) | 2026.01.07 |
| [iOS - SwiftUI] Sticky Header 구현 방법 (Sticky 헤더, List 사용) (1) | 2025.12.31 |
| [iOS - SwfitUI] 탭했을 때 키보드 내리는 법 (simultaneousGesture를 쓸때 주의할 점) (0) | 2025.12.17 |
| [iOS - swift] 4. VScode 단축키 모음 (+깃헙 코파일럿) (0) | 2025.11.19 |
Comments