문서 읽는 데 43분 · A2

A-2: CPU와 메모리 계층

목차 27
전체 12강 중 2강 · CS 기초지식
난이도 · 중급

ℹ️컴퓨터 구조·운영체제·네트워크 — 언어 밑에 깔린 원리와 기술 면접 CS 질문 대비. 코딩에 어느 정도 익숙해진 뒤가 좋아요.

안녕하세요, 홍순구 튜터입니다. CS 기초 두 번째 시간이에요.

지난 시간(A-1)에 우리는 컴퓨터가 0과 1로 숫자와 글자를 표현하는 "가장 단단한 바닥"을 봤습니다. 그리고 마지막에 약속 하나를 남겼죠. CPU는 엄청 빠른데 메모리(RAM)는 상대적으로 느려서, CPU가 데이터를 기다리며 노는 문제가 생긴다고요. 이걸 폰노이만 병목(von Neumann bottleneck)이라 부르고, 컴퓨터는 캐시(cache)라는 빠른 임시 저장소로 풀어낸다고 했습니다. 오늘 그 약속을 지킵니다.

본격적으로 들어가기 전에, 면접에서 통하는 숫자 감각 하나를 보여드릴게요. 요즘 CPU는 1초에 명령을 수십억 번 처리합니다. 그런데 그 빠른 CPU가 RAM에서 데이터 하나를 꺼내오려면, 명령 수백 개를 처리할 시간만큼을 멍하니 기다려야 해요.

비유하면 1초에 수십 가지 일을 해치우는 천재 직원이, 서류 한 장 받겠다고 책상에서 100초씩 손을 놓고 있는 셈입니다. 세상에서 제일 빠른 두뇌를 사 놓고 절반을 놀리는 거죠. 이 모순을 컴퓨터가 어떻게 푸는지가 오늘의 핵심입니다.

그러려면 먼저 CPU 안으로 들어가 "이 두뇌가 대체 어떻게 일하는지"부터 봐야 해요. 오늘 우리가 걸을 길은 이렇습니다.

텍스트
   오늘의 여정 — CPU 안으로, 그리고 메모리 계층으로

   ① CPU 내부       두뇌 안에 뭐가 들었나 (ALU·제어장치·레지스터)
   ② 명령어 사이클    꺼내고-해석하고-실행하는 일의 리듬
   ③ 클럭           CPU가 일하는 박자, 왜 무한정 빨라질 수 없나
   ④ 파이프라이닝     여러 명령을 겹쳐 처리해 속도를 끌어올리기
   ⑤ 메모리 계층      빠른 CPU와 느린 메모리 사이를 피라미드로 메우기
   ⑥ 캐시와 지역성    "캐시가 왜 빠른가"의 진짜 답
   ⑦ 인터럽트        CPU가 딴짓을 알아채고 반응하는 법

①~④는 CPU가 일하는 방식, ⑤~⑦은 그 CPU와 메모리·바깥세상이 호흡을 맞추는 방식이에요. 그리고 길목마다 기술 면접 단골 질문이 숨어 있습니다. "레지스터와 RAM 차이"·"캐시가 왜 빠른가"·"인터럽트란" — 오늘 다 잡고 갑니다.

💡 오늘 수업의 핵심 — "CPU는 명령어를 꺼내·해석·실행하며 일하고, 빠른 CPU와 느린 메모리의 속도 차이는 캐시와 지역성으로 메운다" 🎯

🎯 학습 목표

  • CPU 내부의 세 부품(ALU·제어장치·레지스터)과 명령어 사이클(인출-해독-실행)을 이해하고, 면접 단골인 "레지스터와 RAM의 차이"에 원리로 답합니다.
  • 클럭파이프라이닝으로 CPU가 어떻게 더 빠르게 일하는지, 그리고 왜 클럭만 무한정 올릴 수 없는지를 설명합니다.
  • 메모리 계층 구조캐시·지역성(시간·공간 지역성, 히트/미스)으로 "캐시가 왜 빠른가"에 답하고, 인터럽트가 폴링과 어떻게 다른지 설명합니다.

Step 1: "CPU 안에는 뭐가 들었나 — ALU·제어장치·레지스터"

지난 시간에 CPU를 "실제로 계산하고 판단하는 두뇌"라고만 했죠. 오늘은 그 두뇌의 뚜껑을 열어봅니다. 복잡해 보이지만, 핵심 부품은 딱 셋이에요.

  1. ALU(산술논리연산장치, Arithmetic Logic Unit) — 진짜 계산을 하는 곳. 덧셈·뺄셈 같은 산술과, "크다/같다"·AND·OR 같은 논리 판단을 담당해요.
  2. 제어장치(CU, Control Unit) — 명령어를 해석해서 "ALU야 더해라", "레지스터에 담아라" 하고 각 부품에 신호를 보내는 지휘자.
  3. 레지스터(Register) — CPU 안에 있는 아주 작고 아주 빠른 임시 저장소. 지금 계산에 쓰는 값 몇 개를 잠깐 들고 있어요.

요리사로 비유하면 딱 맞습니다. 으로 직접 재료를 썰고 볶는 게 ALU, 레시피를 읽고 "이제 양파를 넣어라" 지시하는 머리가 제어장치, 지금 당장 쓰는 재료를 올려둔 도마가 레지스터예요. 냉장고(RAM)까지 갈 것 없이 도마 위 재료는 손만 뻗으면 닿죠. 그래서 레지스터가 가장 빠릅니다.

텍스트
   CPU 내부 — 핵심 부품 셋

   ┌─────────────┐── 제어장치(CU) : 명령어를 해석해 각 부품에 지시한다
   │  Control    │
   └─────────────┘
   ┌─────────────┐── 산술논리연산장치(ALU) : 덧셈·비교 같은 실제 계산을 한다
   │  ALU        │
   └─────────────┘
   ┌─────────────┐── 레지스터(Register) : 계산에 쓰는 값을 잠깐 드는 초고속 저장소
   │  Register   │
   └─────────────┘

여기서 초보자가 가장 헷갈리는 한 쌍이 레지스터와 RAM입니다. 둘 다 데이터를 잠깐 저장하는데 뭐가 다를까요? 핵심은 위치·속도·크기예요. 레지스터는 CPU "안"에 있어 손만 뻗으면 닿지만(가장 빠름) 아주 작아서 값 수십 개밖에 못 담습니다. RAM은 CPU "밖"에 따로 떨어져 있어 버스를 타고 갔다 와야 하고(느림) 대신 수십억 개를 담을 만큼 큽니다.

🙋 학생 질문 — "레지스터가 그렇게 빠르면, RAM 대신 레지스터만 잔뜩 쓰면 안 되나요?"

날카로운 질문이에요. 두 가지 이유 때문에 안 됩니다.

첫째, 너무 비쌉니다. 레지스터는 CPU 안에 정교하게 만들어 넣는 초고속 회로라, 같은 용량이면 RAM보다 비교가 안 될 만큼 비싸요.

