중기 스케줄러 (Medium-term Scheduler)와 스와핑
핵심 인사이트 (3줄 요약)
- 본질: 중기 스케줄러 (Medium-term Scheduler)는 메모리 공간이 부족하거나 시스템의 성능 저하(스래싱)가 우려될 때, 메모리에 적재된 프로세스를 일시적으로 디스크 스왑 영역(Swap Space)으로 쫓아내어(Swap-out) 가용 메모리를 확보하는 메모리 관리 스케줄러이다.
- 가치: 다중 프로그래밍 정도 (Degree of Multiprogramming)를 동적으로 완화시킴으로써 시스템이 심각한 성능 저하에 빠지는 것을 막아주는 핵심적인 방어 기제 역할을 한다.
- 융합: 가상 메모리 (Virtual Memory) 환경의 발달로 전통적인 전체 프로세스 단위의 중기 스케줄링보다는, 페이지 단위 교체(Page Replacement) 메커니즘과 긴밀하게 통합되어 동작하게 되었다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
- 개념: 중기 스케줄러 (Medium-term Scheduler)는 실행 중인, 혹은 대기 중인 프로세스 일부를 물리적 주 메모리에서 일시적으로 제거(Swap-out)하고, 나중에 자원에 여유가 생기면 다시 적재(Swap-in)하여 중단된 지점부터 실행을 재개시키는 스케줄러이다.
- 필요성: 시스템에 너무 많은 프로세스가 동시에 로드되어 실행되려 하면, 각 프로세스에 할당되는 메모리 양이 줄어들어 잦은 페이지 부재(Page Fault)를 발생시키는 스래싱(Thrashing) 상태에 돌입할 수 있다. 이때 누군가는 강제로 프로세스를 멈추고 밖으로 빼내어 다중 프로그래밍 정도를 낮춰야 시스템 전체가 살아나게 된다.
- 💡 비유: 인기 있는 식당에서 손님들이 한 번에 몰려 음식이 극도로 늦게 나오는 상황일 때, 식당 지배인이 대기석에 있던 일부 손님들을 근처 카페로 잠시 내보내 식당 내부의 혼잡도를 줄여 정상적인 서빙 속도를 회복시키는 **'혼잡 통제 지배인'**과 같다.
- 등장 배경: 시분할 시스템에서 무수히 많은 사용자가 접속하게 되면서, 메모리는 한정되어 있음에도 단기 스케줄러에만 의존할 수 없는 거시적 메모리 오버로드 문제가 빈번해졌다. 시스템의 생존을 위해 메모리-디스크 간의 '스와핑(Swapping)' 메커니즘과 결합된 중간 계층의 스케줄러가 필수적으로 고안되었다.
[프로세스 상태 전이와 중기 스케줄러의 개입 (Swapping)]
(단기 스케줄러)
[Ready] ◀────────────────────────── [Running]
▲ │ │
│ │ ▼
Swap │ │ Swap [Waiting]
In │ │ Out │
│ ▼ │ (I/O 대기)
[Ready Suspended] ◀────────── [Waiting Suspended]
(중단됨) Swap Out (중단됨)
* Suspended(중지 상태): 프로세스가 주 메모리를 잃고 디스크로 쫓겨난 상태
[다이어그램 해설] 기존의 Ready/Running/Waiting 상태에 더하여 'Suspended (보류/중지)'라는 새로운 상태 공간이 존재함을 보여준다. 중기 스케줄러는 메모리가 극도로 부족할 때 주로 대기 상태 (Waiting)에 있는 프로세스를 1순위 타깃으로 삼아 디스크의 스왑 영역으로 쫓아낸다(Waiting Suspended). 만약 대기 상태의 프로세스가 I/O를 완료하면 메모리로 바로 오지 못하고 'Ready Suspended' 상태로 대기하다가, 메모리 여유가 생겼을 때 다시 Swap In 되어 메인 Ready 큐로 복귀한다.
- 📢 섹션 요약 비유: 비행기에 화물이 가득 차서 이륙이 위험해지면, 급하지 않은 짐을 잠시 물류 창고(디스크)에 내려놓아 비행의 안전(메모리 안정성)을 확보하는 항공기 수하물 조절 시스템과 같습니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
구성 요소
| 요소명 | 역할 | 내부 동작 | 관련 기술 | 비유 |
|---|---|---|---|---|
| 상태 감시기 (Load Monitor) | 시스템의 메모리 가용량과 스래싱 징후 감지 | Page Fault 빈도율 모니터링 | PFF (Page Fault Frequency) | 식당 혼잡도 센서 |
| 희생자 선택 로직 (Victim Selector) | 쫓아낼 프로세스 우선순위 결정 | Sleep 상태인 것, 우선순위 낮은 것 우선 | OOM (Out Of Memory) 스코어 계산 | 카페로 보낼 손님 선별 |
| 스와퍼 (Swapper) | 메모리-디스크 간 데이터 물리적 이동 | 디스크 I/O 발생, PCB 상태 변경 | Backing Store 접근 연산 | 짐차 운전수 |
심층 동작 원리 및 스와핑 (Swapping) 메커니즘
중기 스케줄러의 핵심 동작은 **스와핑 (Swapping)**이다. 스와핑은 실행을 위해 프로세스의 주소 공간 전체를 백킹 스토어(Backing Store, 디스크)로 내보내고(Swap-out), 나중에 다시 메모리로 가져오는(Swap-in) 일련의 입출력 과정이다.
- 상태 감지 및 트리거: 다중 프로그래밍 정도가 너무 높아 메모리 남은 용량이 임계치 이하로 떨어지면 중기 스케줄러가 깨어난다.
- 희생자 (Victim) 프로세스 선정: 무작위로 쫓아내는 것이 아니라, 현재 CPU를 사용하지 않고 I/O 이벤트를 대기 중인(Waiting) 프로세스를 1순위로 찾는다. 우선순위가 낮거나 메모리를 과다하게 차지하는 녀석도 후보가 된다.
- Swap Out 수행: 선정된 프로세스의 메모리 이미지를 디스크의 예약된 공간(Swap Area)으로 복사한다. 프로세스 제어 블록(PCB)의 상태를 'Suspended'로 마킹하고, 해당 물리 메모리(Frame)를 회수한다.
- 시스템 복원 대기: 다중 프로그래밍 정도가 낮아져 시스템 성능이 정상을 되찾을 때까지 대기한다.
- Swap In 수행: 디스크로 쫓겨났던 프로세스가 실행 가능한 상태(이벤트 완료)가 되고 메모리 여유가 확보되면, 다시 메모리의 가용 공간으로 복원시킨다. (이때 원래 있던 주소와 다른 곳에 적재될 수 있으므로 동적 주소 바인딩 지원이 필수적이다.)
┌───────────────────────────────────────────────────────────────────┐
│ 메모리와 디스크 간의 스와핑 동작 흐름 │
├───────────────────────────────────────────────────────────────────┤
│ │
│ [물리 메모리 (Main Memory)] │
│ ┌──────────┬──────────┬──────────┬──────────┐ │
│ │ OS │ 프로세스A │ 프로세스B │ 프로세스C │ │
│ └──────────┴──────────┴──────────┴──────────┘ │
│ │ ▲ │
│ 1. Swap Out │ │ 2. Swap In │
│ (메모리 부족 시)│ │ (메모리 여유 시) │
│ ▼ │ │
│ ┌───────────────────────────────────────────┐ │
│ │ [디스크 스왑 영역 (Swap Space)] │ │
│ │ (프로세스B 대기 중) │ │
│ └───────────────────────────────────────────┘ │
│ │
│ * 병목 지점: 디스크 I/O 속도가 스와핑 오버헤드를 압도적으로 지배 │
└───────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 프로세스 B가 우선순위가 낮거나 블록 상태일 때, 시스템 메모리가 부족해지면 중기 스케줄러에 의해 디스크의 스왑 공간으로 Swap Out 된다. 이 공간은 일반 파일 시스템과 분리된 로우 디스크(Raw Disk) 영역으로 구성하여 탐색 시간을 줄인다. 중요한 점은 디스크의 전송 시간 단위가 밀리초(ms) 규모이므로 스와핑 자체가 엄청난 오버헤드라는 점이다. 따라서 중기 스케줄러는 시스템 붕괴를 막기 위한 '최후의 보루'로서 극단적인 경우에만 동작해야 한다.
- 📢 섹션 요약 비유: 스마트폰에서 앱을 10개 켰을 때, 안 쓰던 앱이 뒷배경에서 얼어붙어(Freeze) 메모리에서 지워졌다가 다시 켜면 예전 위치부터 조금 느리게 로딩되는 과정과 정확히 같습니다.
Ⅲ. 융합 비교 및 다각도 분석 (Comparison & Synergy)
다중 프로그래밍 조절 스케줄러의 차이 (장기 vs 중기)
| 비교 항목 | 장기 스케줄러 (Long-term) | 중기 스케줄러 (Medium-term) |
|---|---|---|
| 조절 방식 | 프로세스의 최초 진입 자체를 통제 | 이미 들어온 프로세스의 메모리 잔류를 통제 |
| 시스템 개입 시점 | 시스템 생성/시작 시 부하 예측 | 실행 도중 동적 부하 (메모리 포화) 발생 시 |
| 운영체제 패러다임 | 과거 일괄 처리 (Batch) 시스템 특화 | 현대 시분할 (Time-sharing) 가상 메모리 특화 |
| 상태 전이 통제 | New → Ready | Ready/Waiting ↔ Suspended |
장기 스케줄러는 클럽의 '입구 컷(문지기)'이라면, 중기 스케줄러는 이미 클럽에 들어와 춤추던 사람을 '잠시 밖으로 내보내는 보안요원'의 역할이다. 현대 운영체제에서는 프로세스를 일단 띄워버리므로 장기 스케줄러의 역할은 미미해졌으며 중기 스케줄러 중심의 메모리 관리가 압도적으로 중요하다.
순수 스와핑 vs 페이지 단위 교체 (Paging 기반 Swapping)
┌──────────┬──────────────┬──────────────┬─────────────────────┐
│ 분류 │ 순수 스와핑 │ 페이지 스와핑 │ 판단 포인트 │
├──────────┼──────────────┼──────────────┼─────────────────────┤
│ 단위 │ 전체 프로세스 │ 고정 크기(Page)│ 스왑 해상도 │
│ I/O 부하 │ 매우 높음 │ 상대적으로 낮음 │ 시스템 오버헤드│
│ 현대 OS │ 거의 안 쓰임 │ 기본 채택 │ 가상메모리 결합│
└──────────┴──────────────┴──────────────┴─────────────────────┘
전통적인 중기 스케줄러는 수 MB~GB에 달하는 프로세스 메모리 전체를 썼다 지웠다(순수 스와핑) 하므로 전송 속도가 너무 느렸다. 현대 가상 메모리 기반 리눅스/윈도우에서는 전체를 내보내는 대신 '페이지(Page)' 단위로 쪼개어 스왑 아웃(Page Out)하는 방식을 취하며, 이 페이지 교체 알고리즘을 수행하는 데몬(kswapd)이 중기 스케줄러의 현대적 역할을 계승하고 있다.
- 📢 섹션 요약 비유: 무거운 책상 전체를 다른 방으로 옮기는 것(순수 스와핑)이 아니라, 당장 보지 않는 서랍의 책들만 조금씩 상자에 담아 내놓는 것(페이지 교체)으로 진화했습니다.
Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)
실무 시나리오
- OOM (Out Of Memory) 상황 방어: 리눅스 컨테이너(Docker/K8s) 환경에서 특정 Pod가 메모리를 과점유하여 전체 노드 메모리가 부족해지는 상황. 커널의 kswapd 데몬(중기 스케줄러 역할)이 활성화되어 사용 빈도가 낮은 페이지를 스왑 영역으로 내리기 시작한다. 그럼에도 부족하면 결국 OOM Killer가 작동하여 프로세스를 죽여버린다. 실무자는 스왑 공간 할당(Swapness)을 최소화하고 메모리 Limit을 강하게 걸어 스와핑에 의한 지연을 막을 것인지, 아니면 느려지더라도 죽는 것은 막을 것인지(Swap 활성화) 결정해야 한다.
- 스래싱 (Thrashing)에 의한 시스템 멈춤 (Hang) 현상: CPU 이용률은 극도로 낮은데 디스크 I/O (wa: IO-wait)는 100%를 치는 전형적인 스래싱 현상. 너무 많은 프로세스가 올라와 중기 스케줄러가 계속해서 스왑 인/아웃만 반복하느라 실제 연산을 못하는 상황이다. 근본적인 원인은 물리 메모리 절대량 부족이므로 스케일 업(Scale-up) 증설이 시급하다.
┌───────────────────────────────────────────────────────────────┐
│ 메모리 포화 시 실무 시스템 튜닝 판단 트리 │
├───────────────────────────────────────────────────────────────┤
│ │
│ 시스템 가용 메모리 부족 경보 (Swap 사용량 증가) │
│ │ │
│ ▼ │
│ 응답성 저하 vs 프로세스 강제 종료, 어느 쪽이 치명적인가? │
│ ├─ [프로세스 죽음이 치명적 (DB/배치)] │
│ │ │ │
│ │ ▼ │
│ │ [Swap 공간 충분히 확보 및 vm.swappiness 증가] │
│ │ │
│ └─ [응답 지연이 치명적 (웹/API 서버)] │
│ │ │
│ ▼ │
│ Swap 공간 제거 (Swapoff) │
│ │ │
│ ▼ │
│ 메모리 포화 시 즉각 OOM Killer 구동 유도 │
│ (빠르게 죽이고 로드밸런서가 다른 노드로 트래픽 우회) │
└───────────────────────────────────────────────────────────────┘
[다이어그램 해설] 시스템 아키텍트가 스왑(중기 스케줄러 활성화 영역)을 사용할 것인지 말 것인지 정하는 핵심 철학을 보여준다. 쿠버네티스(Kubernetes) 환경에서는 스와핑이 발생할 때 애플리케이션 지연이 예측 불가능해지는 점을 싫어하여 기본적으로 스왑(Swapoff)을 금지한다. 즉, 중기 스케줄러의 역할을 차단하고, 메모리가 부족하면 깔끔하게 포드(Pod)를 죽인 뒤 다시 띄우는 클라우드 네이티브 철학을 따른다.
- 📢 섹션 요약 비유: 빚(디스크 의존)을 져서라도 회사를 간신히 굴러가게 만들 것인가(Swap On), 아니면 빚을 질 바에야 부도를 내고 새롭게 시작할 것인가(Swap Off)를 결정하는 전략적 판단입니다.
Ⅴ. 기대효과 및 결론 (Future & Standard)
정량/정성 기대효과
| 구분 | 중기 스케줄러 작동 전 | 중기 스케줄러 (Swapping) 개입 후 | 개선 효과 |
|---|---|---|---|
| 정량 | 물리 메모리 100% 포화, 스래싱 | 다중 프로그래밍 정도 하락 (메모리 20% 여유 확보) | 커널 패닉 및 즉각적 시스템 정지 방지 |
| 정성 | 메모리 부족 시 즉시 프로세스 강제 종료 | 다소 느려지더라도 정상 기능 유지 및 지연 서비스 | 시스템의 탄력성 (Resilience) 및 가용성 향상 |
미래 전망
현대 클라우드 데이터센터 환경에서는 중기 스케줄러의 전통적인 디스크 스와핑 방식이 점차 SSD와 결합된 초고속 NVMe 인터페이스로 인해 오버헤드가 줄어들고 있다. 또한 ZRAM처럼 메모리의 일부를 압축 디스크처럼 활용하여 초고속으로 인메모리 스와핑을 구현하는 기술이 모바일(Android) 환경과 임베디드 리눅스의 새로운 표준 스케줄링 모델로 정착하고 있다.
- 📢 섹션 요약 비유: 낡은 창고에 짐을 박아두던 과거에서, 이제는 짐을 압축팩(ZRAM)에 넣어 방 한구석에 초스피드로 보관해두는 스마트한 공간 절약 마법사로 진화하고 있습니다.
📌 관련 개념 맵 (Knowledge Graph)
| 개념 명칭 | 관계 및 시너지 설명 |
|---|---|
| 스래싱 (Thrashing) | 프로세스들이 연산보다 디스크 스와핑 I/O 작업에 더 많은 시간을 쏟아부어 시스템 성능이 붕괴하는 현상이다. |
| 요구 페이징 (Demand Paging) | 전체 프로세스를 스왑 아웃하는 전통 방식과 달리, 당장 필요한 페이지만 메모리에 가져오는 가상 메모리의 기본 원리다. |
| 보류 상태 (Suspended State) | 프로세스가 주 메모리를 잃고 디스크 스왑 영역으로 쫓겨난 상태를 일컫는 OS 프로세스 전이 모델의 핵심 상태다. |
| OOM Killer (Out Of Memory) | 중기 스케줄러의 스와핑 노력에도 불구하고 메모리 고갈이 해결되지 않을 때, 점수가 높은 프로세스를 사살하는 극약 처방이다. |
| 동적 재배치 (Dynamic Relocation) | Swap Out 되었던 프로세스가 다시 Swap In 될 때, 원래 메모리 주소가 아닌 새로운 곳에 적재되기 위해 필수적인 하드웨어 바인딩 지원이다. |
👶 어린이를 위한 3줄 비유 설명
- 좁은 장난감 방 (메모리)에 한 번에 너무 많은 장난감 (프로세스)을 꺼내 놓으면 발 디딜 틈도 없고 놀 수가 없어요.
- 이때 중기 스케줄러라는 도우미가 나타나 당장 가지고 놀지 않는 장난감을 잠시 베란다 창고 (디스크 스왑 영역)로 치워준답니다.
- 방이 넓어지면 다시 재미있게 놀 수 있고, 나중에 그 장난감이 필요해지면 창고에서 금방 다시 가져다주니 문제없어요!