본문 바로가기
TYLER SONGBlog
← Blog index
CS6 min read

Swap: 물리 메모리 부족을 보조 기억장치로 메꾸는 가상 메모리 확장 기법

스왑(Swap)은 물리 메모리(RAM)가 부족할 때 사용 빈도가 낮은 페이지를 디스크의 스왑 영역으로 내보내고, 필요할 때 다시 불러오는 운영체제의 메모리 관리 기법이다. 이를 통해 실제 물리 메모리보다 큰 주소 공간을 프로세스에 제공할 수 있지만, 디스크 I/O 비용 때문에 과도하게 발생하면 스래싱(thrashing)으로 이어져 시스템 성능이 급격히 저하

By 송민성

1. 개념

스왑(Swap)은 물리 메모리(RAM)의 일부 내용을 디스크나 SSD 같은 보조 기억장치의 스왑 영역(swap space)으로 옮기고, 필요할 때 다시 물리 메모리로 불러오는 메커니즘이다. 가상 메모리(virtual memory) 시스템의 핵심 구성 요소로, 프로세스는 실제 물리 메모리 크기와 무관하게 자신만의 독립된 가상 주소 공간(virtual address space)을 사용한다.

이 개념은 페이징(paging) 방식과 밀접하게 연결된다. 메모리는 고정 크기의 페이지(page) 단위로 관리되고, 스왑도 페이지 단위로 이루어지는 것이 일반적이다(page-out, page-in). 과거 일부 시스템에서는 프로세스 전체를 통째로 내보내는 스왑도 있었지만, 현대 운영체제는 대부분 페이지 단위 스왑을 사용한다.

2. 왜 사용하는가

  • 물리 메모리 초과 할당 지원: 여러 프로세스가 동시에 실행될 때 요구하는 메모리 총량이 물리 메모리를 초과해도 시스템이 즉시 멈추지 않게 한다.
  • 메모리 오버커밋(overcommit): 실제로 자주 쓰이지 않는 페이지를 스왑으로 내보내고, 물리 메모리는 활발히 쓰이는 페이지에 집중 배분한다.
  • OOM(Out Of Memory) 상황 완화: 스왑이 없으면 메모리 고갈 시 커널의 OOM Killer가 프로세스를 강제 종료할 가능성이 높아진다. 스왑은 이런 상황을 지연시키는 완충 장치 역할을 한다.

3. 동작 원리

  1. 페이지 폴트(page fault) 발생: 프로세스가 접근하려는 페이지가 물리 메모리에 없으면 CPU가 트랩을 발생시킨다.
  2. 커널의 처리: 커널은 해당 페이지가 스왑 영역에 있는지 확인하고, 있다면 디스크 I/O를 통해 물리 메모리로 다시 적재한다(page-in, swap-in).
  3. 공간 확보가 필요한 경우: 물리 메모리가 가득 찬 상태에서 새 페이지를 적재해야 하면, 페이지 교체 알고리즘(page replacement algorithm)이 내보낼 페이지를 선택한다.
  4. 대표적인 교체 알고리즘:

- LRU(Least Recently Used): 가장 오래전에 사용된 페이지를 내보낸다. - Clock 알고리즘: LRU를 근사하되 참조 비트(reference bit)를 순환 검사하여 오버헤드를 줄인다. - Second Chance: Clock 알고리즘의 변형으로, 참조 비트가 1이면 기회를 한 번 더 준다.

리눅스 커널은 실제로 Clock 알고리즘을 변형한 방식과 활성/비활성 리스트(active/inactive list) 기반의 근사 LRU를 사용한다.

4. 코드 예제

LRU 페이지 교체 알고리즘 시뮬레이션 (Python)

python
from collections import OrderedDict class LRUPageReplacement: def __init__(self, capacity: int): self.capacity = capacity self.frames = OrderedDict() # key: page 번호, value: True (더미 값) self.page_faults = 0 self.swap_outs = [] def access_page(self, page: int): if page in self.frames: # 캐시 히트: 최근 사용으로 갱신 (O(1)) self.frames.move_to_end(page) else: # 페이지 폴트 발생 self.page_faults += 1 if len(self.frames) >= self.capacity: # 가장 오래전에 사용된 페이지를 스왑 아웃 evicted_page, _ = self.frames.popitem(last=False) self.swap_outs.append(evicted_page) self.frames[page] = True if __name__ == "__main__": # 물리 메모리 프레임이 3개뿐인 상황을 가정 lru = LRUPageReplacement(capacity=3) reference_string = [1, 2, 3, 4, 1, 2, 5, 1, 2, 3] for page in reference_string: lru.access_page(page) print(f"참조 순서: {reference_string}") print(f"페이지 폴트 횟수: {lru.page_faults}") print(f"스왑 아웃된 페이지: {lru.swap_outs}")