둘째, 공간이 없습니다. 레지스터는 CPU 칩 안에 자리 잡는데, 칩 면적은 한정돼 있어요. 레지스터를 늘릴수록 CPU가 커지고 발열도 심해집니다. 그래서 "아주 빠르지만 아주 작은 레지스터"와 "느리지만 큰 RAM"을 역할에 맞게 나눠 쓰는 거예요. 이 트레이드오프가 바로 Step 5에서 만날 "메모리 계층 구조"의 씨앗입니다.

🎯 면접에서는 이렇게 답하세요

"레지스터와 RAM의 가장 큰 차이는 위치와 속도입니다. 레지스터는 CPU 내부에 있어 가장 빠르지만 용량이 매우 작아 지금 계산에 쓰는 값 몇 개만 담고, RAM은 CPU 외부에 따로 있어 상대적으로 느리지만 실행 중인 프로그램 전체를 담을 만큼 큽니다. 그래서 CPU는 자주 쓰는 값을 레지스터에 올려두고 계산하고, 큰 데이터는 RAM에 둡니다. 빠르고 작은 것과 느리고 큰 것을 역할에 맞게 나눠 쓰는 것이죠."

💡 부품은 봤으니, 이제 이 셋이 어떻게 협력해서 명령어 하나를 처리하는지 볼 차례예요. 지난 시간 폰노이만 구조에서 살짝 맛본 "꺼내고-해석하고-실행하고"를 다음 Step에서 자세히 들여다봅니다.


Step 2: "CPU가 일하는 리듬 — 명령어 사이클"

지난 시간에 폰노이만 구조를 배우며 한 문장을 봤죠. "CPU는 메모리에서 명령어를 하나씩 꺼내 순서대로 실행한다." 이 반복을 명령어 사이클(instruction cycle)이라고 합니다. 오늘은 이 한 바퀴가 정확히 어떻게 도는지, Step 1에서 본 부품들과 함께 봅니다.

한 바퀴는 세 단계예요.

  • ① 인출(Fetch) — 메모리에서 다음 명령어를 꺼내 온다.
  • ② 해독(Decode) — 제어장치가 그 명령어가 무슨 일인지 해석한다.
  • ③ 실행(Execute) — ALU가 해석된 대로 계산하고 실행한다.

그런데 "다음 명령어"가 메모리 어디에 있는지는 어떻게 알까요? 여기서 두 개의 특수한 레지스터가 등장합니다. PC(프로그램 카운터, Program Counter)는 "다음에 실행할 명령어의 주소"를 가리키는 손가락이에요. IR(명령어 레지스터, Instruction Register)은 방금 꺼내 온 명령어를 잠깐 보관하는 곳이고요.

텍스트
   명령어 사이클 — CPU가 쉬지 않고 도는 한 바퀴

   ┌──▶ ① Fetch    PC가 가리키는 주소에서 명령어를 꺼내 IR에 담는다
   │    │
   │    ▼
   │    ② Decode   제어장치(CU)가 그 명령어가 무슨 일인지 해석한다
   │    │
   │    ▼
   │    ③ Execute  ALU가 해석된 대로 계산하고 실행한다
   │    │
   └────┘   PC를 다음 명령어로 옮기고 다시 ①로 — 쉬지 않고 반복

PC가 손가락으로 주소를 가리키면, 그 주소에서 명령어를 꺼내(Fetch) IR에 담고, 제어장치가 해석한 뒤(Decode), ALU가 실행하고(Execute), PC는 다음 명령어로 손가락을 옮깁니다. 그리고 다시 처음으로. CPU는 1초에 이 사이클을 수십억 번 돌려요. 우리가 짠 코드 한 줄도 결국 이 작은 사이클 수십, 수백 개로 쪼개져 처리됩니다.

🙋 학생 질문 — "그럼 if문이나 반복문처럼 순서가 건너뛰는 코드는 어떻게 처리돼요?"

좋은 질문이에요. 핵심은 아까 본 PC(프로그램 카운터)에 있습니다.

보통은 명령어를 실행하고 나면 PC가 "바로 다음 주소"로 한 칸 옮겨갑니다. 순서대로 죽 내려가는 거죠. 그런데 if나 반복문, 함수 호출 같은 경우엔, 실행 단계에서 PC에 "다른 주소"를 직접 적어넣어요. 그러면 다음 인출은 그 주소에서 시작되니까, 코드가 점프하거나 되돌아가는 효과가 생깁니다.

즉 우리가 짠 분기·반복은 컴퓨터 입장에선 "PC가 가리키는 주소를 바꾸는 일"이에요. 이 점프가 잦으면 다음에 배울 파이프라이닝에서 작은 골칫거리가 되는데, 그건 Step 4에서 이야기할게요.

🎯 면접에서는 이렇게 답하세요

"CPU는 명령어 사이클을 반복하며 동작합니다. 프로그램 카운터(PC)가 가리키는 주소에서 명령어를 인출(Fetch)하고, 제어장치가 그 명령어를 해독(Decode)한 뒤, ALU가 실행(Execute)합니다. 그리고 PC를 다음 명령어로 옮겨 이 과정을 1초에 수십억 번 반복합니다. 분기나 반복은 실행 단계에서 PC 값을 바꿔 다음 인출 위치를 옮기는 방식으로 처리됩니다."

💡 그런데 이 사이클을 "1초에 수십억 번" 돌린다는 건 무슨 의미일까요? 그 "박자"를 정하는 게 바로 다음 Step의 클럭입니다.


Step 3: "더 빠르게 일하는 법 ① — 클럭"

CPU가 명령어 사이클을 척척 돌리려면, 모든 부품이 같은 박자에 맞춰 움직여야 합니다. 제어장치가 "지금!" 하면 레지스터가 값을 내보내고, ALU가 계산하고… 이 타이밍을 맞춰주는 메트로놈이 클럭(clock)이에요.

클럭은 1과 0을 규칙적으로 반복하는 전기 신호입니다. 이 신호가 한 번 똑딱일 때마다 CPU가 한 단계씩 일을 진행해요.

텍스트
   클럭(clock) — CPU가 한 동작씩 내딛는 박자

      ┌──┐  ┌──┐  ┌──┐  ┌──┐
      │  │  │  │  │  │  │  │
   ───┘  └──┘  └──┘  └──┘  └───
      └┬─┘
       1 클럭(tick) — 이 한 박자마다 CPU가 한 단계씩 일을 처리한다

클럭이 1초에 몇 번 똑딱이는지를 클럭 속도라 하고, 단위는 헤르츠(Hz)예요. 1Hz는 1초에 한 번. 요즘 CPU는 보통 3~4GHz(기가헤르츠), 즉 1초에 30억~40억 번 똑딱입니다. 박자가 빠를수록 같은 시간에 더 많은 일을 하니, 클럭이 높을수록 대체로 빠른 CPU예요.

