In Veritate Libertas

The Restricted
Section

A collection of spells,
experiments, and forbidden knowledge.

Study/[ OS ] | 2026. 6. 18. 23:58

#02 메모리 계층

728x90

메모리 계층 구조 — CS 공부 두 번째

지난번에 운영체제 구조 정리하면서 레지스터 → 캐시 → RAM → 디스크 흐름을 그냥 "빠른 것부터 느린 것 순서"라고 넘겼는데, 이번엔 이걸 제대로 파보려고 해. 왜 이런 계층이 생겨났는지, 각 계층이 어떻게 동작하는지 알고 나니까 "아, 그래서 그랬구나" 싶은 게 꽤 있었어.


근본적인 질문 — 왜 계층이 필요해?

메모리를 하나로 통일하면 안 될까? 빠른 메모리 하나만 쭉 쓰면 되는 거 아닌가? 라는 생각을 처음에 했어.

근데 이게 물리적으로 불가능한 이유가 있어.

빠른 메모리일수록 트랜지스터를 더 많이 써야 해. 대표적인 예로 캐시에 쓰는 SRAM은 1비트를 저장하는 데 트랜지스터가 6개 필요한데, RAM에 쓰는 DRAM은 트랜지스터 1개 + 커패시터 1개로 끝이야. 구조가 단순하니까 같은 면적에 훨씬 많이 집적할 수 있어. 당연히 DRAM이 SRAM보다 훨씬 저렴하고 용량도 크게 만들 수 있어.

실제로 SRAM 1GB는 약 5,000달러, DRAM 1GB는 20~75달러 수준이야 (Diffen 자료 기준). 용량 대비 가격 차이가 수십~수백 배야.

그래서 어쩔 수 없이 절충안이 필요해.

 

"속도 × 용량 × 비용" 이 세 가지를 동시에 만족하는 메모리는 없어. 메모리 계층 구조는 이 트레이드오프를 영리하게 해결하는 방식이야.

 


메모리 계층의 핵심 전제 — 지역성 원리

계층 구조가 실제로 효과를 내는 이유가 있어. 프로그램이 메모리를 사용하는 방식에 패턴이 있거든.

시간적 지역성 (Temporal Locality) : 한 번 접근한 데이터는 가까운 미래에 또 접근할 가능성이 높아. 예를 들어 반복문 안의 변수 i는 루프를 돌면서 계속 참조돼.

공간적 지역성 (Spatial Locality) : 방금 접근한 주소 근처의 데이터에 곧 접근할 가능성이 높아. 배열을 순서대로 읽을 때처럼. 데이터가 메모리에 연속적으로 저장되어 있으면 한 번 캐시에 올려둔 덩어리(캐시 라인)를 여러 번 재사용할 수 있어.

지역성 원리를 이용해서 계층으로 구성돼! 위로 갈수록 접근 시간은 감소하고, 속도는 증가하고, 비용은 비싸고, 용량은 적어.

 

여기서 드는 의문

"그럼 접근 패턴이 완전히 랜덤한 코드는 캐시 효율이 떨어지겠네?"

맞아. 예를 들어 연결 리스트(Linked List)는 노드가 메모리에 분산 저장되어 있어서 공간적 지역성이 거의 없어. 그래서 배열보다 캐시 미스가 훨씬 많이 발생해. 알고리즘 선택이 성능에 이런 식으로 영향을 미치는 거야.


계층별 상세

계층 위치 접근 속도 용량
레지스터 CPU 내부 ~1 사이클 수백 byte 휘발성
L1 캐시 CPU 내부 (코어별) 3~5 사이클 32~128 KB 휘발성
L2 캐시 CPU 내부 (코어별) 7~14 사이클 256 KB~2 MB 휘발성
L3 캐시 CPU 내부 (공유) 20~40 사이클 4 MB~수백 MB 휘발성
RAM (DRAM) - 메모리 CPU 외부 100~200 사이클 수 GB~수백 GB 휘발성
SSD / HDD - 하드 디스크 CPU 직접 접근 불가 수만~수십만 사이클 수백 GB~수 TB 비휘발성

사이클 수치: ScienceDirect, Intel/AMD 문서 및 Valley AI 분석 자료 기반


