2025-09-08 03:05
컴퓨터 메모리 관리의 핵심 페이징 기법 완벽 정복 핸드북
컴퓨터 프로그램을 실행할 때, 우리는 마치 수십, 수백 기가바이트의 거대한 메모리를 혼자 쓰는 것처럼 느낍니다. 하지만 실제 컴퓨터에 장착된 RAM(물리 메모리)은 8GB, 16GB, 32GB 등으로 한정되어 있습니다. 어떻게 이런 마법 같은 일이 가능할까요? 그 비밀의 중심에는 바로 **페이징(Paging)**이라는 메모리 관리 기법이 있습니다.
페이징은 현대 운영체제(OS)의 심장과도 같은 기술로, 한정된 물리 메모리를 수많은 프로세스가 효율적이고 안전하게 나누어 쓸 수 있도록 해주는 핵심 원리입니다. 이 핸드북에서는 페이징이 왜 탄생했는지부터 시작하여, 그 복잡한 내부 구조와 작동 방식, 그리고 가상 메모리와의 관계까지 깊이 있게 탐험해 보겠습니다.
1. 페이징은 왜 만들어졌나 메모리 단편화와의 전쟁
페이징의 탄생 배경을 이해하려면, 그 이전에 사용되던 메모리 관리 방식의 고질적인 문제점을 알아야 합니다. 바로 단편화(Fragmentation) 문제입니다.
초기 메모리 할당 방식의 한계
초기 컴퓨터 시스템에서는 프로세스를 메모리에 올릴 때, 필요한 크기만큼의 연속된(Contiguous) 공간을 통째로 할당했습니다. 이는 마치 주차장에 차를 대는 것과 같습니다.
-
고정 분할 방식: 주차장 구획이 모두 같은 크기로 정해져 있는 방식입니다. 5인승 세단을 경차 구역에 댈 수 없고, 반대로 트럭을 세단 구역에 댈 수도 없습니다. 프로세스가 할당된 공간보다 작으면 남는 공간이 발생하는데, 이를 내부 단편화라고 합니다.
-
가변 분할 방식: 차 크기에 딱 맞는 주차 공간을 매번 새로 그려주는 방식입니다. 차들이 들어오고 나가는 과정이 반복되면, 주차장 중간중간에 작은 빈 공간들이 생깁니다. 이 공간들을 모두 합치면 큰 차 한 대를 댈 수 있는 충분한 공간이지만, 연속적이지 않아 차를 댈 수 없는 상황이 발생합니다. 이를 외부 단편화라고 합니다.
특히 외부 단편화는 심각한 문제였습니다. 메모리의 총 여유 공간은 충분함에도 불구하고, 연속된 공간이 없어서 새로운 프로세스를 실행시키지 못하는 비효율이 발생했기 때문입니다. 운영체제는 흩어진 빈 공간을 합치는 ‘압축(Compaction)’ 작업을 할 수도 있었지만, 이는 시스템에 상당한 부하를 주는 비싼 작업이었습니다.
이러한 외부 단편화 문제를 근본적으로 해결하기 위해 “프로세스를 굳이 연속된 공간에 할당해야 할까?”라는 혁신적인 질문에서 페이징 기법이 탄생했습니다.
2. 페이징의 구조와 작동 원리 조각내어 정복하라
페이징의 핵심 아이디어는 간단합니다. “크고 연속적인 덩어리를 작고 고정된 크기의 조각으로 나누어 관리하자.”
핵심 구성 요소
페이징 시스템은 다음과 같은 핵심 요소들로 이루어집니다.
-
페이지(Page): 프로세스의 **논리 주소 공간(Logical Address Space)**을 일정한 크기로 자른 조각. 논리 주소는 프로세스 입장에서 바라보는 주소이며, 0번지부터 시작하는 자신만의 가상 공간입니다.
-
프레임(Frame): **물리 메모리(Physical Memory, RAM)**를 페이지와 똑같은 크기로 자른 조각. 실제 데이터가 저장되는 물리적인 공간입니다.
-
페이지 테이블(Page Table): 어떤 페이지가 어떤 프레임에 저장되어 있는지 연결해주는 지도(mapping table). 각 프로세스는 자신만의 페이지 테이블을 가지고 있으며, 운영체제는 이를 통해 주소를 변환합니다.
핵심은 페이지의 크기와 프레임의 크기가 동일하다는 것입니다. 덕분에 어떤 페이지든 비어있는 아무 프레임에나 쏙 들어갈 수 있습니다. 더 이상 연속된 공간을 찾아 헤맬 필요가 없어진 것입니다.
마법 같은 주소 변환 과정
그렇다면 CPU는 어떻게 이 흩어진 조각들을 찾아갈까요? 이 과정에서 하드웨어인 **MMU(Memory Management Unit, 메모리 관리 장치)**가 핵심적인 역할을 합니다.
-
논리 주소 생성: CPU는 프로그램 코드를 실행하며 특정 데이터에 접근하기 위한 논리 주소(예: “내 주소 공간의 1000번지에 있는 데이터를 가져와!“)를 생성합니다.
-
주소 분해: MMU는 CPU가 생성한 논리 주소를 두 부분으로 나눕니다.
-
페이지 번호 (p, page number): 해당 주소가 몇 번째 페이지에 속하는지를 나타냅니다.
-
오프셋 (d, offset): 페이지 내에서 얼마나 떨어져 있는지를 나타내는 상대적인 위치입니다.
-
-
페이지 테이블 조회: MMU는 현재 실행 중인 프로세스의 페이지 테이블에 접근합니다. 그리고 **페이지 번호(p)**를 인덱스(index)로 사용하여 해당 페이지가 저장된 **프레임 번호(f)**를 찾아냅니다.
-
물리 주소 생성: MMU는 페이지 테이블에서 찾은 **프레임 번호(f)**와 원래의 **오프셋(d)**을 조합하여 최종적인 물리 주소를 만듭니다.
-
메모리 접근: 생성된 물리 주소를 통해 실제 RAM에 접근하여 원하는 데이터를 읽거나 씁니다.
이 모든 과정은 하드웨어 수준에서 매우 빠르게 일어나기 때문에, 프로세스는 자신의 코드가 메모리 여러 곳에 흩어져 있다는 사실조차 인지하지 못합니다. 그저 거대하고 연속적인 메모리를 사용하는 것처럼 느낄 뿐입니다.
예시로 이해하기
-
페이지 크기가 1KB(1024바이트)라고 가정해 봅시다.
-
CPU가 논리 주소
2500
번지에 접근하려고 합니다. -
MMU는 주소를 계산합니다.
-
페이지 번호(p) =
2500 / 1024
의 몫 =2
(즉, 2번 페이지) -
오프셋(d) =
2500 % 1024
의 나머지 =452
-
-
프로세스의 페이지 테이블을 보니, 2번 페이지는 10번 프레임에 저장되어 있다고 기록되어 있습니다.
-
최종 물리 주소 = (프레임 번호 * 페이지 크기) + 오프셋 =
(10 * 1024) + 452
=10240 + 452
=10692
번지 -
시스템은 물리 메모리의 10692번지에 접근합니다.
3. 페이징 시스템의 효율을 높이는 기술들
페이징은 외부 단편화를 해결했지만, 새로운 문제점을 낳았습니다. 바로 성능 저하와 메모리 낭비입니다.
속도 문제와 해결사 TLB
주소 변환 과정을 다시 생각해 보면, 원하는 데이터에 접근하기 위해 최소 두 번의 메모리 접근이 필요합니다.
-
페이지 테이블을 보기 위한 메모리 접근
-
실제 데이터에 접근하기 위한 메모리 접근
메모리 접근은 CPU 연산에 비해 매우 느린 작업입니다. 매번 두 번씩 메모리에 접근한다면 시스템 전체의 성능이 크게 저하될 것입니다.
이를 해결하기 위해 **TLB(Translation Lookaside Buffer)**라는 특수한 하드웨어 캐시를 사용합니다. TLB는 최근에 사용된 페이지-프레임 매핑 정보를 소량 저장하는 매우 빠른 메모리입니다.
주소 변환 시, MMU는 페이지 테이블을 보기 전에 먼저 TLB를 확인합니다.
-
TLB Hit: 원하는 페이지 정보가 TLB에 있으면, 즉시 프레임 번호를 얻어 물리 주소를 변환합니다. (메모리 접근 1회)
-
TLB Miss: 정보가 TLB에 없으면, 페이지 테이블을 조회하고(메모리 접근 추가 발생), 그 결과를 TLB에 새로 기록한 후 주소를 변환합니다.
대부분의 프로그램은 특정 시간 동안 특정 영역의 코드와 데이터에 집중적으로 접근하는 지역성(Locality) 특성을 가지므로, TLB의 적중률(Hit ratio)은 매우 높게 나타납니다. 덕분에 페이징으로 인한 성능 저하를 상당 부분 상쇄할 수 있습니다.
페이지 테이블의 크기 문제와 다단계 페이징
현대의 64비트 시스템은 이론적으로 어마어마한 크기의 논리 주소 공간을 가집니다. 이는 곧 페이지 테이블의 크기 또한 엄청나게 커질 수 있음을 의미합니다. 예를 들어, 4KB 페이지 크기를 사용하는 64비트 시스템에서 단일 단계 페이지 테이블을 만든다면, 그 크기만으로도 수십 페타바이트(PB)에 달할 수 있습니다.
이 문제를 해결하기 위해 다단계 페이징(Multi-level Paging) 기법을 사용합니다. 이는 페이지 테이블 자체를 페이징하는 기발한 아이디어입니다.
-
2단계 페이징: 페이지 테이블을 여러 조각으로 나누고, 이 조각들의 위치를 가리키는 상위 레벨의 ‘페이지 디렉터리’를 둡니다.
-
다단계 페이징: 2단계 페이징을 여러 계층으로 확장한 구조입니다.
이 방식을 사용하면, 현재 사용되지 않는 페이지에 대한 페이지 테이블 공간은 할당할 필요가 없으므로 메모리를 크게 절약할 수 있습니다. 다만, 주소 변환을 위해 여러 단계의 테이블을 거쳐야 하므로 메모리 접근 횟수가 늘어난다는 단점이 있습니다.
4. 페이징의 장점과 단점 요약
구분 | 내용 |
---|---|
장점 | 1. 외부 단편화 해결: 물리 메모리의 여유 공간을 조각내어 효율적으로 사용할 수 있습니다. 2. 유연한 메모리 관리: 프로세스를 불연속적인 공간에 배치할 수 있어 메모리 관리가 유연해집니다. 3. 메모리 보호 및 공유 용이: 페이지 테이블에 보호 비트(읽기/쓰기/실행 권한)를 추가하여 페이지별 접근 제어가 가능합니다. 또한, 여러 프로세스의 페이지 테이블이 동일한 프레임을 가리키게 하여 코드나 데이터를 쉽게 공유할 수 있습니다. 4. 가상 메모리의 기반: 페이징은 필요한 페이지만 메모리에 올리고 나머지는 디스크(스왑 공간)에 두는 가상 메모리 시스템을 구현하는 핵심 기술입니다. |
단점 | 1. 내부 단편화 존재: 프로세스의 크기가 페이지 크기의 배수로 딱 떨어지지 않으면, 마지막 페이지에서는 항상 남는 공간(내부 단편화)이 발생합니다. 2. 페이지 테이블 오버헤드: 각 프로세스마다 페이지 테이블을 저장할 공간이 추가로 필요합니다. 3. 주소 변환 오버헤드: 논리 주소를 물리 주소로 변환하는 과정이 필요하며, 이는 TLB가 없을 경우 성능 저하의 원인이 됩니다. |
결론: 현대 컴퓨팅의 보이지 않는 초석
페이징 기법은 단순히 메모리를 나누는 기술을 넘어, 현대 운영체제가 멀티태스킹, 메모리 보호, 가상 메모리 등 핵심적인 기능들을 수행할 수 있도록 받쳐주는 보이지 않는 초석입니다. 외부 단편화라는 거대한 장벽을 무너뜨리고, 한정된 물리 자원을 최대한으로 활용할 수 있는 길을 열어주었습니다.
다음에 우리가 여러 프로그램을 동시에 실행하며 컴퓨터를 사용할 때, 그 이면에서 수많은 페이지와 프레임, 그리고 페이지 테이블이 쉴 새 없이 움직이며 이 모든 것을 가능하게 하고 있음을 기억해 보는 것은 어떨까요? 페이징에 대한 이해는 컴퓨터 시스템의 깊은 곳을 들여다보는 흥미로운 여정의 시작이 될 것입니다.]]