2025-09-10 23:48
-
가상 메모리는 실제 물리 메모리(RAM)의 한계를 넘어 각 프로세스에 거대한 전용 메모리 공간을 제공하는 기술이다.
-
주소 변환(페이징, 페이지 테이블)을 통해 논리적 주소를 물리적 주소로 매핑하며, 필요할 때만 데이터를 RAM으로 가져온다.
-
이를 통해 메모리 사용을 효율화하고, 프로세스를 격리하여 시스템 안정성을 높이며, 멀티태스킹을 원활하게 만든다.
컴퓨터 천재들의 마법 가상 메모리 완벽 핸드북
컴퓨터 전원을 켜고 여러 프로그램을 동시에 실행할 때, 우리는 8GB나 16GB 같은 한정된 RAM 용량을 넘어서는 작업을 아무렇지 않게 수행한다. 어떻게 이런 일이 가능할까? 정답은 바로 ‘가상 메모리(Virtual Memory)‘라는 운영체제의 독창적인 마법에 있다. 이 핸드북은 개발자뿐만 아니라 컴퓨터의 동작 원리가 궁금한 모든 이를 위해 가상 메모리의 탄생 배경부터 구조, 작동 방식, 그리고 심화 내용까지 모든 것을 담았다.
1. 가상 메모리는 왜 만들어졌을까
초창기 컴퓨터는 프로그램을 실행할 때 필요한 모든 코드와 데이터를 물리 메모리(RAM)에 한 번에 올려야 했다. 이는 두 가지 치명적인 문제를 낳았다.
-
메모리 용량의 한계: 프로그램의 크기가 실제 RAM 크기보다 크면 아예 실행조차 할 수 없었다. 16MB RAM을 가진 컴퓨터에서 20MB짜리 프로그램을 실행하는 것은 불가능했다.
-
메모리 관리의 비효율: 여러 프로그램을 동시에 실행하면 문제가 더 복잡해진다. A라는 프로그램이 메모리의 0번지부터 100번지까지 사용하고, B라는 프로그램이 101번지부터 200번지까지 사용한다고 가정해 보자. 만약 A가 종료되면 0-100번지 공간은 비게 된다. 이때 150 크기의 C 프로그램이 실행되려면 이 공간에 들어갈 수 없다. 중간에 빈 공간(단편화)이 많아져도 연속된 큰 공간이 없으면 메모리를 효율적으로 사용할 수 없었다. 또한, 다른 프로그램의 메모리 영역을 침범하여 시스템 전체를 다운시키는 보안 문제도 있었다.
이러한 문제들을 해결하기 위해 컴퓨터 과학자들은 다음과 같은 기발한 아이디어를 떠올렸다. “프로그램에게 실제 메모리가 아닌, 크고 연속적인 가상의 메모리 공간을 하나씩 나눠주면 어떨까?”
이것이 바로 가상 메모리의 출발점이다. 각 프로그램은 자신만이 사용하는 거대한 메모리 공간(예: 4GB)을 할당받은 것처럼 행동한다. 실제로는 운영체제가 이 가상의 주소를 실제 물리 메모리 주소 및 하드디스크(SSD)의 일부 공간과 교묘하게 연결(매핑)해준다.
2. 가상 메모리의 구조와 핵심 용어
가상 메모리를 이해하려면 몇 가지 핵심 용어와 그 관계를 알아야 한다. 마치 도서관에서 책을 찾는 과정에 비유할 수 있다.
용어 | 설명 | 도서관 비유 |
---|---|---|
프로세스 (Process) | 현재 실행 중인 프로그램. | 책을 찾으려는 사람. |
가상 주소 공간 (Virtual Address Space) | 프로세스가 자신만의 것이라고 믿는 연속적인 메모리 공간. | 도서관의 모든 책 목록(인덱스 카드). 사람은 이 목록만 보고 책을 찾는다. |
물리 주소 공간 (Physical Address Space) | 실제 RAM의 주소 공간. | 도서관의 실제 책장. 책은 여기에 꽂혀 있다. |
페이지 (Page) | 가상 주소 공간을 일정한 크기로 나눈 블록. (보통 4KB) | 책 목록(인덱스)의 한 페이지. |
프레임 (Frame) | 물리 주소 공간을 페이지와 같은 크기로 나눈 블록. | 책장의 한 칸. 정확히 책 한 권이 들어갈 크기. |
페이징 (Paging) | 가상 주소 공간을 페이지 단위로 나눠 물리 메모리의 프레임에 불연속적으로 할당하는 기법. | 책 목록의 내용을 실제 책장 위치와 연결하는 작업. |
페이지 테이블 (Page Table) | 가상 주소(페이지 번호)와 실제 물리 주소(프레임 번호)의 매핑 정보를 담고 있는 표. 각 프로세스마다 하나씩 존재. | 책 목록(인덱스)과 실제 책장 위치를 기록해 둔 ‘장부’. |
MMU (Memory Management Unit) | CPU가 요청한 가상 주소를 실제 물리 주소로 변환해주는 하드웨어 장치. | 책 위치를 물어보면 장부를 보고 실제 책장 위치를 알려주는 사서. |
스왑 공간 (Swap Space) | 물리 메모리가 부족할 때, 당장 사용하지 않는 페이지를 잠시 내려놓는 디스크(HDD/SSD)의 특정 영역. | 책장에 자리가 없어 잠시 책을 보관해두는 ‘지하 서고’. |
핵심은 프로세스는 오직 가상 주소만 바라본다는 것이다. CPU가 “가상 주소 100번지에 있는 데이터를 가져와!”라고 명령하면, MMU라는 하드웨어 번역가가 페이지 테이블을 참조하여 “아, 그건 물리 메모리 5000번지에 있군” 하고 실제 위치를 찾아 데이터를 가져다준다.
3. 가상 메모리의 작동 방식 (주소 변환과 페이지 폴트)
가상 메모리의 마법은 ‘주소 변환’과 ‘페이지 폴트’라는 두 가지 메커니즘을 통해 일어난다.
1단계: 주소 변환 (Address Translation)
-
CPU의 요청: CPU가 특정 가상 주소(예:
0x1A2B3C4D
)에 접근하려 한다. -
MMU의 역할: MMU는 이 가상 주소를 페이지 번호(Virtual Page Number, VPN)와 오프셋(Offset)으로 분리한다.
-
페이지 번호
: 페이지 테이블에서 어떤 항목을 찾아야 하는지에 대한 인덱스. -
오프셋
: 해당 페이지 내에서 실제 데이터가 얼마나 떨어져 있는지에 대한 위치.
-
-
TLB 확인 (캐시): MMU는 먼저 **TLB(Translation Lookaside Buffer)**라는 고속 캐시를 확인한다. TLB는 최근에 변환된 주소 정보를 저장하고 있어, 여기에 정보가 있으면(TLB Hit) 페이지 테이블을 거치지 않고 즉시 물리 주소를 얻어 매우 빠르게 처리한다.
-
페이지 테이블 조회 (TLB Miss): TLB에 정보가 없으면(TLB Miss), MMU는 메모리에 있는 해당 프로세스의 페이지 테이블을 조회한다.
-
물리 주소 계산: 페이지 테이블에서 가상 페이지 번호(VPN)에 해당하는 물리 프레임 번호(Physical Frame Number, PFN)를 찾는다. 그리고 이 프레임 번호와 원래의 오프셋을 합쳐 최종 물리 주소를 만들어낸다.
2단계: 페이지 폴트 (Page Fault)
만약 페이지 테이블을 조회했는데, 해당 페이지가 현재 물리 메모리(RAM)에 올라와 있지 않다면 어떻게 될까? (페이지 테이블에 ‘invalid’ 비트가 표시되어 있음) 이때 페이지 폴트라는 특별한 인터럽트(예외 상황)가 발생한다.
-
예외 발생: MMU가 주소 변환에 실패하면 CPU에 트랩(Trap)을 건다.
-
운영체제 개입: CPU는 하던 일을 잠시 멈추고 운영체제의 페이지 폴트 핸들러를 실행시킨다.
-
데이터 위치 확인: 운영체제는 해당 페이지의 데이터가 디스크의 스왑 공간 어디에 있는지 확인한다.
-
메모리 확보: 물리 메모리(RAM)에 빈 프레임이 있는지 찾는다.
- 만약 빈 프레임이 없다면? 페이지 교체 알고리즘(아래에서 설명)을 사용해 기존에 있던 페이지 중 하나를 골라 스왑 공간으로 내보내고 공간을 확보한다.
-
데이터 로딩: 스왑 공간에 있던 페이지 데이터를 비어있는 프레임으로 로드한다.
-
페이지 테이블 갱신: 페이지 테이블을 새로 로드된 물리 프레임 번호로 업데이트하고, ‘valid’ 비트로 변경한다.
-
작업 재개: 중단되었던 명령어를 다시 실행시킨다. 이제는 MMU가 정상적으로 주소를 변환하여 작업을 이어갈 수 있다.
이처럼 프로그램 실행에 필요한 데이터만 그때그때 메모리에 올리는 방식을 **요구 페이징(Demand Paging)**이라고 한다. 덕분에 프로그램 시작 속도가 빨라지고 메모리도 훨씬 효율적으로 사용할 수 있게 된다.
4. 심화 내용: 더 깊은 이해를 위하여
페이지 교체 알고리즘 (Page Replacement Algorithm)
페이지 폴트가 발생했는데 물리 메모리가 꽉 차 있다면, 어떤 페이지를 희생시켜야 할까? 이때 사용되는 정책이 페이지 교체 알고리즘이다.
-
FIFO (First-In, First-Out): 가장 간단한 방식으로, 메모리에 가장 먼저 들어온 페이지를 교체한다. 구현은 쉽지만, 자주 사용되는 페이지가 오래전에 들어왔다는 이유만으로 교체될 수 있어 비효율적일 때가 많다.
-
LRU (Least Recently Used): ‘최근에 가장 적게 사용된’ 페이지를 교체한다. 가장 오랫동안 사용되지 않은 페이지는 앞으로도 사용되지 않을 가능성이 높다는 지역성(Locality) 원리에 기반한다. 성능이 좋지만, 모든 페이지의 최근 사용 시간을 기록해야 하므로 구현이 복잡하고 오버헤드가 크다.
-
Optimal (최적 교체): 앞으로 가장 오랫동안 사용되지 않을 페이지를 예측하여 교체하는 가장 이상적인 방법. 하지만 미래를 예측할 수 없으므로 실제 구현은 불가능하며, 다른 알고리즘의 성능을 평가하기 위한 기준으로만 사용된다.
현대의 운영체제는 LRU의 성능에 근접하면서도 구현이 용이한 변형 알고리즘(예: Clock 알고리즘)을 주로 사용한다.
메모리 보호와 공유
가상 메모리는 각 프로세스에 독립된 주소 공간을 제공하므로, 한 프로세스가 다른 프로세스의 메모리 영역을 침범하는 것을 원천적으로 차단한다. 운영체제는 페이지 테이블에 읽기/쓰기/실행 권한 비트를 두어 특정 메모리 영역에 대한 접근을 제어할 수 있다. 예를 들어 코드 영역은 쓰기가 불가능하도록(read-only) 설정하여 악의적인 코드 변경을 막는다.
또한, 여러 프로세스가 공통으로 사용하는 라이브러리(예: C 표준 라이브러리)가 있다면, 이 라이브러리의 물리 메모리 프레임을 여러 프로세스의 페이지 테이블이 함께 가리키도록 하여 메모리를 절약할 수 있다.
5. 가상 메모리의 장점과 단점
장점 | 단점 |
---|---|
물리 메모리 크기 제약 극복: 프로그램 크기가 RAM보다 커도 실행 가능. | 성능 저하 가능성: 페이지 폴트 처리 및 주소 변환에 따른 오버헤드 발생. |
효율적인 메모리 관리: 단편화 문제를 해결하고, 요구 페이징으로 효율성 증대. | 디스크 I/O 증가: 스와핑이 빈번하게 발생하면(스레싱), 시스템 성능이 급격히 저하됨. |
강력한 메모리 보호: 프로세스 간 메모리 침범을 방지하여 시스템 안정성 향상. | 복잡한 구현: MMU 하드웨어 지원이 필요하며, 운영체제의 관리 로직이 복잡함. |
프로세스 생성 속도 향상: 부모 프로세스의 페이지 테이블을 복사(Copy-on-Write)하여 빠른 생성. | |
메모리 공유 용이: 공유 라이브러리 등을 통해 메모리 사용량 절감. |
결론: 현대 컴퓨터 시스템의 기반
가상 메모리는 단순히 메모리가 부족한 문제를 해결하는 기술을 넘어, 현대 운영체제의 멀티태스킹, 안정성, 효율성을 떠받치는 핵심적인 기반이다. 우리가 수많은 프로그램을 동시에 켜놓고 원활하게 작업을 할 수 있는 것은, 보이지 않는 곳에서 운영체제와 MMU가 쉴 새 없이 가상 주소를 물리 주소로 변환하고 데이터를 디스크와 RAM 사이에서 움직여주는 덕분이다. 이 복잡하고 정교한 ‘착각’의 시스템이야말로 컴퓨터 공학이 이뤄낸 가장 위대한 성취 중 하나라고 할 수 있다.