Skip to content

필사 모드: Modern Swift 2026 — Swift 6.1 / SwiftUI 6 / SwiftData / Vapor 4 / Hummingbird 2 / swift-testing / Android Swift Deep Dive

English
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

Prologue — Eleven years after Objective-C left the building

When Chris Lattner unveiled Swift at WWDC 2014, the audience reacted more with a sigh than applause. "Objective-C was a 30-year-old burden, but a battle-tested burden. Do we really have to learn another language?" That was June 2014. Eleven years later in May 2026, the question has evaporated. Nearly all iOS, macOS, watchOS, visionOS, and tvOS code is Swift. Objective-C survives only in pockets of SDK internals and legacy code; every new project starts in Swift from day one. And now Swift is venturing beyond Apple platforms — onto Linux servers, Android, embedded MCUs, and even Windows.

This post draws the map of the Swift ecosystem as it stands in May 2026. The language (Swift 6.1, Swift 6.2 preview), UI (SwiftUI 6, SwiftData), server (Vapor 4, Hummingbird 2), tools (Tuist, Mint, SwiftPM), code quality (swift-syntax, swift-format, SwiftLint, SwiftFormat), testing (swift-testing), new frontiers (Android Swift WG, Embedded Swift, swift-foundation rewrite), and where Korean and Japanese shops actually use it (Kakao, LINE, Mercari, Cookpad, CyberAgent, pixiv). Which tool when, why strict concurrency is the real change, and whether Swift can really survive outside Apple's walls.

1. Modern Swift in 2026 — the strict concurrency era of Swift 6

One-line summary. **The defining feature of Swift in 2026 is "data races caught at compile time."** Swift 6.0 (September 2024) flipped strict concurrency on by default, Swift 6.1 (2025) stabilized the complete mode, and Swift 6.2 preview promises an even smoother actor migration. Where C++, Rust, and Go each solved concurrency safety their own way, Swift settled on the actor model + the Sendable protocol + the isolated keyword + region-based isolation.

Coordinates of Swift in 2026.

| Area | Status (2026.05) | Representative tool |

| --- | --- | --- |

| Language | Swift 6.1 stable | swift.org / Xcode 16 |

| Language (preview) | Swift 6.2 in Xcode 17 beta | swift.org |

| UI framework (Apple) | SwiftUI 6 (iOS 18 / macOS 15) | Apple SDK |

| Data (Apple) | SwiftData GA | Apple SDK |

| Server (de facto standard) | Vapor 4 | vapor.codes |

| Server (Apple SSWG-backed) | Hummingbird 2 | hummingbird.codes |

| Package manager | swift-package-manager | swift.org |

| Project generation | Tuist 4 | tuist.io |

| CLI tool installation | Mint | github.com/yonaskolb/Mint |

| Macros / AST | swift-syntax | github.com/swiftlang/swift-syntax |

| Formatter (Apple official) | swift-format | github.com/swiftlang/swift-format |

| Formatter (community) | SwiftFormat | github.com/nicklockwood/SwiftFormat |

| Linter | SwiftLint | github.com/realm/SwiftLint |

| Testing (new) | swift-testing (Swift 6.0+) | swift.org |

| Testing (legacy) | XCTest | Apple SDK |

| Android | Android Swift WG (2024.11) | swift.org/android-workgroup |

| Embedded | Embedded Swift | swift.org/embedded |

| Standard library rewrite | swift-foundation | github.com/swiftlang/swift-foundation |

Three core insights.

First, **strict concurrency is the identity of Swift 6.** async/await landed in Swift 5.5, the actor model stabilized in 5.7, strict concurrency arrived opt-in in 5.10. Swift 6.0 made it the default, and compiling old code suddenly emits hundreds or thousands of warnings at once. That migration cost is real — but once you pass through, you get a compile-time guarantee against data races. Apple internally is walking the same road, and externally large iOS shops like Airbnb, Lyft, and Uber are running multi-year migrations.

Second, **Swift is increasingly moving outside Apple.** Vapor has been holding up server-side Swift since 2016, but November 2024's launch of the Android Swift Working Group made the non-Apple track official. Embedded Swift appeared at the 2024 WWDC keynote with a demo running on STM32 with a 16KB binary. swift-foundation is the rewrite of Objective-C-based NSFoundation in pure Swift, in full swing since 2024.

Third, **the tooling ecosystem has shifted from fragmentation to convergence.** swift-format (Apple official) and SwiftFormat (Nick Lockwood) coexist, and SwiftLint (Realm) holds the linter chair, but Apple standardizing swift-syntax means everyone uses the same AST. CocoaPods → Carthage → SwiftPM migration is mostly complete, and SwiftPM is the default for new projects. Tuist filled the gap between SwiftPM and Xcode and has settled into monorepos and multi-target setups.

2. Swift 6.1 — complete mode + raw identifiers

Swift 6.1 was a maintenance + feature release that landed in spring 2025. Two core changes.

**First, the strict concurrency "complete" mode is stable.** Swift 6.0 turned strict concurrency on by default, but the project still picks where on the minimal/targeted/complete ladder to sit. In 6.1, complete mode's false positives and diagnostic quality improved significantly. Sendable inference in particular got smarter, so more legacy code can now be proved safe without explicit `@Sendable` annotations.

