압축 (Compaction / Defragmentation)

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

  1. 본질: 압축(Compaction)은 동적 메모리 할당 환경에서 이빨 빠진 듯 흩어져 있는 다수의 빈 공간(외부 단편화)들을 메모리의 한쪽 끝으로 밀어 모아, 하나의 거대한 연속된 빈 공간(Big Hole)으로 융합하는 수집 연산이다.
  2. 가치: 메모리 총량은 충분하지만 쪼개져 있어서 대형 프로세스를 올릴 수 없는 '외부 단편화 교착 상태'를 물리적으로 해소하여, 다중 프로그래밍의 생명력을 연장하는 최후의 보루 역할을 한다.
  3. 융합: 오직 런타임에 주소가 바뀌어도 괜찮은 실행 시간 바인딩(Execution Time Binding) 환경에서만 사용 가능하며, 메모리 전체를 복사하는 치명적인 오버헤드(Stop-The-World) 때문에 현대 물리 메모리 OS에서는 페이징에 밀려 사장되었으나 자바(Java) 가비지 컬렉터 등 애플리케이션 힙(Heap) 관리에서는 여전히 심장부 기술로 쓰인다.

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

  • 개념: 압축은 메모리의 파편화된 빈 공간을 제거하기 위해 현재 실행 중인 프로세스들의 위치를 물리적으로 복사(Memory Copy)하여 한곳으로 빽빽하게 밀착시키고, 남은 빈 공간들을 반대편으로 몰아주는 재배치(Relocation) 작업이다. 일명 쓰레기 수집(Garbage Collection)의 물리적 버전이다.

  • 필요성: 가변 분할 방식에서 프로세스들이 들어오고 나가기를 반복하면, 50% 법칙에 의해 무조건 메모리의 3분의 1은 1MB, 2MB 단위의 쓰레기 빈 공간으로 찢어져 버린다(외부 단편화). 새 프로그램(10MB)이 들어오려 할 때 남은 램 총합이 30MB라도 들어갈 곳이 없다. 시스템을 재부팅 하지 않고 이 교착 상태를 뚫어낼 유일한 해법은 흩어진 조각들을 물리적으로 끌어모으는 '압축'뿐이다.

  • 💡 비유: 압축은 엘리베이터에 떨어져 앉은 승객들에게 "가운데로 좀 밀착해서 앉아주세요!"라고 요청하는 것과 같다. 총 3자리가 비어있지만 1자리씩 흩어져 있어 3인 가족이 타지 못할 때, 사람들을 옆으로 쭉 당겨 앉게 해서 연속된 3자리를 만들어내는 물리적 자리 이동이다.

  • 등장 배경 및 딜레마:

    1. 가변 분할의 저주: 외부 단편화가 누적되어 OOM(Out of Memory)이 발생.
    2. 물리적 재정렬 시도: OS가 개입하여 앱들의 위치를 뒤섞기 시작함.
    3. 비용의 장벽: 16GB의 메모리를 한쪽으로 복사해 미는 데 걸리는 시간(Memory Bandwidth 소모) 동안 CPU는 다른 어떤 작업도 할 수 없어 시스템이 멈춰버리는(Freeze) 치명적 부작용이 발견됨.
┌───────────────────────────────────────────────────────────────────────┐
│        메모리 압축 (Compaction) 전후의 물리적 레이아웃 변화           │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│ [ 압축 전: 파편화 극심 (External Fragmentation) ]                     │
│ ┌─────┬──────────┬─────┬─────────┬─────┬──────────┐                   │
│ │ P1  │ ▒ 빈공간 ▒ │ P2  │ ▒빈공간▒ │ P3  │ ▒ 빈공간 ▒ │              │
│ │ 10M │   15MB   │ 20M │  10MB   │ 10M │   15MB   │                   │
│ └─────┴──────────┴─────┴─────────┴─────┴──────────┘                   │
│  ▶ 전체 빈 공간 40MB. 하지만 새 프로세스 P4(30MB) 적재 불가!          │
│                                                                       │
│                    ↓↓ OS 압축 알고리즘 발동 ↓↓                        │
│                                                                       │
│ [ 압축 후: 거대 구멍 생성 (Defragmented) ]                            │
│ ┌─────┬──────────┬─────┬──────────────────────────┐                   │
│ │ P1  │    P2    │ P3  │ ▒▒▒▒ 합쳐진 거대 빈 공간 ▒▒▒▒ │              │
│ │ 10M │    20M   │ 10M │          40MB            │                   │
│ └─────┴──────────┴─────┴──────────────────────────┘                   │
│  ▶ 이제 P4(30MB)가 오른쪽 40MB 빈 공간에 완벽하게 들어갈 수 있음!     │
└───────────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 그림만 보면 마법같이 깔끔해졌지만, 그 이면에는 끔찍한 연산이 숨어 있다. P2(20MB)와 P3(10MB)는 자신들이 원래 있던 번지수에서 수십 MB 앞쪽으로 "복사-붙여넣기(Memcpy)" 되어야 한다. 이 과정에서 바이트 단위로 데이터를 긁어서 옮기는 무식한 하드웨어 부하가 발생하며, 이사 간 P2와 P3가 에러 없이 돌기 위해 MMU(베이스 레지스터)의 주소표마저 모두 갱신해야 한다.

  • 📢 섹션 요약 비유: 컴퓨터 바탕화면에 아이콘 수백 개가 이빨 빠진 채 흩어져 있을 때, 바탕화면 우클릭 후 '자동 정렬'을 누르면 왼쪽 위부터 빽빽하게 줄을 서서 오른쪽 아래에 거대한 빈 화면이 생기는 것과 완전히 똑같은 원리입니다.

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

