LFU

AI
gemma-4-31b
작성자
익명
작성일
2026.07.16
조회수
14
버전
v1

LFU (Least Frequently Used)

1. 개요

LFU(Least Frequently Used)캐시 메모리가 가득 찼을 때, 참조 횟수가 가장 적은 항목을 우선적으로 제거하여 새로운 데이터를 수용하는 캐시 교체 알고리즘이다.

캐시 교체 알고리즘의 핵심 목적은 한정된 메모리 공간 내에서 '히트율(Hit Rate, 요청한 데이터가 캐시에 존재할 확률)'을 극대화하는 것이다. LFU는 데이터의 참조 빈도(Frequency)가 미래의 참조 가능성을 예측하는 지표가 된다는 가정하에, 가장 덜 사용된 데이터를 제거함으로써 빈번하게 사용되는 '핫 데이터(Hot Data)'를 최대한 오래 유지하려는 전략을 취한다.

2. 동작 원리

LFU는 각 캐시 항목마다 참조 횟수(Frequency Count)를 기록하는 카운터를 유지한다. 데이터가 요청될 때마다 해당 항목의 카운터를 1씩 증가시키며, 캐시 공간이 부족하여 새로운 데이터를 삽입해야 할 때 카운터 값이 가장 낮은 항목을 찾아 제거한다. 만약 최저 빈도수가 동일한 항목이 여러 개 존재할 경우, 일반적으로 LRU(Least Recently Used) 방식을 적용하여 가장 오래전에 사용된 항목을 제거한다.

[예시] 캐시 크기가 3인 경우의 동작 과정

요청 데이터 캐시 상태 (데이터: 빈도수) 제거 대상 비고
A {A: 1} - 신규 삽입
B {A: 1, B: 1} - 신규 삽입
C {A: 1, B: 1, C: 1} - 신규 삽입 (Full)
A {A: 2, B: 1, C: 1} - A 빈도수 증가
D {A: 2, D: 1, C: 1} B B와 C의 빈도수가 1로 동일하므로, 더 먼저 진입한 B를 제거(LRU 적용)
D {A: 2, D: 2, C: 1} - D 빈도수 증가
E {A: 2, D: 2, E: 1} C 최저 빈도수 C 제거

3. LFU의 특징 및 장단점

특징 및 장점

  • 빈도 기반 최적화: 특정 데이터가 반복적으로 요청되는 패턴(Static Popularity)이 강한 환경에서 매우 높은 효율을 보인다.
  • 안정적인 핫 데이터 유지: 한 번 빈도수가 높게 쌓인 데이터는 일시적인 다른 데이터의 유입으로 인해 쉽게 제거되지 않는다.

단점 및 한계

  • 캐시 오염(Cache Pollution): 과거에 매우 빈번하게 사용되었으나 현재는 더 이상 사용되지 않는 데이터가 높은 빈도수 때문에 캐시에 계속 남아있는 현상이 발생한다.
  • 초기 진입 장벽: 새로 진입한 데이터는 빈도수가 1이므로, 기존 데이터들의 빈도수가 높을 경우 즉시 제거될 가능성이 커 '새로운 핫 데이터'가 정착하기 어렵다.

LFU vs LRU 비교

비교 항목 LFU (Least Frequently Used) LRU (Least Recently Used)
판단 기준 참조 횟수 (Frequency) 마지막 참조 시간 (Recency)
핵심 가정 많이 사용된 것이 앞으로도 사용될 것이다. 최근에 사용된 것이 앞으로도 사용될 것이다.
강점 반복적 요청 패턴에 강함 최근 트렌드 변화에 빠르게 적응함
약점 과거의 높은 빈도수가 현재를 가림 (오염) 일시적인 대량 스캔 시 유용한 데이터가 밀려남

4. 구현 방법 및 복잡도

구현 전략

LFU를 효율적으로 구현하기 위해서는 빈도수 관리와 데이터 접근 속도를 모두 잡아야 한다. 1. Hash Map: 키(Key)를 통해 데이터와 해당 데이터의 빈도수, 그리고 빈도수별 리스트 내 위치를 $O(1)$에 찾기 위해 사용한다. 2. Doubly Linked List (빈도수별 그룹화): 동일한 빈도수를 가진 항목들을 연결 리스트로 관리하여, 최저 빈도수 그룹 내에서 LRU 방식으로 제거 대상을 선정한다. 3. Min-Heap: 모든 항목의 빈도수를 힙으로 관리하여 최솟값을 빠르게 찾을 수 있으나, 업데이트 시 $O(\log N)$의 시간이 소요된다.

복잡도 요약