**Second, raw identifiers.** Identifiers wrapped in backticks can now contain spaces and special characters. Decisive when you want to name test functions in natural language.

@Test func `a user receives a token after logging in`() async throws {

let user = User(email: "test@example.com")

let token = try await login(user)

#expect(!token.isEmpty)

}

// Works for regular functions too

func `compute checksum for v2 protocol`(_ data: Data) -> UInt32 {

// ...

}

Paired with swift-testing this lets you write Korean or Japanese test names naturally, which is part of why iOS teams at Kakao and LINE are likely adopters.

Smaller changes in Swift 6.1.

- **Stronger `@MainActor` inference** — subclasses of UIView/UIViewController are inferred as `@MainActor` automatically.

- **Explicit `nonisolated(unsafe)`** — the escape hatch for knowingly disabling isolation now has an explicit form.

- **typed throws GA** — `func foo() throws(MyError)`. Type-safe error propagation, similar in spirit to Rust's `Result`.

- **package manager noncopyable types support** — `~Copyable` generics are now first-class in SPM package interfaces.

// typed throws

enum NetworkError: Error {

case timeout

case unauthorized

}

func fetch(_ url: URL) async throws(NetworkError) -> Data {

// ...

}

// Caller catches exactly NetworkError

do {

let data = try await fetch(url)

} catch .timeout {

// ...

} catch .unauthorized {

// ...

}

typed throws calls Java's checked exceptions to mind, but Swift's implementation is lighter — it's just a generic. The bare `throws` is modeled as sugar for `throws(any Error)`.

3. Swift 6.2 preview — concurrency improvements

Swift 6.2 is in preview targeting GA in fall 2026. It ships in Xcode 17 beta. The headline direction is one thing — **make strict concurrency feel more like a default than a feature.**

The most common complaint about 6.0/6.1 has been "simple code suddenly gets data-race warnings." 6.2 sands those friction points down.

**1) Expanded default `@MainActor` inference.** Beyond UI code, SwiftUI Views, ViewModel patterns, and Combine publishers are inferred as `@MainActor` automatically. New projects will write almost entirely `@MainActor` code, and only when you explicitly mark `nonisolated` or another actor isolation does the code drop into a worker context.

**2) Stronger Sendable inference.** A struct or enum becomes Sendable automatically when all of its stored properties are Sendable. The change started in 6.1, but 6.2 extends it to cross-module inference.

**3) Improved `async let` / TaskGroup diagnostics.** The most common mistake is "capturing a value and passing it to a task where the value is not Sendable." 6.2 tracks more precisely which variable escapes to which task, and fix-its are friendlier.

**4) `Span` / `RawSpan` types.** Borrowed-view types analogous to Rust's `&[T]` and `&str`. Lighter than ArraySlice, enabling safe zero-copy data access.

// Swift 6.2 preview

extension Array {

func sumFirstHalf() -> Element where Element: Numeric {

let half: Span<Element> = self.span.prefix(self.count / 2)

return half.reduce(0, +)

}

}

**5) C++ interop stabilization.** Swift-to-C++ bidirectional interop gets another level of polish in 6.2. Dependency graphs, template instantiation, and RAII mapping smooth out. This is not just a tooling improvement — it's positioning Swift as a language you can incrementally introduce into an existing C++ codebase.

The slogan for 6.2 is "strict concurrency becomes invisible." Well-written code should let the developer write safe code with almost no isolation annotations at all.

4. SwiftUI 6 (iOS 18) — Mesh gradient / scroll position / View Transition

SwiftUI 6 shipped in fall 2024 alongside iOS 18 / macOS 15 / visionOS 2, and stability patches landed throughout 2025. The three most visible new features.

**1) Mesh gradient.** Place colors on a 2D mesh grid and interpolate between them. Far more expressive than linear or radial gradients — you can finally draw the smooth color transitions you usually saw only in Sketch or Figma, natively in SwiftUI.

struct MeshDemo: View {

var body: some View {

MeshGradient(

width: 3,

height: 3,

points: [

.init(0, 0), .init(0.5, 0), .init(1, 0),

.init(0, 0.5), .init(0.5, 0.5), .init(1, 0.5),

.init(0, 1), .init(0.5, 1), .init(1, 1),

],

colors: [

.red, .purple, .blue,

.orange, .white, .cyan,

.yellow, .green, .mint,

]

)

.ignoresSafeArea()

}

}

**2) Scroll position binding.** Two-way binding between the `ScrollView`'s scroll position and a `@State` value. Without resorting to the old imperative `contentOffset` API you can scroll to a specific row and observe where the user is currently scrolled — declaratively.

struct ScrollDemo: View {

@State private var scrollPosition = ScrollPosition(idType: Int.self)

var body: some View {

ScrollView {

LazyVStack {

ForEach(0..<100, id: \.self) { i in

Text("Row \(i)")

.id(i)

}

}

.scrollTargetLayout()

}

.scrollPosition($scrollPosition)

.safeAreaInset(edge: .top) {

Button("Top") { scrollPosition.scrollTo(id: 0) }

}

}

}

**3) View Transition.** What people called "hero animation" — shared-element transitions between screens — landed cleanly without selectors. Pair `matchedTransitionSource` with `navigationTransition` and it just works inside NavigationStack navigation.

@Namespace var ns

