ZFS on Windows로 게임용 VHDX 풀 만들기: zpool 옵션 고르기와 부팅 시 자동 마운트


OpenZFS on Windows를 게임 저장소로 테스트해봤습니다. 물리 디스크를 통째로 주는 대신 VHDX 파일 안에 풀을 만들고, 부팅할 때 알아서 붙게 했습니다. 옵션을 고르는 과정과 자동 마운트에서 격은 삽질을 정리합니다. (HDD에서 ZFS를 쓸 때의 단점은 예전 글 참고)

🧭 용도

  • 게임 설치용. 업데이트할 때만 쓰고, 플레이할 때는 사실상 읽기만 합니다.
  • Windows에서만 씁니다. 리눅스와 풀을 주고받을 계획은 없음.

📚 공식 권장 vs 옵션 덕지덕지 버전

OpenZFS on Windows 위키의 권장 커맨드는 깔끔합니다.

zpool create -O casesensitivity=insensitive -O normalization=formD -O compression=lz4 -O atime=off -o ashift=12 tank PHYSICALDRIVE1

반면 어떤 블로그에는 이런 풀옵션 버전이 올라와 있었습니다.

zpool create -O casesensitivity=insensitive -o ashift=12 \
  -O acltype=posixacl -O xattr=sa -O atime=off -O relatime=off \
  -O recordsize=256k -O dnodesize=auto -O normalization=formD \
  -o feature@zilsaxattr=disabled -o feature@head_errlog=disabled \
  -o feature@blake3=disabled -o feature@block_cloning=disabled \
  -O compression=zstd-3 zfswin disk

이게 다 필요한지 하나씩 봤습니다.

🔍 옵션별 판단

옵션의미판단
casesensitivity=insensitive대소문자 구분 안 함Windows면 필수
normalization=formD유니코드 파일명 정규화포함
ashift=124K 섹터 정렬명시 권장
atime=off접근 시간 기록 끄기포함
relatime=offatime 완화 모드 끄기atime=off면 의미 없음
acltype=posixacl, xattr=sa리눅스(Samba 등)용 튜닝Windows 전용이면 불필요
dnodesize=autolarge_dnode 기능 활성화다른 구현과의 호환성에 영향, 빼기
recordsize=256k블록 상한(기본 128K)아래에서
compressionlz4 vs zstd-3아래에서

feature 플래그 4개(zilsaxattr, head_errlog, blake3, block_cloning)는 모두 OpenZFS 2.2에서 들어온 기능입니다. 켜져 있으면 2.2보다 오래된 구현에서는 풀을 import할 수 없으니, 구버전 리눅스와 풀을 주고받을 거라면 끄는 게 맞습니다. 공유하지 않는다면 굳이 끌 필요는 없는데, block_cloning만은 2.2 초기에 데이터 손상 이슈가 있었던 기능이라 안정성 차원에서 꺼두었습니다.

🤔 recordsize를 256k로 키울까?

게임 에셋은 수 GB짜리 아카이브(.pak 등)를 쭉 읽는 패턴이라 큰 블록이 유리해 보입니다. 몇 가지 확인해보니:

  • recordsize는 상한선입니다. recordsize보다 작은 파일은 파일 크기에 맞는 블록 하나로 저장되니, 작은 파일 때문에 공간이 낭비되지는 않습니다.
  • ARC도 블록 단위로 캐시합니다. 블록이 커지면 같은 ARC 크기에 담기는 블록 개수는 줄어듭니다.
  • ARC는 기본적으로 압축된 채로 블록을 들고 있습니다. 다만 게임 에셋은 이미 압축된 경우가 많아서 여기서 얻는 건 별로 없습니다.

결론적으로 순차 읽기 위주라 128K든 256K든 체감 차이는 미미할 것 같아서, 기본값 128K를 그대로 두었습니다. 필요하면 나중에 데이터셋 단위로 바꿀 수도 있고요.

