CPU, 메모리, 디스크, 브라우저 캐시, Redis 같은 DB 캐시까지…
다 따로 노는 개념처럼 보이지만, 사실 전부 “느린 것 대신 빠른 곳에 미리/자주 저장해두자”는 같은 아이디어에서 출발한다.
이번 글에서는:
- 메모리 계층 구조
- 캐시와 지역성의 원리
- 캐시 히트 / 캐시 미스
- 캐시 매핑 방식
- 웹 브라우저의 캐시 (쿠키, localStorage, sessionStorage)
- 데이터베이스 캐싱 계층 (Redis)
까지 한 번에 묶어서 정리해본다.
1. 메모리 계층 구조: 왜 계층이 필요할까?
CPU는 엄청 빠른데, 메모리는 그 정도로 빠르지 않다.
디스크나 네트워크까지 가면 더더욱 느려진다. 그래서 시스템 구조는 이렇게 생겼다:
레지스터 (Register)
↓
L1 캐시
↓
L2 캐시
↓
L3 캐시
↓
메인 메모리 (DRAM)
↓
SSD / HDD
↓
원격 스토리지, DB, 네트워크
아래로 갈수록:
- 속도는 느려지고
- 용량은 커지고
- 비용은 싸진다
이 계층 구조 덕분에, 자주 쓰는 데이터는 위쪽(빠른 계층)에 두고,
덜 자주 쓰는 데이터는 아래쪽(느린 계층)에 둬서 속도와 비용을 동시에 잡는 전략을 쓴다.
2. 캐시(Cache)란? — “위 층에 두는 복사본”
캐시는 한 줄로 정리하면:
느린 저장장치(메모리/디스크/네트워크)에 있는 데이터를 빠른 저장장치에 “복사본”으로 보관해두는 구조
CPU 입장에서는:
- 캐시 = 메모리의 복사본
웹 브라우저 입장에서는:
- 캐시 = 서버 리소스(HTML, JS, 이미지 등)의 복사본
DB 입장에서는:
- 캐시 = 디스크나 원격 DB에 있는 데이터의 복사본 (예: Redis)
공통점:
자주 쓰는 것을 더 빠른 공간에 미리 올려둠으로써 평균 접근 시간을 줄인다.
3. 지역성의 원리: 캐시가 먹히는 이유
캐시는 “운 좋으면 빠르고, 아니면 말고”가 아니다.
CPU나 프로그램이 실제로 “지역성(Locality)” 이라는 패턴을 보이기 때문에 잘 먹힌다.
3-1. 시간 지역성 (Temporal Locality)
한 번 접근한 데이터는 가까운 미래에 또 접근될 가능성이 크다.
예:
- for 루프 안에서 같은 변수 계속 사용
- 최근에 사용한 함수가 다시 호출
- 스택 프레임, 전역 변수, 카운터 등
그래서 “최근에 사용한 것들을 캐시에 남겨두자”는 전략이 의미가 있다.
3-2. 공간 지역성 (Spatial Locality)
어떤 주소에 접근했다면, 그 주변 주소에도 곧 접근할 가능성이 크다.
예:
- 배열 순회 arr[0], arr[1], arr[2] …
- 연속된 구조체 접근
- 코드도 메모리에 연속적으로 올라가 있으므로, 인근 명령어들을 순차 실행
그래서 캐시는 한 번에 한 워드만 가져오지 않고, 그 주변까지 한 덩어리(블록 또는 라인)로 가져온다.
3-3. 요약
- 시간 지역성: “다시 쓸 가능성이 크다 → 캐시에 오래 보관”
- 공간 지역성: “옆 주소도 쓸 가능성이 크다 → 주변을 같이 가져오자”
CPU 캐시, 디스크 캐시, DB 캐시, 웹 캐시 모두 이 개념을 활용한다.
4. 캐시 히트와 캐시 미스
캐시를 쓴다는 건 결국 다음 둘 중 하나다.
✔ 캐시 히트(Cache Hit)
CPU(또는 프로그램)가 찾는 데이터가 캐시에 이미 있는 경우
- CPU: L1/L2/L3 캐시에서 찾음
- 브라우저: 로컬 캐시에 HTML/JS/이미지 이미 있음
- Redis: 메모리에서 바로 해당 키를 찾음
→ 매우 빠르다.
→ CPU 캐시의 경우, CPU 내부 버스만 타고 끝나기 때문에 레이턴시가 극도로 짧다.
✔ 캐시 미스(Cache Miss)
캐시에 없어서 더 아래 계층(느린 계층)까지 내려가서 데이터를 가져와야 하는 경우
CPU 입장에서는:
- 캐시에 없음 → 메인 메모리(DRAM)까지 가야 함 → 시스템 버스를 타고 왕복 → 느림
DB 입장에서는:
- Redis에 없음 → 디스크 기반 RDB까지 조회 → 느림
웹 브라우저 입장에서는:
- 브라우저 캐시에 없음 → 서버까지 HTTP 요청 → 느림
그래서 시스템들은 최대한 히트율(hit ratio) 을 올리려고 한다.
5. 캐시 매핑 방식 (CPU 캐시 관점)
CPU 캐시에서 데이터가 “어디에 놓이는가?” 를 결정하는 규칙이 캐시 매핑(Cache Mapping)이다.
5-1. Direct Mapped Cache
메인 메모리의 특정 블록은 캐시의 딱 한 위치에만 저장 가능
- 장점: 구현이 단순, 빠름
- 단점: 충돌이 많을 수 있음 (자주 쓰지만 같은 인덱스를 공유하는 데이터들)
5-2. Fully Associative Cache
메모리 블록이 캐시 어느 곳에나 저장될 수 있음
- 장점: 충돌 최소화
- 단점: 어디에 있는지 찾기가 복잡 (비싸고 느림)
5-3. Set Associative Cache (실제 많이 사용)
캐시를 여러 set으로 나누고,
각 set 안에서는 associative하게 배치 가능
- 예: 4-way set associative
- Direct와 fully associative의 타협안
- 현대 CPU에서 가장 일반적인 방식
이 매핑과 더불어:
- 어떤 블록을 버릴지(교체 정책: LRU, Random 등)
- 쓰기 정책(write-back, write-through)
까지 합쳐져 캐시의 성능이 결정된다.
6. 웹 브라우저의 캐시: 메모리 계층의 “상위 레벨” 버전
웹 개발을 하다 보면 또 이런 캐시들이 등장한다:
- HTTP 캐시 (브라우저가 리소스를 저장)
- 쿠키(Cookie)
- localStorage, sessionStorage
여기서 쿠키 / localStorage / sessionStorage는 좀 역할이 다르다.
6-1. 쿠키(Cookie)
- 서버나 자바스크립트가 브라우저에 심는 작은 데이터 조각
- 매 요청마다 HTTP 헤더에 실려서 서버로 전송됨
- 주로 로그인 세션, 트래킹, 사용자 식별 등에 사용
- 용량이 작음(수 KB 단위), 보안 이슈 있음(HTTP 전송)
쿠키는 “캐시”라기보다는 상태 유지용에 더 가깝지만,
“서버가 매번 다시 묻지 않기 위해” 정보를 로컬에 저장한다는 점에서 넓은 의미의 캐시로 볼 수도 있다.
6-2. localStorage
- 도메인별로 영구 저장되는 키-값 저장소
- 브라우저를 껐다 켜도 남아있음
- JS에서 localStorage.setItem(key, value) 로 접근
- 서버에 자동으로 전송되지 않음 (쿠키와 가장 큰 차이)
예:
- 다크 모드 설정
- 최근 본 상품 리스트
- 사용자의 간단한 환경설정
6-3. sessionStorage
- 탭 단위로 살아있는 저장소
- 탭을 닫으면 사라짐
- 페이지 리로드 시에는 유지됨
예:
- 특정 페이지에서만 쓰는 임시 상태
- 탭마다 분리되어야 하는 데이터
6-4. 진짜 “웹 캐시” — HTTP 캐시
여기까지 오면 진짜 캐시다운 캐시가 나온다.
- HTML, CSS, JS, 이미지 파일 등을 브라우저가 로컬 디스크/메모리에 저장
- 다음에 같은 URL에 접근할 때,
- 만료 안 됐으면 그대로 사용 (Cache Hit)
- 만료됐거나 조건부 요청시 서버에 재검증
이건 CPU–메모리 캐시와 거의 동일한 개념이다:
- 원본: 서버의 리소스
- 복사본: 브라우저 로컬 캐시
- 목표: 네트워크 왕복 줄이기
7. 데이터베이스의 캐싱 계층 (Redis 등)
백엔드 쪽으로 가면 또 하나의 “메모리 계층” 구조가 보인다.
일반적인 구조:
CPU / 애플리케이션 (서버 코드)
↓
Redis (인메모리 캐시, key-value)
↓
RDBMS (MySQL, PostgreSQL 등, 디스크 기반)
↓
디스크 / 스토리지
역시 똑같다.
- 자주 읽히는 데이터는 메모리에 띄워놓고 빠르게 제공
- 덜 자주 쓰이거나, 영구 보관이 필요한 데이터는 디스크 기반 DB에 저장
7-1. Redis의 역할
Redis는:
- 메모리 기반 key-value 저장소
- 읽기·쓰기 속도가 매우 빠름
- 세션 관리, 랭킹, 카운터, 토큰 저장 등에서 자주 사용
예:
- GET user:123 → Redis에서 바로 나오면 DB까지 안 내려감 → Hit
- Redis에 없으면 → MySQL 쿼리 → 결과를 Redis에 저장 → Miss 후 Fill
이 구조를 통해:
- DB 부하 분산
- 응답 시간 단축
- 스케일 아웃 용이
결국 DB도 자체적으로 “메모리 계층”을 쌓는 것이다.
8. 전체 그림: 모든 레벨의 캐시를 한 번에 묶어 보면
조금 과장해서 그려보면, 요즘 서비스 하나를 띄웠을 때 메모리 계층은 이렇게 된다:
[CPU 레지스터]
↓
[CPU 캐시 (L1/L2/L3)]
↓
[메인 메모리 (프로세스 힙/스택)]
↓
[OS 페이지 캐시, 버퍼 캐시]
↓
[DB 캐시 (MySQL InnoDB Buffer Pool 등)]
↓
[Redis 같은 인메모리 캐시]
↓
[디스크 기반 RDBMS 데이터 파일]
↓
[원격 스토리지, 백업, 데이터 레이크 …]
+ 클라이언트 쪽:
[브라우저 메모리]
↓
[브라우저 HTTP 캐시]
↓
[localStorage / sessionStorage / 쿠키]
↓
[네트워크 요청 → 서버]
위에서 아래로 내려갈수록:
- 속도 ↓
- 용량 ↑
- 비용 ↓
- 영속성 ↑
그 사이사이에 “캐시”라는 계층을 끼워넣어 성능을 끌어올리는 구조다.
9. 마무리 요약
- 메모리 계층: 빠른 것(작고 비싸다)부터 느린 것(크고 싸다)까지 층을 쌓아둔 구조
- 캐시: 느린 계층의 복사본을 빠른 계층에 두는 구조
- 지역성의 원리 덕분에 캐시는 잘 먹힌다
- 시간 지역성: 최근 쓴 걸 또 쓴다
- 공간 지역성: 근처도 같이 쓴다
- 캐시 히트/미스: 히트면 빠른 계층에서 해결, 미스면 아래로 내려가야 해서 느림
- 캐시 매핑: 메모리 블록이 캐시에 어디에 배치되는지 결정(direct / associative / set-associative)
- 웹 브라우저 캐시: HTTP 캐시 + 쿠키/localStorage/sessionStorage라는 다양한 형태로 존재
- DB/Redis 캐시: DB 앞에 메모리 캐시 계층을 두어 읽기 성능을 끌어올리는 구조
결국 로우레벨(CPU 캐시)부터 하이레벨(웹, DB)까지 같은 아이디어가 반복해서 등장한다.
목표: Redis는 아직 사용해보지 않아서, 프로젝트에 적용해보려고 한다. 얼마나 빨라지려나!? 😬
오늘의 공부

'CS' 카테고리의 다른 글
| [CS-운영체제] 컴퓨터의 요소 (1) | 2025.11.17 |
|---|---|
| [CS-운영체제] 운영체제의 역할과 구조 (0) | 2025.11.16 |