NavigationLink(value: photo) {

Image(photo.thumb)

.matchedTransitionSource(id: photo.id, in: ns)

}

.navigationDestination(for: Photo.self) { photo in

PhotoDetail(photo: photo)

.navigationTransition(.zoom(sourceID: photo.id, in: ns))

}

**4) Smaller things.**

- `@Entry` macro — define Environment keys in a single line.

- `TabView` rewrite — sidebar adaptive, fluid customization.

- `Charts` improvements — 3D charts, vector-based annotations.

- `Subview` API — a new way to index child views, applicable to general view trees beyond ForEach.

After iOS 18.4, the Translation framework integrated with SwiftUI and added a view modifier that translates on-screen text on-device. It depends on Apple Intelligence so it doesn't run on every device — but for apps that handle Korean and Japanese it's compelling.

5. SwiftData — the Core Data successor

Core Data is Apple's ORM, shipped with macOS 10.4 Tiger in 2005. Solid, but full of old patterns like NSManagedObject and NSFetchRequest from the Objective-C era. SwiftData aims for the same chair as a Swift-native successor; it was announced at iOS 17 in 2023 and stabilized through 2024-2025. As of May 2026, SwiftData is the default for new projects.

The core of SwiftData — **defining a class with the `@Model` macro turns it into a persistent class automatically.**

@Model

final class Note {

var title: String

var body: String

var createdAt: Date

@Relationship(deleteRule: .cascade) var tags: [Tag]

init(title: String, body: String, tags: [Tag] = []) {

self.title = title

self.body = body

self.createdAt = .now

self.tags = tags

}

}

@Model

final class Tag {

@Attribute(.unique) var name: String

init(name: String) { self.name = name }

}

Inside SwiftUI you read with `@Query` and write with `modelContext.insert()`.

struct NoteList: View {

@Query(sort: \Note.createdAt, order: .reverse) var notes: [Note]

@Environment(\.modelContext) var modelContext

var body: some View {

List(notes) { note in

VStack(alignment: .leading) {

Text(note.title).font(.headline)

Text(note.body).lineLimit(2)

}

}

.toolbar {

Button("Add") {

modelContext.insert(Note(title: "New", body: ""))

}

}

}

}

Under the hood Core Data is still running. SwiftData is just a Swift-native layer over Core Data — so incremental migration from a Core Data-based app is possible. iCloud sync (CloudKit) still works as is.

SwiftData's limitations — through 2025 the most common complaint was performance. Large datasets (100K+ rows) saw `@Query` evaluated on the main thread, blocking the UI, and the undo manager would unintentionally pile every change onto its stack. Patches through iOS 18.x made it much better, but for a large catalog app you might still consider Core Data directly.

Other options.

- **GRDB.swift** — Swift-native ORM over SQLite. Light without the Core Data dependency.

- **Realm** — stable since the MongoDB acquisition, but new adoption is dropping.

- **Supabase Swift SDK** — when you want the backend bundled.

- **Drizzle ORM (server Swift side)** — when handling Postgres on the server.

For small data in iOS apps (under 10MB, under 10K rows) SwiftData is the default. Above that, look at GRDB.

6. Vapor 4 — the server Swift standard

The de facto standard for server-side Swift is **Vapor 4**. First released in 2016, Vapor 4 embraced async/await in 2020, and as of May 2026 the 4.x major continues to evolve.

The appeal of Vapor — **familiar routing reminiscent of Express/Koa, Fastify, NestJS combined with Swift's type safety.**

struct TodoController: RouteCollection {

func boot(routes: RoutesBuilder) throws {

let todos = routes.grouped("todos")

todos.get(use: index)

todos.post(use: create)

todos.group(":todoID") { todo in

todo.get(use: show)

todo.delete(use: delete)

}

}

func index(req: Request) async throws -> [Todo] {

try await Todo.query(on: req.db).all()

}

func create(req: Request) async throws -> Todo {

let todo = try req.content.decode(Todo.self)

try await todo.save(on: req.db)

return todo

}

func show(req: Request) async throws -> Todo {

guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {

throw Abort(.notFound)

}

return todo

}

func delete(req: Request) async throws -> HTTPStatus {

guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {

throw Abort(.notFound)

}

try await todo.delete(on: req.db)

return .noContent

}

}

Vapor's building blocks.

- **routing** — async-first handlers, parameter binding.

- **Fluent ORM** — Postgres, MySQL, SQLite, MongoDB drivers.

- **Leaf** — template engine (server-rendered HTML).

- **JWT** — auth/identity.

- **Queues** — background jobs, Redis-backed.

- **WebSocketKit** — bidirectional communication.

- **OpenAPIKit / openapi-generator-swift** — OpenAPI codegen.

Production usage — Vapor runs in production at places like Kodeco (formerly Ray Wenderlich), Transeo, and Emerge Tools, and Apple is known to use Vapor for some internal tooling. Traffic scale isn't quite Node/Go territory, but for teams that want Swift on both client and server it's a strong choice.

7. Hummingbird 2 (Apple-backed) — Swift Server Workgroup

**Hummingbird** is an alternative server framework built by Adam Fowler. In its 1.x days it was sometimes called "lightweight Vapor." With 2.0 in 2024 it gained standing as a candidate backed by Apple's Swift Server Workgroup (SSWG).

Three appeals of Hummingbird 2.

