Hyper-V 관리자에서 Windows VM을 만들면, 기동에 수십 초가 걸리고 메모리 수 기가바이트를 독점합니다. 그런데 같은 PC에서 wsl을 치면 수초 안에 Linux 셸이 돌아오고, Windows Sandbox도 수초 만에 일회용 데스크톱을 엽니다.1
둘 다 같은 Windows 하이퍼바이저 위에 있습니다(제1회, 「당신의 Windows는 어디서 움직이고 있는가」). 제2회에서는 이 토대가 커널보다 강한 격리를 만들 수 있음을 보았습니다. 그렇다면 왜 한쪽은 무겁고 다른 쪽은 가벼울까요?
연재 마지막 회가 답하는 질문은 하나뿐입니다.
풀 VM은 무거운데, 왜 WSL2와 Windows Sandbox는 가벼운가?
대상 독자는 WSL2, Windows Sandbox, Windows 컨테이너를 개발과 검증에 쓰면서, 그 가벼움과 제약을 구조부터 이해하고 싶은 개발자와 운용자입니다. 전제 환경은 Windows 10/11이며, Windows Sandbox 절을 따라가려면 Pro, Enterprise, Education 에디션이 필요합니다(Home과 Windows Server에는 이 기능이 없습니다). 배경 지식은 제1회의 파티션 개념입니다. 난이도는 중급입니다.
1. 먼저 결론
경량 VM은 격리선(전용 커널과 하이퍼바이저 경계)은 남기고, 「완전한 게스트 OS의 복사」를 가볍게 만듭니다. Sandbox는 호스트의 Windows 자체를 공유하고, WSL2는 게스트를 작고 목적에 맞춘 Linux로 바꾸며, 둘 다 메모리는 고정 예약이 아니라 호스트와 동적으로 빌리고 빌려 줍니다.
풀 VM의 무게의 원천은 격리 자체가 아니라 중복입니다. 디스크에 또 하나의 OS 이미지, RAM에 또 하나의 OS분 페이지, 시작할 때마다 또 한 번의 전체 부트. 경량 VM은 그 중복을 두 가지 방침으로 자릅니다. 「공유해도 안전한 것은 공유한다」(Sandbox)와 「공유할 수 없으면 작게 다시 만든다」(WSL2).
flowchart TB
accTitle: 경량 VM을 받치는 세 종류의 공유
accDescr: 풀 VM이 중복하던 OS 이미지는 Sandbox에서는 공유로, WSL2에서는 축소로 자른다. 기본이 고정 할당인 메모리(동적 메모리는 예외)는 호스트와의 동적 대여가 되고, 기동은 가벼운 커널과 최소 설정으로 바뀌며, 격리 경계만 남는다
heavy["풀 VM: 중복"] --> d1["디스크: OS 이미지 복사"]
heavy --> more{"메모리 또는 기동?"}
more --> d2["메모리: 고정 기본값"]
more --> d3["기동: 전체 부트"]
d1 -->|대체| s1["공유(Sandbox)"]
s1 -.-> s1b["또는 축소(WSL2)"]
d2 -->|대체| s2["호스트와의 동적 대여"]
d3 -->|대체| s3["가벼운 커널 + 최소"]
그림 1: 「같은 하이퍼바이저인데 가볍다」에 대한 답의 골격은, 격리를 멈춘 것이 아니라 중복을 멈춘 것이다.
아래에서 WSL2, Windows Sandbox, 컨테이너를 그 순서로, 각각이 어느 종류의 중복을 자르는지를 봅니다.
2. 풀 VM이 지고 있는 것
비교의 기준으로, 전통적인 VM이 지는 것을 적습니다.
- 독립된 OS 이미지. 게스트 OS의 모든 파일을 가상 디스크 안에 둡니다. 호스트에 같은 Windows가 있어도 공유하지 않습니다.
- 거친 메모리 할당. 전통적인 VM의 기본은 호스트 메모리를 정적 크기로 할당하는 것입니다. Hyper-V Dynamic Memory 같은 장치는 설정 범위 안에서 할당을 늘리고 줄일 수 있지만, 수요 변화에 맞추는 수단은 한정됩니다.2
- 범용 전체 부트. 펌웨어, 부트 로더, 서비스 집합이 물리 머신과 같은 순서로 시작합니다.
flowchart TB
accTitle: 풀 VM이 지는 세 가지 부하
accDescr: 풀 VM은 독립된 OS 이미지, 기본이 정적인 메모리 할당, 범용 전체 부트를 지고, 그것들이 디스크, RAM, 기동 시간의 비용으로 나타난다
fullvm["풀 VM"] --> b1["독립된 OS 이미지"]
fullvm --> more{"메모리 또는 부트?"}
more --> b2["정적 메모리 기본값"]
more --> b3["범용 부트"]
b1 -.-> c1["복사본을 위한 추가 디스크"]
b2 -.-> c2["쓰지 않는 RAM도 점유"]
b3 -.-> c3["수십 초가 걸린다"]
그림 2: 풀 VM 비용의 내역은 격리가 아니라 범용성과 중복에 지불된다.
이건 결함이 아니라, 「게스트에 무엇이든 넣을 수 있다」는 범용성의 대가입니다. Windows Server 옆에 옛 Linux를 돌리는 용도에서는 그 범용성이 가치입니다. 하지만 「호스트와 같은(또는 정해진) OS를, 지금 당장, 개발이나 검증에 돌리고 싶다」는 용도에서는 대부분이 낭비 짐입니다. 경량 VM은 목적을 좁혀 그 짐을 내려놓습니다.
3. WSL2 ── 목적에 맞춘 커널을 가진 유틸리티 VM
3.1. 구조: 관리되는 VM과 그 안의 배포판
WSL2는 진짜 Linux 커널을 가벼운 유틸리티 VM 안에서 돌리는 장치입니다.3 점은 세 가지입니다.
- 커널은 진짜이지만, 특화 제품입니다. Microsoft가 Stable 브랜치에서 빌드한 Linux 커널이며, 크기와 성능이 이미 WSL2용으로 튜닝되어 있습니다. 현행 표준인 Microsoft Store 배포 WSL에서는 커널이 WSL 패키지 자체와 함께 갱신되고
wsl --update로 적용됩니다(예전 인박스 배포에서는 Windows Update를 탔습니다).4 진짜 커널이므로 시스템 호출 호환은 완전하고, Docker 같은 도구가 그대로 돕니다. - VM은 뒤에 있습니다. VM의 생성·시작·중지는 WSL이 관리하고, 사용자는 셸만 엽니다. VM 설정 화면도, 체감되는 부트 대기도 없습니다.4
- 배포판은 VM 안의 컨테이너입니다. Ubuntu나 Debian 같은 배포판은 관리되는 VM 하나 안에서 격리된 컨테이너로 돕니다. 네트워크 네임스페이스와 커널은 공유하고, PID, 마운트, 사용자 같은 네임스페이스는 분리됩니다.3
flowchart TB
accTitle: WSL2 아키텍처
accDescr: 호스트 Windows와 가벼운 유틸리티 VM이 하이퍼바이저 위에 나란히 앉고, VM 안에서는 Microsoft가 빌드한 Linux 커널이 돌며, 각 배포판은 그 안에서 격리된 컨테이너로 돈다
hv["하이퍼바이저"] --> host["호스트 Windows"]
hv --> uvm["가벼운 유틸리티 VM"]
uvm --> lk["Linux 커널(Microsoft 빌드. wsl --update로 갱신)"]
lk --> u1["Ubuntu(컨테이너)"]
lk --> u2["Debian(컨테이너)"]
host <-->|"Interop(명령, 파일, 네트워크)"| uvm
그림 3: 「WSL2는 VM인가?」에 대한 답은 「그렇다. 다만 뒤에서 관리되는 VM이다」이며, 배포판을 여러 개 설치해도 VM은 하나다.
wsl을 친 순간의 뒷면은 이렇습니다.
flowchart TB
accTitle: wsl 명령을 실행해서 수초 안에 셸이 돌아오기까지
accDescr: wsl을 실행했을 때 유틸리티 VM이 돌고 있지 않으면 경량 VM과 Linux 커널이 시작하고, 이미 돌고 있으면 재사용하며, 배포판의 컨테이너 안에서 셸이 돌아온다
cmd["wsl을 실행"] --> vmq{"유틸리티 VM이 이미 도는가?"}
vmq -->|아니오| bootvm["경량 VM과 Linux 커널을 시작(수초)"]
vmq -->|예| reuse["이미 도는 VM을 재사용"]
bootvm --> shell["컨테이너 안에서 셸이 돌아온다"]
reuse --> shell
그림 4: 대기는 최소 VM 시작뿐이며, 전체 부트의 짐을 내려놓은 결과가 여기서 나타난다.
3.2. 파일 I/O: 어디에 두느냐에 따라 다른 것이 된다
WSL2 성능 이야기에 항상 나오는 주제는, 파일을 어디에 두느냐입니다.
- Linux 측 파일(ext4 가상 디스크)에 대한 작업은 빠릅니다. Linux 커널이 자신의 파일 시스템에 직접 말하기 때문이며, tarball 전개에서 WSL1 대비 최대 20배,
git clone과npm install에서 2–5배의 속도 향상이 보고되어 있습니다.4 - Windows 측 파일(/mnt/c 등)에 대한 작업은 OS 경계를 넘는 파일 공유를 지나므로 느려집니다. OS를 넘나드는 파일 시스템 성능은 WSL2가 WSL1보다 나쁜 주요 항목 하나입니다.4
그래서 규칙은 이것입니다. 「프로젝트 파일은 그것을 다루는 도구와 같은 OS 측에 둔다」.4 Linux 빌드 도구로 다루는 저장소는 Linux 측에, Visual Studio에서 빌드하는 솔루션은 Windows 측에 둡니다.
flowchart TB
accTitle: WSL2 파일 I/O 경로의 갈림
accDescr: Linux 측 ext4 가상 디스크로의 접근은 Linux 커널에서 직접이므로 빠르고, Windows 측 파일로의 접근은 OS 경계를 넘는 파일 공유를 지나므로 느리다
io["WSL2 안의 파일 작업"] --> place{"파일은 어느 측인가?"}
place -->|"Linux 측(home 등)"| ext4["ext4 가상 디스크로의 직접 I/O"]
place -->|"Windows 측(/mnt/c 등)"| p9["OS 경계를 넘는 공유를 경유"]
ext4 --> fast["빠름(WSL1 대비 최대 20배의 예)"]
p9 --> slow["느려지기 쉽다"]
slow -.-> fix["대책: 파일을 쓰는 OS 측에 둔다"]
그림 5: 느린 것은 WSL2가 아니라 경로이므로, 파일을 두는 자리를 바꾸면 성능 문제가 사라지는 경우가 많다.
3.3. 메모리: 늘고 줄지만, 항상 전부 돌려주지는 않는다
WSL2의 메모리 사용량(작업 관리자에서는 vmmem 프로세스로 보입니다)은 고정 예약이 아니라, 사용에 따라 늘고 줍니다. 프로세스가 해제한 메모리는 기본으로 켜진 pageReporting 설정 아래 Windows로 자동 반환됩니다.5 파일 캐시로 들고 있던 페이지는 예전에는 VM이 끝날 때까지 Windows로 돌아가지 않았습니다.4 현행 WSL에서는 실험적 .wslconfig 설정 autoMemoryReclaim(기본값은 dropCache)이 캐시도 자동으로 회수합니다.5 이 설정이 disabled인 환경이나 예전 WSL에서는, 긴 세션의 캐시가 VM이 끝날 때까지 남아 호스트 메모리를 압박할 수 있습니다.
flowchart TB
accTitle: WSL2 메모리가 늘고 줄고 반환되는 방식
accDescr: WSL2 안의 수요 증가가 VM의 메모리 사용량을 올린다. 프로세스가 해제한 페이지는 기본으로 켜진 pageReporting 아래 Windows로 돌아가고, 파일 캐시는 기본으로 autoMemoryReclaim이 자동 회수한다. 다만 설정이 꺼져 있거나 예전 WSL에서는 VM이 끝날 때까지 남으며, wsl --shutdown이 전부를 반환한다
grow["WSL2 안에서 메모리 수요가 증가"] --> vm["vmmem 사용량이 증가"]
vm --> freed{"그 페이지가 해제되었는가?"}
freed -->|"프로세스가 해제(pageReporting이 켜진 때)"| ret["Windows로 자동 반환"]
freed -->|파일 캐시로 보유| amr["autoMemoryReclaim이 자동 회수(기본)"]
amr -.-> old2["꺼진 설정이나 예전 WSL에서는 VM이 끝날 때까지 남음"]
old2 --> sd["wsl --shutdown이 전부를 반환"]
그림 6: 「늘기만 했다」처럼 보이는 것은 주로 캐시(그리고 pageReporting이 꺼져 있으면 프로세스가 해제한 페이지도)이므로, 누수라고 단정하기 전에 반환 경로를 알라.
명시적 상한을 두고 싶다면 %UserProfile%\.wslconfig로 VM 전체의 메모리, CPU 수, 스왑을 제어할 수 있습니다.5
# %UserProfile%\.wslconfig
[wsl2]
memory=8GB
processors=4
swap=2GB
설정을 바꾼 뒤에는 wsl --shutdown으로 VM을 다시 시작해야 반영됩니다. 「상한은 설정, 실제 사용량은 수요를 따른다」는 이 동적 할당은, 다음 주제인 Windows Sandbox에서 더 나아갑니다.
4. Windows Sandbox ── 호스트의 Windows를 재사용한다
4.1. 동적 베이스 이미지: 500 MB의 완전한 Windows
Windows Sandbox는 하이퍼바이저가 격리한 일회용 Windows 데스크톱입니다. 닫으면 모든 것이 사라지고, 다음에는 깨끗한 상태에서 수초 만에 시작합니다.1
첫 수수께끼는 디스크입니다. 완전한 Windows를 기동할 수 있는데, Sandbox의 베이스 이미지는 설치 후 약 500 MB, 배포 시 압축하면 30 MB입니다.2 비밀은 동적 베이스 이미지입니다.
- 대부분의 OS 파일은 불변이므로, 호스트의 복사본을 그대로 공유할 수 있습니다.
- 소수의 가변 파일은 공유할 수 없으므로, 그 깨끗한 복사본을 베이스 이미지 안에 둡니다.
- 시작 시 호스트의 불변 파일과 가변 파일의 로컬 복사본을 합쳐 완전한 Windows 이미지를 조립합니다.2
즉 Sandbox는 Windows의 복사본을 내려받거나 저장하지 않고, 호스트에 이미 설치된 Windows를 재사용해 시작합니다.
flowchart TB
accTitle: 동적 베이스 이미지가 조립되는 방식
accDescr: 호스트 Windows의 불변 OS 파일은 공유하고, 가변 파일만 베이스 이미지에 깨끗한 복사본으로 두며, 둘을 합쳐 Sandbox의 완전한 Windows 이미지를 조립한다
hostw["호스트의 완전한 Windows"] --> imm["불변 OS 파일(대다수)"]
hostw --> mut["가변 OS 파일(소수)"]
imm -->|그대로 공유| img["Sandbox 부트 이미지"]
mut -->|깨끗한 복사본을 보관| img
img --> boot["완전한 Windows로 부트"]
img -.-> size["저장할 것은 약 500 MB뿐"]
그림 7: 디스크 중복을 포기하는 형태는 「또 하나의 Windows를 소유하는」것이 아니라 「호스트의 Windows에서 조립하는」것이다.
그 구성이 다음 수명을 가능하게 합니다. 버려지는 것은 Sandbox 안의 로컬 상태입니다. .wsb 구성 파일에서 호스트의 쓰기 가능 폴더를 매핑했다면, 그곳의 변경은 호스트에 남습니다.6
flowchart TB
accTitle: Windows Sandbox의 수명
accDescr: 시작하면 수초 만에 깨끗한 Windows가 준비되고, 앱 검증이나 실험 후 닫으면 Sandbox 안의 모든 상태가 버려져 다음에도 깨끗하게 시작된다. 다만 쓰기 가능으로 매핑한 호스트 폴더의 변경은 남는다
launch["시작(수초)"] --> clean["깨끗한 Windows"]
clean --> work["앱 검증이나 실험"]
work --> close2["닫기"]
close2 --> discard["Sandbox 안의 모든 상태를 버림"]
discard -.-> mapped["매핑한 쓰기 가능 폴더의 변경은 호스트에 남음"]
discard -->|다음 시작| launch
그림 8: 매번 깨끗하게 돌아갈 수 있는 것은, 가변 부분이 일회용 복사본이고 버리는 일이 설계의 일부이기 때문이다.
4.2. 다이렉트 맵: 같은 ntdll.dll이 같은 물리 페이지
디스크뿐 아니라 RAM도 공유됩니다. Sandbox는 호스트와 같은 OS 이미지를 돌리므로, 「다이렉트 맵」이라는 기법으로 OS 바이너리에 대해 호스트와 같은 물리 메모리 페이지를 씁니다. Sandbox 안에서 ntdll.dll이 메모리에 로드되면, 호스트에 이미 로드된 같은 바이너리와 같은 물리 페이지를 가리킵니다. 호스트의 비밀을 위험에 노출하지 않으면서, 전통적인 VM보다 훨씬 작은 메모리 발자국을 얻습니다.2
「같은 물리 페이지를 여러 사용자가 공유한다」──그건 메모리 연재 제3회에서 따라간, 섹션 객체를 통한 DLL 공유와 같은 생각입니다(「섹션 객체와 카피 온 라이트」). 그 장치는 프로세스 사이의 공유였고, Sandbox는 이를 VM 경계를 넘어 합니다.
flowchart TB
accTitle: 다이렉트 맵을 통한 물리 페이지 공유
accDescr: 호스트의 앱과 Sandbox 안의 앱이 ntdll 같은 OS 바이너리에 대해 같은 물리 메모리 페이지를 공유해 메모리 사용량을 줄인다
happ["호스트의 앱"] --> hva["호스트 측 가상 주소"]
sapp["Sandbox 안의 앱"] --> sva["Sandbox 측 가상 주소"]
hva --> phys["같은 물리 페이지(ntdll.dll 같은 OS 바이너리)"]
sva --> phys
phys -.-> save["OS분의 RAM을 중복할 필요가 없다"]
그림 9: 다이렉트 맵은 프로세스 사이에서 쓰이던 페이지 공유의 생각을 VM 경계 너머에 적용한 것이다.
4.3. 메모리를 빌리고 빌려 주기: VM보다 프로세스에 가깝다
전통적인 VM의 정적 메모리 할당에 대해, Sandbox가 앉는 컨테이너 기술은 호스트와 협력해 자원 할당을 동적으로 정합니다. 호스트가 메모리가 부족하면, 일반 프로세스에서 회수하듯 컨테이너에서도 메모리를 회수할 수 있습니다.2 Hyper-V Dynamic Memory도 설정 범위 안에서 VM의 할당을 늘리고 줄이지만, Sandbox는 한 걸음 더 갑니다. 차이는 호스트의 메모리 관리와 같은 장에서 빌리고 빌려 준다는 점입니다.
flowchart TB
accTitle: 호스트와 Sandbox의 메모리 협력
accDescr: 전통적인 VM의 기본은 정적 크기의 독점 할당이며 조정 수단이 한정된다. Sandbox는 호스트 메모리 압박에 따라 회수 대상이 되어, 일반 프로세스와 같은 장에서 메모리를 빌리고 빌려 준다
pressure["호스트 메모리 압박이 오른다"] --> from{"어디서 회수하는가?"}
from --> proc["일반 프로세스의 Working Set"]
from --> sbx["Sandbox(컨테이너)의 사용량"]
proc --> relief["여유 메모리가 확보된다"]
sbx --> relief
relief -.-> contrast["전통적인 VM은 조정 수단이 한정된다"]
그림 10: 메모리의 대여에서 Sandbox는 VM 측이 아니라 프로세스 측에 서고, 호스트가 곤란할 때 메모리를 내놓는다.
제1회에서 「VM의 성능은 호스트 측에도 달렸다」고 말했지만, 경량 VM에서는 한 걸음 더 갑니다. 메모리 할당 자체가 호스트와의 공동 작업입니다. Sandbox를 「무거운 가상화 제품」이 아니라 「또 하나의 앱」처럼 쓸 수 있는 이유는 이 협력입니다.
업무 앱 검증에 Sandbox를 쓰는 구체적 절차는 이전 글 「Windows 샌드박스로 앱 검증을 빠르게 하는 방법」에서 다룹니다. 이 글은 그 아래의 구조입니다.
5. 컨테이너 ── 격리선을 어디에 긋는가
5.1. 프로세스 격리와 Hyper-V 격리
Windows 컨테이너에는 실행 시 두 가지 격리 모드가 있습니다. 이미지는 공유되고, 시작할 때 플래그로 고릅니다.7
- 프로세스 격리: 여러 컨테이너가 호스트와 커널을 공유하고, 파일 시스템, 레지스트리, 네트워크 포트, 프로세스 ID 공간, Object Manager 네임스페이스 등을 네임스페이스마다 가상화해 격리합니다. Linux 컨테이너와 본질적으로 같은 접근입니다.
- Hyper-V 격리: 각 컨테이너가 고도로 최적화된 VM 안에서 돌고, 사실상의 전용 커널을 가집니다. VM의 존재가 컨테이너와 호스트 사이에 하드웨어 수준 격리를 둡니다.7
네임스페이스를 통한 격리는, 레지스트리 가상화 기사(「Windows의 레지스트리 리다이렉트와 가상화」)에서 본 「같은 API 아래에 다른 현실을 보여 준다」는 기법을 철저하게 한 것으로 설명할 수 있습니다.
flowchart TB
accTitle: 프로세스 격리와 Hyper-V 격리
accDescr: 프로세스 격리에서는 컨테이너가 호스트와 커널을 공유하고 네임스페이스로 격리한다. Hyper-V 격리에서는 각 컨테이너가 최적화된 VM 안에 전용 커널을 갖는다
subgraph pi ["프로세스 격리"]
c1["컨테이너 A"] --> sk1["호스트와 공유하는 커널"]
c2["컨테이너 B"] --> sk1
end
subgraph hi ["Hyper-V 격리"]
c3["컨테이너 C"] --> k3["전용 커널(최적화된 VM 안)"]
c4["컨테이너 D"] --> k4["전용 커널(최적화된 VM 안)"]
end
sk1 ~~~ c3
그림 11: 같은 컨테이너 이미지라도, 격리선을 커널 위에 긋느냐 커널 자체를 나누느냐는 시작 때의 선택이다.
5.2. 어느 쪽을 「보안 경계」라고 부를 수 있는가
이 두 모드의 차이는 성능 이야기만이 아닙니다. Microsoft는 프로세스 격리 컨테이너를 견고한 보안 경계로 보지 않습니다. 보안 경계로서(취약점 대응과 함께) 유지되는 컨테이너는 하이퍼바이저 격리 컨테이너이며, 적대적 멀티테넌트 시나리오에서는 Hyper-V 격리를 골라야 합니다.8
제2회에서 본 VBS도 「커널이 뚫릴 수 있다」를 가정하고 하이퍼바이저 경계로 물러나는 설계였습니다. 같은 기준이 컨테이너 세계에도 적용됩니다. 신뢰할 수 없는 코드를 가두는 선은, 공유 커널의 안이 아니라 하이퍼바이저 경계에 긋습니다.
flowchart TB
accTitle: 코드를 얼마나 신뢰하느냐에 따른 격리 선택
accDescr: 워크로드를 신뢰할 수 있으면 프로세스 격리로 밀도와 성능을 취하고, 코드를 신뢰할 수 없거나 남의 것이면 Hyper-V 격리 컨테이너, 네트워크를 끈 강화된 Windows Sandbox, 격리된 VM 같은 하이퍼바이저 경계를 고른다
trust{"그 코드를 신뢰할 수 있는가?"} -->|예| dens["프로세스 격리(밀도와 속도를 우선)"]
trust -->|아니오 / 남의 코드| bound["하이퍼바이저 경계를 고른다"]
bound --> opt1["Hyper-V 격리 컨테이너"]
bound --> opt2["강화된 Sandbox 또는 격리된 VM"]
그림 12: 격리 모드는 성능 이야기 이전에 보안 이야기이며, 신뢰가 선을 어디에 긋을지를 정한다.
덧붙여, Hyper-V VM 안에서 Hyper-V 격리 컨테이너를 돌리면 하이퍼바이저가 두 층이 됩니다──중첩 가상화입니다. 한 단계의 중첩은 조건을 충족하는 환경(Intel 프로세서와 Windows 10 / Windows Server 2016 이후 호스트, 또는 AMD 프로세서와 Windows 11 / Windows Server 2022 이후 호스트, 그리고 각각에 대응하는 VM 구성 버전)에서 프로덕션으로 지원되며, 추가 전제는 바깥 VM에 가상화 확장을 노출하는 설정입니다(Hyper-V의 Set-VMProcessor에 대한 ExposeVirtualizationExtensions). VM 안에서 WSL2를 도는 것도 같은 방식으로 지원됩니다.9 클라우드의 개발 VM에서 WSL2나 Docker를 쓸 수 있는지도, 그 VM 크기와 구성이 중첩 가상화를 노출하는지로 정해집니다.
flowchart TB
accTitle: 중첩 가상화의 구조
accDescr: 클라우드 VM은 물리 호스트의 하이퍼바이저 위에 앉고, 그 안에서 또 하나의 하이퍼바이저(지원되는 중첩은 한 단계)가 돌아 WSL2와 Hyper-V 격리 컨테이너를 받친다
phys3["물리 호스트의 하이퍼바이저"] --> cvm["클라우드 VM(개발 머신)"]
cvm --> nhv["VM 안의 하이퍼바이저(중첩 수준 1)"]
nhv --> w2["WSL2"]
nhv --> hvc["Hyper-V 격리 컨테이너"]
nhv -.-> limit["지원되는 중첩은 한 단계"]
그림 13: 클라우드 VM 안에서 wsl이 도는 이유는, 중첩 가상화가 한 단계만 공식 지원되기 때문이다.
5.3. 격리와 가벼움의 스펙트럼
지금까지의 등장인물을 한 축에 늘어놓으면 이렇습니다.
flowchart TB
accTitle: 격리 강도와 가벼움의 스펙트럼
accDescr: 프로세스 격리 컨테이너가 가장 가볍지만 커널을 공유한다. WSL2, Sandbox, Hyper-V 격리 컨테이너는 전용 커널을 가진 경량 VM이다(Sandbox는 공유로, WSL2는 목적에 맞춘 커널로 가볍게 한다). 풀 VM이 가장 무겁지만 범용이다
ax["가벼움 ← → 무거움"] ~~~ p1
p1["프로세스 격리 컨테이너(공유 커널)"] --> p2["WSL2, Sandbox, Hyper-V 격리(전용 커널의 경량 VM)"]
p2 --> p3["풀 VM(무엇이든 돈다. 완전한 복사본을 보유)"]
p1 -.-> n1["경계: 네임스페이스"]
p2 -.-> n2["경계: 하이퍼바이저"]
p3 -.-> n3["경계: 하이퍼바이저 + 완전한 독립"]
그림 14: 경량 VM 그룹은 하이퍼바이저 경계는 남기고 중복을 자른 중간해이며, 자르는 방식은 Sandbox의 공유와 WSL2의 목적 맞춤 커널로 갈린다.
6. 직접 확인해 보기
가벼움과 공유는 눈앞의 머신에서 관찰할 수 있습니다.
기동 시간과 메모리의 오르내림(WSL2). 작업 관리자를 연 채로 다음을 시도해 보십시오.
# 체감 기동 시간 (첫 실행은 VM을 시작하고, 두 번째부터는 더 빠르다)
Measure-Command { wsl -e true }
# WSL2 VM의 메모리 사용량 (vmmem / Virtual Machine Memory)
Get-Process -Name vmmem* | Select-Object Name, WorkingSet64
# VM 전체를 끝내고 메모리가 돌아오는 것을 본다
wsl --shutdown
WSL2 안에서 큰 빌드나 파일 작업을 하면 vmmem이 늘고, wsl --shutdown으로 한꺼번에 돌아오는 것을 관찰할 수 있습니다.
파일을 두는 자리에 따른 속도 차이(WSL2). 같은 저장소를 Linux 측(~/repo)과 Windows 측(/mnt/c/repo)에 두고 git status나 전개 시간을 비교하면, 3.2절의 차이가 숫자로 나타납니다.
다이렉트 맵의 배경(Sandbox). Sandbox를 시작하고 호스트 작업 관리자에서 메모리 증가분을 보십시오. 증가분이 「또 하나의 Windows」가 상상하게 하는 것보다 훨씬 작다는 것이, 공유의 효과를 말해 줍니다. 호스트 측 메모리 내역을 더 파고들려면, RAMMap과 VMMap 사용법을 다루는 Sysinternals 도구 기사(「Process Explorer / Handle / VMMap 실전」)가 유용합니다. 다만 이들은 호스트 측 프로세스와 물리 메모리의 분류를 보는 도구이며, 게스트와의 공유 자체를 직접 관찰하지는 않습니다.
컨테이너 격리 모드(Docker / Windows 컨테이너). Windows 컨테이너 환경이 있으면, 같은 이미지를 docker run --isolation=process와 --isolation=hyperv로 시작해 기동 시간과 작업 관리자에서의 모습(프로세스 격리에서는 컨테이너 안의 프로세스가 호스트의 프로세스 목록에 나타납니다)을 비교하면, 격리선이 어디에 있는지 체감할 수 있습니다.7 다만 프로세스 격리는 호스트와 이미지 버전이 맞을 것을 전제로 하며, 클라이언트 OS에서는 개발·테스트 용도로 한정됩니다. Hyper-V 격리는 더 넓은 조합을 허용하므로, 비교는 호환되는 쌍에서 하십시오.10
7. 실무에서 피해야 할 세 가지 오해
7.1. 「WSL2는 느리다」
느린 것은 WSL2가 아니라 OS 경계를 넘는 파일 I/O 경로입니다. 프로젝트를 Linux 측으로 옮기기만 해도 체감이 달라지는 경우가 많습니다.4 반대로 Windows 도구가 만질 파일을 Linux 측에 두는 것도, 같은 이유로 불리합니다. 「쓰는 측과 같은 OS에 둔다」로 판단하십시오.
7.2. 「vmmem이 커지는 것은 메모리 누수다」
WSL2 메모리는 수요에 따라 늘고 줄며, 해제된 부분은 반환됩니다. 현행 WSL에서는 파일 캐시도 autoMemoryReclaim(기본값은 dropCache)이 자동 회수하므로, 「커진 채로 남았다」는 시간이 지나면 해소되는 경우가 많습니다.5 그래도 남으면, autoMemoryReclaim이 disabled로 되어 있지 않은지, 해제분 반환을 담당하는 pageReporting이 꺼져 있지 않은지(또는 예전 WSL이 아닌지)를 확인한 뒤, .wslconfig의 memory로 상한을 명시하거나 세션 경계에서 wsl --shutdown으로 전부를 되돌리십시오. 누수와 누수가 아닌 것을 가르는 사고방식은 메모리 연재 입문회, 「Windows의 「메모리 사용량」은 무엇을 나타내는가」와 같습니다.
7.3. 「컨테이너 안에 있으니 안전하다」
프로세스 격리 컨테이너는 커널을 공유하며, Microsoft의 기준으로는 보안 경계가 아닙니다.8 신뢰할 수 없는 코드나 표본을 돌릴 때는 Hyper-V 격리 컨테이너, Windows Sandbox, 전용 VM처럼 하이퍼바이저 경계가 있는 격리를 고르십시오. 다만 하이퍼바이저 경계가 만능 면책은 아닙니다. Windows Sandbox의 기본 설정은 네트워크 연결이 켜져 있어, 신뢰할 수 없는 앱을 내부 네트워크에 노출할 수 있습니다.1 표본을 돌릴 때는 .wsb 구성 파일에서 네트워크와 클립보드 리다이렉트를 끄거나, 격리된 네트워크의 전용 VM을 써서 격리를 강화하십시오.
8. 정리 ── 연재를 닫으며
제3회의 요점입니다.
- 경량 VM의 가벼움은 「격리를 약하게 한」결과가 아니라 「중복을 멈춘」결과입니다.
- WSL2는 진짜 Linux 커널을 관리되는 경량 유틸리티 VM에서 돌리고, 배포판은 그 VM 안에서 컨테이너로 격리됩니다.3 성능의 규칙은 파일을 쓰는 OS에 두는 것이고, 메모리는 동적으로 늘고 줄며 상한은
.wslconfig로 제어할 수 있습니다.45 - Windows Sandbox는 동적 베이스 이미지로 호스트의 불변 OS 파일을 공유하고, 다이렉트 맵으로 대상 OS 바이너리의 물리 페이지도 공유하므로, 완전한 Windows의 복사본을 갖지 않습니다.2 가변 파일용으로 약 500 MB와, 안에서 돌리는 앱의 메모리는 여전히 필요합니다.
- 컨테이너 격리 모드는 시작 때 고르고, 보안 경계라고 부를 수 있는 쪽은 Hyper-V 격리입니다.78
그리고 연재 전체를 한 장에 두면 이렇습니다.
- 제1회: Windows 아래에 하이퍼바이저 층이 있고, 호스트 OS 자체는 루트 파티션으로 움직입니다. CPU와 메모리(SLAT)의 중재는 이 층이 직접 하고, 합성 디바이스의 I/O는 VMBus 너머의 루트 파티션(VSP)이 중개합니다.
- 제2회: 그 층은 VM끼리 격리하는 데만이 아니라, 같은 OS 안에 커널보다 강한 경계(VTL)를 긋는 데도 쓰입니다. Windows 11의 기본 보안은 그 위에 세워져 있습니다.
- 제3회: 같은 층에서 중복을 자르는 일이 「수초 만에 시작하는 가상 머신」을 가능하게 합니다. 격리선은 남기고, 일상의 도구가 되었습니다.
flowchart TB
accTitle: 연재 전체의 한 장
accDescr: 하드웨어 바로 위의 하이퍼바이저가 제1회, 호스트 Windows 안의 VTL0과 VTL1의 분할이 제2회, 같은 층 위 WSL2·Sandbox·Hyper-V 격리의 가벼움이 제3회다. 프로세스 격리 컨테이너는 호스트 커널을 공유하고, Sandbox는 공유로, WSL2는 목적에 맞춘 커널로 가볍게 한다
hw3["하드웨어"] --> hv3["하이퍼바이저(제1회)"]
hv3 --> rp3["호스트 Windows(VTL 격리는 제2회)"]
hv3 --> lw3["WSL2, Sandbox, Hyper-V 격리(제3회)"]
rp3 --> pc3["프로세스 격리 컨테이너(공유 커널)"]
lw3 -.-> mech3["Sandbox는 공유, WSL2는 목적 맞춤 커널로 가볍게"]
그림 15: 세 회를 쌓으면 현행 Windows 아래 지반의 전체 그림이 된다.
가상화는 더 이상 서버실의 기술도, VM을 세우는 사람만의 기술도 아닙니다. 당신의 Windows 아래 지반에서, 보안과 개발 경험을 조용히 받치고 있는 것──그게 지금의 자리입니다.
관련 기사
- Windows 가상화의 심층(제1회) ── 당신의 Windows는 어디서 움직이고 있는가: 하이퍼바이저와 파티션
- Windows 가상화의 심층(제2회) ── 커널에서도 보이지 않는 메모리: VBS, HVCI, Credential Guard의 구조
- The Depths of Windows Memory (Part 3) — Section Objects and Copy-on-Write: What DLLs and File Mappings Really Are
- Windows 샌드박스로 Windows 앱 개발의 검증을 빠르게 하는 방법 - 관리자 권한 문제, 클린 환경, 권한 부족・리소스 부족의 재현을 실무용으로 정리
- 레지스트리의 32bit/64bit 리다이렉트와 가상화의 함정 ── Wow6432Node와 ‘분명히 썼는데 값이 없다’ 문제
관련 상담 영역
합동회사 코무라소프트에서는 WSL2와 컨테이너를 쓰는 개발 환경 구축, Windows 앱 검증 환경 설계, 가상화 환경의 성능·호환성 조사를 다루고 있습니다.
참고 링크
-
Microsoft Learn, Windows Sandbox. Windows Sandbox가 일회용 VM으로 수초 만에 시작하고 닫으면 모든 것을 버린다는 점, Microsoft 하이퍼바이저로 별도 커널을 돌려 호스트에서 격리한다는 점, 네트워크 연결이 기본으로 켜져 있고 구성 파일에서 끌 수 있다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Windows Sandbox architecture. 동적 베이스 이미지가 호스트의 불변 OS 파일 공유와 가변 파일의 깨끗한 복사본(설치 후 약 500 MB)으로 완전한 Windows 이미지를 조립한다는 점, 전통적인 VM의 정적 메모리 할당에 대해 컨테이너가 호스트와 협력해 동적으로 할당해 호스트가 메모리를 회수할 수 있다는 점, 다이렉트 맵이 ntdll.dll 같은 OS 바이너리를 호스트와 같은 물리 페이지로 쓰게 한다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, What is the Windows Subsystem for Linux?. WSL2가 가벼운 유틸리티 VM 안에서 Linux 커널을 돌린다는 점, 각 배포판이 격리된 컨테이너로 돌며 네트워크 네임스페이스와 커널은 공유하고 PID, 마운트, 사용자 같은 네임스페이스는 분리한다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Comparing WSL Versions. WSL2 커널이 Microsoft가 Stable 브랜치에서 빌드한다는 점, Store 배포 WSL이 OS 이미지에서 떨어진 패키지로 갱신을 받고
wsl --update로 적용한다는 점(예전 인박스 배포에서는 Windows Update), tarball 전개에서 최대 20배 같은 성능 예, OS를 넘나드는 파일 시스템 성능은 WSL1이 더 빨라 파일은 쓰는 OS에 두어야 한다는 점, 메모리가 늘고 줄며 해제분은 반환되지만 캐시는 VM이 끝날 때까지 돌아가지 않을 수 있다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 -
Microsoft Learn, Advanced settings configuration in WSL. .wslconfig의 [wsl2] 절에서 WSL2 VM의 전체 메모리 상한, 프로세서 수, 스왑, pageReporting(기본 사용. 미사용 메모리 검출과 반환을 담당)을 설정할 수 있다는 점, 실험적 설정 autoMemoryReclaim의 기본이 dropCache여서 캐시 메모리가 자동 회수된다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Use and configure Windows Sandbox. .wsb 구성 파일의 MappedFolders가 호스트 폴더를 읽기 전용 또는 쓰기 가능으로 공유할 수 있다는 점에 대해. ↩
-
Microsoft Learn, Isolation Modes. Windows 컨테이너의 프로세스 격리가 호스트와 커널을 공유하고 네임스페이스로 격리한다는 점, Hyper-V 격리가 최적화된 VM 안에 사실상의 전용 커널을 가진다는 점, 시작 시 플래그로 같은 이미지를 어느 모드로든 돌릴 수 있다는 점에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Secure Windows containers. 하이퍼바이저 격리 컨테이너만 보안 경계로 다룬다는 점, 프로세스 격리 컨테이너는 견고한 보안 경계로 보지 않는다는 점, 적대적 멀티테넌트 시나리오에서는 하이퍼바이저 격리를 골라야 한다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, What is Nested Virtualization?. Hyper-V VM 안에서 Hyper-V 격리 컨테이너를 도는 것(한 단계의 중첩)이 프로덕션으로 지원된다는 점, 요건이 Intel 프로세서와 Windows Server 2016 / Windows 10 이후, 또는 AMD 프로세서와 Windows Server 2022 / Windows 11 이후, 그리고 각각에 대응하는 VM 구성 버전이라는 점, 바깥 VM에 가상화 확장을 노출하는 것(ExposeVirtualizationExtensions)이 전제라는 점, Hyper-V VM 안에서 WSL2를 도는 것이 지원된다는 점에 대해. ↩
-
Microsoft Learn, Windows container version compatibility. 프로세스 격리가 호스트와 컨테이너 이미지 버전이 맞을 것을 전제로 한다는 점, Hyper-V 격리가 호스트와 다른 OS 버전의 이미지를 돌릴 수 있다는 점, 클라이언트 OS의 프로세스 격리가 개발·테스트 용도로 한정된다는 점에 대해. ↩
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
Windows 가상화의 심층(제1회) ── 당신의 Windows는 어디서 움직이고 있는가: 하이퍼바이저와 파티션
Hyper-V를 켜면 호스트 Windows 자체가 루트 파티션으로서 하이퍼바이저 위에서 움직입니다. VT-x, SLAT, VMBus의 역할까지, 가상화의 토대를 해설합니다.
Windows 가상화의 심층(제2회) ── 커널에서도 보이지 않는 메모리: VBS, HVCI, Credential Guard의 구조
호환 하드웨어에 대한 클린 설치에서 기본으로 켜지는 VBS는, 하이퍼바이저와 SLAT로 커널보다 강한 격리를 만듭니다. VTL, Secure Kernel, HVCI, Credential Guard의 구조를 해설합니다.
Windows 샌드박스로 Windows 앱 개발의 검증을 빠르게 하는 방법 - 관리자 권한 문제, 클린 환경, 권한 부족・리소스 부족의 재현을 실무용으로 정리
Windows Sandbox로 Windows 앱의 클린 환경 검증을 빠르게 하는 실무 노하우를 정리합니다. .wsb 파일을 용도별로 나누고, 입력은 읽기 전용・출력만 쓰기 가능으로 분리하며, 표준 사용자나 메모리 부족, GPU 없는 상태의 재현까...
Win32 스레드 풀 API ── CreateThreadpoolWork로 「스레드를 만들지 않는」병렬 처리
네이티브 코드에서 CreateThread를 여기저기 만들고 있지는 않은가요. Vista에서 개편된 Win32 스레드 풀 API의 work·timer·wait·io 네 객체, 클린업 그룹, 콜백에서 해서는 안 되는 일까지 1차 정보를 바탕으로 해설...
네임드 파이프의 실무 ── Windows 프로세스 간 통신의 정석을 설계부터 보안까지
Windows 프로세스 간 통신의 정석인 네임드 파이프를 실무 관점에서 정리합니다. 바이트/메시지 모드 선택, 여러 클라이언트를 받는 서버 설계, ACL과 위장 보안, .NET NamedPipeStream까지 1차 정보를 바탕으로 설명합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- WSL2는 VM인가요?
- 그렇습니다. WSL2는 Microsoft가 빌드한 진짜 Linux 커널을 가벼운 유틸리티 VM 안에서 돌립니다. VM은 WSL이 뒤에서 관리하므로, 설계는 사용자에게 VM 설정이나 부트 대기를 의식시키지 않습니다. 각 Linux 배포판은 이 관리되는 VM 안에서 격리된 컨테이너로 돕니다.
- WSL2에서 /mnt/c 아래의 파일 작업이 느린 이유는 무엇인가요?
- WSL2 Linux 커널에서 Windows 측 파일 시스템으로의 접근이, OS 경계를 넘는 파일 공유를 지나기 때문입니다. Linux 파일 시스템(ext4 가상 디스크)에 대한 작업은 빠르므로, 프로젝트 파일은 그것을 다루는 도구와 같은 OS 측에 두는 것이 규칙입니다.
- vmmem 프로세스의 큰 메모리 사용량은 누수인가요?
- 대부분의 경우 누수가 아닙니다. WSL2 메모리는 사용에 따라 늘고 줄며, 프로세스가 해제한 메모리는 기본으로 켜진 pageReporting 설정 아래 Windows로 돌아갑니다. 파일 캐시 페이지도 현행 WSL에서는 .wslconfig의 autoMemoryReclaim(기본값은 dropCache)이 자동으로 회수합니다. 이 설정이 꺼진 환경이나 예전 WSL에서는 메모리가 VM이 끝날 때까지 남을 수 있으며, 그때는 memory 설정으로 상한을 두거나 wsl --shutdown으로 되돌리십시오.
- Windows Sandbox는 수백 메가바이트의 디스크로 완전한 Windows를 어떻게 기동하나요?
- 동적 베이스 이미지라는 장치입니다. 호스트에 이미 설치된 Windows의 불변 OS 파일을 공유하고, 소수의 가변 파일만 깨끗한 복사본으로 둡니다. 그래서 Windows의 전체 복사본을 저장하지 않고도 기동 가능한 완전한 이미지를 조립할 수 있습니다.
- 컨테이너는 VM보다 안전한가요?
- 격리 모드에 달립니다. 프로세스 격리 컨테이너는 호스트와 커널을 공유하며, Microsoft는 이를 견고한 보안 경계로 보지 않습니다. 적대적 코드를 다룰 때는 컨테이너마다 전용 커널을 주는 Hyper-V 격리가 필요합니다.