Communitygithub.com

swift-actor-persistence

Swift 액터를 사용한 스레드-세이프 데이터 지속성 — 설계적으로 데이터 레이스를 제거하는 인메모리 캐시와 파일 기반 저장소. Swift에서 데이터를 지속하고 데이터 레이스나 스레드 안전성 문제를 설계적으로 해결해야 할 때 사용합니다.

swift-actor-persistence란 무엇인가요?

이 스킬은 Swift 5.5+에서 액터(actor) 모델을 사용하여 스레드-세이프한 데이터 지속성 계층을 구축하는 패턴을 제공합니다. 인메모리 캐싱과 파일 기반 저장소를 결합하여 컴파일 타임에 데이터 레이스를 제거하며, `Sendable` 타입과 `Identifiable` 제네릭을 활용해 모든 모델 타입에 재사용 가능합니다. iOS/macOS 앱의 로컬 저장소나 오프라인 우선 아키텍처에서 기존 `DispatchQueue` 기반 동기화를 대체하는 데 적합하며, `@Observable` ViewModel과 결합하여 반응형 UI 업데이트를 지원합니다. 주요 디자인 결정으로는 액터를 통한 컴파일러 강제 스레드 안전성, 동기식 초기화 로딩, `.atomic` 파일 쓰기 방식을 채택하여 안정성을 높였습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/swift-actor-persistence

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

스레드-세이프 지속성을 위한 Swift 액터

액터를 사용하여 스레드-세이프한 데이터 지속성 계층을 구축하는 패턴입니다. 인메모리 캐싱과 파일 기반 저장소를 결합하여 액터 모델을 활용해 컴파일 타임에 데이터 레이스를 제거합니다.

활성화 시점

  • Swift 5.5+에서 데이터 지속성 계층을 구축할 때
  • 공유 가변 상태에 대한 스레드-세이프한 접근이 필요할 때
  • 수동 동기화(락, DispatchQueue)를 제거하고 싶을 때
  • 로컬 저장소를 사용하는 오프라인 우선 앱을 구축할 때

핵심 패턴

액터 기반 저장소

액터 모델은 직렬화된 접근을 보장합니다 — 데이터 레이스가 없으며, 컴파일러가 강제합니다.

public actor LocalRepository<T: Codable & Identifiable> where T.ID == String {
    private var cache: [String: T] = [:]
    private let fileURL: URL

    public init(directory: URL = .documentsDirectory, filename: String = "data.json") {
        self.fileURL = directory.appendingPathComponent(filename)
        // init 중 동기 로드 (액터 격리가 아직 활성화되지 않음)
        self.cache = Self.loadSynchronously(from: fileURL)
    }

    // MARK: - 공개 API

    public func save(_ item: T) throws {
        cache[item.id] = item
        try persistToFile()
    }

    public func delete(_ id: String) throws {
        cache[id] = nil
        try persistToFile()
    }

    public func find(by id: String) -> T? {
        cache[id]
    }

    public func loadAll() -> [T] {
        Array(cache.values)
    }

    // MARK: - 비공개

    private func persistToFile() throws {
        let data = try JSONEncoder().encode(Array(cache.values))
        try data.write(to: fileURL, options: .atomic)
    }

    private static func loadSynchronously(from url: URL) -> [String: T] {
        guard let data = try? Data(contentsOf: url),
              let items = try? JSONDecoder().decode([T].self, from: data) else {
            return [:]
        }
        return Dictionary(uniqueKeysWithValues: items.map { ($0.id, $0) })
    }
}

사용법

액터 격리로 인해 모든 호출은 자동으로 비동기(async)입니다:

let repository = LocalRepository<Question>()

// 읽기 — 인메모리 캐시에서 O(1) 빠른 조회
let question = await repository.find(by: "q-001")
let allQuestions = await repository.loadAll()

// 쓰기 — 캐시 업데이트 후 파일에 원자적으로 저장
Try await repository.save(newQuestion)
Try await repository.delete("q-001")

@Observable ViewModel과 결합

@Observable
final class QuestionListViewModel {
    private(set) var questions: [Question] = []
    private let repository: LocalRepository<Question>

    init(repository: LocalRepository<Question> = LocalRepository()) {
        self.repository = repository
    }

    func load() async {
        questions = await repository.loadAll()
    }

    func add(_ question: Question) async throws {
        try await repository.save(question)
        questions = await repository.loadAll()
    }
}

주요 디자인 결정

결정근거
액터(클래스 + 락 대신)컴파일러가 강제하는 스레드 안전성, 수동 동기화 불필요
인메모리 캐시 + 파일 지속성캐시에서 빠른 읽기, 디스크에 안정적인 쓰기
동기식 init 로딩비동기 초기화의 복잡성 방지
ID를 키로 하는 딕셔너리식별자로 O(1) 조회
Codable & Identifiable 제네릭모든 모델 타입에 재사용 가능
원자적 파일 쓰기 (.atomic)충돌 시 부분 쓰기 방지

모범 사례

  • 액터 경계를 넘는 모든 데이터에는 Sendable 타입 사용
  • 액터의 공개 API를 최소화 — 도메인 작업만 노출하고 지속성 세부 사항은 숨기기
  • .atomic 쓰기 사용 — 앱이 쓰기 도중 충돌할 때 데이터 손상 방지
  • init에서 동기적으로 로드 — 비동기 초기화는 로컬 파일에 비해 복잡성만 증가
  • @Observable ViewModel과 결합하여 반응형 UI 업데이트

피해야 할 안티 패턴

  • 새로운 Swift 동시성 코드에 액터 대신 DispatchQueue 또는 NSLock 사용
  • 내부 캐시 딕셔너리를 외부 호출자에게 노출
  • 검증 없이 파일 URL을 설정 가능하게 함
  • 모든 액터 메서드 호출이 await임을 잊음 — 호출자는 비동기 컨텍스트를 처리해야 함
  • 액터 격리를 우회하기 위해 nonisolated 사용 (목적을 무의미하게 만듦)

사용 시기

  • iOS/macOS 앱의 로컬 데이터 저장(사용자 데이터, 설정, 캐시된 콘텐츠)
  • 나중에 서버와 동기화하는 오프라인 우선 아키텍처
  • 앱의 여러 부분이 동시에 접근하는 공유 가변 상태
  • 기존 DispatchQueue 기반 스레드 안전성을 최신 Swift 동시성으로 대체

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

관련 스킬