포스트

32비트 vs 64비트 OS와 메모리 계층 구조

'두 배 빠르다'가 아니라 무엇이 다른가

차이를 설명하려 하면 막히는 주제. 주소 공간과 레지스터 폭 두 축으로 가르고, 거기서 이어지는 메모리 계층 — 레지스터에서 디스크까지 왜 층을 쌓는가 — 를 한 축 위에 놓았다.

32비트 vs 64비트 OS와 메모리 계층 구조

“64비트가 32비트보다 두 배 빠르다”는 말은 틀렸지만, 어디가 어떻게 다른지 설명하려 하면 막힌다. 이 글에서는 그 차이를 주소 공간과 레지스터 폭이라는 두 축으로 정리하고, 거기서 자연스럽게 이어지는 메모리 계층 구조 — 레지스터에서 디스크까지 왜 층을 쌓는가 — 를 이야기하려 한다. 두 주제는 따로 배웠지만 “CPU가 데이터에 닿는 거리”라는 하나의 축 위에 놓인다.

32비트 vs 64비트 — 주소 공간과 레지스터 폭

다음 모의면접 주제 — “32비트 운영체제와 64비트 운영체제의 가장 큰 차이점은 무엇인가요?”

작성 의도 — 10·11번을 묶는 “시스템 폭”이라는 큰 그림

10번에서 “포인터 크기는 주소 공간에 따라 결정된다 — 32비트는 4바이트, 64비트는 8바이트”를 짚었고, 11번에서 가상 주소 공간을 다뤘다. 28번은 이 단편적 사실들을 “비트 수가 CPU 레지스터·주소 버스·ALU·가상 주소 공간·포인터 크기·호출 규약을 한꺼번에 결정하는 시스템 폭(system width)” 이라는 한 그림으로 묶는 자리.

면접에서 “가장 큰 차이”를 묻는 의도는 보통 4GB 한계 vs 사실상 무제한과 그 파급 효과. 거기서 멈추면 단순 암기로 보이니까, 그 한계가 왜 생기고, 어떤 연쇄 효과를 일으키는지를 풀어내는 것이 답변 깊이를 만든다.

핵심 골격 — 6축으로 묶기

32비트64비트
가상 주소 공간2³² = 4GB (사용자 공간 2~3GB)2⁴⁸ = 256TB 실효 (5-level paging은 2⁵⁷ = 128PB)
포인터·size_t·intptr_t4바이트8바이트 (int는 LP64/LLP64 모델에서 그대로 4바이트)
범용 정수 레지스터8개 × 32비트 (EAX~ESP)16개 × 64비트 (RAX~R15)
XMM(SSE) 레지스터8개16개
호출 규약__cdecl은 인자 전부 스택Win64: RCX·RDX·R8·R9 + XMM0~3 / Sys V: RDI·RSI·RDX·RCX·R8·R9 6개
메모리 모델PAE로 물리 36비트 늘려도 한 프로세스는 4GB단일 평탄 256TB, mmap·메모리 매핑 자유

이 표가 본문의 중심축. 각 행은 단일 비트 수 결정이 일으키는 연쇄 효과의 단편을 보여준다.

면접 답변에서 가장 신경 쓴 한 줄

“비트 수”는 단순히 한 번에 처리하는 비트 수가 아니라, CPU 레지스터·주소 버스·ALU·가상 주소 공간·포인터 크기·호출 규약을 한꺼번에 결정하는 시스템 폭(system width)입니다.

이걸 답변 초반에 깔아두면 — 뒤따라오는 6축이 전부 이 한 줄의 구체화라는 게 자연스럽게 이어진다. 면접관 입장에선 “왜 이렇게 많은 축이 한 번에 바뀌는가”의 답을 첫 문장에서 듣는 셈.

또 하나 — 트레이드오프 한 줄도 빼먹지 않았다. “64비트가 단순히 더 좋다”가 아니라 포인터 크기 두 배 → 같은 자료구조의 L1 hit rate 하락이라는 비용을 짚어야 균형 잡힌 답변. V8 JavaScript 엔진의 Compressed OOPs·JVM의 포인터 압축이 이 비용을 피하려는 사례.

27번 단편화와의 연결고리

28번에서 굳이 27번과 잇는 한 줄은 — “32비트의 4GB 가상 주소 공간 협소가 외부 단편화 압박을 키운다”. 64비트는 큰 블록이 부족해도 다른 위치를 잡으면 그만이지만, 32비트는 4GB 안에서 큰 free 블록을 못 찾으면 그대로 OOM. 그래서 32비트 시대의 게임 엔진·DB 엔진이 자체 메모리 풀과 메모리 매핑 우회를 적극적으로 썼던 배경.

