스래싱 원인 - 최소 프레임 확보 실패

핵심 인사이트 (3줄 요약)

  1. 본질: 스래싱(Thrashing)이 폭발하는 가장 근본적이고 기계적인 원인은, 각 프로세스가 에러 없이 단 1개의 명령어를 실행하기 위해 하드웨어적으로 절대 보장받아야 하는 '최소 프레임 수(Minimum Frames)'조차 운영체제가 빼앗아 가버렸기 때문이다.
  2. 가치: 이 원인 분석은 "램이 넉넉하면 스래싱이 안 난다"는 1차원적 생각을 넘어, 특정 CPU 아키텍처(예: x86 간접 주소 지정)가 태생적으로 요구하는 하드웨어 명령어의 한계와 메모리 교체 정책(전역 교체)의 모순이 충돌하는 지점을 정확히 타격한다.
  3. 융합: 운영체제는 이 참사를 막기 위해 단순히 앱의 개수를 제한하는 것을 넘어, 런타임에 동적으로 각 앱의 워킹 셋(Working Set) 크기를 측정하고 이를 최소 프레임 보장선과 융합하여 방어벽을 세우는 진화된 스케줄링을 완성했다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

  • 개념: 시스템이 스래싱(CPU 가동률 1% 미만, 디스크 I/O 100%)에 빠지는 원인을 파고들면, 결국 프로세스가 '숨을 쉴 수 있는 최소한의 램 공간'인 **최소 프레임(Minimum Frames)**을 확보하지 못했기 때문이다. 여기서 '최소 프레임'이란 쾌적하게 도는 권장 사양이 아니라, "명령어 1줄을 치기 위해 하드웨어 적으로 동시에 램에 올려둬야 하는 낱장 페이지의 개수"를 뜻한다.

  • 필요성: 왜 OS가 전역 교체(Global Replacement)를 하다 보면 스래싱이 터지는가? 램 16GB가 꽉 차서 남의 램을 뺏는 건 좋다. 하지만 OS가 눈이 돌아가서 어떤 앱(A)의 램을 너무 많이 뺏어버린 나머지, A가 가진 램이 딱 2장밖에 안 남았다고 치자. A가 C = A + B라는 덧셈 명령어를 실행하려면 1) 명령어 페이지, 2) A 변수 페이지, 3) B 변수 페이지 등 최소 3장이 동시에 램에 있어야 한다. 램이 2장뿐이면? 1, 2장을 가져온 뒤 3장을 가져오려고 1장을 버리고, 다시 1장을 부르느라 영원히 덧셈 1번을 끝내지 못하고 디스크만 긁는 **무한 루프(Infinite Page Fault)**에 갇힌다. 시스템 개발자는 이 하드웨어적 최소 요구치를 정확히 계산하여 락(Lock)을 걸어주는 안전장치가 반드시 필요했다.

  • 💡 비유: 스래싱 원인은 요리사의 도마 크기 한계와 같다. 요리사가 햄버거를 만들려면 최소한 빵, 패티, 양상추 세 가지 재료를 동시에 도마(최소 프레임 3장) 위에 올려놓아야 햄버거 1개를 조립(명령어 완성)할 수 있다. 그런데 사장(OS)이 도마를 뺏어가서 도마 크기가 재료 2개 들어갈 크기(2장)로 줄어들었다. 요리사는 빵과 패티를 올린 뒤 양상추를 올릴 자리가 없어서 패티를 냉장고(디스크)에 도로 넣는다. 그리고 양상추를 올렸더니 패티가 없어서 양상추를 넣고 다시 패티를 가져온다. 햄버거는 영원히 완성되지 않고 냉장고 문만 하루 종일 열고 닫는 미친 짓(스래싱)이 반복된다.

  • 등장 배경 및 아키텍처의 비극:

    1. 요구 페이징의 오만: 필요할 때마다 1장씩 가져오면 무한대의 앱을 돌릴 수 있을 줄 알았다.
    2. ISA (명령어 집합 구조)의 복잡성: 인텔 x86 같은 CISC 명령어는 1개의 어셈블리 명령어가 램의 6곳(간접 참조 등)을 찌를 수 있는 복잡한 구조로 진화했다.
    3. 충돌과 파국: 명령어 1줄 실행에 필요한 램 공간(최소 6장)조차 배급해주지 못한 OS의 무자비한 교체 정책이 만나며 컴퓨터가 완전히 얼어붙는 시스템 버그로 터져 나왔다.
