Case 01 · Prefetch / Cache
인스타식 브리핑 뷰어 · URL을 HTML로 미리 받아 캐싱
슬라이드를 넘길 때마다 서버 URL을 그때그때 로드하면 흰 화면이 깜빡입니다. 봤던 장으로 되돌아올 때 같은 본문을 다시 그리는 것도 낭비였습니다.
콘텐츠 파이프라인을 건드리지 않고 UX만 끌어올릴 수 있는 WKWebView 프리로드를 택했습니다. 현재 스토리 첫 장을 최우선으로, 나머지는 utility 우선순위 Task로 병렬 프리페치합니다.
슬라이드 URL에서 HTML을 미리 내려받아 [slideID: HTML] 메모리 캐시에 담아 둡니다. 화면이 보일 때는 네트워크 없이 캐시에서 꺼내 그리고, 벗어나면 deinit에서 진행 중인 프리페치를 취소합니다.
넘기는 즉시 다음 장이 뜨고, 되돌아와도 다시 그리지 않습니다.
실기기 데모 · 브리핑 뷰어
@Observable final class BriefingStore { // slideID → HTML (메모리 캐시) private(set) var preloaded: [String: String] = [:] private var task: Task<Void, Never>? func load() { task?.cancel() task = Task { [weak self] in await self?.prefetch() } } // 첫 장 최우선, 나머지는 병렬로 미리 받아 캐시 private func prefetch() async { await withTaskGroup(of: (String, String?).self) { group in for slide in currentSlides { group.addTask { (slide.id, await fetchHTML(slide)) } } for await (id, html) in group { if let html { preloaded[id] = html } } } } // URL → HTML 다운로드 (프리페치 내부 전용) private func fetchHTML(_ slide: Slide) async -> String? { guard let (data, _) = try? await URLSession.shared.data(from: slide.htmlURL) else { return nil } return String(data: data, encoding: .utf8) } // 화면이 보일 때 캐시에서 꺼내 쓴다 func html(for id: String) -> String? { preloaded[id] } deinit { task?.cancel() } }