Python으로 코드 속도 10배 빠르게 만드는 `functools.lru_cache` 활용법

카테고리

프로그래밍/소프트웨어 개발

서브카테고리

개발 툴

대상자

- 대상: Python 개발자, 성능 최적화가 필요한 프로젝트 담당자

- 난이도: 중간 (Python 기본 지식과 데코레이터 개념 이해 필요)

핵심 요약

  • @lru_cache는 반복 호출 시 계산 결과를 캐시하여 중복 연산 방지속도 향상 가능
  • 캐시 기능maxsize 설정, typed 옵션, cache_info()/cache_clear() 메서드로 세부 조절 가능
  • 적용 사례: 재귀 함수(예: 피보나치), API 호출, DB 쿼리에서 대규모 성능 향상

섹션별 세부 요약

  1. lru_cache 기능 개요
  • 인자 기반 키 생성: 위치 인자와 키워드 인자를 해시 가능한 고유 키로 변환
  • 캐시 저장 방식: 결과를 딕셔너리에 저장하여 O(1) 조회 가능
  • LRU 알고리즘: 사용 빈도 기반으로 오래된 항목 자동 제거
  • 통계 및 제어: .cache_info()로 캐시 히트/미스 확인, .cache_clear()로 캐시 초기화
  1. 기본 사용 예시
  • 피보나치 수열

```python

@lru_cache(maxsize=None)

def fib(n):

if n < 2:

return n

return fib(n-1) + fib(n-2)

```

  • 무캐시 시: fib(35) 실행 시간 ~1.2초
  • 캐시 적용 후: fib(35) 실행 시간 ~20마이크로초
  1. 실용 사례
  • API 호출 최적화

```python

@lru_cache(maxsize=32)

def get_weather(city):

return requests.get(f"https://api.weather.com/{city}").json()

```

  • 중복 요청 시: 10번 호출 시 500ms → 0.05ms로 감소
  • DB 쿼리 최적화

```python

@lru_cache(maxsize=64)

def fetch_user_profile(user_id):

return User.objects.get(id=user_id)

```

  • 100번 요청 시: 10ms → 0.01ms
  1. 고급 팁 및 주의사항
  • maxsize 조정:
  • maxsize=None: 무한 캐시 (메모리 사용 주의)
  • maxsize=128: 제한된 메모리 사용
  • 타입 구분: typed=True11.0구분된 키로 처리
  • 가변 인자 처리: 리스트/딕셔너리 → 튜플/불변 집합으로 변환
  • 캐시 관리: expensive_operation.cache_clear()로 수동 초기화
  1. 성능 비교

| 시나리오 | 무캐시 시간 | lru_cache 시간 | 속도 향상 비율 |

|-----------------------|----------------|------------------|----------------|

| 피보나치(35) 재귀 | ~1.2초 | ~20마이크로초 | 60,000배 |

| API 호출(10번) | ~500ms/호출 | ~0.05ms/호출 | 10,000배 |

| DB 쿼리(100번) | ~10ms/쿼리 | ~0.01ms/쿼리 | 1,000배 |

  1. 문제 해결 및 팁
  • 메모리 사용 과다: maxsize 값을 합리적으로 설정
  • 가변 인자 문제: tuple()/frozenset()으로 전환
  • 사이드 이펙트: 순수 함수만 캐시 (I/O/상태 변경 함수는 피함)
  • 디스크 기반 캐시: diskcache와 결합하여 재시작 시 데이터 보존
  • 비동기 함수: async-lru 라이브러리 사용

결론

- 핵심 팁: timeit 또는 프레임워크 프로파일링 도구로 환경별 실제 성능 측정

- 실무 적용: 핫스팟 함수 식별 후 @lru_cache 적용 및 maxsize/typed 옵션 조정

- 추천: lru_cache은 성능 향상, 지연 감소, 확장성 향상의 전략적 도구로 활용해야 함