그렇다면 클럭을 무한정 높이면 되지 않을까요? 여기서 막히는 게 발열의 벽입니다. 클럭을 높이려면 전압을 올려야 하고, 전압을 올리면 열이 급격히 납니다. 어느 선을 넘으면 CPU가 녹아버릴 만큼 뜨거워져요. 그래서 2000년대 중반부터 클럭 경쟁은 약 3~4GHz 근처에서 멈췄습니다. 대신 컴퓨터는 다른 방향으로 길을 틀었어요. 박자를 더 빨리 하는 대신, 한 박자에 더 많은 일을 욱여넣는 쪽으로요. 그게 다음 Step의 파이프라이닝입니다.

🙋 학생 질문 — "그럼 클럭이 높은 CPU가 무조건 빠른 거 아니에요? GHz만 보고 고르면 되겠네요."

흔한 오해예요. 클럭은 "박자의 빠르기"일 뿐, 한 박자에 얼마나 일하는지는 또 다른 문제거든요.

같은 3GHz라도, 한 박자에 명령을 더 많이 처리하도록 잘 설계된 CPU가 더 빠릅니다. 이걸 "사이클당 처리하는 명령 수"(IPC)라고 해요. 또 Step 6에서 볼 캐시가 크고 똑똑하면, 데이터를 기다리는 시간이 줄어 체감 속도가 확 올라갑니다.

그래서 요즘은 클럭 숫자만으로 CPU를 비교하지 않아요. 코어 수, 캐시 크기, 설계 세대까지 같이 봐야 합니다. "GHz 높은 게 무조건 빠르다"는 옛날 마케팅이 남긴 착각이에요.

🎯 면접에서는 이렇게 답하세요

"클럭은 CPU가 동작하는 박자이고, 1초에 몇 번 똑딱이는지를 헤르츠(Hz)로 나타냅니다. 클럭이 높으면 대체로 빠르지만, 무조건 빠른 건 아닙니다. 한 박자에 처리하는 명령 수(IPC)나 캐시 효율에 따라 같은 클럭이라도 성능이 다릅니다. 또 클럭을 무한정 올리지 못하는 이유는 발열 때문이에요. 그래서 클럭 경쟁은 멈췄고, 대신 파이프라이닝이나 멀티코어처럼 한 박자에 더 많은 일을 하는 방향으로 발전했습니다."

💡 클럭을 더 못 올린다면, 같은 박자 안에서 어떻게 일을 더 많이 할까요? 그 첫 번째 답이 여러 명령을 겹쳐서 처리하는 파이프라이닝입니다.


Step 4: "더 빠르게 일하는 법 ② — 파이프라이닝"

명령어 하나를 인출→해독→실행 세 단계로 처리한다고 했죠. 만약 한 명령을 완전히 끝낸 다음에야 다음 명령을 시작한다면, 단계 하나가 일할 때 나머지 둘은 놀게 됩니다. 너무 아깝죠.

파이프라이닝(pipelining)은 이 낭비를 없앱니다. 핵심 아이디어는 빨래예요. 빨래를 세탁기→건조기→개기 순서로 한다고 해봅시다. 첫 번째 빨래를 세탁기에서 꺼내 건조기에 넣었으면, 세탁기를 놀리지 말고 곧장 두 번째 빨래를 돌려야 하잖아요? CPU도 똑같이, 첫 명령이 해독 단계로 넘어가면 인출기는 바로 다음 명령을 꺼내옵니다.

시간 → t1 t2 t3 t4 t5
명령어 1 인출 해독 실행
명령어 2 인출 해독 실행
명령어 3 인출 해독 실행

표를 세로로 보세요. t3 시점에 세 명령이 동시에 각기 다른 단계를 밟고 있습니다. 명령 1은 실행, 명령 2는 해독, 명령 3은 인출. 단계를 겹쳐 돌리니, 명령을 하나씩 끝낼 때보다 전체 처리량이 몇 배로 뜁니다. 클럭을 안 올리고도 빨라지는 거예요.

다만 파이프라인에도 약점이 있어요. Step 2에서 본 if처럼 다음에 어디로 갈지 모르는 분기를 만나면 문제가 됩니다. 이미 다음 명령들을 파이프라인에 넣어뒀는데 갑자기 다른 곳으로 점프해야 하면, 미리 넣은 걸 버리고 다시 채워야 해요. 이걸 "파이프라인이 비워진다"고 합니다. 그래서 CPU는 "분기가 어디로 갈지" 미리 예측하는 기술(분기 예측)까지 동원하는데, 그 깊이는 면접에서 여기까지만 알아도 충분합니다.

🎯 면접에서는 이렇게 답하세요

"파이프라이닝은 명령어 처리 단계(인출·해독·실행)를 겹쳐서 동시에 진행해 처리량을 높이는 기법입니다. 빨래를 세탁기·건조기에 연달아 돌리듯, 첫 명령이 해독으로 넘어가면 곧장 다음 명령을 인출하는 식이죠. 덕분에 클럭을 올리지 않고도 단위 시간당 처리하는 명령 수가 늘어납니다. 단, 분기를 만나면 미리 채워둔 파이프라인을 버려야 해서 성능이 떨어지는데, 이를 줄이려고 분기 예측을 사용합니다."

💡 여기까지가 "CPU가 어떻게, 얼마나 빠르게 일하는가"였어요. 이제 시선을 밖으로 돌립니다. 아무리 CPU가 빨라도, 데이터를 가져올 메모리가 느리면 결국 기다려야 하죠. 오프닝에서 던진 그 모순 — 다음 Step에서 정면으로 풉니다.


Step 5: "빠른 CPU, 느린 메모리 — 메모리 계층 구조"

드디어 오프닝의 그 질문으로 돌아왔습니다. CPU는 1초에 수십억 번 일하는데, RAM에서 데이터 하나 가져오는 데 그 수백 배의 시간이 걸린다고 했죠. 이 속도 차이 때문에 CPU가 데이터를 기다리며 노는 현상, 이게 지난 시간에 예고한 폰노이만 병목입니다.

가장 단순한 해법은 "그럼 RAM을 레지스터만큼 빠르게 만들자"겠죠. 그런데 Step 1에서 봤듯, 빠른 저장장치는 너무 비싸고 너무 작습니다. 모든 메모리를 레지스터 속도로 만들면 컴퓨터 한 대 값이 집 한 채가 될 거예요. 반대로 다 싸고 큰 걸로 채우면 느려서 못 씁니다.

그래서 컴퓨터가 택한 절충안이 메모리 계층 구조(memory hierarchy)입니다. 빠르고 작고 비싼 것부터 느리고 크고 싼 것까지 피라미드처럼 층층이 쌓아, 자주 쓰는 데이터는 위(빠른 곳)에, 가끔 쓰는 데이터는 아래(느리지만 큰 곳)에 두는 거예요.

