Communitygithub.com

콘텐츠 해시 캐시 패턴

SHA-256 콘텐츠 해시를 사용하여 비용이 많이 드는 파일 처리 결과를 캐시합니다. 경로와 무관하며 자동 무효화되고 서비스 계층이 분리됩니다. 반복적인 파일 처리가 느리고 결과가 경로가 아닌 콘텐츠에 의해 캐시되고 무효화되어야 할 때 사용합니다.

콘텐츠 해시 캐시 패턴란 무엇인가요?

이 스킬은 파일 처리 비용이 높고 동일 파일이 반복 처리되는 시나리오(예: PDF 파싱, 텍스트 추출, 이미지 분석)를 위한 **콘텐츠 해시 기반 캐시 패턴**을 제공합니다. 핵심 아이디어는 파일 경로 대신 SHA-256 콘텐츠 해시를 캐시 키로 사용하는 것입니다. 이를 통해 파일 이동/이름 변경에도 캐시가 유지되고, 파일 콘텐츠가 변경될 때만 자동으로 캐시가 무효화됩니다. 패턴은 `compute_file_hash()`, `CacheEntry` 데이터클래스, `{hash}.json` 형식의 파일 기반 캐시 저장소, 그리고 순수 함수와 캐시 로직을 분리하는 서비스 계층 래퍼로 구성됩니다. 설계 결정에는 SHA-256 사용, O(1) 조회를 위한 해시 기반 파일 이름, SRP 준수, 수동 JSON 직렬화, 손상된 캐시 처리 등이 포함됩니다. 이 패턴은 `--cache/--no-cache` CLI 옵션을 지원하며, 기존 순수 함수를 수정하지 않고 캐시를 추가하는 데 특히 유용합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/content-hash-cache-pattern

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

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

문서

콘텐츠 해시 파일 캐시 패턴

비용이 많이 드는 파일 처리 결과(PDF 파싱, 텍스트 추출, 이미지 분석)를 SHA-256 콘텐츠 해시를 캐시 키로 사용하여 캐시합니다. 경로 기반 캐싱과 달리 이 접근 방식은 파일 이동/이름 변경 시에도 유효하며, 콘텐츠가 변경되면 자동으로 무효화됩니다.

활성화 시기

  • 파일 처리 파이프라인 구축(PDF, 이미지, 텍스트 추출)
  • 처리 비용이 높고 동일한 파일이 반복적으로 처리되는 경우
  • --cache/--no-cache CLI 옵션이 필요한 경우
  • 기존 순수 함수를 수정하지 않고 캐싱을 추가하려는 경우

핵심 패턴

1. 콘텐츠 해시 기반 캐시 키

파일 경로가 아닌 파일 콘텐츠를 캐시 키로 사용합니다:

import hashlib
from pathlib import Path

_HASH_CHUNK_SIZE = 65536  # 대용량 파일을 위한 64KB 청크

def compute_file_hash(path: Path) -> str:
    """파일 콘텐츠의 SHA-256 해시(대용량 파일은 청크 단위로 처리)."""
    if not path.is_file():
        raise FileNotFoundError(f"파일을 찾을 수 없습니다: {path}")
    sha256 = hashlib.sha256()
    with open(path, "rb") as f:
        while True:
            chunk = f.read(_HASH_CHUNK_SIZE)
            if not chunk:
                break
            sha256.update(chunk)
    return sha256.hexdigest()

왜 콘텐츠 해시인가? 파일 이름 변경/이동 = 캐시 적중. 콘텐츠 변경 = 자동 무효화. 인덱스 파일이 필요 없습니다.

2. 불변 데이터클래스(캐시 항목)

from dataclasses import dataclass

@dataclass(frozen=True, slots=True)
class CacheEntry:
    file_hash: str
    source_path: str
    document: ExtractedDocument  # 캐시된 결과

3. 파일 기반 캐시 저장소

각 캐시 항목은 {hash}.json으로 저장됩니다. 해시로 O(1) 조회가 가능하며 인덱스 파일이 필요 없습니다.

import json
from typing import Any

def write_cache(cache_dir: Path, entry: CacheEntry) -> None:
    cache_dir.mkdir(parents=True, exist_ok=True)
    cache_file = cache_dir / f"{entry.file_hash}.json"
    data = serialize_entry(entry)
    cache_file.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")