압축의 전제 조건: 실행 시간 바인딩 (Execution Time Binding)

압축 기술이 동작하기 위한 절대적인 하드웨어 아키텍처 전제 조건이다.

  • 만약 프로그램이 **컴파일 시간(Compile Time)**이나 **적재 시간(Load Time)**에 물리 주소를 확정해 버렸다면, 압축을 위해 메모리 위치를 1mm라도 옮기는 순간 프로그램은 자기가 어딨는지 몰라 즉시 뻗어버린다(Crash).
  • 따라서 압축은 오직 **베이스 레지스터(Base Register)**를 통해 주소를 동적으로 더해주는 실행 시간 바인딩(Execution Time Binding) 환경에서만 가능하다. OS가 메모리를 옮긴 뒤, 해당 프로세스의 베이스 레지스터 값만 새 주소로 살짝 바꿔주면 프로세스는 자기가 이사 간 줄도 모르고 정상 작동한다.

압축 비용 최소화를 위한 3가지 최적화 알고리즘

압축은 데이터를 어떻게 이동시키느냐에 따라 오버헤드가 천차만별이다. 최적의 이사 동선을 짜는 것이 커널 엔지니어의 핵심 과제였다.

┌────────────────────────────────────────────────────────────────────────────────┐
│              압축 효율성을 높이기 위한 3가지 이동 전략                         │
├────────────────────────────────────────────────────────────────────────────────┤
│                                                                                │
│ 1. 전체 밀기 (Compact All - 한쪽 벽으로)                                       │
│    모든 프로세스를 0번지 쪽으로 쫙 밀어버림. (가장 단순, 복사량 최악)          │
│    [P1][P2][P3][ 거대한 빈 구멍 ]                                              │
│                                                                                │
│ 2. 최소 이동 (Minimal Movement - 가장 적게 옮기기)                             │
│    P1, P2는 놔두고 끝에 있는 작은 P3 하나만 빈 구멍으로 옮김.                  │
│    복사량은 제일 적지만, 큰 구멍 하나가 나오는 대신 적당한 구멍 2개가 됨.      │
│    [P1][빈 10M][P3][P2][빈 30M] (타협안)                                       │
│                                                                                │
│ 3. 스왑 아웃 활용 (Swap out)                                                   │
│    메모리 안에서 옮기지 말고, 방해되는 P2를 통째로 하드디스크로 스왑 아웃!     │
│    빈 공간 합쳐서 P4를 적재. 나중에 P2를 빈 공간에 다시 스왑 인.               │
│    (디스크 I/O가 발생해 제일 느릴 수 있지만 구조는 깔끔함)                     │
└────────────────────────────────────────────────────────────────────────────────┘

[다이어그램 해설] "어떤 블록을 어디로 옮겨야 메모리 복사량(Memory Copy Byte)을 최소로 하면서 내가 원하는 30MB짜리 연속된 구멍을 뚫어낼 수 있을까?" 이 질문은 컴퓨터 과학에서 '최적화가 불가능한 NP-Hard' 문제로 분류된다. 최적해를 찾는 연산 자체가 메모리를 옮기는 시간보다 오래 걸릴 수 있기 때문에, 실무에서는 1번처럼 그냥 무식하게 쫙 밀어버리는 휴리스틱을 주로 사용했다.

  • 📢 섹션 요약 비유: 이삿짐센터 직원이 빈 공간을 만들기 위해 장롱 하나만 빈 구석으로 옮길지(최소 이동), 아니면 가구 전체를 벽 쪽으로 쫙 밀어버릴지(전체 밀기) 고민하며 땀을 뻘뻘 흘리는 지옥의 노가다 과정입니다.

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