텍스트
   ┌────────────┐
   │ Register   │── 레지스터 : CPU 안, 가장 빠름·가장 작음·가장 비쌈 (1 사이클)
   ├────────────┤
   │ Cache      │── 캐시 L1~L3 : 자주 쓰는 데이터를 미리 (수~수십 사이클)
   ├────────────┤
   │ RAM        │── 메인 메모리 : 실행 중인 프로그램이 사는 곳 (수백 사이클)
   ├────────────┤
   │ SSD / HDD  │── 보조 기억장치 : 전원이 꺼져도 남음 (수만~수백만 사이클)
   └────────────┘
     위로 갈수록 빠르고 작고 비싸다 · 아래로 갈수록 느리고 크고 싸다

여기서 새 얼굴이 캐시(cache)입니다. 레지스터와 RAM 사이에 끼어 있는 중간 저장소예요. RAM보다 훨씬 빠르고 레지스터보다는 크죠. CPU가 RAM까지 매번 다녀오기엔 너무 머니까, 자주 쓸 데이터를 미리 캐시에 복사해 두고 거기서 꺼내 씁니다. 캐시도 보통 L1·L2·L3 세 층으로 나뉘는데, L1이 가장 빠르고 작고, L3로 갈수록 느리지만 큽니다. 결국 같은 발상(빠른 소량 + 느린 대량)을 캐시 안에서 한 번 더 반복하는 셈이에요.

이 그림을 머릿속에 박아두세요. 이게 오늘의 핵심 그림이자, 다음 과목들에서 "가상 메모리"·"버퍼"·"브라우저 캐시" 같은 말을 만날 때마다 다시 꺼내 쓸 틀입니다.

🙋 학생 질문 — "데이터를 가져올 때 레지스터→캐시→RAM→SSD를 매번 다 거쳐 가나요?"

전부 거치는 건 아니고, 위에서부터 차례로 "있나?"를 물어봅니다.

CPU가 어떤 값이 필요하면, 먼저 가장 빠른 캐시(L1)부터 봐요. 있으면 거기서 바로 꺼내고 끝(가장 빠름). 없으면 L2, 그래도 없으면 L3, 그래도 없으면 RAM, 거기도 없으면 SSD까지 내려갑니다. 아래로 내려갈수록 점점 느려지는 거죠.

핵심은 대부분의 요청이 위쪽에서 해결된다는 거예요. 그 비율이 높을수록 평균 속도가 레지스터·캐시 쪽에 가까워집니다. "어떻게 위쪽에서 자주 해결되게 만드나"가 바로 다음 Step의 지역성 이야기입니다.

🎯 면접에서는 이렇게 답하세요

"메모리를 계층으로 나누는 이유는 속도와 가격의 트레이드오프 때문입니다. 빠른 저장장치는 비싸고 작고, 싼 저장장치는 느립니다. 그래서 레지스터·캐시·RAM·보조기억장치를 피라미드처럼 쌓아, 자주 쓰는 데이터는 빠른 위쪽에 두고 가끔 쓰는 데이터는 크고 느린 아래쪽에 둡니다. CPU와 RAM의 속도 차이(폰노이만 병목)를 그 사이의 캐시가 메워서, 전체적으로는 빠른 메모리에 가까운 평균 속도를 내면서도 큰 용량을 확보합니다."

💡 그런데 캐시에 "자주 쓸 데이터를 미리" 넣는다고 했죠. 컴퓨터가 미래를 보는 것도 아닌데, 무엇을 미리 넣을지 어떻게 알까요? 그 비밀이 오늘의 심장, 지역성입니다.


Step 6: "캐시가 왜 빠른가 — 지역성의 비밀"

이번 Step이 오늘의 심장이자 면접 최빈출입니다. "캐시가 왜 빠른가"라는 질문에는 사실 두 겹의 답이 있어요. 첫째는 "물리적으로 CPU 가까이 있고 빠른 회로라서"(Step 5). 둘째는 더 중요한 "미리 가져다 둔 게 실제로 자주 맞아떨어져서"입니다. 이 두 번째 답의 정체가 지역성(locality)이에요.

지역성이란 "프로그램이 메모리를 쓰는 데는 쏠리는 경향이 있다"는 관찰입니다. 아무 데나 마구잡이로 접근하지 않고, 비슷한 곳을 반복해서 건드린다는 거죠. 두 종류가 있어요.

  • 시간 지역성(temporal locality) — 방금 쓴 데이터는 곧 또 쓸 가능성이 높다. (예: 반복문 안의 변수 i는 매 반복마다 다시 쓰인다)
  • 공간 지역성(spatial locality) — 어떤 데이터를 썼으면 그 옆 데이터도 곧 쓸 가능성이 높다. (예: 배열을 0번부터 순서대로 훑는다)

캐시는 이 경향에 베팅합니다. 방금 쓴 데이터를 캐시에 남겨두고(시간 지역성), 데이터 하나를 가져올 때 그 옆 동네까지 한 덩어리로 끌어옵니다(공간 지역성). 그러면 다음에 필요한 값이 이미 캐시에 있을 확률이 높아져요. 미래를 본 게 아니라, 사람이 짠 프로그램이 원래 그렇게 쏠리게 동작한다는 통계에 기댄 겁니다.

CPU가 필요한 값을 캐시에서 찾으면 캐시 히트(cache hit), 없어서 RAM까지 내려가야 하면 캐시 미스(cache miss)라고 해요.

텍스트
   CPU가 값 하나를 찾을 때

   CPU ─▶ "캐시에 있나?"
            ├─ 있다 (캐시 히트) ─▶ 즉시 가져온다 (빠름)
            └─ 없다 (캐시 미스) ─▶ RAM까지 갔다 오고, 그 김에 캐시에도 복사 (느림)

전체 요청 중 히트가 차지하는 비율을 적중률(hit rate)이라 하는데, 실제 프로그램에서 이게 보통 90%를 훌쩍 넘깁니다. 열 번 중 아홉 번 이상은 빠른 캐시에서 해결된다는 뜻이에요. 그래서 평균 접근 속도가 RAM이 아니라 캐시 쪽에 바짝 붙고, 그게 "캐시 덕분에 빠르다"의 진짜 정체입니다.

🙋 학생 질문 — "그럼 프로그래머가 지역성을 신경 써서 코드를 짜면 더 빨라지나요?"

네, 그게 핵심입니다. 같은 일을 하는 코드라도 지역성을 살리면 훨씬 빨라져요.

대표적인 예가 2차원 배열(표 모양 데이터)을 훑는 순서예요. 컴퓨터 메모리에서는 표의 한 줄(행)이 쭉 이어서 저장됩니다. 그래서 행을 따라 가로로 훑으면 옆 데이터가 이미 캐시에 끌려와 있어(공간 지역성) 빠르고, 열을 따라 세로로 훑으면 매번 멀리 떨어진 값을 건드려 캐시 미스가 잦아져 느려집니다. 똑같은 계산인데 순회 방향만 바꿔도 몇 배씩 차이가 나기도 해요.

그래서 성능이 중요한 코드에서는 "캐시 친화적으로 짠다"는 감각이 중요합니다. 이건 생각해볼 주제에서 한 번 더 파볼게요. (실제 측정과 구현 연습은 data-structures-algorithms 과목에서 더 깊이 다룹니다.)

