기본 콘텐츠로 건너뛰기

추천 가젯

리액트 + 비트(Vite)로 모바일 청첩장 만들기 — 2편

모바일 청첩장 시리즈 2편 · R2 갤러리 & Firebase 방명록 Cloudflare R2 · Functions Firebase Firestore 클라우드플레어 R2로 갤러리 저장하고, Firebase로 방명록 달기 안녕하세요, 병민입니다 🙌 1편에서 전체 흐름을 잡았고, 이번엔 사진 업로드/보관 과 방명록 을 연결합니다. 서버는 따로 없고 Cloudflare Pages 를 쓰고 있으니, Pages Functions (= 워커)로 R2에 사전서명 URL을 만들어주고, 프론트에서 그 URL로 바로 업로드하는 구조예요. 방명록은 Firebase DB로 간단·안전하게! 전체 그림 프론트(React) → /api/r2/upload 로 업로드용 URL 요청 → R2에 파일 PUT 프론트(React) → /api/r2/list 로 목록 요청 → 갤러리 렌더 프론트(React) → Firebase SDK로 방명록 작성/조회 1) R2 버킷 & Pages Functions 준비 Cloudflare 대시보드 > R2 > Create bucket (예: wedding-gallery ) 버킷 > Settings > CORS 에서 사이트 도메인 허용(예: https://*.pages.dev , 커스텀 도메인) Pages 프로젝트 > Settings > Functions 에서 R2 바인딩 추가: ...

⚡ functools.lru_cache로 함수 속도 100배 UP!

Cache icon

⚡ functools.lru_cache로 함수 속도 100배 UP!

lru_cache는 캐싱(memoization)을 자동으로 적용해 함수의 중복 호출 시간을 줄여줍니다. 연산이 무거운 함수에 이 데코레이터만 붙여도 성능 극적 향상이 가능합니다.

✅ 1. 기본 적용 방법

from functools import lru_cache

@lru_cache(maxsize=128)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

print(fib(30))  # 빠른 계산 완료!
print(fib.cache_info())
# CacheInfo(hits=28, misses=31, maxsize=128, currsize=31)
  • 📈 피보나치 같은 재귀 함수에 특히 효과적.
  • cache_info()는 히트율, miss 수, 캐시 크기 등 성능 지표 제공.

✅ 2. 캐시 크기 조정과 캐시 비우기

@lru_cache(maxsize=None)  # 무제한 캐시
def heavy_calc(x):
    # 가벼운 흉내
    return x ** 2

print(heavy_calc(10))
heavy_calc.cache_clear()
  • 🛠 캐싱 크기를 조절해 메모리 사용과 속도 사이 밸런스 설정.
  • cache_clear()로 캐시 초기화 가능.

✅ 3. 키로 사용되는 인자 타입 주의사항

@lru_cache()
def concat(a, b):
    return f"{a}-{b}"

print(concat("A", "B"))  # OK
# concat([1,2], [3,4])  # TypeError: unhashable type: 'list'
  • ⚠ 인자는 **해시 가능해야(hashable)** 하며, 리스트/딕셔너리 같은 mutable 타입 사용 불가.
  • 📝 튜플이나 frozenset 등으로 변환해 안전하게 캐싱 가능.

✅ 4. 데코레이터 조합 예: 캐싱 + 로깅

from functools import lru_cache, wraps

def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"[LOG] Calling {func.__name__}{args}")
        return func(*args, **kwargs)
    return wrapper

@log
@lru_cache(maxsize=32)
def factorial(n):
    return 1 if n < 2 else n * factorial(n-1)

print(factorial(5))
print(factorial.cache_info())
  • 데코레이터 순서에 따라 로깅 시점과 캐싱 대상이 달라지니 주의!

✅ 5. 실제 성능 테스트 비교

import timeit

setup = """
from functools import lru_cache
@lru_cache()
def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)
"""

t_cached = timeit.timeit("fib(30)", setup=setup, number=10)
t_nocache = timeit.timeit("""
def fib2(n):
    return n if n < 2 else fib2(n-1) + fib2(n-2)
fib2(30)
""", number=10)

print("With lru_cache:", t_cached)
print("Without cache:", t_nocache)
  • 🔎 실제 벤치마크로 캐싱 전후 시간 비교.
  • 재귀 없이 루프형 함수에도 적용해 볼 수 있으니 **전략적 활용**이 중요!

✨ 요약 & 활용 팁

  • lru_cache()만 붙이면 재귀나 반복 함수 속도 대폭 개선!
  • 캐시 사용량과 히트율을 확인하며 **maxsize 조절** 가능
  • 인자 타입은 반드시 **hashable**해야 함
  • 여러 데코레이터 조합 시 **순서와 의도 이해** 중요
  • 성능 테스트로 효과 검증, 실제 시스템 적용 시 유용

댓글

가장 많이 본 글

Icons by Flaticon