1. 레지스터 (Register)

CPU 안에 있는 임시기억장치야. 연산은 전부 여기서 이루어져.

CPU는 자체적으로 데이터를 저장할 방법이 없어서 계산할 값을 레지스터에 로드하고, 계산 결과도 레지스터에 저장했다가 메모리로 내보내. 연산이 레지스터를 거쳐야 하는 이유야.

레지스터 종류를 알고 있으면 CPU 동작 흐름이 좀 더 명확하게 보여.

 

[레지스터 역할]

PC (Program Counter) - 프로그램 계수기 다음에 실행할 명령어 주소 가지고 있음
IR (Instruction Register) - 명령어 레지스터 현재 실행 중인 명령어 가지고 있음
AC (Accumulator) - 누산기 연산 결과를 임시 저장
MAR (Memory Address Register) - 메모리 주소 레지스터 메모리 읽기/쓰기 위한 주소 가지고 있음
MBR (Memory Buffer Register) - 메모리 버퍼 레지스터 메모리에서 읽은 데이터 또는 써야 할 데이터를 가지고 있음
SR (Status Register) - 상태 레지스터 CPU 현재 상태 (오버플로, 인터럽트 등)
I/O AR - 입출력 주소 레지스터 입출력 장치 주소
I/O BR - 입출력 버퍼 레지스터 입출력 데이터 교환 버퍼

 

PC 레지스터가 왜 중요한지 처음엔 몰랐는데, 나중에 프로세스 문맥 교환(Context Switching)을 보면서 이해됐어. CPU가 A 프로세스 실행하다가 B로 넘어갈 때, A의 PC 값을 저장해두지 않으면 나중에 어디서부터 재개해야 할지 모르거든. PC는 프로세스의 "책갈피"인 셈이야.

 

2. 캐시 (Cache)

CPU(중앙처리장치)와 RAM(주기억장치) 사이의 속도 차이를 줄이기 위한 고속 메모리야. SRAM으로 만들어져서 빠른 대신 비싸고 용량이 작아.

왜 필요한지 수치로 보면

RAM 접근에 100~200 사이클이 걸리는데, CPU가 5GHz로 돌면 1사이클이 0.2나노초야. 100사이클이면 20나노초. 이 시간 동안 CPU는 그냥 손 놓고 기다려야 해. 이걸 메모리 레이턴시 문제 또는 폰 노이만 병목(Von Neumann Bottleneck) 이라고 불러.

폰 노이만 병목이란?
현대 컴퓨터의 대부분은 폰 노이만 구조야. CPU와 메모리가 단일 버스로 연결되어 있어서, 명령어를 가져오는 것과 데이터를 주고받는 것이 동시에 일어날 수 없어.
CPU 클럭 속도는 1975년 대비 약 5,000배 빨라졌는데, DRAM 대역폭은 같은 기간 500배 개선에 그쳤어 (출처: The Core IT 분석). CPU가 메모리보다 약 10배 더 빠르게 발전했다는 뜻이야. 이 격차가 커질수록 CPU는 메모리 데이터를 기다리느라 노는 시간이 늘어.
1977년 ACM 튜링상 강연에서 John Backus가 이 문제를 "작은 병목(tiny bottleneck)"이라고 표현했어. 40년이 지난 지금도 해결 중인 문제야.

 

이 병목을 줄이기 위해 캐시 계층이 발전했고, 현재 3단계(L1 → L2 → L3)로 구성되어 있어.

L1 캐시

일반적으로 CPU 칩안에 내장되어 데이터 사용 및 참조에 가장 먼저 사용되는 캐시 메모리야.

가장 빠르고 가장 작아. 각 코어마다 독립적으로 가지고 있어. 접근 속도는 3~5 사이클 (약 0.7~1 나노초).

보통 두 개로 나뉘어.

  • L1i (Instruction Cache): 다음에 실행할 명령어 저장
  • L1d (Data Cache): 명령어가 조작할 데이터 저장

이렇게 나뉜 게 하버드 아키텍처 변형이야. 명령어와 데이터를 동시에 가져올 수 있어서 파이프라이닝 효율이 올라가.