🎯 면접에서는 이렇게 답하세요

"캐시가 빠른 이유는 두 가지입니다. 물리적으로 CPU 가까이 있는 빠른 메모리이기도 하지만, 더 본질적으로는 지역성 덕분입니다. 프로그램은 방금 쓴 데이터를 곧 다시 쓰고(시간 지역성), 어떤 데이터를 쓰면 그 옆도 곧 쓰는(공간 지역성) 경향이 있어요. 캐시는 이 경향에 맞춰 자주 쓸 데이터를 미리 담아두기 때문에, 실제 적중률이 90%를 넘습니다. 그래서 대부분의 접근이 느린 RAM까지 가지 않고 빠른 캐시에서 끝나, 평균 속도가 크게 빨라집니다."

💡 여기까지가 CPU와 메모리가 호흡을 맞추는 이야기였어요. 마지막으로 하나 남았습니다. CPU가 한창 일하는 중에 키보드가 눌리거나 파일 다운로드가 끝나면, 그 "바깥의 사건"을 어떻게 알아챌까요? 마지막 Step의 인터럽트입니다.


Step 7: "CPU는 어떻게 딴짓을 알아채나 — 인터럽트"

CPU는 명령어 사이클을 돌리며 자기 일에 푹 빠져 있습니다. 그런데 그사이 바깥에서는 사건이 터지죠. 사용자가 키보드를 누르고, 다운로드가 끝나고, 마우스가 움직이고. CPU가 이런 사건을 알아채는 방법은 두 가지예요.

첫 번째는 폴링(polling)입니다. CPU가 직접 "키보드 눌렸어? 아직? 눌렸어? 아직?" 하고 계속 물어보는 방식이에요. 라면을 끓이면서 1초마다 냄비 뚜껑을 열어보는 것과 같죠. 확실하긴 한데, 묻느라 CPU가 다른 일을 못 하고 시간을 통째로 낭비합니다.

두 번째가 인터럽트(interrupt, 끼어들기)예요. CPU는 그냥 자기 일을 하고, 사건이 생긴 장치가 CPU에게 "저 일 다 됐어요!" 하고 신호를 보내는 방식입니다. 라면 타이머를 맞춰두고 딴 일을 하다가, 알람이 울리면 그때 가서 냄비를 보는 거죠. CPU는 알림이 올 때까지 다른 일에 집중할 수 있어 훨씬 효율적이에요.

구분 폴링(Polling) 인터럽트(Interrupt)
방식 CPU가 계속 "다 됐어?" 확인 장치가 끝나면 CPU에게 신호
비유 1초마다 냄비 뚜껑 열어보기 타이머 맞춰두고 딴 일 하기
CPU 효율 낮음 (확인하느라 바쁨) 높음 (다른 일 하다 호출받음)
약점 자원 낭비가 큼 처리 과정이 더 복잡함

인터럽트가 들어오면 CPU는 어떻게 반응할까요? 하던 일을 잠깐 멈추고, 지금 어디까지 했는지(PC와 레지스터 값들)를 안전한 곳에 저장한 뒤, 인터럽트를 처리하는 전용 코드로 잠깐 다녀옵니다. 처리가 끝나면 저장해둔 값을 도로 불러와 원래 하던 일을 아무 일 없었다는 듯 이어서 합니다.

이 "현재 상태를 저장했다가 나중에 그대로 복원한다"는 발상은 오늘 두 번째로 나온 중요한 개념이에요. 그리고 이게 다음 시간으로 이어지는 다리입니다. 운영체제가 프로그램 여러 개를 번갈아 실행할 때 쓰는 바로 그 기술이거든요.

🙋 학생 질문 — "인터럽트가 일하던 걸 끊으면, CPU가 까먹지 않고 정확히 이어서 할 수 있어요?"

네, 그래서 인터럽트 처리의 핵심이 "문맥 저장과 복원"이에요.

CPU가 인터럽트를 받으면, 끼어들기 전에 자기의 현재 상태(PC가 가리키던 주소, 레지스터에 들어 있던 값들)를 통째로 안전한 곳에 저장합니다. 이렇게 저장한 상태 전체를 "문맥"(context)이라고 불러요. 그리고 인터럽트 처리가 끝나면 저장해둔 문맥을 그대로 불러와 PC와 레지스터를 원래대로 되돌리니, CPU 입장에선 끊겼던 줄도 모르고 이어서 일하게 됩니다.

이 문맥을 저장하고 복원하는 일은 공짜가 아니에요. 시간이 들죠. 그래서 다음 시간(B-1, 운영체제와 프로세스)에서 운영체제가 프로그램 여러 개를 번갈아 돌릴 때, 이 "문맥 전환" 비용이 중요한 주제로 다시 등장합니다.

🎯 면접에서는 이렇게 답하세요

"인터럽트는 외부 장치나 사건이 CPU에게 '처리할 일이 생겼다'고 알리는 신호입니다. 폴링이 CPU가 직접 계속 상태를 확인하는 방식이라면, 인터럽트는 사건이 생긴 쪽이 CPU를 부르는 방식이라 CPU가 그동안 다른 일을 할 수 있어 훨씬 효율적입니다. 인터럽트가 들어오면 CPU는 현재 상태(PC와 레지스터)를 저장하고 처리 루틴을 실행한 뒤, 저장한 상태를 복원해 원래 작업을 이어갑니다. 이 '상태 저장·복원'은 운영체제의 문맥 전환과도 직결되는 개념입니다."

💡 이걸로 CPU가 일하는 방식부터, 메모리·바깥세상과 호흡을 맞추는 방식까지 한 바퀴 돌았습니다. 오늘 배운 걸 정리하고, 다음 시간으로 이어갈 다리를 놓아볼게요.


마무리

오늘 배운 핵심 세 가지

🎯 하나, CPU 안에는 계산하는 ALU·지휘하는 제어장치·값을 잠깐 드는 레지스터가 있고, 이들이 명령어 사이클(인출-해독-실행)을 1초에 수십억 번 반복하며 일합니다. 레지스터는 RAM보다 빠르지만 작아요.

🎯 , CPU를 빠르게 하는 두 방법은 클럭(박자, 단 발열 때문에 무한정 못 올림)과 파이프라이닝(명령 단계를 겹쳐 처리)입니다. 그래서 클럭만 보고 빠른 CPU라 단정할 수 없어요.

🎯 , 빠른 CPU와 느린 메모리의 차이(폰노이만 병목)는 메모리 계층 구조캐시가 메우고, 캐시가 빠른 진짜 이유는 지역성(자주 쓰는 데이터가 쏠린다)입니다. 인터럽트는 CPU가 바깥 사건에 효율적으로 반응하는 법이에요.

다음 시간 예고

