1. 서론: 캐싱의 필요성과 파이썬에서의 선택지
데이터를 반복적으로 계산하거나 외부에서 받아오는 작업은 시간이 오래 걸린다. 예를 들어, 복잡한 수학 계산, API 호출, 대용량 파일 읽기 등의 작업이 그럴 수 있다. 이런 작업을 매번 새로 하지 않고 결과를 저장해두었다가 재사용하면 실행 속도가 빨라지고 효율이 올라간다. 이를 "캐싱"이라고 합니다.
파이썬에서는 다양한 방법으로 캐싱을 구현할 수 있다. 메모리에 저장하는 functools.lru_cache, 파일 기반으로 저장하는 pickle, 혹은 Redis와 같은 외부 시스템을 사용하는 방식이 있다. 이 글에서는 가장 직관적이고 간단한 방식인 pickle 모듈을 활용하여 캐싱을 구현하는 방법을 다룬다.
2. pickle 모듈 개요
pickle은 파이썬의 객체를 바이트 스트림으로 직렬화(serialize)하거나, 그 반대로 역직렬화(deserialize)할 수 있도록 도와주는 내장 모듈이다.
import pickle
# 예시: 리스트를 pickle로 저장하고 다시 불러오기
numbers = [1, 2, 3, 4, 5]
with open("numbers.pkl", "wb") as f:
pickle.dump(numbers, f)
with open("numbers.pkl", "rb") as f:
loaded = pickle.load(f)
print(loaded) # [1, 2, 3, 4, 5]
pickle은 리스트, 딕셔너리, 클래스 인스턴스 등 대부분의 파이썬 객체를 지원한다. 단, 외부 라이브러리 객체나 네트워크 연결, 파일 핸들 등은 저장되지 않을 수 있으므로 주의가 필요하다.
3. 캐싱에 pickle을 사용하는 기본 구조
캐싱의 핵심은 결과가 이미 존재하면 다시 계산하지 않고, 기존 결과를 사용하는 것이다. 이를 위해 캐시 파일이 있는지 확인하고, 있다면 불러오고 없다면 계산 후 저장하는 구조로 구성된다.
다음 간단한 예제를 살펴보자.
import os
import pickle
def cached_function(x):
cache_file = f"cache_{x}.pkl"
if os.path.exists(cache_file):
with open(cache_file, "rb") as f:
print("캐시에서 불러옵니다.")
return pickle.load(f)
print("계산 중...")
result = x * x # 예: 무거운 계산
with open(cache_file, "wb") as f:
pickle.dump(result, f)
return result
print(cached_function(5))
print(cached_function(5))
첫 번째 호출에서는 계산이 수행되고, 두 번째 호출에서는 캐시된 파일을 사용한다.
4. 실전 예제: API 결과 캐싱
실제로는 외부 API를 반복적으로 호출하는 경우가 많다. 예를 들어, 뉴스 API나 환율 정보 API 등은 호출 비용이 크고 제한이 있을 수 있다. 이를 pickle을 통해 캐싱할 수 있다.
import os
import pickle
import time
import requests
def fetch_exchange_rate():
cache_file = "exchange_rate.pkl"
expire_seconds = 3600 # 1시간 캐시 유지
if os.path.exists(cache_file):
modified = os.path.getmtime(cache_file)
if time.time() - modified < expire_seconds:
with open(cache_file, "rb") as f:
print("캐시된 환율 데이터를 사용합니다.")
return pickle.load(f)
print("API에서 환율 데이터를 가져옵니다.")
response = requests.get("https://api.exchangerate-api.com/v4/latest/USD")
data = response.json()
with open(cache_file, "wb") as f:
pickle.dump(data, f)
return data
rate = fetch_exchange_rate()
print(rate["rates"]["KRW"])
5. 마무리: 언제 pickle 캐싱을 선택할 것인가?
pickle 기반 캐싱은 간단하고 강력하지만 다음과 같은 상황에서 특히 유용하다.
- 단일 사용자 환경: 파일에 동시에 접근하지 않으므로 충돌 위험이 적다.
- 복잡한 데이터 저장 필요: 리스트나 딕셔너리, 클래스 객체 등 다양한 형태의 데이터를 저장할 수 있다.
- 빠른 구현이 필요한 실험 코드: 머신러닝, 데이터 분석, 스크립트 자동화 등
하지만 보안상 pickle 파일은 신뢰할 수 없는 환경에서 열지 않는 것이 좋다. pickle은 임의의 코드를 실행할 수 있으므로, 외부에서 전달된 파일은 반드시 검증 후 사용해야 한다.
성능, 보안, 확장성 등이 중요한 상황에서는 JSON, sqlite, joblib, Redis 등 대체 기술을 사용하는 것이 바람직하다. 그러나 간단한 캐싱이 필요할 때는 pickle이 매우 유용한 도구가 될 수 있다.
'잡(job)기술' 카테고리의 다른 글
| CMake --preset: 더 이상 길고 복잡한 빌드 명령어에 시달리지 말자 (1) | 2025.06.28 |
|---|---|
| Node.js child_process의 exec와 spawn 차이 정리 (0) | 2025.06.20 |
| TypeORM 마이그레이션 사용하기: 안전한 데이터베이스 관리를 위한 단계별 가이드 (0) | 2025.05.30 |
| gst-rtsp-server 시그널 이해하기: media-configure와 media-constructed (0) | 2025.05.16 |
| PM2에서 ecosystem.config.js를 사용하는 이유와 장점 (0) | 2025.05.15 |