용량은 32KB~128KB. 작게 유지하는 이유가 있어 — 캐시가 크면 그 안에서 원하는 데이터를 찾는 시간도 길어지거든. 빠른 속도를 유지하려면 작아야 해.

 

L2 캐시

L1보다 크고 느려. 접근 속도 7~14 사이클 (약 3~5 나노초). 용량은 보통 코어당 256KB~2MB.

L1 캐시 메모리와 용도와 역할은 비슷한데 L1에서 미스가 나면 L2를 봐. L2도 대부분 코어마다 개별적으로 가지고 있어. Intel Raptor Lake는 퍼포먼스 코어당 2MB, AMD Zen 5는 코어당 1MB를 사용해.

 

L3 캐시

가장 크고 가장 느린 온다이 캐시야. 접근 속도 20~40 사이클. 모든 코어가 공유해.

용량이 굉장히 다양해. 일반 데스크탑 CPU는 4~32MB, AMD EPYC 같은 서버 CPU는 수백 MB까지 올라가.

대부분 CPU가 아닌 메인보드에 내장되어있어서 유일하게 CPU 성능에 직접적인 영향을 주진 않아.

L3가 중요한 이유 중 하나가 멀티코어 환경에서의 캐시 일관성(Cache Coherency) 이야. 코어 A가 데이터를 수정했는데 코어 B가 아직 L1에 가지고 있는 구버전 데이터를 읽으면 문제가 생겨. 이걸 막기 위해 MESI 프로토콜 같은 캐시 일관성 프로토콜이 사용돼.

 

MESI는 각 캐시 라인의 상태를 Modified / Exclusive / Shared / Invalid 네 가지로 관리해. 코어 하나가 데이터를 수정하면 다른 코어의 해당 캐시 라인을 Invalid로 표시해서 구버전을 읽는 걸 막아.

 

캐시 히트와 캐시 미스

CPU가 데이터를 요청하면 L1 → L2 → L3 순서로 찾아.

  • 캐시 히트(Cache Hit): 원하는 데이터가 캐시에 있어서 빠르게 가져옴
  • 캐시 미스(Cache Miss): 캐시에 없어서 다음 계층에서 가져와야 함 — 이 순간 CPU가 기다려야 해

캐시 미스가 많으면 파이프라인이 자주 끊겨. 코드 짤 때 캐시 미스를 줄이는 게 고성능 코드의 핵심 중 하나야. 그래서 시니어 개발자들이 "캐시 친화적인 코드"를 강조하는 거야.

 

캐시 매핑 방식

캐시가 RAM의 어떤 데이터를 어느 위치에 올릴지 결정하는 방식이야.

  • 직접 매핑(Direct-mapped): RAM의 특정 블록이 캐시의 딱 한 군데만 들어갈 수 있어. 구조가 단순해서 빠르지만 충돌(Conflict Miss)이 자주 일어날 수 있어
  • 완전 연관(Fully Associative): 어느 위치에나 들어갈 수 있어. 충돌은 없지만 원하는 걸 찾는 데 캐시 전체를 뒤져야 해서 느려
  • 집합 연관(Set-Associative): 위 두 방식의 절충. 캐시를 여러 집합(Set)으로 나누고, 특정 블록은 정해진 집합 안의 어느 위치든 들어갈 수 있어. 현대 CPU는 대부분 8-way나 12-way 집합 연관 방식을 써

Write-through vs Write-back

캐시의 데이터를 수정했을 때 언제 RAM에 반영하느냐의 정책이야.

  • Write-through: 수정 즉시 다음 계층에 반영. 일관성은 좋은데 메모리 버스 트래픽이 많아짐
  • Write-back: 캐시 라인이 교체될 때까지 반영을 미룸 (Dirty bit로 표시). 메모리 트래픽은 줄어들지만 관리가 복잡해. 현대 CPU 대부분이 사용

하드웨어 프리페처(Prefetcher)

CPU는 캐시 미스를 수동적으로 기다리지만은 않아. 메모리 접근 패턴을 분석해서 "곧 이 데이터를 쓸 것 같다"싶으면 미리 캐시에 올려놓아. 이게 하드웨어 프리페칭이야. 배열을 순서대로 읽는 패턴이 전형적인 프리페칭의 대상이야.

 