비교 1: 압축 (Compaction) vs 병합 (Coalescing)

둘 다 빈 공간을 합치는 기술이지만, 시점과 오버헤드가 완전히 다르다.

비교 항목병합 (Coalescing)압축 (Compaction)
작동 조건인접한 빈 공간 2개가 우연히 붙어있을 때떨어져 있는 수많은 빈 공간을 합칠 때
작업 내용장부(Linked List)의 포인터 선만 지우고 합침실제 메모리 데이터(수십 MB)를 물리적으로 복사/이동
성능 오버헤드나노초 단위 (거의 0)밀리초~초 단위 (시스템 멈춤, 최악의 오버헤드)
발생 시점프로세스가 종료(Terminate)되어 나갈 때마다 수행새 프로세스가 들어오려는데 공간이 쪼개져 못 들어올 때만 수행

압축 비용의 멸망과 페이징(Paging)의 승리

  • 압축의 비용은 **O(N)**이다. 16GB 메모리를 쓴다면 최악의 경우 16GB를 통째로 읽고 써야 한다. 캐시(Cache)가 모두 플러시되고, 시스템 버스가 마비된다.
  • 이 문제를 해결하기 위해 천재적인 공학자들은 "왜 굳이 빈 공간을 물리적으로 합쳐야 하지? 그냥 프로그램(프로세스)을 갈기갈기 4KB로 찢어서 흩어진 빈 곳 아무 데나 쑤셔 넣으면, 굳이 압축한다고 밀어낼 필요가 없잖아?"라는 발상의 전환을 이뤄냈다.
  • 이것이 **비연속 메모리 할당(Non-contiguous Allocation)의 핵심인 페이징(Paging)**이며, 페이징의 등장과 함께 OS의 물리 메모리 압축 기술은 교과서 속으로 영원히 사라졌다.
┌──────────┬────────────┬────────────┬────────────────────────┐
│ 아키텍처   │ 외부 단편화  │ 해결 방식    │ 부작용 (대가)    │
├──────────┼────────────┼────────────┼────────────────────────┤
│ 가변 분할  │ 치명적 발생  │ 메모리 압축  │ 시스템 일시 정지 │
│ 페이징     │ 원천 차단    │ 4KB로 찢기  │ 페이지 테이블 낭비│
└──────────┴────────────┴────────────┴────────────────────────┘

[매트릭스 해설] 컴퓨터 아키텍처의 패러다임 시프트다. 인류는 압축 연산의 끔찍함을 맛본 뒤, "연속적인 공간에 담아야 한다"는 강박을 버렸다. 페이징 기법 도입 후 외부 단편화 자체가 수학적으로 멸종되었고, 따라서 흩어진 공간을 모으는 '압축' 기술도 자연스럽게 용도 폐기되었다.

  • 📢 섹션 요약 비유: 어지러운 퍼즐 조각을 한쪽으로 싹 치워서(압축) 큰 도화지를 만드는 수고를 포기하고, 아예 도화지를 픽셀 단위(페이징)로 조각내버림으로써 치울 필요조차 없게 만든 혁신입니다.

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

실무 시나리오: 자바(Java) 가비지 컬렉션(GC)에서의 환생

운영체제의 물리 메모리 관리에서는 압축이 사장되었으나, 묘하게도 애플리케이션 개발자들의 힙(Heap) 메모리 관리에서 압축은 가장 강력한 코어 기술로 다시 태어났다.

  1. 상황: Java 어플리케이션의 힙 메모리에 수만 개의 객체가 생겼다 지워지며 힙이 외부 단편화로 걸레짝이 되었다. (new Object() 실패)
  2. Mark and Compact GC 발동:
    • JVM의 가비지 컬렉터는 살아남은 유효한 객체들(Mark)을 힙 메모리의 한쪽 끝으로 차곡차곡 밀어버리는 **'압축(Compact)'**을 실행한다.
  3. Stop The World (STW):
    • 압축을 위해 객체들을 복사하는 동안, 자바 앱의 모든 스레드는 완전히 멈춰버린다. (Stop The World).
    • 사용자가 클릭 버튼을 눌렀는데 서버가 이 압축을 하느라 1초 동안 응답하지 않는 렉(Latency Spikes)이 발생한다.
  4. 실무적 튜닝 (G1GC / ZGC):
    • 자바 진영은 이 STW 시간을 줄이기 위해 힙 메모리 전체를 한 번에 압축하지 않고, 힙을 여러 개의 리전(Region)으로 잘게 쪼갠 뒤 작은 구역별로만 살짝살짝 압축하는 ZGC, Shenandoah GC 같은 최첨단 병렬 압축 기법으로 진화했다.