**1) Fewer dependencies.** Where Vapor bundles a full stack — Fluent, Leaf, JWT — Hummingbird offers just routing + middleware + HTTP handling. ORM, templating, and auth are assembled from separate packages. Similar to the Express vs NestJS relationship.

**2) Native Swift Concurrency.** Designed from day one on top of async/await and structured concurrency. It runs on SwiftNIO but doesn't expose NIO's EventLoopFuture directly.

**3) AWS Lambda friendly.** Cold starts are fast and binary sizes small. It pairs nicely with swift-aws-lambda-runtime — Hummingbird is increasingly the default in the Swift on Lambda story.

let router = Router()

router.get("/") { _, _ in

"Hello, Hummingbird 2"

}

router.get("/users/:id") { req, ctx in

let id = try ctx.parameters.require("id", as: Int.self)

return User.fetch(id: id)

}

let app = Application(

router: router,

configuration: .init(address: .hostname("0.0.0.0", port: 8080))

)

try await app.runService()

Vapor vs Hummingbird decision guide.

| Item | Vapor 4 | Hummingbird 2 |

| --- | --- | --- |

| Positioning | Full-stack framework | Micro router |

| ORM | Fluent bundled | GRDB / others separate |

| async/await | Inside backward compatibility | Native design |

| Lambda | Possible but heavy | Fast cold start |

| Learning curve | Low (Express-like) | Low (smaller) |

| Community | Large (older) | Growing |

| Apple backing | Unofficial | SSWG official |

Large monoliths or server-rendered HTML apps — Vapor. Microservices, Lambda, minimal binary — Hummingbird. API-only with no SSR — both work well.

8. Tuist + Mint + swift-package-manager — build and tooling

**SwiftPM (swift-package-manager)** is Apple's official package manager. The CocoaPods/Carthage era is essentially over and SwiftPM is the default in new 2026 projects. You declare dependencies in `Package.swift`, and both Xcode and the CLI understand it.

// swift-tools-version: 6.1

let package = Package(

name: "MyLib",

platforms: [.iOS(.v17), .macOS(.v14)],

products: [

.library(name: "MyLib", targets: ["MyLib"]),

],

dependencies: [

.package(url: "https://github.com/apple/swift-collections.git", from: "1.1.0"),

],

targets: [

.target(name: "MyLib", dependencies: [

.product(name: "Collections", package: "swift-collections"),

]),

.testTarget(name: "MyLibTests", dependencies: ["MyLib"]),

]

)

**Limitation** — SwiftPM is good for simple library packages, but for iOS apps with the storyboard/xcassets/info.plist/scheme web tangled together it falls short. That gap is where Tuist came in.

**Tuist** generates Xcode projects from `Project.swift` (a Tuist-specific DSL, not SwiftPM). In big monorepos it splits modules finely, expresses inter-module dependencies as code, and supports caching and incremental builds.

// Project.swift

let project = Project(

name: "MyApp",

targets: [

.target(

name: "MyApp",

destinations: .iOS,

product: .app,

bundleId: "com.example.MyApp",

infoPlist: .extendingDefault(with: [

"CFBundleShortVersionString": "1.0.0",

]),

sources: ["Sources/**"],

resources: ["Resources/**"],

dependencies: [

.target(name: "Core"),

.target(name: "Network"),

]

),

.target(name: "Core", destinations: .iOS, product: .framework, bundleId: "com.example.Core", sources: ["Modules/Core/**"]),

.target(name: "Network", destinations: .iOS, product: .framework, bundleId: "com.example.Network", sources: ["Modules/Network/**"], dependencies: [.target(name: "Core")]),

]

)

Tuist has cemented itself at places like Kakao, LINE, and Mercari with 100+ module monorepos. `tuist generate` creates the Xcode project and `tuist build` runs cached incremental builds. In 2024 Tuist Cloud (since folded into Tuist itself) added team-wide shared build cache.

**Mint** installs CLI tools written in Swift. If you install SwiftLint, SwiftFormat, swiftgen, xcodegen, and Sourcery via Mint instead of Homebrew, you can pin the team's versions with a `Mintfile`.

Mintfile example

realm/SwiftLint@0.59.1

nicklockwood/SwiftFormat@0.55.0

yonaskolb/XcodeGen@2.42.0

Install

mint bootstrap

Run

mint run swiftlint

Larger teams typically combine all three — SwiftPM (libraries) + Tuist (project generation) + Mint (CLI tools) — as the standard recipe.

9. swift-syntax / swift-format / SwiftLint / SwiftFormat

These four tools all belong to the same family in that they "handle Swift source code."

**swift-syntax** — Apple's official AST library. Exposes the same lexer/parser that the swift compiler uses. Essential when writing macros (`@Macro`, Swift 5.9+). Lets user code extend compiler features like ResultBuilder and Codable.

**swift-format** — Apple's official formatter. Apple absorbed Google's swift-format and moved it under the swiftlang/ org. Follows a fixed style guide (largely Apple style) with few options. swift-syntax based.

**SwiftFormat** — community formatter by Nick Lockwood. Many options — over 100 rules to toggle. Strong fit for incrementally tidying a legacy codebase.

**SwiftLint** — linter by Realm. Enforces JonAS/Mac/iOS standard coding conventions. Not a formatter (some auto-fix exists but the primary purpose is checking). 200+ rules, custom rules supported.