🗜️ lz4 vs zstd-3

zstd-3이 압축률은 좋지만, lz4는 해제가 아주 빠릅니다. 읽기가 대부분인 게임 용도에서는 lz4가 맞고, 어차피 에셋이 이미 압축돼 있어서 zstd의 압축률 이득도 크지 않을 겁니다.

✅ 최종 커맨드

VHDX를 만들어 붙이면 새 디스크로 보입니다. PowerShell Get-Disk의 Number가 n이면 PHYSICALDRIVEn입니다. 풀 이름은 vhdxo로 했습니다.

zpool create ^
  -O casesensitivity=insensitive ^
  -O normalization=formD ^
  -O compression=lz4 ^
  -O atime=off ^
  -o ashift=12 ^
  -o feature@block_cloning=disabled ^
  vhdxo PHYSICALDRIVEn

공식 권장에 block_cloning 비활성화만 더한 겁니다.

🔁 부팅할 때 자동으로 붙이기

VHDX는 재부팅하면 분리됩니다. 그래서 부팅 때마다 VHDX를 붙이고 zpool import를 해줘야 합니다. 작업 스케줄러로 하되, 스크립트 파일 없이 인라인으로 끝내고 싶었습니다.

삽질 1: schtasks

처음엔 schtasks로 등록하려고 /tr "powershell -Command \"...\""처럼 썼는데 /sc가 없다는 에러가 났습니다. CMD는 \"를 이스케이프로 보지 않아서 따옴표 짝이 꼬이고, 뒤에 오는 /sc까지 /tr 인자에 삼켜져 버린 겁니다. 게다가 schtasks는 작업 하나에 동작(action)을 하나밖에 못 넣습니다.

PowerShell의 Register-ScheduledTask를 쓰면 동작도 트리거도 여러 개 넣을 수 있고, 동작은 적은 순서대로 실행됩니다. 두 작업을 따로 만들고 지연 시간으로 순서를 맞출 필요가 없어집니다.

삽질 2: Mount-VHD가 없다

Mount-VHD는 Hyper-V PowerShell 모듈에 들어 있어서, 없으면 먼저 켜야 합니다(재부팅 필요).

dism /online /enable-feature /featurename:Microsoft-Hyper-V-Management-PowerShell /all /norestart

Hyper-V 기능을 건드리기 싫다면 diskpart 스크립트(select vdisk file=... / attach vdisk)로 대체할 수 있는데, 이때는 스크립트 파일이 하나 필요합니다.

삽질 3: 시작 트리거만으로는 안 붙었다

제 환경에서는 ‘시작 시’ 트리거만으로는 풀이 안 붙어서 ‘로그온 시’ 트리거도 같이 걸었습니다. 이미 붙어 있을 때 두 번째로 실행되면 Mount-VHD와 import가 “이미 있음” 에러를 내고 끝나니 해는 없습니다.

최종 등록 스크립트 (관리자 PowerShell)

$triggers = @(
    New-ScheduledTaskTrigger -AtStartup
    New-ScheduledTaskTrigger -AtLogOn
)
$actions = @(
    New-ScheduledTaskAction -Execute "powershell" -Argument "-Command Mount-VHD -Path 'O:\zfs.vhdx'"
    New-ScheduledTaskAction -Execute "zpool" -Argument "import vhdxo"
)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest

Register-ScheduledTask -TaskName "ZFS Auto Mount" -Trigger $triggers -Action $actions -Principal $principal

📝 정리

  • Windows 전용 풀이면 공식 권장 옵션 + block_cloning 끄기면 충분합니다. 나머지는 리눅스용 튜닝이거나 구버전 호환용입니다.
  • recordsize는 상한선이고, 순차 읽기 위주라면 기본 128K로도 충분합니다.
  • 읽기 위주면 lz4.
  • VHDX 자동 마운트는 schtasks 대신 Register-ScheduledTask. 동작 여러 개를 순서대로 넣을 수 있습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다