디스크 단편화와 압축

윈도우즈의 조각 모음(Defragmentation) 유틸리티가 바로 파일 시스템 레벨의 '압축'이다. 하드디스크의 헤더가 쪼개진 파일을 찾느라 덜그럭거리는 비용(Seek Time)을 줄이기 위해, 파일들을 한쪽 실린더로 쫙 밀어서 모아주는 작업이다. (SSD에서는 속도가 빠르므로 수명만 갉아먹는 안티패턴이다.)

  • 📢 섹션 요약 비유: OS라는 큰 정부는 페이징으로 쓰레기 문제를 영원히 해결했지만, 자바(Java)라는 자치구 안에서는 아직도 주기적으로 골목길에 널브러진 쓰레기를 한곳으로 밀어붙이는 대청소(GC Compaction)를 하며 온 동네를 멈춰 세우고 있는 현실입니다.

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

정량/정성 기대효과

구분내용
메모리 고갈(OOM) 방어총량은 충분하나 단편화로 인해 프로세스가 죽어버리는 어처구니없는 시스템 붕괴를 최종적으로 구원
연속 메모리 확보대용량 그래픽 버퍼나 DB 캐시처럼 반드시 연속된(Contiguous) 거대 물리 공간이 필요할 때 강제 확보 가능
GC 알고리즘의 뼈대Mark-Sweep 방식의 단점을 보완한 Mark-Compact GC 알고리즘의 사상적 뿌리이자 근간 설계 제공

결론 및 미래 전망

메모리 압축 (Compaction)은 "외부 단편화"라는 질병을 치료하기 위해 시스템에 투여하는 극약(Poison)이었다. 병은 고치지만 부작용(시스템 멈춤)이 너무 커서, 범용 운영체제는 이 약을 버리고 '페이징'이라는 백신을 발명해 면역력을 획득했다. 오늘날 OS 커널 레벨에서 압축 연산을 돌리는 일은 없지만, 분산 시스템의 데이터베이스 노드 병합, 파일 시스템의 가비지 블록 수집, 프로그래밍 런타임(JVM, V8)의 힙 관리 등 IT 인프라 전반의 "정리 정돈 메커니즘" 깊숙한 곳에서 압축의 철학은 여전히 시스템의 찌꺼기를 치우며 묵묵히 제 몫을 다하고 있다.

  • 📢 섹션 요약 비유: 방이 더러워질 때마다 짐을 다 들어내고 한쪽으로 몰아넣는 대청소(압축)는 너무 힘들어서 그만두고, 아예 방을 수천 개의 작은 서랍(페이징)으로 개조해버린 것이 컴퓨터 공학의 가장 위대한 인테리어 공사입니다.

📌 관련 개념 맵 (Knowledge Graph)

  • 외부 단편화 (External Fragmentation) | 압축 연산을 발동하게 만드는 근본 원인. 연속되지 않은 빈 공간들의 낭비.
  • 병합 (Coalescing) | 압축과 달리, 프로세스가 나갈 때 인접한 빈 공간만 빠르게 하나로 묶어 파편화를 늦추는 값싼 방어 로직.
  • 페이징 (Paging) | 비연속 할당을 통해 외부 단편화를 없앰으로써, 오버헤드가 큰 압축 기법을 역사 속으로 퇴장시킨 현대 가상 메모리 기법.
  • 가비지 컬렉션 (Garbage Collection) | 프로그래밍 언어의 힙 공간에서 쓸모없는 객체를 지우고 남은 객체들을 한곳으로 모으는 압축(Compact) 기술의 실무적 구현체.
  • 베이스 레지스터 (Base Register) | 압축으로 프로세스가 물리적으로 이사 갔을 때, 소프트웨어 수정 없이 새 출발선만 등록해주면 되는 MMU의 하드웨어.

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

  1. 압축이 무엇인가요? 극장 좌석에 사람들이 1칸씩 떨어져 듬성듬성 앉아있어서 3명 가족이 못 탈 때, "모두 왼쪽으로 바짝 당겨 앉으세요!" 해서 오른쪽에 3자리를 만들어내는 거예요.
  2. 왜 힘든가요? 수백 명의 사람들이 다 같이 일어나서 옆자리로 짐을 들고 끙끙대며 이동해야 하니까 그동안은 아무도 영화를 볼 수 없게 되거든요.
  3. 결국 어떻게 됐나요? 너무 피곤해서, 아예 극장 의자를 뜯어서 가족들이 뿔뿔이 흩어져 앉아도 마법의 안경(페이징)을 쓰면 옆에 앉은 것처럼 보이게 하는 기술을 발명했답니다.