오늘 우리는 CPU 한 대가 명령을 처리하고, 메모리와 호흡을 맞추는 원리를 봤습니다. 그런데 우리가 쓰는 컴퓨터는 한 번에 프로그램을 하나만 돌리지 않죠. 음악을 틀어놓고, 브라우저를 켜고, 메신저를 띄우고 — 수십 개가 동시에 돌아가는 것처럼 보입니다. CPU는 (코어 수만큼만) 하나뿐인데, 어떻게 이게 가능할까요?

다음 시간(B-1)에는 그 마법을 부리는 운영체제(OS)로 들어갑니다. 핵심은 오늘 마지막에 본 인터럽트와 문맥 저장·복원이에요. 운영체제는 타이머 인터럽트로 CPU를 잠깐씩 되찾아, 프로그램들의 상태를 저장했다 복원하며 번갈아 실행합니다. 그래서 사람 눈에는 동시에 도는 것처럼 보이죠. 실행 중인 프로그램 하나하나를 프로세스(process)라 부르는데, 이 프로세스가 메모리를 어떻게 나눠 쓰고 어떤 상태를 오가는지 — 면접에서 가장 깊게 파고드는 운영체제 영역으로 다음 시간에 들어가 봅시다!


과제

[기초] 메모리 계층 직접 그리고 비유로 채우기

연필과 종이만 있으면 됩니다.

  1. 오늘 배운 메모리 계층 피라미드를 보지 않고 직접 그려보세요. 레지스터·캐시·RAM·SSD 네 층을 위에서 아래로 쌓고, 각 층 옆에 속도·크기·가격을 "빠름/느림", "작음/큼", "비쌈/쌈"으로 채웁니다.
  2. 네 층을 각각 일상의 무언가에 비유해보세요. (예: 레지스터=손에 든 펜, RAM=책상 위, SSD=책장…) 정답은 없어요. 자기만의 비유가 기억에 더 오래 남습니다.
  3. "전원을 끄면 내용이 사라지는" 층과 "남는" 층을 구분해서 표시해보세요. (힌트: 지난 시간에 배운 휘발성)

[응용] 내 컴퓨터의 진짜 스펙 들여다보기

자기 컴퓨터(또는 스마트폰)의 실제 부품 정보를 찾아보는 과제입니다. 설치할 건 없어요.

  1. 작업 관리자(윈도우) 또는 시스템 정보(맥)에서 CPU 클럭 속도(GHz)·코어 수·RAM 용량을 찾아 적어보세요.
  2. 가능하면 캐시 크기(L1/L2/L3)도 찾아보세요. 캐시는 보통 KB~MB 단위, RAM은 GB 단위일 거예요.
  3. "왜 캐시는 MB 단위로 작고, RAM은 GB 단위로 큰가?"를 오늘 배운 메모리 계층의 트레이드오프(빠르고 작고 비쌈 ↔ 느리고 크고 쌈)로 한 문단 설명해보세요.

[심화] 같은 계산, 다른 속도 — 지역성 체감하기

조사하고 생각을 정리하는 과제입니다. (코드를 직접 돌려봐도 좋지만 필수는 아니에요.)

  1. 2차원 배열(표 모양 데이터)을 행 우선(가로로 한 줄씩)으로 훑는 것과 열 우선(세로로 한 칸씩)으로 훑는 것 중, 왜 보통 행 우선이 더 빠른지 공간 지역성으로 설명해보세요.
  2. "캐시 친화적인 코드"라는 말이 무슨 뜻인지, 오늘 배운 지역성과 캐시 히트/미스 개념으로 한 문단 정리해보세요.

생각해볼 주제

1. 클럭 경쟁은 왜 멈췄을까?

2000년대 초반만 해도 CPU 회사들은 "우리 건 3GHz, 다음엔 4GHz!" 하고 클럭 숫자로 경쟁했습니다. 그런데 어느 순간 그 경쟁이 뚝 멈추고, 대신 "코어 4개, 8개"처럼 코어 수로 자랑하기 시작했어요. 클럭을 계속 올리지 못하게 만든 물리적 한계는 무엇이었을까요? 그리고 "박자를 빨리 하기"에서 "여러 개를 동시에 돌리기"로 방향이 바뀐 게 우리가 짜는 프로그램에는 어떤 숙제를 남겼을지 생각해보세요. (여러 개를 동시에 돌리는 구체적 원리는 운영체제 과목에서 깊이 다룹니다.)

2. 캐시가 그렇게 빠르면, RAM을 통째로 캐시로 만들면 안 될까?

캐시는 RAM보다 훨씬 빠릅니다. 그렇다면 "RAM 전체를 캐시 속도의 메모리로 바꿔버리면 컴퓨터가 엄청 빨라지지 않을까?"라는 생각이 들 수 있어요. 실제로는 아무도 그렇게 하지 않습니다. 왜일까요? 메모리 계층이 존재하는 근본 이유(속도·가격·물리적 크기의 트레이드오프)를 떠올리면서, "가장 빠른 부품으로만 컴퓨터를 채우는 게 왜 비현실적인지" 자기 언어로 정리해보세요.

3. 같은 일을 하는데 왜 어떤 코드는 빠르고 어떤 코드는 느릴까?

두 프로그래머가 똑같은 결과를 내는 코드를 짰는데, 한쪽이 몇 배 빠른 경우가 있습니다. 알고리즘이 같은데도요. 그 차이의 한 원인이 오늘 배운 지역성이에요. 캐시를 잘 활용하는(자주 쓸 데이터가 가까이 모이게 짠) 코드와 그렇지 않은 코드는 같은 계산을 해도 캐시 미스 횟수가 크게 달라집니다. "성능을 높인다"는 게 단순히 "연산을 줄인다"를 넘어 "메모리를 어떻게 건드리느냐"까지 포함한다는 점을, 오늘 배운 캐시 히트/미스로 풀어 생각해보세요.

✅ 예시 답안정답 보기

과제 예시답안

🎯 [과제 1 예시답안] 메모리 계층 직접 그리고 비유로 채우기

채점 포인트

항목 배점 기준
4층 계층 순서 30% 레지스터→캐시→RAM→SSD를 위(빠름)에서 아래(느림)로 올바로 쌓았는가
속도·크기·가격 채우기 30% 위로 갈수록 빠름·작음·비쌈, 아래로 갈수록 느림·큼·쌈을 일관되게 적었는가
자기만의 비유 25% 각 층을 일상에 비유했는가 (정답 없음, 일관성만)
휘발성 구분 15% 전원 끄면 사라지는 층(레지스터·캐시·RAM)과 남는 층(SSD)을 구분했는가

풀이 예시

피라미드를 그리고 각 층 옆에 세 값을 채우면 이렇게 됩니다.

텍스트
   ┌────────────┐
   │ Register   │── 가장 빠름 · 가장 작음 · 가장 비쌈 · (전원 끄면 사라짐)
   ├────────────┤
   │ Cache      │── 매우 빠름 · 작음 · 비쌈 · (전원 끄면 사라짐)
   ├────────────┤
   │ RAM        │── 빠름 · 큼 · 보통 · (전원 끄면 사라짐 — 휘발성)
   ├────────────┤
   │ SSD / HDD  │── 느림 · 가장 큼 · 가장 쌈 · (전원 꺼져도 남음 — 비휘발성)
   └────────────┘

