0Pricing
Swift Academy · 강의

일반적인 래퍼 패턴(검증, 캐싱)

일반적인 검증 및 캐싱 래퍼를 만듭니다. 입력을 검사하고 기본값을 제공하며, 비용이 큰 작업을 메모이제이션하고, 투영된 값으로 도우미 플래그를 제공합니다.

일반적인 래퍼 패턴(검증, 캐싱)은(는) CoddyKit의 무료 Swift Academy 강의입니다. 이것은 3개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Swift Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Swift Academy 강의에는 총 3개의 강의가 포함되어 있습니다.

만들어 볼 것

이 수업에서는 두 가지 실용적인 패턴을 살펴봅니다.

  • 검증: 기본값과 메시지를 사용해 입력을 수락하거나 수정합니다.
  • 캐싱: 결과를 저장하고 도우미와 clear(), isCached를 제공합니다.

검증: 비어 있지 않음

@NonEmpty는 빈 입력을 막고 기본값을 제공합니다. 투영값은 마지막 설정이 자동으로 수정되었는지 알려 줍니다.

@propertyWrapper
struct NonEmpty {
    private var value: String = ""
    private(set) var lastFixed: Bool = false

    var wrappedValue: String {
        get { value }
        set {
            if newValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                value = "N/A"          // default fallback
                lastFixed = true
            } else {
                value = newValue
                lastFixed = false
            }
        }
    }

    var projectedValue: Bool { lastFixed } // $name -> was fixed?

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

struct Profile {
    @NonEmpty var displayName: String = "  "
}
var p = Profile()
print(p.displayName)  // "N/A"
print(p.$displayName) // true (was fixed)

검증: 규칙 기반

@Validated는 제네릭이며 규칙 클로저와 대체값을 받습니다. 길이, 범위 또는 사용자 지정 검사를 수행할 때 사용하십시오.

@propertyWrapper
struct Validated<Value> {
    private var value: Value
    private let rule: (Value) -> Bool
    private let fallback: Value
    private(set) var lastValid: Bool = true

    var wrappedValue: Value {
        get { value }
        set {
            if rule(newValue) {
                value = newValue
                lastValid = true
            } else {
                value = fallback
                lastValid = false
            }
        }
    }

    var projectedValue: Bool { lastValid } // $prop -> is valid?

    init(wrappedValue: Value, rule: @escaping (Value) -> Bool, fallback: Value) {
        self.rule = rule
        self.fallback = fallback
        self.value = wrappedValue
        self.lastValid = rule(wrappedValue)
        if !lastValid { self.value = fallback }
    }
}

struct Form {
    @Validated(rule: { $0.count >= 3 }, fallback: "???")
    var nickname: String = "hi"
}
var f = Form()
print(f.nickname)   // "???" (invalid -> fallback)
print(f.$nickname)  // false

캐싱: 지연 메모이제이션

@LazyCached는 클로저에서 얻은 값을 메모이제이션합니다. $result는 isCached와 clear() 도우미를 제공합니다.

@propertyWrapper
struct LazyCached<Value> {
    private var storage: Value?
    private let build: () -> Value

    var wrappedValue: Value {
        mutating get {
            if let v = storage { return v }         // hit
            let v = build()                         // miss -> compute
            storage = v
            return v
        }
        // Optional: allow manual set to override cache
        set { storage = newValue }
    }

    struct Controls {
        private let getter: () -> Bool
        private let clearer: () -> Void
        var isCached: Bool { getter() }
        func clear() { clearer() }
    }

    var projectedValue: Controls {
        Controls(
            getter: { self.storage != nil },
            clearer: { self.storage = nil }
        )
    }

    init(_ build: @escaping () -> Value) {
        self.build = build
        self.storage = nil
    }
}

// Demo: expensive computation (simulated)
var calls = 0
func heavy() -> Int { calls += 1; return (1...10_000).reduce(0, +) }

struct Engine {
    @LazyCached(heavy) var result: Int
}
var e = Engine()
print(e.$result.isCached) // false
print(e.result)           // computes once
print(e.result)           // uses cache
print(calls)              // 1

캐싱: TTL 기반

@TimedCache는 TTL이 지나면 갱신합니다. 투영값에서 age를 제공하면 호출부가 언제 갱신할지 결정할 수 있습니다.

@propertyWrapper
struct TimedCache<Value> {
    private var storage: Value?
    private var timestamp: Date?
    private let ttl: TimeInterval
    private let build: () -> Value

    var wrappedValue: Value {
        mutating get {
            let now = Date()
            if let t = timestamp, let v = storage, now.timeIntervalSince(t) < ttl {
                return v                              // fresh
            }
            let v = build()                           // refresh
            storage = v
            timestamp = now
            return v
        }
    }

    struct Status { let age: TimeInterval? }
    var projectedValue: Status {
        let age = timestamp.map { Date().timeIntervalSince($0) }
        return Status(age: age)
    }

    init(ttl: TimeInterval, _ build: @escaping () -> Value) {
        self.ttl = ttl
        self.build = build
    }
}

// Demo (age only; TTL behavior depends on real time)
struct Stats {
    @TimedCache(ttl: 60) { Int.random(in: 0...1000) } var score: Int
}
var s2 = Stats()
print(s2.score)         // computes
print(s2.$score.age ?? -1)

설계 지침

설계 팁:

  • 검증은 순수하고 예측 가능하게 유지하며, 수정 사항은 플래그로 보고하십시오.
  • 캐싱에서는 상태를 작게 유지하고 clear() 또는 isCached를 제공하십시오.
  • 정책(대체값, TTL)에는 초기화 인수를 우선 사용하십시오.

캐싱을 위한 투영 도우미

빠른 확인: 캐싱 래퍼에서 $value는 무엇을 제공해야 할까요?

복습

복습: 래퍼를 사용해 입력을 검증하고(기본값, 규칙), 비용이 큰 결과를 캐시하십시오(지연 방식, TTL). 깔끔한 호출부를 위해 제어 기능과 상태를 투영값에 넣으십시오.

자주 묻는 질문

“일반적인 래퍼 패턴(검증, 캐싱)” 강의는 무료인가요?

네 — “일반적인 래퍼 패턴(검증, 캐싱)” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Swift Academy 강의 전체를 잠금 해제할 수 있습니다. Swift Academy 강의에는 총 3개의 강의가 포함되어 있습니다.

“일반적인 래퍼 패턴(검증, 캐싱)”에서 뭘 배우나요?

일반적인 검증 및 캐싱 래퍼를 만듭니다. 입력을 검사하고 기본값을 제공하며, 비용이 큰 작업을 메모이제이션하고, 투영된 값으로 도우미 플래그를 제공합니다. 브라우저에서 직접 실행하는 실습 코드로 Swift Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Swift Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Swift Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 3번째 강의입니다.

“일반적인 래퍼 패턴(검증, 캐싱)” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Swift Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Swift Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 래퍼 만들기, projectedValue
  2. 재사용성과 제약 조건
  3. 일반적인 래퍼 패턴(검증, 캐싱)
← Swift Academy(으)로 돌아가기