이 한 줄로 27번과 28번이 따로 노는 주제가 아니라 같은 문제(메모리 자원의 부족)의 다른 측면이라는 게 분명해진다.



메모리 계층 구조 — 왜 층을 쌓는가

다음 모의면접 주제 — “컴퓨터의 메모리 계층 구조에 대해서 설명해 주세요”

작성 의도 — 25·26·27·28번의 상위 프레임

25번(캐시 히트/미스)·26번(페이지 폴트)·27번(메모리 단편화)·28번(32/64비트 OS)이 전부 메모리 계층의 어느 한 부분을 다룬 거였다면, 29번은 그 모두를 한 그림으로 묶는 상위 프레임. 작성하면서 가장 의식한 건 — “모든 메모리 최적화는 이 계층의 비용 차이를 이용한다” 가 마무리 한 줄.

6계층 표 — 본문 중심축

계층접근 시간용량기술코어별
레지스터<1 cycle (~0.3ns)16개 GPR × 8B = 128B / 코어SRAM전용
L1 (D+I)약 4 cycles (~1ns)32+32 ~ 64+64 KB / 코어SRAM전용
L2약 12 cycles (~3ns)256KB ~ 2MB / 코어SRAM전용
L3 (LLC)약 40 cycles (~10ns)4 ~ 64MB / 소켓SRAM공유
DRAM (DDR4/5)약 200~300 cycles (~70ns)8 ~ 256GBDRAM공유
NVMe SSD~100µs256GB ~ 4TBNAND Flash공유
HDD~10ms1 ~ 20TB자기 디스크공유
테이프수십 초 ~ 분수십 TB ~ PB자기 테이프아카이브

인접 계층 간 속도·용량·가격 비율이 대체로 10~100배. 이 한 장이 답변에서 가장 강한 시각적 정박점이 된다.

지역성이 계층을 떠받친다는 한 줄

메모리 계층은 “이상적인 메모리(빠르고·크고·싼)가 물리적으로 불가능하기 때문에 만들어진 절충안”. 이게 동작하는 이유는 단 하나 — 지역성(Locality).

이상적 메모리는 SRAM·DRAM·NAND가 동시에 만족시킬 수 없는 제약 조합(빠름·큼·싸다). 그래서 여러 계층을 쌓아 평균적으로 빠르고 평균적으로 크게 만든 절충안이 메모리 계층. 이게 통하는 통계적 토대가 시간 지역성(루프 변수·반복 호출) + 공간 지역성(배열 순회·구조체 필드 연속 접근).

답변에서 한 가지 꼭 짚은 것 — L1 hit rate가 95% 이상으로 유지되는 통계 덕분에 평균 메모리 접근 시간이 거의 L1 수준으로 수렴한다는 점. 이 한 줄이 “왜 캐시가 이렇게 작아도 통하는가”의 답.

TLB·캐시 일관성·NUMA — 답변 깊이를 만드는 3개의 측면 축

본 계층(레지스터→L1→L2→L3→DRAM→SSD/HDD) 위에 답변 깊이를 더하는 3개의 측면 축을 따로 묶었다.

  • TLB(Translation Lookaside Buffer) — 가상→물리 주소 변환 캐시. 64~512 엔트리로 작지만 hit는 거의 0 cycle, miss면 페이지 테이블 walk로 수십 cycles. 캐시 계층과 별개로 동작하는 주소 변환 계층
  • 캐시 일관성(MESI) — 멀티코어에서 같은 메모리 주소를 여러 코어가 캐시할 때 Modified·Exclusive·Shared·Invalid 상태로 일관성 유지. false sharing(다른 스레드들이 같은 캐시 라인의 서로 다른 변수를 건드려 라인이 계속 무효화되는 현상)으로 성능이 수십 배 떨어지는 게 이 비용이 가장 흔하게 드러나는 지점
  • NUMA(Non-Uniform Memory Access) — 멀티 소켓에서 로컬 DRAM(100ns) vs 원격 DRAM(200~300ns). NUMA-aware 스케줄링이 서버 성능에 직접 영향

이 3개 축이 답변에 있으면 “기본 6계층만 외운 사람”과 “메모리 시스템 전체 구조를 본 사람”의 차이가 분명해진다.

작성 정책에 따라 예상 문제 슬롯은 비워둠. 이론·꼬리질문 대비까지만.