A one-table summary.

| Tool | Role | Options | Apple official | Auto-fix |

| --- | --- | --- | --- | --- |

| swift-syntax | AST library | n/a | Yes | n/a |

| swift-format | Formatter | Few | Yes | Yes |

| SwiftFormat | Formatter | Many | No | Yes |

| SwiftLint | Linter | Many | No | Partial |

Practical combinations.

- **New project** — swift-format (follow Apple style) + SwiftLint (checks).

- **Legacy project** — SwiftFormat (preserve old style via options) + SwiftLint.

- **Macros / metaprogramming** — swift-syntax directly.

SwiftLint config example.

disabled_rules:

- trailing_whitespace

opt_in_rules:

- empty_count

- missing_docs

included:

- Sources

excluded:

- Tests/Resources

- .build

line_length:

warning: 120

error: 200

identifier_name:

min_length: 2

excluded:

- id

- i

- x

- y

custom_rules:

no_print:

name: "No print()"

regex: "print\\("

message: "Use Logger instead of print()"

severity: error

The standard CI setup runs SwiftLint with `--strict` and swift-format or SwiftFormat with `--lint` and blocks the PR on failures.

10. swift-testing (new in Swift 6.0) — replacing XCTest

XCTest is a relic of the Objective-C era. `func test...` naming, `XCTAssertEqual()` helpers, instance-time lifecycle — all OOP-first design. **swift-testing** is the new testing framework that shipped formally with Swift 6.0 (September 2024) and embraces Swift's macro system.

Basic comparison.

// XCTest (the old way)

final class CalculatorTests: XCTestCase {

func testAddition() {

let result = Calculator.add(2, 3)

XCTAssertEqual(result, 5)

}

func testDivision() throws {

let result = try Calculator.divide(10, 2)

XCTAssertEqual(result, 5)

}

}

// swift-testing (Swift 6.0+)

@Test func addition() {

let result = Calculator.add(2, 3)

#expect(result == 5)

}

@Test func division() throws {

let result = try Calculator.divide(10, 2)

#expect(result == 5)

}

The difference jumps out. No need to memorize a different helper per assertion shape like `XCTAssertEqual(a, b)`, and `#expect(...)` is a macro that automatically decomposes the full expression on failure — similar in spirit to Rust's `assert!` or Catch2's `REQUIRE`.

Parameterized tests.

@Test(arguments: [(2, 3, 5), (10, -3, 7), (0, 0, 0)])

func addition(a: Int, b: Int, expected: Int) {

#expect(Calculator.add(a, b) == expected)

}

Conditional execution.

@Test(.enabled(if: ProcessInfo.processInfo.environment["CI"] == nil))

func localOnlyTest() {

// Local machines only

}

Async tests are just an `async` away.

@Test func fetchesUser() async throws {

let user = try await api.fetchUser(id: 1)

#expect(user.name == "Alice")

}

Coexistence with XCTest — swift-testing runs in the same binary as XCTest. You can mix `import Testing` and `import XCTest` in the same target. So you don't have to migrate everything at once; new tests can use swift-testing while old tests stay put.

XCTest isn't going away. UI tests (`XCUIApplication`) and performance tests (`measure { }`) remain XCTest territory. swift-testing targets unit and integration tests.

11. Android Swift Working Group (2024.11) — Swift on Android

In November 2024, swift.org ran a short but decisive post — **"the Android Swift Working Group has been formed."** Apple, Google (on the Android side), and the community would together make Swift a first-class citizen on Android.

Background. There were earlier attempts at Swift on Android. Readdle famously wrote Android apps internally in Swift, commercial tools like scade.io existed, and swift-corelibs-foundation partially supported the Android target. All were unofficial and experimental, with parts of the standard library missing, NDK integration incomplete, and the App-Store-vs-Play-Store path blocked.

Goals of the Android Swift WG (disclosed at launch in November 2024).

1. **Official toolchain** — distribute Android-target binaries directly from swift.org.

2. **Standard library compatibility** — Foundation, Network, Concurrency all work on Android.

3. **JNI bridge** — call Swift from Kotlin/Java and vice versa.

4. **Android-specific libraries** — Swift-native bindings for core Android APIs like Activity and Intent.

5. **Build integration** — a standard for building Swift modules inside Gradle.

Status as of May 2026 — a year and a half after the WG launched, experimental toolchains are distributed and hello world runs reliably. Foundation and Concurrency mostly work. We're not at the point of writing real production apps yet — but by 2027 it could be a viable option competing with Kotlin Multiplatform.

Expectation setting — "let's write Android apps only in Swift" isn't the real Swift on Android scenario. "Let's reuse iOS business logic on Android" is more realistic. UI is SwiftUI (iOS) + Compose (Android), and only the model/network/domain logic is shared in Swift.

Alternatives — Kotlin Multiplatform is already doing the same thing, more mature thanks to JetBrains backing. Compose Multiplatform now supports iOS, expanding the territory. For Swift on Android to take root it needs to offer something KMP doesn't — what exactly that is will become clear around 2027.

12. swift-foundation rewrite (open source) + Embedded Swift

**swift-foundation** is the project rewriting Foundation (NSString, NSDate, URLSession, JSONSerialization, etc.) in pure Swift without Objective-C dependencies. Developed at github.com/swiftlang/swift-foundation.