┌──────────────────────────────────────────────────────────────────────────┐
│        최소 프레임(Minimum Frames) 부족으로 터지는 무한 폴트 지옥        │
├──────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│ [ 전제 조건 ]                                                            │
│ - 하드웨어 CPU 명령어: `MOV [주소1], [주소2]` (값 복사 명령)             │
│ - 이 명령어를 1클럭에 끝내기 위해 필요한 절대 '최소 램 페이지 수': 3장   │
│   1) 명령어가 쓰여진 텍스트 페이지 1장                                   │
│   2) Source 데이터(주소2)가 있는 페이지 1장                              │
│   3) Target 데이터(주소1)가 있는 페이지 1장                              │
│                                                                          │
│ [ 💥 비극의 발생: OS가 이 프로세스에게 램을 '2장'만 줬을 때 ]            │
│                                                                          │
│ 1. CPU가 명령어(MOV)를 램으로 가져옴. [램 남은 방 1개]                   │
│ 2. Source(주소2)를 램으로 가져옴. [램 남은 방 0개 - 꽉참!]               │
│ 3. Target(주소1)을 램으로 가져와야 하는데 램이 꽉 찼네? 교체 발동!       │
│ 4. OS가 '명령어' 페이지를 스왑으로 쫓아내고 Target을 램에 올림.          │
│ 5. CPU 왈: "어? 나 방금 무슨 명령어 치고 있었지? (명령어 날아감)"        │
│ 6. 명령어를 다시 디스크에서 읽어오기 위해 Target을 쫓아냄... (무한 반복) │
│                                                                          │
│ ✅ 결과: 명령어 딱 1줄을 치는데 디스크만 평생 긁는 순수 100% 스래싱 도래.│
└──────────────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 이 현상은 소프트웨어 버그가 아니다. 운영체제의 '메모리 수탈(전역 교체)' 정책이 CPU 하드웨어의 설계 한계선(Minimum)을 침범했을 때 발생하는 완벽한 물리적 교착 상태(Deadlock)다. 이 지뢰를 밟는 순간, 시스템 전체가 CPU는 놀고 디스크만 미친 듯이 타오르는 스래싱의 절벽으로 추락한다.

  • 📢 섹션 요약 비유: 은행 강도를 잡으려고 경찰 3명이 포위망을 짜야 하는데(최소 필요 인원), 서장이 병력이 모자라다고 경찰 2명만 보냈습니다. 앞문을 지키던 경찰이 뒷문을 막으러 뛰어가면 강도가 앞문으로 도망가고, 다시 앞문으로 뛰어가면 뒷문으로 도망가는 영원한 숨바꼭질 헛수고(스래싱)가 벌어지는 최악의 병력 배분 실패입니다.

Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

하드웨어 아키텍처별 최소 프레임 요구량 차이

CPU를 만드는 제조사(ISA)마다 이 "최소 프레임(Minimum Frames)"의 개수는 판이하다.

  • 단순한 RISC (초기 ARM, MIPS): 명령어가 4바이트로 고정되어 있고, 메모리 접근도 단순한 Load/Store 명령어 하나뿐이다. 이들은 보통 최소 2~3프레임만 있으면 명령어가 안 멈추고 돈다.
  • 복잡한 CISC (인텔 x86_64, VAX): 명령어가 1바이트부터 15바이트까지 가변적이라 명령어 자체가 페이지 2장에 걸쳐 쪼개질 수 있다. 게다가 간접 주소 지정(Indirect Addressing: 주소에 적힌 주소를 또 찾아가는 것) 기능 때문에, 명령어 하나가 데이터 페이지 4~5개를 연속으로 찔러볼 수 있다. 인텔 계열은 최악의 경우 명령어 하나 실행을 위해 최소 6~8개의 프레임을 램에 깔아놔야 한다.

스래싱 유발의 2차 원인: "전역 교체 (Global Replacement)"의 오만

