
가상화(Virtualization): 하나의 물리 자원을 여러 논리 자원으로
내 맥북 안에 윈도우와 리눅스를 동시에 띄우는 법. 클라우드 컴퓨팅(AWS)의 기반 기술.

내 맥북 안에 윈도우와 리눅스를 동시에 띄우는 법. 클라우드 컴퓨팅(AWS)의 기반 기술.
내 서버는 왜 걸핏하면 뻗을까? OS가 한정된 메모리를 쪼개 쓰는 처절한 사투. 단편화(Fragmentation)와의 전쟁.

미로를 탈출하는 두 가지 방법. 넓게 퍼져나갈 것인가(BFS), 한 우물만 팔 것인가(DFS). 최단 경로는 누가 찾을까?

이름부터 빠릅니다. 피벗(Pivot)을 기준으로 나누고 또 나누는 분할 정복 알고리즘. 왜 최악엔 느린데도 가장 많이 쓰일까요?

매번 3-Way Handshake 하느라 지쳤나요? 한 번 맺은 인연(TCP 연결)을 소중히 유지하는 법. HTTP 최적화의 기본.

창업 초기, AWS 청구서를 처음 받았을 때 멍했다. "EC2 인스턴스 t2.micro" 같은 용어들이 난무했는데, 도대체 이게 뭘 의미하는지 몰랐다. 물리 서버를 빌린 건가? 아니면 뭔가 다른 건가? 친구는 "그냥 가상 머신이야"라고 했지만, 그게 정확히 뭔지 몰라서 불안했다.
그러다 우연히 Parallels로 맥북에 윈도우를 깔아 쓰면서 깨달았다. 내 맥북은 하나인데, 그 위에서 macOS와 Windows가 동시에 돌아간다. 이게 바로 가상화구나. 그제야 클라우드가 어떻게 작동하는지 이해되기 시작했다.
처음 서비스를 런칭할 때 물리 서버를 직접 사서 IDC에 입주시키는 방안을 고려했다. 견적을 받아보니 서버 1대에 500만 원. CPU 16코어, RAM 64GB였다. 문제는 우리 트래픽이 하루 중 특정 시간대에만 몰린다는 거였다. 새벽 2시엔 서버가 거의 놀고 있었다.
"서버 여러 대를 시간대별로 껐다 켰다 할 수 있으면 좋겠는데..." 하지만 물리 서버는 그게 안 된다. 한 번 사면 24시간 전기세 나오고, 공간 차지하고, 냉각 비용도 든다. 그때 떠올린 게 AWS였다. "쟤네는 어떻게 필요할 때만 서버를 빌려줄까?"
답은 가상화였다. 생각해보면 간단한 원리다.
물리 자원과 논리 자원을 분리하는 것.건물주가 건물 하나를 여러 세입자에게 쪼개 빌려주듯, 서버 1대를 여러 "가상 컴퓨터"로 쪼개는 거다. 각 세입자(VM)는 자기 집이 독립된 건물인 줄 안다. 사실은 한 건물 안의 방일 뿐인데.
물리 서버 1대 (CPU 16코어, RAM 64GB)
├── VM1: CPU 4코어, RAM 16GB (웹서버)
├── VM2: CPU 4코어, RAM 16GB (DB서버)
├── VM3: CPU 4코어, RAM 16GB (개발서버)
└── VM4: CPU 4코어, RAM 16GB (테스트서버)
이게 서버 통합(Server Consolidation)의 핵심이다. 예전엔 서버 4대가 필요했던 걸 서버 1대로 해결한다. 전기세, 공간, 냉각 비용이 1/4로 줄어든다.
이 마법을 부리는 소프트웨어를 하이퍼바이저(Hypervisor)라고 부른다. VM들과 물리 하드웨어 사이의 중재자 역할을 한다.
내가 혼동했던 부분이 여기였다. 하이퍼바이저에는 두 종류가 있다.
Type 1 (Bare-Metal): 하드웨어 위에 바로 설치된다.
[하드웨어]
↓
[VMware ESXi / Hyper-V / KVM]
↓
[VM1] [VM2] [VM3]
호스트 OS가 없다. 하이퍼바이저 자체가 OS처럼 작동한다. 성능이 좋아서 데이터센터, 클라우드 환경에서 사용한다. AWS EC2가 이 방식이다.
Type 2 (Hosted): 일반 OS 위에 설치된다.
[하드웨어]
↓
[Windows / macOS (호스트 OS)]
↓
[VirtualBox / Parallels / VMware Workstation]
↓
[VM1] [VM2]
내 맥북에서 쓰는 Parallels가 이거다. 호스트 OS를 거쳐야 해서 Type 1보다 느리지만, 개인용으로 쓰기엔 충분하다.
하이퍼바이저가 VM을 속이는 방식에도 두 가지가 있다.
Full Virtualization (완전 가상화): VM은 자신이 가상 환경인 걸 모른다.
게스트 OS가 "하드웨어야, CPU 명령어 실행해줘"라고 하면, 하이퍼바이저가 가로채서 "알았어, 대신 실행해줄게"라고 한다. 하드웨어를 완벽히 에뮬레이션한다. 장점은 게스트 OS를 수정할 필요가 없다는 것. 단점은 느리다.
Para-Virtualization (반가상화): VM은 자신이 가상 환경인 걸 안다.
게스트 OS가 "하이퍼바이저야, 이거 좀 대신 실행해줘"라고 직접 요청한다. 하이퍼바이저가 중간에서 가로챌 필요가 없어서 훨씬 빠르다. 단점은 게스트 OS를 수정해야 한다는 것. Xen이 이 방식을 사용한다.
요즘 CPU들은 가상화를 하드웨어 레벨에서 지원한다.
CPU 자체에 "가상화 모드"가 있어서, 하이퍼바이저가 훨씬 효율적으로 VM을 관리할 수 있다. 예전엔 CPU 명령어를 소프트웨어로 에뮬레이션했는데, 이제는 CPU가 직접 처리한다.
BIOS에서 "Intel VT-x" 옵션을 켜야 하는 이유가 이거다. 이게 꺼져 있으면 가상화가 엄청 느려지거나 아예 안 된다.
VM과 컨테이너(Docker)를 혼동하는 사람이 많은데, 둘은 무게급이 다르다.
VM (무거운 격리):
[물리 하드웨어]
↓
[하이퍼바이저]
↓
[VM1: Ubuntu + 앱] [VM2: CentOS + 앱] [VM3: Windows + 앱]
각 VM이 전체 OS를 가진다. Ubuntu VM은 커널부터 전부 독립적이다. 완벽한 격리지만 무겁다. VM 하나 띄우는 데 수 GB의 디스크와 수백 MB의 RAM이 필요하다.
Container (가벼운 격리):
[물리 하드웨어]
↓
[호스트 OS 커널]
↓
[Docker Engine]
↓
[컨테이너1] [컨테이너2] [컨테이너3]
커널을 공유한다. 컨테이너는 프로세스 레벨 격리만 한다. 훨씬 가볍고 빠르지만, 완벽한 격리는 아니다. 같은 커널을 쓰기 때문에 보안적으로 VM보다 약하다.
언제 뭘 쓸까?
가상화를 이해하니 클라우드가 보였다.
IaaS (Infrastructure as a Service): VM을 빌려준다.
AWS EC2가 대표적이다. "여기 CPU 2개, RAM 4GB짜리 VM 있어요. 시간당 10센트입니다." 나는 그 VM에 OS 깔고, 웹서버 설치하고, 코드 배포한다. 모든 걸 내가 관리한다.
PaaS (Platform as a Service): 플랫폼(런타임 환경)을 빌려준다.
Heroku, Google App Engine이 여기 속한다. "코드만 올려. 우리가 서버 관리 다 해줄게." VM을 직접 관리할 필요가 없다. 편하지만 커스터마이징이 제한된다.
SaaS (Software as a Service): 완성된 소프트웨어를 빌려준다.
Gmail, Notion, Slack이 여기 속한다. 나는 그냥 브라우저로 접속해서 쓴다. 서버고 뭐고 신경 쓸 필요 없다.
EC2 인스턴스를 띄울 때 이런 옵션들을 본다.
Instance Type: t2.micro
- vCPU: 1
- Memory: 1 GB
- Network Performance: Low to Moderate
vCPU (Virtual CPU)가 핵심이다. 물리 CPU 코어를 여러 VM에 나눠준 것. t2.micro는 vCPU 1개지만, 실제로는 물리 CPU 1개를 여러 VM이 시분할로 나눠 쓴다.
AWS는 물리 서버 1대에 수십 개의 t2.micro 인스턴스를 띄운다. 내가 CPU를 100% 안 쓸 때, 다른 인스턴스들이 그 자원을 쓴다. 이게 Resource Overcommitment (자원 초과 할당)다.
항공사는 좌석보다 많은 티켓을 판다. "노쇼 승객이 있을 거야" 라고 예상하고. 클라우드도 똑같다.
물리 서버에 CPU 16코어가 있다면, 이론적으로는 vCPU 16개짜리 VM을 딱 1개만 띄워야 한다. 하지만 실제로는 vCPU 2개짜리 VM을 20개 띄운다. (총 vCPU 40개 = 250% 오버커밋)
왜? VM들이 동시에 CPU를 100% 쓰는 경우는 드물기 때문이다. 대부분의 VM은 idle 상태로 놀고 있다. 이걸 활용해서 더 많은 VM을 띄우고, 더 많은 돈을 번다.
물론 모든 VM이 동시에 CPU를 100% 쓰면 문제가 생긴다. 이때는 noisy neighbor 문제가 발생한다. 옆집이 시끄러워서 내 집이 피해를 본다. 클라우드 업체들은 이걸 막기 위해 모니터링하고 VM을 재배치한다.
물리 서버 1대가 고장나면 어떻게 될까? 그 위의 VM들도 다 죽는 거 아닐까?
아니다. Live Migration 덕분에 VM을 다른 서버로 옮길 수 있다. 서비스 중단 없이.
# 개념적 예시 (실제 코드는 더 복잡함)
def live_migrate(vm, source_server, dest_server):
# 1단계: 메모리 페이지를 조금씩 복사
while True:
dirty_pages = vm.get_dirty_memory_pages()
dest_server.receive_memory(dirty_pages)
if len(dirty_pages) < threshold:
break
# 2단계: VM을 잠깐 멈추고 마지막 메모리 복사
vm.pause() # 수 밀리초만 중단
dest_server.receive_final_memory()
# 3단계: 목적지 서버에서 VM 재개
dest_server.resume_vm()
source_server.destroy_vm()
실제로는 수 밀리초만 중단되기 때문에, 사용자는 눈치채지 못한다. AWS가 하드웨어 점검할 때 이 방식으로 VM을 다른 서버로 옮긴다.
VM의 스냅샷을 찍으면 특정 시점의 상태를 저장할 수 있다.
[2025-02-06 10:00] 스냅샷 1: 배포 전 상태
↓
[배포 실행]
↓
[2025-02-06 11:00] 스냅샷 2: 배포 후 상태
↓
[버그 발견!]
↓
[스냅샷 1로 복원] → 10:00 상태로 돌아감
디스크 전체를 복사하는 게 아니라, 변경된 부분만 저장한다. Copy-on-Write 방식이다. 메모리 효율적이고 빠르다.
실수로 DB를 날렸을 때 스냅샷으로 되살린 적이 있다. 그때 가상화의 위대함을 느꼈다. 물리 서버였으면 복구 불가능했을 거다.
VM 안에서 또 VM을 띄울 수 있을까? 된다. 이게 Nested Virtualization이다.
[물리 서버]
↓
[하이퍼바이저 L0]
↓
[VM (L1)]
↓
[하이퍼바이저 L1]
↓
[VM (L2)]
인셉션처럼 꿈속의 꿈. 성능은 당연히 떨어진다. L2 VM이 CPU 명령어를 날리면 L1 하이퍼바이저를 거쳐 L0 하이퍼바이저를 거쳐 물리 하드웨어에 도달한다.
언제 쓸까? Kubernetes 클러스터를 테스트할 때. VM 여러 대로 클러스터를 구성하고 싶은데, 물리 서버가 1대밖에 없을 때. L1 VM 안에 L2 VM 여러 개를 띄워서 가상 클러스터를 만든다.
회사 컴퓨터를 집에서 쓸 수 있을까? VDI (Virtual Desktop Infrastructure) 덕분에 가능하다.
회사 데이터센터에 VM을 띄우고, 그 VM의 화면을 원격으로 스트리밍한다. 내 집 컴퓨터는 단순히 화면만 보여주는 역할. 실제 연산은 전부 회사 서버에서 일어난다.
[집 컴퓨터 (씬 클라이언트)]
↓ (화면 스트리밍)
[회사 데이터센터]
↓
[Citrix / VMware Horizon]
↓
[Windows VM (내 업무용 데스크톱)]
장점:
코로나 때 이걸 도입한 회사가 많았다.
가상화를 이해하고 나니 클라우드가 더 이상 블랙박스가 아니었다.
AWS EC2 인스턴스는 누군가의 물리 서버 위에서 도는 VM이다. 내가 "인스턴스 정지" 버튼을 누르면, 하이퍼바이저가 그 VM의 전원을 끈다. "인스턴스 삭제" 버튼을 누르면, 그 VM이 차지하던 디스크 공간을 해제하고 다른 고객의 VM에게 할당한다.
클라우드는 마법이 아니라, 가상화 기술을 극한으로 활용한 결과다. 물리 자원을 논리적으로 쪼개고, 초과 할당하고, 실시간으로 이동시키고, 시간 단위로 빌려준다.
이제 AWS 청구서를 보면 두렵지 않다. "아, 이건 vCPU 2개짜리 VM을 720시간 돌렸구나. 물리 서버로 따지면 CPU 코어 0.1개 정도 썼겠네." 이렇게 계산할 수 있다.
가상화는 단순히 컴퓨터를 에뮬레이션하는 기술이 아니다. 물리적 한계를 뛰어넘어 자원을 유연하게 관리하고, 그걸 서비스로 만드는 혁명이다. 스타트업이 초기 자본 없이 서비스를 시작할 수 있는 이유, 넷플릭스가 전 세계에 동영상을 스트리밍할 수 있는 이유, 모두 가상화 덕분이다.