구현 방식 시간 복잡도 (접근/삽입/삭제) 공간 복잡도 특징
단순 리스트/배열 $O(N)$ $O(N)$ 구현이 간단하나 성능이 매우 낮음
Min-Heap $O(\log N)$ $O(N)$ 빈도수 최솟값 탐색에 유리
Hash Map + DLL $O(1)$ $O(N)$ 최적의 성능, 구현 복잡도 높음

Python 예제 코드

import collections

class LFUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.min_freq = 0
        self.key_to_val = {} # {key: value}
        self.key_to_freq = {} # {key: freq}
        self.freq_to_keys = collections.defaultdict(collections.OrderedDict)

    def get(self, key: int) -> int:
        if key not in self.key_to_val:
            return -1
        
        # 빈도수 업데이트 로직
        freq = self.key_to_freq[key]
        self.freq_to_keys[freq].pop(key)
        
        # 현재 최저 빈도수 그룹이 비었는지 확인 후 갱신
        if not self.freq_to_keys[self.min_freq]:
            self.min_freq += 1
            
        self.key_to_freq[key] = freq + 1
        self.freq_to_keys[freq + 1][key] = None
        return self.key_to_val[key]

    def put(self, key: int, value: int) -> None:
        if self.capacity == 0: 
            return
        
        if key in self.key_to_val:
            self.key_to_val[key] = value
            self.get(key) # 빈도수 갱신을 위해 get 호출
            return

        if len(self.key_to_val) >= self.capacity:
            # 최저 빈도수 그룹에서 가장 오래된 항목(LRU) 제거
            evict_key, _ = self.freq_to_keys[self.min_freq].popitem(last=False)
            del self.key_to_val[evict_key]
            del self.key_to_freq[evict_key]

        # 신규 데이터 삽입
        self.key_to_val[key] = value
        self.key_to_freq[key] = 1
        self.min_freq = 1
        self.freq_to_keys[1][key] = None

5. 한계점 및 개선 방안

에이징(Aging) 기법

LFU의 최대 단점인 '과거의 높은 빈도수' 문제를 해결하기 위해 에이징(Aging) 기법을 도입한다. 이는 시간이 지남에 따라 기존의 빈도수 값을 점진적으로 감소시켜, 현재 시점의 참조 빈도가 더 중요하게 반영되도록 하는 방식이다.

[에이징 동작 과정] 1. 참조 발생: 요청된 데이터의 카운트를 증가시킨다. 2. 주기 도달: 설정된 일정 주기(T)가 경과한다. 3. 카운트 감소: 모든 항목의 카운트를 $\frac{1}{2}$로 감소(Shift Right)시킨다. 4. 반복: 위 과정을 반복하여 오래된 데이터의 영향력을 점차 줄인다.

이 과정을 통해 오래전에 많이 사용되었지만 현재는 사용되지 않는 데이터의 카운트가 자연스럽게 낮아져, 결국 제거 대상이 되도록 유도한다.

6. 최신 변형 알고리즘: W-TinyLFU

전통적인 LFU의 메모리 오버헤드와 캐시 오염 문제를 해결하기 위해 등장한 W-TinyLFU(Window TinyLFU)는 현대적인 고성능 캐시 라이브러리(예: Caffeine Cache)에서 사용된다.

  • Admission Policy: 새로운 데이터가 들어올 때 무조건 삽입하는 것이 아니라, 현재 제거 대상이 될 데이터와 새로운 데이터의 빈도수를 비교하여 더 가치 있는 데이터만 수용한다.
  • Count-Min Sketch: 모든 키의 빈도수를 정확히 저장하는 대신, 확률적 자료구조인 Count-Min Sketch(해시 함수를 이용하여 메모리 사용량을 최소화하며 빈도수를 근사치로 계산하는 알고리즘)를 사용하여 메모리 사용량을 획기적으로 줄이면서 빈도수를 추정한다.
  • 구조: Window LRU (최근 데이터 보호) $\rightarrow$ Probation Segment (빈도수 검증) $\rightarrow$ Main Segment (검증된 핫 데이터 유지)의 다단계 구조를 가진다.

7. 활용 사례

  • 데이터베이스 버퍼 풀: 자주 액세스되는 인덱스 페이지나 테이블 데이터를 메모리에 유지하여 디스크 I/O를 줄이는 데 사용된다.
  • 네트워크 패킷 캐싱: 특정 목적지로 향하는 빈번한 요청 패킷의 경로 정보를 캐싱하여 라우팅 속도를 높일 때 적용된다.
  • 콘텐츠 전송 네트워크(CDN): 전 세계적으로 요청 빈도가 매우 높은 인기 콘텐츠(Viral Content)를 엣지 서버에 우선 배치하는 전략에 LFU 개념이 활용된다.

분류: 기술 / 캐시 관리 / 치환 정책

AI 생성 콘텐츠 안내

이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.

주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.

이 AI 생성 콘텐츠가 도움이 되었나요?