최소 프레임이 깨지는 근본적인 이유는 OS가 쓰는 '전역 교체' 알고리즘 때문이다.

  • 전역 교체는 특정 앱 A가 페이지 폴트를 마구 뿜어내면 "아 이놈 램이 고프구나" 하고, 가만히 잘 돌고 있는 착한 앱 B의 램을 뺏어다가 A에게 상납한다.

  • A가 미쳐 날뛰며 B, C, D의 램을 모조리 뺏어가 버리면, B, C, D가 가진 램 개수가 '하드웨어 최소 프레임 수(예: 6장)' 이하로 강제로 깎여버리게 된다.

  • 그 순간 B, C, D도 덧셈 1번을 하기 위해 모자란 프레임을 찾느라 폴트를 뿜어대고, 그 폴트 때문에 다시 A의 램을 뺏어오는 진흙탕 개싸움(전역적 스래싱)이 터지며 서버가 완전히 마비된다.

  • 📢 섹션 요약 비유: 전역 교체는 조별 과제에서 일 제일 많이 하는 놈(A)한테 다른 조원들(B, C)의 노트북 배터리까지 싹 다 뽑아서 몰아주는 것과 같습니다. 결국 배터리가 0%가 된 B와 C는 노트북이 꺼져서(최소 프레임 붕괴) 과제 발표를 망치고 조 전체(시스템)가 F 학점을 받는 연쇄 파멸의 길입니다.


Ⅲ. 융합 비교 및 다각도 분석

워킹 셋(Working Set) vs 최소 프레임(Minimum Frames)

초보 공학도들이 가장 많이 헷갈리는 두 개념의 완벽한 층위(Layer) 비교다.

비교 항목최소 프레임 (Minimum Frames)워킹 셋 (Working Set)
정의명령어 1줄 실행 시 에러(루프)가 안 날 하드웨어적 최소 생존선렉(폴트) 없이 쾌적하게 돌기 위한 소프트웨어적 최적(Optimal) 덩어리
결정 주체CPU 아키텍처 (x86, ARM 등) 기계가 정함프로세스의 런타임 코드 로직(배열 루프 등)이 동적으로 정함
규모보통 2장 ~ 6장 수준 (아주 작음)수천 장 ~ 수만 장 (수십 메가바이트 단위)
부족 시 결과아예 명령어 1줄이 진행 안 되는 100% 무한 스래싱 지옥속도는 뚝뚝 끊기지만 어찌어찌 실행은 됨 (체감 렉 발생)

Page Fault Rate (부재율) 곡선의 해부

  • 프레임 < 최소 프레임: 시스템 즉사. 폴트율(Page Fault Rate) 100%. (아예 측정 불가)
  • 최소 프레임 < 프레임 < 워킹 셋: 명령은 먹히지만, 루프 돌 때마다 디스크 긁어옴. 폴트율이 매우 높아 체감 렉 심함.
  • 프레임 = 워킹 셋: 폴트율이 바닥에 달라붙는 '무릎(Knee)' 지점. 가성비 극강의 황금 포인트.
  • 프레임 > 워킹 셋: 램을 10GB 더 꽂아줘도 어차피 쓰는 변수만 쓰기 때문에 폴트율은 더 떨어지지 않음. 램 낭비 구간.
┌──────────┬────────────┬────────────┬──────────────────────────────────┐
│ 램 할당량 │ 1~5장 (최소미달)│ 100장 (워킹셋 미달)│ 1만장 (워킹셋 충족)│
├──────────┼────────────┼────────────┼──────────────────────────────────┤
│ 시스템 상태│ ☠️ 무한 스래싱 │ 🐢 렉 걸림 (느림) │ 🚀 최고 속도 도달   │
│ 디스크 I/O│ 100% 락 걸림 │ 잦은 드르륵 소리 │ 0% (고요함)             │
└──────────┴────────────┴────────────┴──────────────────────────────────┘

