페이지 교체 (Page Replacement)
핵심 인사이트 (3줄 요약)
- 본질: 페이지 교체는 시스템의 물리적 메모리(RAM)가 꽉 찼을 때, CPU가 새로 요구한 페이지를 적재하기 위해 현재 램에 올라와 있는 페이지 중 하나를 골라 디스크(Swap)로 내쫓는(Swap-out) 운영체제의 생존 매커니즘이다.
- 가치: 이 메커니즘 덕분에 실제 물리 메모 용량의 한계를 초월하여 수백 GB의 가상 메모리(Virtual Memory)를 사용자에게 제공할 수 있는 궁극의 **다중 프로그래밍 환상(Illusion)**이 완성된다.
- 융합: "누구를 내쫓을 것인가?"를 결정하는 교체 알고리즘(LRU, LFU, Clock 등)은 참조의 지역성(Locality)이라는 통계적 법칙과 융합하여, 페이지 폴트(Page Fault)를 최소화하고 스래싱(Thrashing)을 방어하는 최전선 방어막 역할을 수행한다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
- 개념: 빈 프레임(Free Frame)이 0개인 상태에서 페이지 폴트가 발생했을 때, OS가 희생양(Victim) 페이지를 선정하여 디스크에 쓰고 빈 공간을 확보한 뒤, 그 자리에 새로운 페이지를 올려놓는 일련의 과정이다.
- 필요성: 컴퓨터의 램(RAM)은 유한하지만 프로그램의 욕심은 무한하다. 16GB 램을 가진 컴퓨터에서 30GB짜리 게임과 10GB짜리 크롬을 동시에 실행하면 언젠가는 램이 100% 꽉 차게 된다. 꽉 찼다고 컴퓨터를 멈추거나 에러를 뱉게 할 순 없다. "안 쓰는 짐을 창고에 던져놓고 새 짐을 들여오자"는 우아한 타협이 필요했다.
- 💡 비유: 도서관(RAM) 책상에 책을 더 펼칠 자리가 없을 때, **'새 책을 펴기 위해 당장 안 읽고 있는 책 한 권을 골라 지하 서고(디스크)에 반납하는 행위'**와 정확히 일치한다.
- 등장 배경: 요구 페이징(Demand Paging) 시스템이 활성화되면서 "디스크에서 가져오는 기술"은 완성되었으나, "어떻게 자리를 비워줄 것인가"에 대한 최적화가 운영체제 성능의 99%를 좌우하게 되었다. 1970년대 벨 연구소 등에서 최적(Optimal) 교체부터 LRU까지 수많은 알고리즘이 쏟아져 나오며 학문적 전성기를 맞이했다.
[페이지 교체(Page Replacement)의 4단계 라이프사이클]
[ 🚨 물리 메모리(RAM) 100% Full 상태에서 Page Fault 발생! ]
1. 희생자 선정 (Victim Selection)
▶ OS 스케줄러: "LRU 알고리즘 돌려봐! 제일 안 쓴 놈 누구야?"
▶ "Frame 3번에 있는 Page A가 1시간째 안 쓰였습니다!"
2. Swap-Out (디스크 쓰기)
▶ Page A가 램에 올라온 이후로 값이 수정(Dirty)되었다면, 디스크에 덮어쓴다.
▶ (수정 안 됐으면 덮어쓸 필요 없이 그냥 버림. 속도 개이득!)
▶ 페이지 테이블에서 Page A의 상태를 Invalid(i)로 바꾼다.
3. Swap-In (새 페이지 적재)
▶ 방금 비워진 Frame 3번 자리에, 지금 당장 필요한 Page B를 디스크에서 퍼 올린다.
4. 테이블 갱신 및 재시작
▶ 페이지 테이블에 "Page B는 Frame 3에 있음"을 적고 Valid(v)로 켠다.
▶ 멈췄던 CPU 명령어를 다시 실행한다.
[다이어그램 해설] 페이지 교체는 단순히 자리를 바꾸는 게 아니다. "디스크 쓰기(Swap-Out)"와 "디스크 읽기(Swap-In)"라는 최악의 오버헤드가 연속으로 터지는(최대 2,000만 ns 소요) 끔찍한 과정이다. 운영체제가 이 과정을 얼마나 덜 일어나게(Page Fault Rate 감소) 알고리즘을 짜느냐가 아키텍트의 실력을 증명한다.
- 📢 섹션 요약 비유: 냉장고(RAM)가 꽉 찼는데 마트에서 수박(새 페이지)을 사 왔습니다. 수박을 넣으려면 유통기한이 지났거나 안 먹는 반찬(Victim)을 골라 쓰레기통(디스크)에 버려야 합니다. 이때, 내일 아침 당장 먹을 반찬을 버리면 낼 아침에 또 마트에 가야 하는 대참사가 일어납니다. 누구를 버릴지 고르는 센스가 교체의 핵심입니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
교체 대상 선정을 위한 2가지 하드웨어 비트 (Hardware Bits)
OS가 소프트웨어로만 "누가 가장 오래됐나?"를 추적하면 CPU가 터진다. 그래서 CPU 내장 MMU 하드웨어가 페이지 테이블에 2개의 힌트 비트를 몰래 적어둔다.
- Reference Bit (참조 비트 / Accessed Bit)
- 의미: "최근에 이 페이지를 누군가 한 번이라도 읽거나 썼는가?"
- 동작: CPU가 이 페이지를 건드리는 순간 하드웨어가 0에서 1로 바꾼다. OS는 가끔씩 이걸 0으로 초기화해 주며, 교체 시 1인 놈은 살려주고 0인 놈을 죽인다.
- Dirty Bit (수정 비트 / Modify Bit)
- 의미: "이 페이지가 램에 올라온 이후로 내용이 변경되었는가?"
- 동작: CPU가 이 페이지에
Write명령을 때리는 순간 1로 바뀐다. - 가치 (극강의 최적화): 만약 희생자로 선정된 페이지가 Dirty Bit = 0 이라면? 램과 디스크의 내용이 100% 똑같다는 뜻이므로, 굳이 디스크에 쓸(Swap-out) 필요 없이 그냥 램에서 지워버려도 무방하다. 디스크 I/O 시간을 절반으로 줄여주는 최고의 치트키다.
교체의 2대 철학: Global vs Local Replacement
램이 부족할 때 "누구의 것을 뺏을 것인가?"에 대한 운영체제의 철학적 선택이다.
-
전역 교체 (Global Replacement):
- "시스템 전체의 모든 페이지 중 만만한 놈 뺏어!"
- A가 메모리가 부족하면, 잘 돌고 있는 B나 C의 메모리도 뺏어버린다.
- 장점: 전체 램의 효율성이 극대화된다. 단점: A 때문에 C가 렉이 걸리는 연대 책임(스래싱 전염)이 발생한다. (현대 Windows, Linux의 기본 정책).
-
지엽적 교체 (Local Replacement):
- "너한테 할당된 프레임 풀 안에서만 뺏고 버려!"
- A가 메모리 부족하면 A가 쓰던 옛날 페이지만 버릴 수 있다.
- 장점: 한 놈의 렉이 다른 프로세스에 절대 전이되지 않는다(안정성). 단점: A는 터지기 일보 직전인데 B의 메모리가 텅텅 비어있어도 빌려 쓸 수 없어 전체 시스템 효율이 박살 난다.
-
📢 섹션 요약 비유: Global 교체는 공산주의식 징발입니다. "국가(OS)가 급하니까 옆집 부자의 쌀통(메모리)을 털어서 배고픈 놈한테 줘라!" Local 교체는 철저한 자본주의입니다. "네가 배고프면 네가 가진 낡은 구두를 팔아서 쌀을 사라, 남의 집 쌀은 절대 못 건드린다!"
Ⅲ. 융합 비교 및 다각도 분석 (Comparison & Synergy)
페이지 교체 알고리즘 3대장 스펙 비교
"미래를 아는 신(OPT)" vs "과거를 기억하는 자(LRU)" vs "시계바늘을 돌리는 자(Clock)"
| 알고리즘 | 선정 기준 (누구를 쫓아내는가?) | 구현 난이도 | 특징 및 한계 |
|---|---|---|---|
| OPT (Optimal) | **"미래에 가장 오~랫동안 안 쓸 놈"**을 쫓아냄 | 구현 불가 (신만이 미래를 안다) | 모든 알고리즘 성능 평가의 비교 기준점(Theoretical Bound) 역할. |
| FIFO | "메모리에 가장 먼저 들어온(오래된) 놈" 쫓아냄 | 극강 단순 (큐 구조) | Belady's Anomaly(모순) 발생! 램을 늘려줬는데 오히려 폴트가 더 터짐. |
| LRU (Least Recently Used) | "과거에 가장 오~랫동안 안 쓴 놈" 쫓아냄 | 이론상 쉬우나 실무에선 무거움 | 참조 지역성을 가장 잘 반영한 황제. (단, 연결 리스트 오버헤드가 큼). |
LRU의 실무적 한계와 클럭(Clock) 알고리즘의 탄생
교과서에서는 LRU가 최고라고 배운다. 하지만 프로세스가 메모리를 참조할 때마다(1초에 수억 번) LRU 연결 리스트의 순서를 맨 뒤로 옮기는 짓을 OS가 하면 CPU는 다른 연산을 아무것도 못 한다. 현대 OS의 타협 (Clock / NUR 알고리즘):
-
OS는 1초에 수억 번 감시하는 걸 포기했다.
-
대신 프레임들을 시계 모양(원형 큐)으로 배치하고, 바늘(Pointer)이 빙글빙글 돈다.
-
바늘이 가리키는 페이지의
Reference Bit를 본다.- 1이면? "최근에 썼구나, 기회를 한 번 더 줄게!" 하고 0으로 바꾼 뒤 다음 바늘로 넘어간다.
- 0이면? "내가 한 바퀴 돌고 올 때까지 한 번도 안 썼네? 넌 아웃!" 하고 즉시 교체해 버린다.
-
이 Clock(Second-Chance) 기법이 바로 현대 리눅스와 윈도우, 데이터베이스 버퍼 풀이 사용하는 실전용 LRU 근사치 알고리즘이다.
-
📢 섹션 요약 비유: 진짜 LRU는 백화점 주차요원이 "이 차가 정확히 몇 시 몇 분에 들어왔는지" 초 단위로 장부를 쓰는 겁니다(과로사). Clock 알고리즘은 요원이 주차장을 빙빙 돌면서, 차 유리에 먼지가 없으면(Ref=1) 먼지를 묻히고(Ref=0) 지나갑니다. 한 바퀴 돌고 왔는데 여전히 먼지가 쌓여있으면(Ref=0) 오랫동안 안 탔다고 확신하고 견인해 버리는 천재적인 꼼수입니다.
Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)
실무 시나리오
- Linux 서버의 Swappiness 파라미터 튜닝: 시스템 엔지니어가 리눅스 서버 커널을 튜닝할 때 가장 먼저 건드리는 값이다.
vm.swappiness(0 ~ 100): "OS야, 램이 부족할 때 파일 캐시(Page Cache)를 먼저 버릴래, 아니면 유저 애플리케이션의 메모리를 스왑 아웃(Swap-out) 시킬래?"를 결정하는 성향 값이다.- 실무 튜닝: 디폴트 60을 쓰면 DB 서버가 수시로 앱 메모리를 디스크로 내쫓아버려(Swap-out) API 지연이 1초씩 튄다.
- 아키텍트 결단: Hadoop이나 Elasticsearch 같은 메모리 깡패 서버에서는 무조건
swappiness = 1또는0으로 세팅한다. "애플리케이션 메모리는 절대 내쫓지 말고(Swap 금지), 차라리 OS가 쥐고 있는 파일 캐시를 먼저 쫓아내라!"라고 강제하여 스래싱을 막는다.
- LRU Cache (Redis, Memcached)의 만능화: OS의 페이지 교체 이론은 백엔드 애플리케이션의 아키텍처로 100% 이식되었다.
- Redis(인메모리 캐시)를 쓸 때, 메모리가
maxmemory에 도달하면 데이터를 어떻게 버릴지 정책을 정해야 한다. allkeys-lru: Redis에 들어있는 모든 키 중 가장 오래 안 쓴 놈을 지운다. (LRU의 완벽한 실무적 현현).- 이 설정 하나만 잘 맞춰도 DB로 쏟아지는 트래픽의 90%를 막아내고 "스스로 오래된 찌꺼기를 치우며 자가 생존하는" 무한 캐시 시스템이 완성된다.
- Redis(인메모리 캐시)를 쓸 때, 메모리가
┌──────────────────────────────────────────────────────────────────────┐
│ 백엔드 In-Memory 시스템 캐시 교체 정책(Eviction Policy) 트리 │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ [요구사항: 10GB 용량의 Redis 캐시 서버 운영. 꽉 찼을 때 어떡할까?] │
│ │
│ [ 1. No Eviction (버리지 않음) ] │
│ ▶ 작동: 10GB 꽉 차면 OOM 에러 뱉고 새 데이터 쓰기 거부! │
│ ▶ 사용처: 절대로 데이터가 유실되면 안 되는 '세션 저장소' 등. │
│ │
│ [ 2. AllKeys-LRU (가장 안 쓰는 놈 버림) ] │
│ ▶ 작동: 최근에 찾지 않은 오래된 캐시부터 조용히 날려버림. │
│ ▶ 사용처: 웹페이지 HTML 캐싱, 상품 정보 (90% 실무의 디폴트). │
│ │
│ [ 3. AllKeys-LFU (가장 인기 없는 놈 버림) ] │
│ ▶ 작동: 빈도수(Frequency)를 체크하여, 가장 조회수가 낮은 놈 처형.│
│ ▶ 사용처: 최신순보다 "누적 인기순"이 중요한 랭킹 시스템 보드 등. │
└──────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] "메모리가 부족하면 지워라"라는 OS의 철학을 100% 이해한 개발자는, Redis나 애플리케이션 로컬 캐시(Caffeine Cache)를 짤 때도 반드시 이 Eviction Policy(교체 정책)를 설계에 박아 넣는다. 쫓아내는 정책(LRU)이 없는 캐시는 캐시가 아니라 곧 서버를 찢어발길 '메모리 릭(Memory Leak)' 시한폭탄에 불과하다.
- 📢 섹션 요약 비유: 구글 포토 용량(15GB)이 꽉 찼을 때, 1번 정책은 "더 이상 사진 못 찍음(에러)"입니다. 2번 LRU 정책은 "10년 전에 찍고 한 번도 안 열어본 옛날 사진부터 몰래 지우기"입니다. 3번 LFU 정책은 "최근에 찍었더라도 내가 하트(빈도수)를 안 누른 인기 없는 사진부터 지우기"입니다. 목적에 맞게 버리는 기술이 캐싱의 전부입니다.
Ⅴ. 기대효과 및 결론 (Future & Standard)
기대효과
페이지 교체 알고리즘(LRU, Clock)을 완벽하게 튜닝하면, 물리적 메모리가 16GB밖에 없는 서버라도 수십 명의 사용자가 체감하는 페이지 폴트(렉)를 1% 미만으로 억제하며 100GB급 서버처럼 느끼게 만드는 마술 같은 가용성 확장을 이룩할 수 있다.
결론 및 미래 전망
페이지 교체 기술은 하드 디스크 시대의 1,000만 나노초에 달하는 지연을 덮기 위해 잉태된 방어막이었다. 하지만 NVMe SSD가 RAM의 속도를 맹추격하고, 클라우드의 노드(서버) 스펙이 RAM 1TB를 우습게 넘기면서, 이 무거운 스왑-아웃(교체) 시스템은 오히려 계륵이 되고 있다. K8s 중심의 클라우드 네이티브 환경은 "느리게 램을 비우며(Swap) 버티지 말고, 차라리 쿨하게 죽고(OOM Kill) 새 컨테이너를 다른 노드에 띄워라(Fail-fast)"라는 철학으로 선회했다. 미래에는 디스크와 램이 교체되는 것이 아니라, CXL(Compute Express Link) 기반의 **메모리 풀링(Memory Pooling)**을 통해 여러 대의 서버가 하나의 거대한 RAM을 랙(Rack) 단위로 동적 공유하며, 페이지를 '디스크로 내쫓는' 대신 '옆 서버의 남는 램으로 빛의 속도로 이사 보내는' 진정한 초연결 메모리 시대로 진화할 것이다.
- 📢 섹션 요약 비유: 옛날엔 내 방(RAM)에 짐이 꽉 차면 무조건 지하 창고(디스크)에 버리고 왔습니다(페이지 교체). 미래의 시스템(CXL, 클라우드)은 내 방이 꽉 차면 벽이 스르륵 열리면서 옆집 빈방(다른 서버의 RAM)과 연결되어, 창고에 다녀올 필요 없이 1초 만에 짐을 옆방으로 밀어버리는 무한 확장의 공간 마법을 실현합니다.
📌 관련 개념 맵 (Knowledge Graph)
| 개념 명칭 | 관계 및 시너지 설명 |
|---|---|
| 가상 메모리 (Virtual Memory) | 페이지 교체가 존재하기 때문에 비로소 "무한한 메모리"라는 사기가 완성되는 시스템 전체 틀이다. |
| 요구 페이징 (Demand Paging) | 페이지 교체가 "누굴 내쫓을까?"라면, 요구 페이징은 "누굴 데려올까?"를 결정하는 쌍둥이 기술이다. |
| 참조의 지역성 (Locality) | LRU 알고리즘이 "과거를 보면 미래를 알 수 있다"고 확신하며 낡은 놈을 쫓아내게 만든 수학적 통계 근거다. |
| 페이지 폴트 (Page Fault) | 램이 꽉 찼을 때 이 사이렌이 울려야만 페이지 교체(Victim 선정) 메커니즘이 강제로 가동된다. |
| 스래싱 (Thrashing) | 페이지 교체 알고리즘(LRU)이 오판을 거듭하며 엉뚱한 놈을 내쫓았다 데려왔다 반복할 때 터지는 재앙이다. |
👶 어린이를 위한 3줄 비유 설명
- 내 책상(RAM)에는 책을 3권만 놓을 수 있는데, 4번째 책을 보려면 어떻게 해야 할까요? 맞아요, 지금 책상에 있는 3권 중 1권을 서랍(디스크)에 넣어야 해요.
- 이때 **"어떤 책을 서랍에 넣을까?"**를 고민하는 게 바로 페이지 교체예요.
- 가장 똑똑한 방법(LRU 알고리즘)은 "가장 오~~래동안 한 번도 안 들여다본 먼지 쌓인 책"을 고르는 거랍니다. 그래야 당장 또 찾을 일이 적으니까요!