정리 — 두 주제를 잇는 축

  1. “비트 수”는 단일 숫자가 아니라 시스템 폭(system width) — 32비트와 64비트의 차이를 “한 번에 처리하는 비트 수”로 외우면 단순 암기에 그친다. 실제로는 레지스터 너비 + 주소 버스 비트 수 + ALU 폭 + 가상 주소 공간 + 포인터 크기 + 호출 규약 이 한꺼번에 바뀌는 패키지 결정. 이 한 줄로 6축의 차이가 한 그림으로 묶인다. 트레이드오프(포인터 두 배 → L1 hit rate 하락, V8 Compressed OOPs·JVM 포인터 압축이 이걸 우회) 한 줄까지 더해야 균형 잡힌 답변

  2. 메모리 계층은 “이상적 메모리가 불가능하기 때문에 만들어진 절충안” — 통하는 이유는 단 하나, 지역성 — 빠르고·크고·싼 메모리는 물리적으로 동시에 불가능(SRAM·DRAM·NAND 제약). 그래서 여러 계층을 쌓아 평균적으로 빠르고 평균적으로 크게 만든 것이 메모리 계층. 이게 동작하는 통계적 토대가 시간 지역성 + 공간 지역성 단 두 가지. L1 hit rate 95%가 가능한 이유. 답변에서 이 한 줄을 첫머리에 두면 뒤따라오는 6계층·MESI·TLB·NUMA가 자연스럽게 연결된다

  3. 25·26·27·28번이 29번의 부분집합 — CS 흐름의 상위 프레임이 잡힌다 — 캐시 히트/미스(25)는 캐시 계층 내부, 페이지 폴트(26)는 DRAM↔디스크 경계, 메모리 단편화(27)는 할당기 효율, 32/64비트(28)는 워드 크기가 계층 전반에 미치는 영향. 메모리 계층(29)은 이 모두의 상위 프레임. 모의면접에서 한 주제 답변 중 다른 주제로 자연스럽게 확장할 수 있는 “주제 간 다리”가 생긴 셈

  4. 발표 6일 전 프로토타입의 의미 — 완성품의 축소판이 아니라 “전체 합의 충분성 검증 도구” — 각 컴포넌트가 동작해도 전체 흐름이 어색하면 발표 임팩트가 깎인다. 프로토타입을 굴려본 결과 — 시각 피드백(피격 VFX·처형 컷·카메라 셰이크) 3종이 임팩트 직격, 의심2 슬로우 약화는 카메라 워크로 가려진다는 우선순위 재조정의 근거가 잡혔다. “기능 완성도 vs 발표 임팩트”의 트레이드오프에서 후자를 선택하는 결정

  5. 헤더 변경이 들어가는 패치는 별도 PR로 분리 — 빌드 시간·리뷰 부담·rebase 위험을 동시에 줄인다 — PR #34는 cpp만 들어가 빠르게 머지됐다. 의심2 패치는 WeaponComponent.hTMap<TWeakObjectPtr<AActor>, FTimerHandle> 멤버 추가가 따라가야 해서 ABI 영향이 있고, 리뷰어가 인터페이스 변경을 별도로 살필 수 있어야 한다. cpp 패치 PR과 헤더 변경 PR을 분리하는 워크플로우가 팀 작업에서 머지 충돌·리뷰 누락을 막는 패턴

  6. 팀 코드를 미리 읽어두면 rebase 충돌을 사전 해결할 수 있다 — develop에 동시 머지된 PR #32·#33의 변경 범위를 미리 읽어보니 — HealthComponent 델리게이트 시그니처가 PR #33의 위젯 결선과 묶여 있어, 처형 트리거 구현 시점에 영향이 있을 수 있음을 발견. 의심2 패치 자체에는 충돌 위험이 거의 없다는 결론까지 — rebase 직전에 변경분을 읽는 5분이, rebase 후 충돌 디버깅 30분을 절약한다

  7. Portal은 자산 수입의 단일 경로 — 팀 환경 일관성을 위한 인프라 — 팀원마다 외부 자산 import 경로가 다르면 .uasset 종속성·GitHub LFS 추적 경로가 어긋난다. Portal을 통일 경로로 두면 표준화된 마켓플레이스 디렉토리로 들어와 빌드·쿡 단계의 누락이 줄어든다. 팀 작업의 인프라 정리는 기능 작업 사이에 끼워넣어도 비용 대비 효과가 큰 작업


핵심 요약 — 32비트와 64비트의 차이는 “비트 수”가 아니라 레지스터·주소 버스·주소 공간·포인터·호출 규약이 한꺼번에 바뀌는 시스템 폭의 차이다. 메모리 계층은 빠르고 크고 싼 메모리가 물리적으로 불가능해서 만든 절충안이고, 시간·공간 지역성 덕분에 동작한다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.