[매트릭스 해설] 운영체제의 지상 목표는 모든 프로세스의 램 할당량을 딱 저 '1만 장(워킹 셋)' 언저리에 칼같이 맞춰주는 것이다. 10만 장을 주는 건 낭비고, 5장 밑으로 빼앗는 건 살인 행위다. 이 절묘한 줄타기를 위해 OS는 'Page Fault Frequency(PFF)'라는 실시간 모니터링 레이더를 켜두고 앱들을 감시한다.

  • 📢 섹션 요약 비유: 최소 프레임은 사람이 살기 위한 '물과 산소'입니다. 없으면 1분 만에 죽습니다. 워킹 셋은 행복하게 살기 위한 '집과 밥'입니다. 없어도 고통받으며 살 순 있지만 삶의 질(속도)이 박살 납니다. 워킹 셋보다 더 많은 램을 주는 건 부자에게 '금송아지'를 주는 격으로, 행복도(속도)는 더 오르지 않는 낭비입니다.

Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)

실무 시나리오: Java OOM과 Swappiness에 얽힌 스래싱 방어

현업 백엔드 엔지니어는 커널의 이 '최소 프레임' 붕괴를 막기 위해 하드코어한 튜닝을 한다.

  1. 문제 상황: 메모리가 32GB인 서버에 20GB 힙을 쓰는 자바 앱 2개를 무지성으로 올렸다. (Total 40GB).
  2. 리눅스의 딜레마:
    • 전역 교체가 돌며 램을 미친 듯이 스왑 파티션(디스크)으로 쫓아낸다.
    • 자바의 가비지 컬렉터(GC)가 한 번 돌면 힙(Heap) 메모리 전체를 다 훑어봐야(Full Scan) 한다.
    • 쫓겨났던 페이지들을 램으로 퍼오느라 다른 자바 앱의 핵심 워킹 셋(최소 프레임)마저 스왑으로 쫓겨나는 **초대형 스래싱(Thrashing)**이 폭발한다.
  3. 신의 한 수 튜닝:
    • 실무자들은 이런 깡패 짓을 막기 위해 애초에 서버의 Swap(스왑) 파티션을 100% 꺼버린다(Swapoff). (쿠버네티스 표준).
    • "스래싱 지옥(최소 프레임 붕괴)에 빠져 서버 전체가 10분 동안 뻗어버리느니, 차라리 램이 모자랄 때 1개의 자바 앱을 OOM 킬러로 총 쏴 죽이고(Kill) 즉시 새 컨테이너로 재시작(Fail-fast)시키는 게 아키텍처 상 수만 배 안전하다"는 냉혹한 실무적 진리에 도달한 것이다.

안티패턴: 무분별한 Thread 생성과 스택 파편화

C++이나 Python에서 스레드(Thread)를 10만 개 띄우면 코드가 멈춘다. 스레드 하나당 최소 1~2MB의 스택(Stack) 가상 메모리를 가지는데, 이 스레드들이 1초마다 컨텍스트 스위칭을 하며 번갈아 깨어난다. 깨어날 때마다 각 스레드는 자기가 실행될 '최소 프레임'을 램에 요구한다. 10만 개의 스레드가 요구하는 최소 프레임 합이 물리 램 크기를 아득히 뚫어버린다. 디스크가 비명을 지르며 서버가 얼어붙는다(Thrashing). 이래서 Node.js나 Nginx 같은 1개의 스레드로 수만 개를 돌리는 비동기 논블로킹(Event-driven) 아키텍처가 램 파편화를 막아주는 현대 서버의 구원자로 등극한 것이다.

  • 📢 섹션 요약 비유: 알바생(스레드) 10만 명을 고용해놓고 좁은 주방(램)에 번갈아 투입시키면, 알바생들이 자기 앞치마랑 도마(최소 프레임) 꺼내오느라 주방 문만 하루 종일 열고 닫으며 요리는 1개도 못 나갑니다(스래싱). 차라리 고수 알바생 1명(단일 스레드 비동기)이 도마 1개 펴놓고 주문 10만 개를 연속으로 다 쳐내는 게 백배 빠른 이치입니다.

Ⅴ. 기대효과 및 결론 (Future & Standard)

정량/정성 기대효과