비유 예시(정답은 없어요):

  • 레지스터 = 지금 손에 쥔 펜 한 자루 (바로 쓰지만 하나뿐)
  • 캐시 = 책상 위 펜꽂이 (손 뻗으면 닿는 자주 쓰는 것들)
  • RAM = 책상 서랍 (열어야 하지만 가까움)
  • SSD = 방 한쪽 책장 (많이 들어가지만 일어나 걸어가야 함)

💡 튜터의 포인트

이 과제의 진짜 목적은 "빠른 것은 작고 비싸다"는 트레이드오프를 손으로 한 번 적어보는 거예요. 이 한 장을 그려두면 앞으로 "가상 메모리"·"버퍼"·"브라우저 캐시" 같은 말을 만날 때마다 이 피라미드가 자동으로 떠오릅니다. 비유는 자기 것일수록 좋아요. 남이 만든 비유보다 내가 만든 어설픈 비유가 훨씬 오래 기억에 남습니다.


🎯 [과제 2 예시답안] 내 컴퓨터의 진짜 스펙 들여다보기

채점 포인트

항목 배점 기준
클럭·코어·RAM 확인 35% 실제 수치를 찾아 적었는가
캐시 크기 확인 25% L1/L2/L3 또는 전체 캐시 크기를 찾아봤는가
단위 차이 관찰 20% 캐시(KB~MB)와 RAM(GB)의 단위 차이를 인식했는가
트레이드오프 설명 20% 단위 차이를 계층 트레이드오프로 설명했는가

풀이 예시

확인 방법(설치 불요):

  • 윈도우: 작업 관리자(Ctrl+Shift+Esc) → 성능 탭 → CPU. 클럭·코어·L1/L2/L3 캐시가 보입니다.
  • 맥: 메뉴 → 이 Mac에 관하여 → 자세히 정보. (캐시는 별도 도구가 필요할 수 있어요.)

찾은 값 예시:

텍스트
   CPU 클럭 :  3.2 GHz
   코어 수  :  8 코어
   RAM 용량 :  16 GB
   캐시     :  L1 80KB / L2 1.25MB / L3 24MB  (CPU마다 다름)

"왜 캐시는 MB, RAM은 GB인가" 설명 예시:

캐시는 레지스터 다음으로 빠른 메모리라 만들기가 매우 비싸고, CPU 칩 안에 들어가야 해서 물리적 공간도 좁습니다. 그래서 꼭 필요한 양만 MB 단위로 작게 둡니다. 반대로 RAM은 캐시보다 느리지만 훨씬 싸고 칩 밖에 자유롭게 둘 수 있어, 실행 중인 프로그램 전체를 담도록 GB 단위로 크게 씁니다. "빠르면 작고 비싸다"는 계층의 트레이드오프가 그대로 단위 차이로 나타난 거예요.

💡 튜터의 포인트

교과서 속 피라미드가 내 컴퓨터 안에 진짜로 있다는 걸 눈으로 확인하는 게 핵심이에요. 특히 캐시가 RAM보다 천 배쯤 작다는 걸 숫자로 보면, "그 작은 캐시로 어떻게 속도를 끌어올리지?"라는 의문이 자연스럽게 듭니다. 그 답이 바로 과제 3과 생각해볼 주제에서 다루는 지역성이에요.


🎯 [과제 3 예시답안] 같은 계산, 다른 속도 — 지역성 체감하기

채점 포인트

항목 배점 기준
행 우선이 빠른 이유 45% 메모리에 행이 연속 저장됨 + 공간 지역성으로 설명했는가
캐시 미스 연결 30% 열 우선이 캐시 미스를 자주 내는 점을 짚었는가
캐시 친화적 코드 정의 25% "자주 쓸 데이터가 가까이 모이게 짠 코드"로 정리했는가

풀이 예시

1. 왜 행 우선이 더 빠른가

2차원 배열은 메모리에 한 줄(행)이 쭉 이어서 저장됩니다. 그래서 행을 따라 가로로 훑으면, 첫 값을 가져올 때 캐시가 그 옆 데이터까지 한 덩어리로 끌어와 둡니다(공간 지역성). 다음 값들이 이미 캐시에 있으니 캐시 히트가 연달아 나서 빠릅니다. 반대로 열을 따라 세로로 훑으면 매번 멀리 떨어진 다른 행의 값을 건드리게 되어, 캐시에 미리 끌어온 옆 데이터가 거의 쓸모없어집니다. 캐시 미스가 잦아져 RAM까지 자주 내려가니 느려지죠.

2. 캐시 친화적 코드란

같은 결과를 내더라도, 데이터를 메모리에서 연속된 순서로, 한 번 가져온 김에 몰아서 쓰도록 짠 코드를 캐시 친화적이라고 합니다. 이런 코드는 캐시 히트율이 높아 평균 메모리 접근이 빨라집니다. 연산 횟수가 같아도 메모리를 건드리는 패턴에 따라 실제 속도가 몇 배씩 차이 날 수 있어요.

💡 튜터의 포인트

여기서 중요한 깨달음은 "성능 = 연산 횟수 줄이기"가 전부가 아니라는 것이에요. 알고리즘이 똑같아도 메모리를 어떻게 건드리느냐(지역성)에 따라 속도가 갈립니다. 이 감각이 있으면 나중에 "왜 이 반복문이 이상하게 느리지?" 하는 상황에서 캐시를 의심할 수 있어요. 실제 측정과 자료구조별 분석은 data-structures-algorithms 과목에서 더 깊이 다룹니다 — 여기서는 "원리를 말로 설명할 수 있다"까지면 충분합니다.


생각해볼 주제 예시답안

🤔 [생각해볼 주제 1 예시답안] 클럭 경쟁은 왜 멈췄을까?

[문제 상황 요약]

한때 CPU 회사들은 클럭 숫자(3GHz, 4GHz…)로 경쟁했는데, 어느 순간 그 경쟁이 멈추고 코어 수(4코어, 8코어…)로 방향이 바뀌었습니다. 무엇이 클럭을 더 못 올리게 막았고, 그 방향 전환은 우리 프로그램에 어떤 숙제를 남겼을까요?

[튜터의 가이드 및 해설]

핵심 원인은 Step 3에서 본 발열과 전력의 벽입니다.

클럭을 높이려면 전압을 올려야 하는데, 소비 전력은 전압에 따라 가파르게 늘고 그 전력이 거의 다 열로 바뀝니다. 어느 선을 넘으면 CPU가 스스로를 식히지 못해 녹아버릴 지경이 돼요. 그래서 2000년대 중반, 클럭은 약 3~4GHz 근처에서 사실상 천장을 만났습니다.