3. 메인 메모리 — RAM 주기억장치

CPU가 현재 처리 중인 프로그램과 데이터를 보관하는 공간이야. 캐시보다 훨씬 크지만 느려.

RAM(Random Access Memory)의 "Random Access"는 어느 주소든 동일한 속도로 접근할 수 있다는 의미야. 빠른 액세스를 위해 단기간 저장하는 휘발성 기억 장치야.

 

DRAM과 SRAM의 구조적 차이

앞에서 계층이 필요한 이유를 언급하면서 잠깐 나왔는데, 좀 더 구체적으로 보면 이래.

  DRAM SRAM
저장 방식 커패시터 + 트랜지스터 (1T1C) 플립플롭 회로 (트랜지스터 6개)
리프레시 필요 여부 필요 (수백 ms마다) 불필요
속도 느림 빠름
용량 대용량 가능 소용량
가격 저렴 비쌈
사용처 주기억장치(RAM) 캐시, 레지스터

DRAM이 리프레시가 필요한 이유가 재미있어. 커패시터가 데이터를 전하(Charge)로 저장하는데, 전하가 시간이 지나면 조금씩 새어나가 (Leakage). 몇 밀리초만 방치해도 데이터가 사라지거든. 그래서 메모리 컨트롤러가 수백 ms마다 커패시터를 다시 충전해줘 — 이게 리프레시야. 이 작업 자체가 시간을 잡아먹으니까 DRAM이 느린 거야.

SRAM은 플립플롭 회로로 데이터를 유지하니까 리프레시가 필요 없어. 전원이 있는 한 안정적으로 유지돼. 대신 1비트에 트랜지스터 6개를 써야 하니까 집적도가 낮고 비싼 거야.

 

DDR의 의미

흔히 DDR4, DDR5라고 부르는 게 뭔지 짚고 가면 — DDR은 Double Data Rate의 약자야. 클럭 신호의 상승 엣지와 하강 엣지 모두에서 데이터를 전송해서 같은 클럭에서 두 배의 데이터를 보낼 수 있어. DDR5는 DDR4 대비 대역폭이 약 2배야.

 

ROM은 뭐야?

RAM이랑 자주 같이 나오는데, ROM(Read Only Memory)은 역할이 달라. 고정 기억 장치로, 비휘발성이라 전원이 꺼져도 데이터가 유지돼. 변경 가능성이 거의 없는 펌웨어를 저장하는 데 써.

대표적인 게 BIOS야. 컴퓨터를 켤 때 제일 먼저 실행되는 프로그램인데, 여기가 ROM에 저장되어 있어서 전원이 꺼져도 안 날아가.

 

4. 보조기억장치 — HDD / SSD

물리적 디스크가 연결되어있는 기억장치로, 비휘발성 저장 장치야. CPU가 직접 접근할 수 없어서 데이터를 RAM으로 먼저 올린 다음 CPU가 읽어.

 

SSD vs HDD

SSD는 낸드 플래시(NAND Flash) 메모리를 사용해. HDD는 자기 디스크를 물리적으로 회전시키면서 데이터를 읽어. 물리적 이동이 없는 SSD가 당연히 빠르고 충격에 강해.

접근 속도 차이가 꽤 커. 수만~수십만 사이클 수준인데, RAM(100~200 사이클)과 비교하면 몇 백~몇 천 배 느린 거야.

 

여기서 드는 의문

"그럼 왜 RAM을 더 크게 만들지 않아?" 

RAM은 전원이 꺼지면 날아가는 휘발성이야. 영구 저장이 안 돼. 그리고 앞에서 봤듯이 DRAM도 SSD/HDD에 비하면 비싸. 같은 가격에 DRAM 1TB를 사느니 NVMe SSD 2TB를 사는 게 훨씬 현실적이야.

 

CPU가 하드디스크에 바로 접근하지 않는 이유

원문에 있던 질문인데 명확하게 정리하면 이래. CPU와 하드디스크 사이에는 표준화된 고속 인터페이스가 없어. 하드디스크는 자체 컨트롤러가 있고, 거기서 처리한 데이터를 RAM으로 올리고, CPU는 RAM에서 읽어. 이게 설계 구조야. CPU가 모든 저장 장치에 직접 접근하려면 CPU에 수십 가지 인터페이스가 달려야 하고 복잡도가 폭발해.