Why rewrite. The old Foundation had two versions. Apple Darwin used Objective-C-based NSFoundation; Linux used swift-corelibs-foundation (C-based). They promised the same API but behaved subtly differently — date formatting, URL parsing, JSON encoding all varied across OSes, and bugs lived on only one side.

The promise of swift-foundation — **the same code runs on every OS and behaves the same way.** Darwin is gradually switching to swift-foundation too. In 2024-2025 core types like Calendar, Date, JSONEncoder, and URL were migrated; in 2026 URLSession and FileManager are mid-migration.

Impact — biggest on Linux and server Swift. Code that ran fine on macOS used to break randomly on Linux; with swift-foundation those incidents nearly vanish. Embedded Swift and Android Swift get to use the same Foundation, which is a major shift.

**Embedded Swift** is a new mode introduced at the 2024 WWDC keynote. Regular Swift carries ARC, dynamic dispatch, exception handling, and a Foundation dependency that make it too heavy for microcontrollers like STM32 or ESP32. Embedded Swift strips down a subset of the language so it can run on those targets and produce small binaries.

What's missing.

- **Parts of the standard library** — nearly all of Foundation, Combine, parts of the Concurrency runtime.

- **Dynamic features** — runtime metadata reflection (Mirror), full dynamic decoding in JSONDecoder.

- **Exceptions** — `throws` works, but no runtime exception unwinding.

What remains.

- **Language basics** — struct, enum, class, generic, protocol.

- **Ownership system** — `~Copyable`, `~Escapable`.

- **Concurrency subset** — a lightweight async/await (`embedded` mode).

- **C interop** — works as is.

Use cases — microcontroller firmware, IoT devices, some drivers and kernel modules. Apple is known to be rewriting some SecureEnclave components in Embedded Swift. Outside Apple there are demos running Embedded Swift on ESP32 boards and Raspberry Pi Pico samples in swift-embedded-examples.

// Embedded Swift example — Raspberry Pi Pico LED blink

@main struct App {

static func main() {

let led = GPIO(pin: 25, direction: .output)

while true {

led.high()

sleep(milliseconds: 500)

led.low()

sleep(milliseconds: 500)

}

}

}

Competition with Rust on embedded (embedded-hal, esp-rs) has begun. Rust got a 5-6 year head start — but with Apple's weight behind it, how far Embedded Swift goes will be one of the more interesting threads to watch.

13. Concurrency — actors / async / await / Sendable

Swift Concurrency began in 5.5 (2021) and completed in stages through 5.7 (actors), 5.9 (macros), 6.0 (strict), and 6.1 (complete). Four core concepts.

**1) async/await.** Write asynchronous code as if it were synchronous. Promise/Future are not exposed explicitly.

func fetchUser(id: Int) async throws -> User {

let (data, _) = try await URLSession.shared.data(from: url)

return try JSONDecoder().decode(User.self, from: data)

}

// Call site

let user = try await fetchUser(id: 1)

**2) actor.** A stateful object. Access to its internal data is serialized, blocking data races.

actor Counter {

private var count = 0

func increment() { count += 1 }

func value() -> Int { count }

}

let counter = Counter()

await counter.increment() // await required from outside the actor

let v = await counter.value()

**3) Sendable.** A marker protocol for "a type that can be safely shared across threads." The compiler uses this marker to check value passing across actor boundaries.

struct UserInfo: Sendable {

let id: Int

let name: String // String is automatically Sendable

}

class MutableBox {

var value: Int = 0 // class with mutable property → cannot be Sendable

}

// MutableBox is not Sendable → compiler error when sent across actor boundary

**4) Strict Concurrency.** A compiler mode that decides how strictly to check Sendable. "complete" became the default in Swift 6.0, and false positives dropped considerably in 6.1.

Enable in Package.swift

.target(

name: "MyLib",

swiftSettings: [

.enableExperimentalFeature("StrictConcurrency"),

]

)

**`@MainActor`.** The compiler enforces the convention that all UI code runs on the main thread.

@MainActor

class ViewModel: ObservableObject {

@Published var users: [User] = []

func load() async {

let result = try? await api.fetchUsers() // runs on a worker actor

self.users = result ?? [] // hops back to the main actor

}

}

Here `api.fetchUsers()` runs on a non-MainActor context, and when assigning to `self.users` execution hops back to the main thread automatically. In C++ or Java you'd have to write `dispatch_async(main_queue, ^{...})` yourself — Swift's compiler handles it.

**Region-based isolation** (Swift 6.0+). A new mechanism that lets a single instance be "sent" from one task to another. Where it used to require Sendable to cross an actor boundary, region isolation lets a value cross if "we can prove the value is only used in one place right now."

func process() async {

let data = NonSendableData()

await someActor.use(data) // error in Swift 5.x; allowed in Swift 6.x with region isolation

// But: using `data` after this point becomes a compile error

}

This is the single biggest improvement that reduces strict concurrency's false positives.

14. Observation + Macros — iOS 17+ features

**The Observation framework** is the new reactive system introduced in iOS 17 (2023). It replaces the older `@Published`/Combine-based `ObservableObject` pattern more lightly.

Old way (Combine ObservableObject).

class UserStore: ObservableObject {

@Published var users: [User] = []

@Published var isLoading = false

}