구분내용
스케줄링의 레드라인 설정다중 프로그래밍 정도(Degree)를 무한정 높이려는 어리석은 스케줄러에게, "이 선 넘으면 시스템 뇌사 옴"이라는 수학적 브레이크를 제공
OOM(Out Of Memory) 정당성"램 모자라면 그냥 죽이자"는 과격한 OOM 킬러 로직이, 사실은 스래싱이라는 더 끔찍한 동반 자살을 막기 위한 불가피한 성전임을 입증
아키텍처 맞춤형 OS 최적화x86의 무거운 명령어 구조와 ARM의 가벼운 구조를 OS 커널이 인지하여, 하드웨어 칩셋 맞춤형으로 램 할당 하한선을 세팅하는 토대 마련

결론 및 미래 전망

스래싱의 근본 원인인 '최소 프레임 확보 실패'는 가상 메모리가 쳐놓은 위대한 속임수의 바닥에 숨겨진 치명적인 물리적 진실이다. "램이 없어도 디스크로 버틸 수 있다"는 마법은, 결국 하드웨어 트랜지스터가 명령어 하나를 씹어 삼키기 위해 절대적으로 요구하는 한 줌의 '연속된 램 쪼가리' 앞에서 무참히 박살 났다. 이 뼈아픈 원인 분석 덕분에 인류는 무지성 전역 교체의 폭주를 멈추고, 프로세스의 숨통(Working Set)을 지켜주는 정교한 동적 할당과 PFF(페이지 부재 빈도 제어) 기술을 발명할 수 있었다. 다가올 미래의 초거대 클라우드 환경에서도, 하드웨어가 요구하는 이 잔인한 '최소 단위의 법칙'은 가상화 기술(Hypervisor)이 절대 넘지 말아야 할 가장 엄격한 물리적 한계선으로 남아 시스템 튜닝의 나침반이 될 것이다.

  • 📢 섹션 요약 비유: 100만 원짜리 마이너스 통장(가상 메모리)만 믿고 외제 차를 샀다가, 당장 오늘 점심 먹을 라면값 3천 원(최소 프레임) 현금이 지갑에 없어서 길거리에서 굶어 쓰러지는(스래싱) 카푸어의 눈물겨운 현실입니다. 아무리 신용이 빵빵해도 숨 쉴 현금은 주머니에 쥐고 있어야 시스템이 굴러갑니다.

📌 관련 개념 맵 (Knowledge Graph)

  • 다중 프로그래밍 정도 (Degree of Multiprogramming) | 앱을 많이 띄울수록 CPU가 바빠져 좋아하다가, 최소 프레임 한계를 뚫는 순간 벼락같이 스래싱 절벽으로 꽂히는 원인 제공자
  • 전역 교체 (Global Replacement) | 남의 램을 뺏어 내 배를 불리려다, 남의 램을 최소 프레임 이하로 깎아버려 결국 다 같이 죽는 동반 자살(스래싱)의 기폭제
  • 워킹 셋 (Working Set) | 최소 프레임 붕괴를 막기 위해 "최소한 얘한테는 램 이만큼 보장해 줘라"라고 OS가 쳐주는 안전한 울타리
  • PFF (Page Fault Frequency) | 폴트가 펑펑 터져 스래싱 조짐이 보이면, 즉각 램을 더 줘서 최소 프레임 붕괴를 틀어막는 스마트 심박수 모니터
  • OOM Killer | 시스템이 스래싱 절벽으로 떨어지기 직전, 거대한 앱 하나를 쏴 죽여서 램을 토해내게 만들어 서버 전체를 구하는 다크나이트

👶 어린이를 위한 3줄 비유 설명

  1. 스래싱이 왜 일어나나요? 그림을 그리려면 최소한 '종이 1장, 크레파스 1개, 연필 1개(최소 프레임 3장)'가 내 책상 위에 동시에 있어야 그릴 수 있잖아요.
  2. 근데 책상이 너무 좁으면요? 책상에 딱 2개만 올라가면, 종이랑 크레파스 올리고 연필을 가져오려다 종이를 떨어뜨리고, 종이를 주우려다 크레파스를 떨어뜨려요.
  3. 그럼 어떻게 되나요? 영원히 그림(명령어)은 1줄도 못 그리고, 하루 종일 바닥에 떨어진 물건만 줍고 올리고(디스크 스왑) 울면서 시간을 다 버리게(스래싱) 된답니다.