일반적인 래퍼 패턴(검증, 캐싱)
일반적인 검증 및 캐싱 래퍼를 만듭니다. 입력을 검사하고 기본값을 제공하며, 비용이 큰 작업을 메모이제이션하고, 투영된 값으로 도우미 플래그를 제공합니다.
일반적인 래퍼 패턴(검증, 캐싱)은(는) 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 래퍼 만들기, projectedValue
- 재사용성과 제약 조건
- 일반적인 래퍼 패턴(검증, 캐싱)