Vrew autosave_backup 96GB 자동 정리 — Windows 자동화 함정 5가지
96.5GB 라는 숫자를 본 순간
한 Windows PC 를 점검할 일이 있었습니다. 평소에 영상 편집을 자주 하시는 분이었고, C 드라이브 여유가 점점 줄어드는데 어디서 누적되는지 모르겠다는 모호한 호소가 시작이었습니다. 처음에는 Windows Update 캐시나 Recycle Bin 정도를 의심했는데, %APPDATA% 폴더를 열어본 순간 위화감이 들었습니다. vrew 한 폴더가 96.5GB 를 점유하고 있었습니다.
프로그램 하나가 OS 드라이브 절반을 먹는다는 사실이 어색했습니다. 일단 폴더를 분해해보기로 했습니다.
autosave_backup 의 정체
PowerShell 로 하위 폴더를 용량 순으로 정렬해봤습니다.
Get-ChildItem "$env:APPDATA\vrew" -Directory |
ForEach-Object {
$size = (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
[PSCustomObject]@{
Folder = $_.Name
SizeGB = [math]::Round($size / 1GB, 2)
}
} | Sort-Object SizeGB -Descending결과는 다음과 같았습니다.
하위 폴더 | 용량 | 정체 |
|---|---|---|
| 48.5 GB | Vrew 자동저장 백업 (.vrew 12 개, 영상 raw 내장) |
| 31.7 GB | Electron Chromium File System API blob |
| 18.1 GB | Electron IndexedDB (STT, 썸네일 메타) |
| ~500 MB | Chromium 렌더 캐시 + ffmpeg 바이너리 |
가장 큰 덩어리는 autosave_backup 이었고, .vrew 파일 12 개의 평균 크기가 한 개당 4GB 였습니다. Vrew 의 .vrew 포맷이 영상 원본을 그대로 내장하는 구조라는 점이 그제서야 분명해졌습니다. 자동 저장이 한 번 일어날 때마다 영상 raw 가 통째로 한 벌 더 쌓이는 셈입니다.
공식이 안 주는 옵션
처음에는 Vrew 안에 보관 개수나 주기 설정이 있을 거라고 생각했습니다. 메뉴를 다 뒤져봤지만 [도움말] → [설정] → [백업 파일 삭제] 라는 전체 삭제 버튼 하나뿐이었습니다. 일부만 남기고 정리하는 옵션도, 자동 저장을 끄는 옵션도, 주기를 늘리는 옵션도 없었습니다.
같은 문제로 막힌 사람이 또 있는지 검색해봤습니다. Google 검색 결과에 Vrew 공식 Q&A 의 “자동 저장&캐시 설정 요청” 이라는 제목 글이 잡혀고, 답변 스니펫에 “검토 중” 이라는 표현이 언뜻 보였습니다. 시점상 가까운 시일 안에 구현될 것 같지는 않다는 인상이었습니다. 같은 검색 결과에 “100G가 순식간에 없어짐” 같은 제목도 잡혔습니다. 다들 같은 문제로 막혀 있는 모양이었습니다. Q&A 게시판 본문 자체는 비로그인 상태에서 열리지 않아 스니펫 수준으로만 확인했습니다.
공식이 옵션을 줄 때까지 기다릴 수도 있겠지만, 그 사이 디스크는 계속 차오릅니다. 외부에서 한 겹 덮어두는 쪽이 합리적이라는 결론이 들었습니다.
자동 저장 주기 실측
스크립트를 짜기 전에 한 가지가 걸렸습니다. 자동 저장 주기가 어느 정도인지 공식 문서에 명시가 없다는 점이었습니다. 5 분인지 10 분인지, 변경 이벤트 기반인지 알 수 없으면 "active 한 백업까지 같이 지워버리는" 사고가 날 수 있습니다.
그래서 같은 폴더의 .vrew 12 개에 대해 LastWriteTime gap 을 계산해봤습니다. 같은 세션으로 추정되는 60 분 이내 gap 만 골라 정리한 결과는 다음과 같았습니다.
n = 7 (same-session gap, ≤ 60 min)
min = 1.8 분
max = 51.9 분
avg = 23.2 분5 분 / 10 분 같은 고정 주기가 아니었습니다. 영상 편집 중 변경이 누적되면 다양한 간격으로 백업이 떨어지는 모양이었습니다. 가장 긴 gap 이 약 52 분이라는 점이 다음 설계의 기준이 되었습니다.
스크립트 설계 — 이중 가드 + OS file lock 3 겹
삭제 조건을 다음 한 줄로 잡았습니다.
삭제 = (mtime ≥ OlderThanHours 시간)
AND (최근 KeepCount 개 보존 후보 아님)
AND OS file lock 실패 시 catch + skip세 겹의 이유는 각각 다음과 같습니다.
가드 | default | 이유 |
|---|---|---|
| 1 시간 | active session 의 백업 회피. 실측 max 51.9 분 대비 약 16% 마진 |
| 3 | 크래시 복구 보험. 시간 룰을 통과해도 최근 3 개는 무조건 보존 |
OS file lock | 자동 | Vrew 가 쥐고 있는 파일은 |
OS file lock 이 사실상 마지막 안전망입니다. 시간 가드와 KeepCount 가 둘 다 뚫려도, Vrew 가 현재 쓰고 있는 파일은 Windows 가 막아주기 때문에 "활성 백업을 지우는" 사고는 구조적으로 일어나기 어렵습니다.
Task Scheduler 에 매 30 분 등록
한 번 정리해서 끝낼 일이 아니라 매번 차오를 일이었습니다. Task Scheduler 로 30 분 간격 실행을 잡았습니다.
$trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date).Date.AddHours(9)
$trigger.Repetition = (New-ScheduledTaskTrigger -Once -At (Get-Date).Date.AddHours(9) `
-RepetitionInterval (New-TimeSpan -Minutes 30) `
-RepetitionDuration (New-TimeSpan -Hours 24)).Repetition매일 오전 9 시 트리거가 갱신되고, 그 트리거가 24 시간 동안 30 분 간격으로 반복합니다. 결과적으로 사실상 영구 30 분 반복과 동등합니다. 왜 이렇게 우회한 패턴이 필요했는지는 함정 섹션에서 다시 다루겠습니다.
실증된 함정 5 가지
여기서부터가 이 글의 진짜 가치라고 생각합니다. 큰 그림은 평범한 스크립트 + 스케줄러였지만, 작은 가장자리에서 다섯 번 막혔습니다. 다음에 같은 작업을 하실 분을 위해 적어둡니다.
함정 1 — PowerShell 5.1 의 BOM 의존성
Windows 10 / 11 에 기본 설치된 PowerShell 5.1 은 .ps1 파일에 UTF-8 BOM 이 없으면 시스템 default 인코딩으로 fallback 합니다. 한국 환경에서는 CP949 입니다. 한글 주석이나 문자열을 CP949 로 해석하다가 깨지면, 깨진 바이트가 PowerShell 파서에게 정체 모를 토큰으로 보입니다.
증상은 이렇게 나옵니다.
식 또는 문에서 예기치 않은 'MB' 토큰입니다.
식 또는 문에서 예기치 않은 'DEL:' 토큰입니다.실제 코드 안에 MB 토큰은 없습니다. 한글 문자열이 깨지면서 우연히 만들어진 바이트 시퀀스를 파서가 그렇게 읽은 것입니다. 처음 봤을 때는 어디가 잘못된지 짚기 어려웠습니다.
흥미로운 점은 같은 파일을 iwr <raw URL> | iex 로 받아서 실행하면 잘 동작했다는 것입니다. Invoke-WebRequest 경로는 HTTP 응답을 UTF-8 로 처리하기 때문에 BOM 유무에 영향을 받지 않습니다. 문제는 파일을 직접 전송했을 때 (Taildrop, USB, OneDrive 등) 발생합니다. fix 는 단순합니다.
{ printf '\xef\xbb\xbf'; cat vrew-cleanup.ps1; } > new.ps1 \
&& mv new.ps1 vrew-cleanup.ps1확인은 file 명령으로 합니다.
file vrew-cleanup.ps1
# 기대: UTF-8 (with BOM) text함정 2 — Task Scheduler RepetitionDuration out of range
처음에는 "사실상 영구 반복" 을 표현하기 위해 [TimeSpan]::MaxValue 나 New-TimeSpan -Days 36500 을 넣어봤습니다. 둘 다 다음과 같이 실패합니다.
Register-ScheduledTask : The task XML contains a value
which is incorrectly formatted or out of range.Task Scheduler 내부의 XML 스키마가 허용하는 Duration 의 상한을 넘는 값이라 그렇습니다. 검색을 좀 해보다가 결국 다음 패턴으로 우회했습니다.
$trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date).Date.AddHours(9)
$trigger.Repetition = (New-ScheduledTaskTrigger -Once -At (Get-Date).Date.AddHours(9) `
-RepetitionInterval (New-TimeSpan -Minutes 30) `
-RepetitionDuration (New-TimeSpan -Hours 24)).RepetitionDaily 트리거가 매일 새로 살아나면서 24 시간 안에 30 분 간격으로 반복하므로, 효과적으로는 영구 30 분 반복과 같아집니다. 위 도입부에서 우회 패턴을 먼저 보인 이유가 여기에 있습니다.
함정 3 — Private repo + Invoke-WebRequest 401/404
install 스크립트 안에서 Invoke-WebRequest 로 GitHub raw URL 의 .ps1 을 받아오는 흐름을 짰는데, private repo 일 때는 인증 헤더가 없어서 404 가 돌아옵니다. 처음에는 401 을 기대했지만 GitHub 의 raw 도메인은 private 자원에 대해 의도적으로 404 를 응답합니다. (resource 존재 자체를 가리기 위함입니다.)
이 시점에는 레포가 아직 private 였습니다. 해결은 "원격 다운로드를 항상 시도하기 전에 같은 디렉토리의 sibling .ps1 부터 본다" 였습니다.
$siblingScript = Join-Path $PSScriptRoot 'vrew-cleanup.ps1'
if (Test-Path $siblingScript) {
# 로컬 sibling 사용 (Taildrop / USB / 오프라인 호환)
$scriptPath = $siblingScript
} else {
# public 일 때만 원격 다운로드 fallback
Invoke-WebRequest -Uri $ScriptUrl -OutFile $localPath -UseBasicParsing
$scriptPath = $localPath
}$PSScriptRoot 를 활용하면 install 스크립트와 같은 폴더에 있는 .ps1 을 안전하게 가리킬 수 있습니다. 결과적으로 private 여부와 무관하게 동작하는 install 스크립트가 됐습니다.
함정 4 — bash echo 의 \v 함정
이 함정은 한참을 헤맸습니다. macOS 에서 PowerShell 명령을 base64 로 인코딩해 Windows 로 던지는 흐름이 있었는데, 그 안에 $env:APPDATA\vrew 같은 경로 문자열이 들어 있었습니다.
echo 의 escape 해석에서 \v 가 vertical tab (ASCII 0x0B) 으로 치환됩니다. Roaming\vrew 가 Roaming<VT>rew 로 깨지고, 그걸 받은 PowerShell 은 경로를 인식하지 못 합니다. 처음에는 인코딩 문제로 의심했지만, 실제 원인은 그 한 글자 escape 였습니다.
미묘한 점은 대문자 \V 는 escape 가 아니라는 점입니다. case-sensitive 가드 한 줄이 한 시간을 잡아먹었습니다. fix 는 echo 를 버리는 것입니다.
ENCODED=$(printf '%s' "$SCRIPT" \
| iconv -f UTF-8 -t UTF-16LE \
| base64 \
| tr -d '\n')printf '%s' 는 %s 뒤의 인자를 escape 해석 없이 그대로 출력합니다. 비슷한 자동화 스크립트에서는 가능하면 처음부터 echo 를 안 쓰는 습관이 안전합니다.
함정 5 — Elevated SSH + New-Item Directory → SYSTEM-only ACL
다섯 가지 중 가장 의외였던 함정입니다. Windows OpenSSH 서버를 통해 SSH 로 들어가서 install 스크립트를 elevated 권한으로 돌렸을 때 발생했습니다.
OpenSSH 서버는 Windows 에서 NT AUTHORITY\SYSTEM 계정으로 동작합니다. SSH 세션 자체가 elevated 로 시작되는데, 이 상태에서 New-Item -ItemType Directory 로 폴더를 만들면, 그 폴더의 ACL 이 부모 ($LOCALAPPDATA) 의 권한을 상속받지 않고 SYSTEM 만 FullControl 로 잡힙니다.
진단은 Get-Acl 한 줄로 확인할 수 있습니다.
Get-Acl $env:LOCALAPPDATA\windows-bootstrap |
Format-List Owner, AccessToString출력은 이렇게 나옵니다.
Owner : 도메인\사용자
AccessToString : NT AUTHORITY\SYSTEM Allow FullControl같은 사용자명임에도 사용자 entry 가 ACL 에 없습니다. 결과적으로 이후의 Copy-Item 이 PermissionDenied 로 막힙니다. 처음에는 antivirus 나 OneDrive 동기화를 의심했지만, 원인은 SSH 가 만든 폴더의 권한 상속 단절이었습니다.
해결은 별도 디렉토리를 새로 만드는 대신, 원본 sibling 의 경로를 Task action 의 -File 인자로 직접 넘기는 것이었습니다.
$scriptPath = Join-Path $env:USERPROFILE "Downloads\vrew-cleanup.ps1"
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -OlderThanHours 1 -KeepCount 3"폴더를 새로 만들지 않으니 ACL 문제 자체가 발생하지 않습니다. install 스크립트의 복잡도도 한 단계 줄었습니다.
검증 결과
등록된 Task 의 상태를 확인하고, 첫 실행을 강제로 트리거해봤습니다.
Task State : Ready
LastTaskResult : 0
NextRunTime : 22:00
NumberOfMissedRuns : 0첫 정리에서 35.65GB 가 회수됐습니다. .vrew 12 개가 3 개로 줄었고, autosave_backup 폴더가 47.38GB 에서 11.73GB 로 안정화됐습니다. 이후 30 분 단위로 트리거가 도는 동안 폴더 크기는 약 12GB 근방에서 더 늘지 않고 유지됐습니다.
정리 — 공식이 안 주는 옵션을 외부에서 메우기
돌이켜 생각해보면 이번 작업의 본체는 PowerShell 스크립트 한 개와 Task Scheduler 설정 한 줄이었습니다. 복잡한 코드는 거의 없었습니다. 그럼에도 다섯 번 막혔던 이유는, Windows 자동화의 함정이 대부분 큰 그림이 아니라 BOM 유무, vertical tab, ACL 상속 단절 같은 작은 가장자리에 숨어 있기 때문이라는 생각이 들었습니다.
공식이 옵션을 줄 때까지 기다리는 것도 한 방법이지만, 그 사이에 디스크가 100GB 씩 차오르는 상황이라면 외부에서 한 겹 덮어두는 쪽이 합리적입니다. 이번 사례에서는 PowerShell 과 Task Scheduler 의 조합이 그 한 겹의 역할을 했습니다.
스크립트와 install 도구는 별도 레포에 정리해두었지만, 비공개로 운영 중이라 링크는 박지 않았습니다. 대신 핵심 코드 조각은 이 글의 단락들에 그대로 옮겨두었으니 그 코드 자체를 복사해 쓰셔도 동일한 결과를 만드실 수 있습니다. 통합 install 스크립트 전체가 필요하시면 댓글이나 이메일로 가볍게 문의 주시면 되겠습니다. 같은 문제로 헤매시는 분께 작은 단축키가 되었으면 합니다.
관련 글
Vrew %TEMP% 18GB 자동 정리 — 5-layer 가드와 OS file lock 의 한계
1편 autosave 정리 후일담입니다. Vrew %TEMP% 18.2GB 를 PowerShell 5-layer 가드로 자동 정리하려 했지만 OS file lock 이 회수를 0 으로 만든 과정, Electron helper 백그라운드 잔존 진단까지 함께 정리했습니다.
Vrew 하드웨어 가속, 켜야 하나 꺼야 하나 — 지인 노트북에 SSH 로 들어가 확인한 13개 sub-feature 이야기
"Vrew 의 하드웨어 가속, 켜야 하나 꺼야 하나" 라는 한 줄짜리 질문에서 시작해, 지인 노트북에 SSH 로 들어가 Chromium 의 13개 sub-feature 와 4개 레이어를 직접 확인해본 기록. NVENC 가 살아 있는 환경의 결론과, 흔한 오해.
Vrew 내보내기가 0%에서 멈출 때 — 로그가 알려준 진짜 원인
Vrew 내보내기가 특정 프로젝트만 0%에서 멈췄습니다. 처음엔 투명 GIF의 알파 채널이 원인이라 확신했지만, 과거 성공 로그에도 투명 GIF가 멀쩡히 들어 있었습니다. 가설을 버리고 성공·실패 GIF를 나란히 비교하니 진짜 차이는 길이였습니다. 안 되는 사례만이 아니라 되는 사례를 함께 봐야 진짜 변수가 드러난다는 것을, 로그를 따라가며 다시 배운 기록입니다.