실행 결과:

text
참조 순서: [1, 2, 3, 4, 1, 2, 5, 1, 2, 3]
페이지 폴트 횟수: 8
스왑 아웃된 페이지: [1, 3, 4, 5]

리눅스 스왑 상태 확인 및 설정 (Shell)

shell
# 현재 스왑 사용량 확인 free -h # 스왑 영역 목록과 우선순위 확인 swapon --show # 스왑 파일 생성 (2GB) 및 활성화 sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 스왑 사용 성향(swappiness) 확인 - 0~100, 값이 낮을수록 스왑을 늦게 사용 cat /proc/sys/vm/swappiness # swappiness를 10으로 조정 (재부팅 전까지만 적용) sudo sysctl vm.swappiness=10

5. 시간 복잡도 또는 성능 특성

  • LRU 자료구조 접근: OrderedDict를 사용하면 페이지 조회, 갱신, 제거 모두 O(1)에 처리된다. 배열 기반으로 구현하면 최근 사용 순서를 찾는 데 O(n)이 걸릴 수 있다.
  • 스왑 I/O 비용: 물리 메모리 접근은 나노초(ns) 단위인 반면, 디스크 접근은 밀리초(ms) 단위로 수 배에서 수만 배까지 느리다. SSD는 HDD보다 빠르지만 여전히 RAM 접근 속도에는 크게 못 미친다. 정확한 배율은 하드웨어에 따라 달라지므로 절대 수치보다는 자릿수 차이로 이해하는 것이 정확하다.
  • 스래싱(thrashing): 프로세스가 필요로 하는 작업 집합(working set)이 물리 메모리 크기를 초과하면, 페이지 폴트와 스왑이 반복되면서 CPU가 실제 연산보다 페이지 교체에 더 많은 시간을 쓰게 된다. 이 상태에서는 시스템 처리량이 급격히 떨어진다.

6. 실무 사용 사례

  • 서버 운영: 메모리 사용량이 순간적으로 튀는 워크로드에서 스왑을 소량 설정해 OOM Killer에 의한 프로세스 강제 종료를 방지한다.
  • 컨테이너 환경: 쿠버네티스(Kubernetes)는 기본적으로 스왑이 활성화된 노드를 지원하지 않거나 제한적으로 지원한다. 컨테이너의 메모리 제한(memory limit)과 스왑이 상호작용하면 리소스 격리가 예측 불가능해지기 때문이다.
  • swappiness 튜닝: 데이터베이스 서버처럼 지연 시간에 민감한 애플리케이션에서는 vm.swappiness 값을 낮춰 커널이 가능한 한 스왑을 늦게 사용하도록 조정한다.
  • 하이버네이션(hibernation): 리눅스는 절전 모드 진입 시 RAM 전체 내용을 스왑 영역에 저장했다가 복귀 시 복원하는 방식으로 스왑 공간을 활용하기도 한다.

7. 주의할 점

  • 스왑은 근본적인 메모리 부족 해결책이 아니다: 스왑이 지속적으로 활발히 일어난다면 물리 메모리 증설이나 애플리케이션의 메모리 사용량 최적화가 필요하다는 신호다.
  • SSD 마모: SSD를 스왑 장치로 사용하면 쓰기 횟수 증가로 수명이 단축될 수 있다. 다만 최근 SSD는 내구성이 크게 개선되어 일반적인 사용에서는 큰 문제가 되지 않는 경우가 많다.
  • 컨테이너 오케스트레이션 환경: 스왑이 활성화된 상태에서 메모리 제한을 설정하면 컨테이너가 예상보다 느리게 동작하거나 리소스 제한이 무력화될 수 있어, 운영 환경에서는 스왑을 비활성화하는 경우가 많다.
  • 모니터링 필수: vmstat, sar 같은 도구로 si(swap-in), so(swap-out) 수치를 지속적으로 관찰해 스왑 발생 빈도를 파악해야 한다.

8. 핵심 정리

스왑은 물리 메모리 부족 상황에서 보조 기억장치를 활용해 시스템이 계속 동작할 수 있게 해주는 안전장치다. 페이지 교체 알고리즘이 어떤 페이지를 내보낼지 결정하며, LRU와 그 근사 방식이 널리 쓰인다. 하지만 디스크 I/O는 물리 메모리 접근보다 자릿수 단위로 느리기 때문에, 스왑이 과도하게 발생하면 스래싱으로 이어져 성능이 급격히 저하된다. 실무에서는 스왑을 완전히 없애기보다 적절히 설정하고 모니터링하며, 근본 원인인 메모리 부족 자체를 해결하는 방향으로 접근해야 한다.