struct UserList: View {

@StateObject var store = UserStore()

var body: some View {

if store.isLoading { ProgressView() }

else { List(store.users) { Text($0.name) } }

}

}

New way (Observation).

@Observable

class UserStore {

var users: [User] = []

var isLoading = false

}

struct UserList: View {

@State var store = UserStore()

var body: some View {

if store.isLoading { ProgressView() }

else { List(store.users) { Text($0.name) } }

}

}

Differences.

- No `@Published` needed — Observation handles it via macro.

- No `ObservableObject` conformance needed.

- `@StateObject` simplifies to `@State`.

- **Fine-grained invalidation** — where previously any published property change re-rendered the whole view, Observation tracks which property a view actually reads and invalidates only that. Major performance win.

Under the hood, the `@Observable` macro generates KeyPath-based tracking code inside the class. It's built on swift-syntax and users can extend it themselves.

**Macros (Swift 5.9+).** Macros are a mechanism for generating code at compile time. Unlike C macros, they are not text substitution — they're AST transformations. Functions that take ASTs exposed by swift-syntax and return new ASTs.

Two kinds of macros.

**1) Freestanding macros** — invoked like `#stringify`.

let (result, code) = #stringify(2 + 3)

// After compile: (5, "2 + 3")

**2) Attached macros** — attached to a declaration like `@AddCompletionHandler`.

@AddAsync

func fetch(completion: @escaping (Result<Data, Error>) -> Void) {

// ...

}

// Macro auto-generates:

// func fetch() async throws -> Data { ... }

The standard library and SDKs use macros aggressively.

- `@Observable` — what we saw above.

- `@Model` (SwiftData) — generates the persistent class.

- `#expect` (swift-testing) — assertion macro.

- `@Entry` (SwiftUI 6) — Environment key definition.

- `#Predicate` (SwiftData/Foundation) — type-safe query.

Writing a user macro (sketch).

public struct StringifyMacro: ExpressionMacro {

public static func expansion(

of node: some FreestandingMacroExpansionSyntax,

in context: some MacroExpansionContext

) -> ExprSyntax {

guard let argument = node.argumentList.first?.expression else {

fatalError("compiler bug: the macro does not have any arguments")

}

return "(\(argument), \(literal: argument.description))"

}

}

Macros live in a separate target (`.macro(...)`) and build as a compiler plugin. They're isolated from regular code so they guarantee compile-time safety.

Macro tradeoff — compile time goes up (swift-syntax is a heavy dependency). Popular macros are increasingly shipped as pre-compiled binaries.

15. Korea / Japan — Kakao, LINE, Mercari, Cookpad, pixiv

Swift is the default language for iOS teams in Korea and Japan. Who uses it how — synthesized from public conferences, blog posts, and job listings.

**Korea.**

- **Kakao** — iOS apps (KakaoTalk, Kakao Bank, Kakao Map, KakaoWebtoon) are nearly all Swift. KakaoTalk is a large monorepo with well over 100 modules and is known for its Tuist adoption. They're walking the staged RxSwift → Combine → Swift Concurrency migration. The internal "if(kakao)" conference shares SwiftUI/SwiftData adoption retrospectives annually.

- **LINE** — the LINE app from the Tokyo HQ is Swift-based. Korea's LINE Plus is Swift standard too. Known as one of the teams quick to try swift-testing.

- **Toss** — all iOS is Swift. Adopted Tuist plus modularization plus Combine plus some SwiftUI. Distributes design system and component libraries internally as SwiftPM packages.

- **Coupang** — iOS app in Swift. A migration case with some old ObjC still around.

- **Karrot** — Swift plus aggressive SwiftUI adoption. Published an internal RFC evaluating SwiftData adoption.

- **Naver** — Naver app, Naver Map, Webtoon, V LIVE, and friends are iOS in Swift. Known for cleaning up internal libraries into SwiftPM packages.

**Japan.**

- **Mercari** — iOS app in Swift; some microservices being evaluated on Vapor or Hummingbird. Published internal swift-testing migration guides.

- **Cookpad** — iOS app in Swift. Shared SwiftUI adoption stories at iOSDC Japan.

- **CyberAgent (ABEMA, AmebaTV)** — ABEMA iOS is Swift + SwiftUI. Many internal iOS apps use Tuist. Many CyberAgent iOS engineers contribute actively to swift.org and iOSDC.

- **pixiv** — iOS app in Swift. Sister apps like pixivFANBOX, pixivSketch, and BOOTH are also Swift.

- **DeNA** — all internal iOS apps are Swift. Maintains an internal Swift toolchain mirror.

- **Yahoo! Japan (LY Corporation)** — Yahoo!, Yahoo! News, Yahoo! Transit and friends are Swift.

Common patterns.

- **CocoaPods to SwiftPM** migration is nearly done.

- **Combine to Swift Concurrency** migration ongoing. New code is async/await first.

- **UIKit + SwiftUI hybrid** — new screens in SwiftUI, old screens in UIKit. Incremental migration.

- **Tuist adoption** — basically any team with 50+ modules.

- **XCTest to swift-testing** — migration starting in 2025-2026.

In both Korea and Japan, iOS hiring increasingly lists "Swift Concurrency experience," "production SwiftUI experience," and "modularization/Tuist experience" as essential keywords.