그래서 업계는 방향을 틀었어요. "한 일꾼을 더 빨리 굴리기"(클럭 ↑) 대신 "일꾼을 여러 명 두기"(코어 ↑)로요. CPU 안에 계산 단위(코어)를 여러 개 넣어, 여러 일을 진짜로 동시에 처리하게 한 겁니다.

그런데 이게 프로그래머에게 숙제를 남겼습니다. 일꾼이 한 명일 땐 그냥 순서대로 시키면 됐는데, 여러 명이 되니 일을 어떻게 쪼개 나눠줄지를 고민해야 해요. 코어가 8개라도 프로그램이 한 줄로만 일하면 7개는 놀거든요. 그래서 "여러 일을 동시에 안전하게 처리하는" 능력이 점점 중요해졌습니다. (그 구체적 원리 — 스레드·동시성·동기화는 운영체제 과목에서 깊이 다룹니다.)

🎯 면접관을 홀리는 핵심 멘트

"클럭 경쟁이 멈춘 건 발열과 전력의 물리적 한계 때문입니다. 클럭을 높이려면 전압을 올려야 하고, 그 전력이 열로 바뀌어 어느 선을 넘으면 식힐 수가 없습니다. 그래서 업계는 '한 코어를 더 빠르게'에서 '코어를 여러 개로'로 방향을 바꿨습니다. 다만 코어가 많아도 프로그램이 일을 병렬로 나누지 못하면 노는 코어가 생기기 때문에, 동시성을 다루는 능력이 그만큼 중요해졌습니다."


🤔 [생각해볼 주제 2 예시답안] 캐시가 그렇게 빠르면, RAM을 통째로 캐시로 만들면 안 될까?

[문제 상황 요약]

캐시는 RAM보다 훨씬 빠릅니다. 그렇다면 RAM 전체를 캐시 속도의 메모리로 바꾸면 컴퓨터가 엄청 빨라질 것 같은데, 실제로는 아무도 그렇게 하지 않습니다. 왜일까요?

[튜터의 가이드 및 해설]

이건 메모리 계층이 왜 존재하는가를 거꾸로 묻는 질문이에요. 답은 Step 5의 트레이드오프에 다 들어 있습니다.

가격 — 캐시에 쓰는 초고속 메모리(SRAM)는 RAM에 쓰는 메모리(DRAM)보다 같은 용량당 수십 배 비쌉니다. RAM 16GB를 전부 캐시 속도로 만들면 컴퓨터 한 대 값이 감당 못 할 수준으로 치솟아요.

물리적 크기 — 빠른 메모리는 한 비트를 저장하는 데 더 많은 회로(트랜지스터)가 듭니다. 그래서 같은 용량이라도 캐시가 차지하는 면적이 훨씬 큽니다. RAM만큼의 용량을 캐시로 만들면 칩이 비현실적으로 커지고, 커지면 신호가 오가는 거리가 길어져 오히려 느려지는 역설까지 생겨요. "빠르려면 작고 가까워야 한다"는 물리적 제약이 있는 겁니다.

결국 메모리 계층은 "어쩔 수 없이 만든 절충"이 아니라, 현실의 제약 아래에서 평균 속도를 최대로 끌어올리는 최선의 설계예요. 자주 쓰는 소량만 빠른 캐시에 두고, 나머지는 싸고 큰 RAM에 두면, 적은 비용으로 빠른 메모리에 가까운 평균 속도를 얻습니다.

🎯 면접관을 홀리는 핵심 멘트

"RAM 전체를 캐시로 만들 수 없는 이유는 가격과 물리적 제약 때문입니다. 캐시용 초고속 메모리는 RAM보다 단위 용량당 수십 배 비싸고, 한 비트에 더 많은 회로가 들어 같은 용량이면 훨씬 큰 면적을 차지합니다. 게다가 메모리가 커지면 신호 거리가 길어져 오히려 느려집니다. 그래서 자주 쓰는 소량만 빠른 캐시에 두고 나머지는 크고 싼 RAM에 두는 계층 구조가, 제한된 비용에서 평균 속도를 가장 높이는 현실적 최선입니다."


🤔 [생각해볼 주제 3 예시답안] 같은 일을 하는데 왜 어떤 코드는 빠르고 어떤 코드는 느릴까?

[문제 상황 요약]

두 사람이 똑같은 결과를 내는 코드를 짰는데 한쪽이 몇 배 빠른 경우가 있습니다. 알고리즘이 같은데도요. 그 차이의 한 원인이 지역성입니다. 같은 계산이 왜 메모리 사용 방식에 따라 속도가 달라질까요?

[튜터의 가이드 및 해설]

Step 6에서 본 지역성과 캐시 히트/미스가 핵심이에요.

연산 횟수가 같아도 메모리 접근이 다르다

성능을 "얼마나 많이 계산하느냐"로만 보면, 같은 알고리즘은 같은 속도여야 합니다. 그런데 CPU는 계산만 하는 게 아니라 데이터를 가져와서 계산해요. 그 데이터를 캐시에서 가져오면(히트) 빠르고, RAM까지 내려가면(미스) 수백 배 느립니다. 그래서 "메모리를 어떤 순서로 건드리느냐"가 속도를 가릅니다.

지역성을 살린 코드 vs 깬 코드

자주 쓸 데이터가 메모리에서 가까이 모여 있고, 그걸 연속된 순서로 훑으면 캐시 히트가 줄줄이 납니다(공간 지역성). 반대로 데이터를 여기저기 멀리 떨어진 곳에서 띄엄띄엄 가져오면 캐시 미스가 잦아져, 같은 계산인데도 CPU가 데이터를 기다리느라 느려져요. 과제 3의 행 우선 vs 열 우선 순회가 바로 이 차이입니다.

그래서 "성능"의 의미가 넓어진다

성능을 높인다는 건 단순히 "연산을 줄인다"를 넘어, "메모리를 캐시 친화적으로 건드린다"까지 포함합니다. 알고리즘의 빅오가 같아도 실제 실행 속도는 지역성에서 갈릴 수 있어요. (자료구조마다 메모리 배치가 어떻게 다른지, 그게 성능에 어떻게 작용하는지는 data-structures-algorithms 과목에서 본격적으로 다룹니다.)

🎯 면접관을 홀리는 핵심 멘트

"알고리즘이 같아도 속도가 다른 건 메모리 접근 패턴, 즉 지역성 때문입니다. CPU는 데이터를 캐시에서 가져오면 빠르고 RAM까지 내려가면 수백 배 느린데, 데이터를 연속된 순서로 모아서 쓰면 캐시 히트가 많아지고 띄엄띄엄 흩어 쓰면 캐시 미스가 잦아집니다. 그래서 성능 최적화는 연산을 줄이는 것뿐 아니라 캐시 친화적으로 메모리를 건드리는 것까지 포함합니다. 빅오가 같아도 실제 속도는 지역성에서 갈릴 수 있습니다."

전체 목록 CS 기초지식

더 배우려면

실무 프로젝트까지 가고 싶다면

팀스파르타 백엔드 부트캠프에서 인스타그램 클론을 풀스택으로 완성합니다.