def read_cache(cache_dir: Path, file_hash: str) -> CacheEntry | None:
    cache_file = cache_dir / f"{file_hash}.json"
    if not cache_file.is_file():
        return None
    try:
        raw = cache_file.read_text(encoding="utf-8")
        data = json.loads(raw)
        return deserialize_entry(data)
    except (json.JSONDecodeError, ValueError, KeyError):
        return None  # 손상은 캐시 미스로 처리

4. 서비스 계층 래퍼 (SRP)

처리 함수는 순수하게 유지하고, 캐싱은 별도의 서비스 계층으로 추가합니다.

def extract_with_cache(
    file_path: Path,
    *,
    cache_enabled: bool = True,
    cache_dir: Path = Path(".cache"),
) -> ExtractedDocument:
    """서비스 계층: 캐시 확인 -> 추출 -> 캐시 쓰기."""
    if not cache_enabled:
        return extract_text(file_path)  # 순수 함수, 캐시를 알지 못함

    file_hash = compute_file_hash(file_path)

    # 캐시 확인
    cached = read_cache(cache_dir, file_hash)
    if cached is not None:
        logger.info("캐시 적중: %s (hash=%s)", file_path.name, file_hash[:12])
        return cached.document

    # 캐시 미스 -> 추출 -> 저장
    logger.info("캐시 미스: %s (hash=%s)", file_path.name, file_hash[:12])
    doc = extract_text(file_path)
    entry = CacheEntry(file_hash=file_hash, source_path=str(file_path), document=doc)
    write_cache(cache_dir, entry)
    return doc

주요 설계 결정

결정근거
SHA-256 콘텐츠 해시경로 무관, 콘텐츠 변경 시 자동 무효화
{hash}.json 파일 이름O(1) 조회, 인덱스 파일 불필요
서비스 계층 래퍼SRP: 추출은 순수하게, 캐시는 별도 관심사
수동 JSON 직렬화불변 데이터클래스 직렬화에 대한 완전한 제어
손상 시 None 반환정상적 저하, 다음 실행 시 재처리
cache_dir.mkdir(parents=True)첫 쓰기 시 지연 생성

모범 사례

  • 경로가 아닌 콘텐츠를 해싱하세요. 경로는 변경되지만 콘텐츠의 정체성은 변경되지 않습니다.
  • 대용량 파일 해싱 시 청크 단위로 처리하여 메모리에 전체 파일을 로드하지 않도록 합니다.
  • 처리 함수를 순수하게 유지하세요. 캐싱에 대해 알 필요가 없습니다.
  • 캐시 적중/미스를 잘린 해시와 함께 로그로 기록하여 디버깅합니다.
  • 손상을 정상적으로 처리하세요. 잘못된 캐시 항목은 미스로 처리하고 절대 충돌하지 않습니다.

피해야 할 안티 패턴

# 나쁨: 경로 기반 캐싱 (파일 이동/이름 변경 시 깨짐)
cache = {"/path/to/file.pdf": result}

# 나쁨: 처리 함수 내부에 캐시 로직 추가 (SRP 위반)
def extract_text(path, *, cache_enabled=False, cache_dir=None):
    if cache_enabled:  # 이제 이 함수는 두 가지 책임을 가짐
        ...

# 나쁨: 중첩된 불변 데이터클래스와 함께 dataclasses.asdict() 사용
# (복잡한 중첩 타입에서 문제를 일으킬 수 있음)
data = dataclasses.asdict(entry)  # 대신 수동 직렬화 사용

사용 시점

  • 파일 처리 파이프라인 (PDF 파싱, OCR, 텍스트 추출, 이미지 분석)
  • --cache/--no-cache 옵션이 유용한 CLI 도구
  • 여러 실행에 걸쳐 동일한 파일이 나타나는 배치 처리
  • 기존 순수 함수를 수정하지 않고 캐싱 추가

사용하지 말아야 할 경우

  • 항상 최신 데이터가 필요한 경우 (실시간 피드)
  • 캐시 항목이 매우 큰 경우 (대신 스트리밍 고려)
  • 파일 콘텐츠 외부의 매개변수에 의존하는 결과 (예: 다른 추출 설정)

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/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

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.

관련 스킬