16. Who should pick Swift — iOS / Apple ecosystem / server / embedded

Recommendations by domain.

**iOS / macOS / visionOS / watchOS / tvOS apps.**

- Nearly default. Swift + SwiftUI or Swift + UIKit. New projects are SwiftUI first.

- If there's a giant legacy ObjC codebase, incremental migration. Apple itself walks the same road.

- Flutter / React Native / Kotlin Multiplatform exist as alternatives — but when you actually need native experience and the newest OS APIs, Swift is default.

**Server.**

- **Vapor** — full-stack web apps, server-rendered HTML, want the familiar Express-like experience.

- **Hummingbird** — microservices, AWS Lambda, want minimal dependencies.

- Swift isn't a server standard the way Go, Rust, or Node are. **When would you bother using Swift on the server?** When you want to share models and domain logic with the iOS team. A company doing both iOS and server in Swift consolidates code reuse and the hiring pool.

**Linux / containers.**

- Containerized microservices via Vapor or Hummingbird are possible. With distroless base images you're in the 50-100MB neighborhood.

- Binary size is bigger than Go or Rust, but Swift stripped binaries are workable.

**Android.**

- Not recommended for production in 2026. Kotlin Multiplatform is more stable.

- If the goal is reusing iOS business logic on Android — wait on the Android Swift WG and re-evaluate after 2027.

**Embedded / IoT.**

- Embedded Swift runs experimentally fine on ESP32, STM32, Raspberry Pi Pico.

- For production, Rust (embedded-hal) or C remain the defaults.

- Scenarios where Swift makes sense — firmware for Apple accessories, AirTag-style devices. Otherwise it needs more time.

**ML / data.**

- Python is default. Swift only when calling Core ML models on device.

- Swift for TensorFlow shut down. Unlikely to come back.

**Scripting / CLI.**

- swift-argument-parser is excellent for CLIs.

- That said, startup time lags Python and Node, and single-binary distribution comes via SwiftPM build into a stripped binary.

- Great choice for macOS dev tools. For cross-platform CLIs, Go and Rust still win.

**So the decisive reasons to pick Swift.**

1. **You're building an iOS or macOS app** — default with no doubt.

2. **You're going deep into Apple platforms** — visionOS, watchOS, tvOS are essentially Swift-only.

3. **You want strict concurrency seriously** — Rust-like safety without GC or lifetime overhead.

4. **You love type-safe SwiftUI declarative UI** — many find it more familiar with a cleaner API than Compose.

5. **The iOS team wants to write server code too** — Vapor/Hummingbird for internal standardization.

**Reasons not to pick Swift.**

1. **Windows desktop is your main target** — Swift runs on Windows but isn't a first-class citizen.

2. **You only do cross-platform mobile** — Flutter, React Native, and Kotlin Multiplatform are more mature.

3. **Your server domain standardized on another language** — if the team already lives in Go, Node, or Java, there's little reason to switch.

4. **ML/data** — Python.

5. **You need maximum safety in systems programming** — Rust.

The Swift of 2026 — default on Apple platforms, carving out its own space on the server, and still working to deliver on its promises in Android and embedded. The next 1-2 years will decide the fate of Swift outside Apple.

References

- swift.org official — https://www.swift.org/

- Swift 6 announcement — https://www.swift.org/blog/announcing-swift-6/

- Swift 6.1 release — https://www.swift.org/blog/swift-6.1-released/

- Android Swift Working Group — https://www.swift.org/blog/swift-on-android-workgroup/

- Embedded Swift — https://www.swift.org/blog/embedded-swift-examples/

- swift-foundation — https://github.com/swiftlang/swift-foundation

- swift-syntax — https://github.com/swiftlang/swift-syntax

- swift-format — https://github.com/swiftlang/swift-format

- swift-testing — https://github.com/swiftlang/swift-testing

- swift-package-manager — https://github.com/swiftlang/swift-package-manager

- SwiftLint — https://github.com/realm/SwiftLint

- SwiftFormat — https://github.com/nicklockwood/SwiftFormat

- Tuist — https://tuist.io/

- Mint — https://github.com/yonaskolb/Mint

- Vapor — https://vapor.codes/

- Hummingbird — https://hummingbird.codes/

- Swift Server Workgroup — https://www.swift.org/sswg/

- SwiftUI documentation — https://developer.apple.com/documentation/swiftui

- SwiftData documentation — https://developer.apple.com/documentation/swiftdata

- Observation framework — https://developer.apple.com/documentation/observation

- Macros proposal (SE-0382) — https://github.com/swiftlang/swift-evolution/blob/main/proposals/0382-expression-macros.md

- Strict Concurrency proposal (SE-0337) — https://github.com/swiftlang/swift-evolution/blob/main/proposals/0337-async-await-sendable-migration.md

- iOSDC Japan — https://iosdc.jp/

- if(kakao) conference — https://if.kakao.com/

- Cookpad iOS engineering — https://techlife.cookpad.com/

- Mercari engineering blog — https://engineering.mercari.com/

- pixiv developer blog — https://devpixiv.hatenablog.com/

현재 단락 (1/623)

When Chris Lattner unveiled Swift at WWDC 2014, the audience reacted more with a sigh than applause....

작성 글자: 0원문 글자: 35,938작성 단락: 0/623