← Study Hub

09 · Swift 6 마이그레이션

컴파일러 버전·언어 모드·strict 레벨은 서로 다른 스위치
진행률
0 / 0 완료

← 문항 인덱스

면접 질문
  1. 컴파일러 버전을 올리는 것과 언어 모드를 올리는 것의 차이는?
  2. 마이그레이션 중 만나는 대표적 경고(글로벌 가변 변수, non-Sendable 캡처 등)의 해결 패턴은?

답변 ① — 서로 다른 세 개의 스위치 🔥 핵심

흔히 두 개로 뭉뚱그리지만, 실제로 관련된 스위치는 세 개이고 서로 독립입니다.

이 셋을 조합하면 결과는 이렇게 갈립니다.

그래서 "Swift 6 컴파일러만 깔면 경고가 뜬다"는 strict 레벨을 올렸을 때만 맞는 말이고, 컴파일러 버전을 올리는 것과 언어 모드를 올리는 것은 전혀 다른 스위치입니다. 정석 순서는 언어 모드를 5로 둔 채 strict를 minimal → targeted → complete로 올리며 경고를 다 잡고, 마지막에 타깃별로 언어 모드를 6으로 전환하는 것입니다.

세 스위치는 서로 다른 노브다 (Package.swift)
// swift-tools-version: 6.0        ← ① 툴체인/매니페스트 버전

.target(
    name: "MyApp",
    swiftSettings: [
        .swiftLanguageMode(.v5),                                    // ② 언어 모드 = 5 → 진단은 '경고'
        .enableExperimentalFeature("StrictConcurrency=complete")     // ③ strict 레벨 = complete
    ]
)

// ②를 .v6 로 올리는 순간, 같은 진단이 '에러'가 되어 빌드가 막힌다.
// 그래서 ③으로 경고를 먼저 다 잡은 뒤 ②를 올리는 것이 정석.

답변 ② — 격리하거나, 스냅샷을 뜨거나, 임시로 막는다

대표 경고별 해결 패턴은 다음과 같습니다.

⚠️ 주의

경고를 없애려고 @MainActor를 아무 데나 붙이는 것은 안티패턴입니다. 무거운 작업까지 메인에서 돌게 되어 성능이 나빠집니다. 다만 app 타깃이라면 Swift 6.2의 Default Actor Isolation = MainActor가 경고를 가장 크게 줄여 주는 정당한 레버입니다(대부분의 앱 코드는 실제로 메인에서 도니까요).

대표 경고 3종 해결 패턴 (Swift)
// ① 글로벌 가변 변수
enum Config { nonisolated(unsafe) static var shared: Config? }   // 최후의 수단
// → 더 나은 방법: let + Sendable, 또는 @MainActor / actor 로 격리

// ② non-Sendable 캡처 — 캡처 리스트로 불변 스냅샷을 뜬다
var query = "swift"
Task { [query] in
    await search(query)          // 가변 변수가 아니라 복사된 값을 캡처
}

// ③ 서드파티 non-Sendable
@preconcurrency import OldLibrary   // 임시 조치 + 사유 주석 + 제거 티켓

쉽게 이해하기

(질문 ①) 스위치가 세 개라고 생각하면 쉬워요. 학교 시험에 비유해 볼게요.

그러니까 도구만 바꾸면 잔소리도 별로 안 나오고, 깐깐함을 올리면 잔소리가 많아지고, 규칙까지 바꾸면 통과가 필수가 됩니다. 세 개를 한꺼번에 다 세게 하면 벌점 폭탄을 맞아서 아무것도 못 해요. 요령은 깐깐함을 조금씩 올리며 잔소리를 하나씩 다 고치고, 맨 마지막에 규칙을 강하게 바꾸는 겁니다.

(질문 ②) 잔소리를 고치는 방법도 세 가지예요. 아무나 못 바꾸게 못 박거나(불변으로 만들기), "이건 이 방에서만 만져"라고 방을 정해주거나(actor·MainActor로 격리), 그것도 안 되면 사진을 찍어서 그 사본만 들고 가는 거예요(캡처 스냅샷). 남의 라이브러리라 내가 못 고칠 때는 "일단 이건 넘어가자"라고 표시해 두되, 반드시 나중에 치울 메모를 남깁니다.

🔑 한 문장

도구 교체 ≠ 규칙 강화. 경고로 먼저 다 잡고, 에러는 맨 마지막에 켠다.