그래서! 메모리 계층 구조가 필요한 이유?

1. 빠른 메모리일수록 크게 만들기 어려워. SRAM은 비싸서 수 MB 이상 쓰기 어려워.

2. 자주 쓰는 데이터는 계속 자주 쓰여. 전체 데이터의 극히 일부만 자주 접근되니까, 그 일부만 캐시에 올려놓아도 대부분의 접근이 빠르게 처리돼.

3. 경제성. 비싼 메모리는 꼭 필요한 만큼만, 싼 메모리를 넉넉하게.

 

아래는 오늘 내용에 대한 Q&A 정리야.

 

더보기

Q1. 필요한 데이터가 HDD에 있는데 CPU가 바로 가져오면 더 빠르지 않을까?

위에서 설명했듯이 CPU-HDD 사이엔 직접 접근 인터페이스가 없어. 데이터를 RAM으로 올리는 게 설계 구조야. 게다가 HDD는 수만 사이클, RAM은 100~200 사이클인데 "바로 접근"이 오히려 더 느려.

Q2. RAM을 주기억장치라고 부르는 이유는?

CPU가 현재 처리하는 작업의 데이터를 실시간으로 담고 있어서야. 프로그램도, 그 프로그램의 데이터도 전부 RAM에 올라와 있어야 CPU가 쓸 수 있어. 일하는 책상 공간이라고 생각하면 돼.

Q3. 왜 불편하게 휘발성 장치를 써?

속도 때문이야. DRAM이 빠른 건 커패시터 기반 단순 구조 덕분인데, 그 구조가 동시에 전하 누수(leakage)를 일으켜. 비휘발성이면서 빠른 메모리를 만들면 좋겠지만, 현재 기술로는 속도 / 비용 / 비휘발성을 동시에 만족하기 어려워. 그래서 빠른 쪽(RAM)과 영속적인 쪽(SSD/HDD)을 역할 분담하는 거야.

Q4. 캐시 메모리의 역할과 동작 원리는? CPU와 RAM의 속도 격차를 줄이기 위한 고속 메모리. 지역성 원리를 이용해 자주 쓰이는 데이터를 가까운 곳에 미리 올려놓아. L1 → L2 → L3 순서로 찾고, 없으면 RAM 접근.

Q5. 캐시 히트율이 성능에 미치는 영향은? 캐시 미스 한 번에 수십~수백 사이클 페널티가 생겨. 미스율이 1%만 올라도 전체 성능이 눈에 띄게 떨어질 수 있어.

Q6. DRAM과 SRAM의 차이는? DRAM은 커패시터 기반이라 리프레시가 필요하고 느리지만 저렴하고 대용량. SRAM은 플립플롭 기반이라 리프레시 불필요하고 빠르지만 비싸고 소용량. DRAM은 RAM, SRAM은 캐시에 사용.

Q7. 메모리 계층이 왜 필요한가? 빠른 메모리는 비싸고 용량이 작음. 지역성 원리를 활용해 자주 쓰이는 데이터만 빠른 계층에 올려두고 나머지는 싸고 큰 계층에 두는 방식으로 비용과 성능을 동시에 잡음.

Q8. 폰 노이만 병목이란? CPU와 메모리가 단일 버스를 공유하면서 생기는 성능 한계. CPU 속도가 메모리 대역폭 향상보다 훨씬 빠르게 발전하면서 CPU가 메모리를 기다리는 시간이 늘어나는 문제. 캐시 계층이 이 병목을 완화하는 주요 수단이야.


오늘 공부는 끝!!

다음엔 프로세스와 스레드 정리해볼게.

728x90

'Study > [ OS ]' 카테고리의 다른 글

#06 시스템콜 System Call  (0) 2026.06.24
#05 인터럽트 Interrupt  (0) 2026.06.23
#04 CPU 스케줄링 알고리즘  (0) 2026.06.22
#03 프로세스와 스레드  (0) 2026.06.20
#01 운영체제와 컴퓨터  (0) 2026.06.18
흐이서

흐이서

Writer

공순이 흐이서