기본 콘텐츠로 건너뛰기

추천 가젯

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

모바일 청첩장 시리즈 1편 · 기획/스택/배포 리액트 + 비트(Vite)로 모바일 청첩장 만들기 — 1편 안녕하세요, 이번에 결혼 준비를 하면서 여자친구와 같이 모바일 청첩장 을 만들고 있어요. 여자친구가 디자인을 해서 전달해주면 제가 개발을 진행하고 있어요. 이 글은 구현기 1편 으로, 전체 흐름과 스택, 배포 구성까지 “부담 없이” 훑어봅니다. (코드는 여러 버전 테스트 중!) 이 글에서 보는 것 왜 SPA 모바일 청첩장인가? 기본 스택 & 폴더 구조 라우팅 선택: HashRouter가 편한 이유 Cloudflare Pages로 자동 배포 현재 진행 중인 UI 버전들(테스트 기록) 1) 왜 SPA 모바일 청첩장인가? 모바일 청첩장은 핵심이 명확해요. 가볍고 빠르고 끊김이 없어야 하고, 사진/지도/일정이 터치에 친화적 이어야 합니다. 그래서 React + Vite 로 싱글 페이지 앱(SPA)을 구성했고, 정적 호스팅(CDN)인 Cloudflare Pages 에 올려 GitHub 푸시 → 자동 배포 까지 한 번에 묶었습니다. UX 팁 · 이미지 WebP, loading="lazy" 기본 · 큰 터치 타깃 · BGM은 “사용자 탭 후” 재생(모바일 정책) 2) 기본 스택 & 폴더 구조 서버는 따로 두지 않았고, 정적 빌드 결과물( dist/ )만 올립니다. 현재 의존성은 아래와 같아요. package.json(요약) { "name": ...

⚡ 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