devAlice
← Windows

Windows 개발 환경 정기 유지관리 — MSYS2·winget·언어 툴체인을 한 명령으로

주 1회 한 번의 실행으로 MSYS2 pacman, winget, Scoop, npm globals, rustup, cargo binaries, pipx, Flutter를 모두 갱신하는 PowerShell 스크립트.

Windows에서 개발 환경을 굴리는 건 늘 의존성이 흩어져 있다. winget으로 받은 IDE, MSYS2로 깐 gcc·make·git, scoop으로 받은 CLI, npm/pip/cargo로 깐 글로벌 도구. 각각 갱신 명령이 다르고, 잊으면 어느 날 Tauri 빌드가 ld.exe: cannot find -lcrypt32 같은 헛소리로 죽는다.

이 글은 그걸 막는 8단계 통합 PowerShell 스크립트다. 주 1회 한 번이면 끝.

TL;DR

  • MSYS2 pacmanwingetScoopnpm -grustupcargo install-updatepipxflutter 8개 순서
  • MSYS2가 1번: Windows에서 빌드 환경의 OS다. 여기 묵으면 네이티브 빌드 줄줄이 깨진다
  • 각 단계는 도구가 없으면 자동 SKIP, 한 단계 실패해도 나머지는 진행
  • 약 100줄짜리 단일 PowerShell 스크립트, update-system.bat으로 더블클릭 실행

왜 MSYS2가 1번인가

Windows의 winget은 사용자 앱(Chrome, Slack 등)이나 개발 도구 최종 산출물을 다룬다. 하지만 실제로 코드를 컴파일하는 환경은 MSYS2 안에 있다 — pacman으로 깐 gcc, make, autotools, openssl 헤더, libsqlite, zlib 등.

이걸 한 달만 묵히면:

  • Rust + Tauri 크로스 컴파일이 OpenSSL 헤더 미스매치로 깨짐
  • Python C extension 빌드 (pip install pillow 등)이 freetype 버전 어긋남으로 실패
  • MinGW 기반 어떤 빌드든 의존 라이브러리 ABI 깨짐

그래서 pacman -Syuu (double u — 다운그레이드까지 동기화)가 항상 첫 단계여야 한다.

사전 조건

  • Windows 10 1709+ / 11 (winget 기본 포함)
  • 8단계 전부 채우려면: MSYS2, pipx, cargo-update, Flutter 미리 설치
  • Scoop은 선택 — 없으면 단계 자동 SKIP

사전 설치 (한 번만)

PowerShell 관리자 권한:

# MSYS2 (~700MB) — 빌드 환경의 OS
winget install MSYS2.MSYS2
 
# pipx (Python 글로벌 패키지 매니저)
python -m pip install --user pipx
python -m pipx ensurepath
 
# cargo-update 확장
cargo install cargo-update
 
# Flutter (~1GB)
winget install Flutter.Flutter
# winget에 없으면 https://docs.flutter.dev/get-started/install/windows

MSYS2 설치 후엔 한 번 MSYS2 셸을 열어서 pacman -Syuu로 베이스 패키지 동기화 권장.

8단계 갱신 대상

#단계명령비고
1MSYS2pacman -Syuu빌드 환경의 OS — 1순위
2wingetwinget upgrade --all시스템 패키지
3Scoopscoop update *있을 때만
4npm globalsnpm update -g글로벌 npm 패키지
5Rust toolchainrustup updatestable channel
6Cargo binariescargo install-update -acargo-update 확장 필요
7pipxpipx upgrade-allPython global tools
8Flutter SDKflutter upgrade현재 채널의 최신

통합 스크립트

저장 2개:

update-system.ps1 (실제 로직):

<#
.SYNOPSIS
    시스템 도구 일괄 업데이트 — Windows
.DESCRIPTION
    빌드 환경 / 패키지 매니저 / 언어 툴체인을 한 번에 갱신.
.NOTES
    실행: update-system.bat (관리자 권한 권장)
    대상: Windows 10/11
#>
 
$ErrorActionPreference = "Continue"
$script:Total = 8
$script:Step  = 0
 
function Step-Header {
    param([string]$Message)
    $script:Step++
    Write-Host ""
    Write-Host ("[{0}/{1}] {2}" -f $script:Step, $script:Total, $Message) -ForegroundColor Cyan
}
 
function Has-Command {
    param([string]$Cmd)
    $null = Get-Command $Cmd -ErrorAction SilentlyContinue
    return $?
}
 
function Write-OK   { param([string]$m) Write-Host "  OK   $m" -ForegroundColor Green }
function Write-Skip { param([string]$m) Write-Host "  SKIP $m" -ForegroundColor DarkGray }
function Write-Warn { param([string]$m) Write-Host "  WARN $m" -ForegroundColor Yellow }
function Write-Fail { param([string]$m) Write-Host "  FAIL $m" -ForegroundColor Red }
 
Write-Host "━━━ 시스템 업데이트 (Windows) ━━━" -ForegroundColor Cyan
 
# 1. MSYS2 (가장 중요 — 빌드 환경의 OS)
Step-Header "MSYS2 (pacman -Syuu) — 핵심"
$msys2Candidates = @(
    "C:\msys64\usr\bin\bash.exe",
    "D:\msys64\usr\bin\bash.exe",
    "C:\tools\msys64\usr\bin\bash.exe"
)
$msys2Bash = $msys2Candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($msys2Bash) {
    Write-Host "  → 사용 경로: $msys2Bash" -ForegroundColor DarkGray
    & $msys2Bash -lc "pacman -Syuu --noconfirm"
    if ($LASTEXITCODE -eq 0) {
        Write-OK "pacman -Syuu 완료 (core 업데이트가 있었다면 한 번 더 권장)"
    } else {
        Write-Fail "pacman -Syuu (core 패키지 갱신 후엔 셸 재시작 후 재실행 필요할 수 있음)"
    }
} else {
    Write-Skip "MSYS2 미설치 (확인: C:\msys64, D:\msys64, C:\tools\msys64)"
}
 
# 2. winget
Step-Header "winget (시스템 패키지)"
if (Has-Command winget) {
    winget upgrade --all --silent --accept-package-agreements --accept-source-agreements
    if ($LASTEXITCODE -eq 0) { Write-OK "winget upgrade --all" }
    else { Write-Fail "winget upgrade --all (일부 패키지가 관리자 권한/대화형 입력 필요)" }
} else {
    Write-Skip "winget 미설치"
}
 
# 3. Scoop (선택)
Step-Header "Scoop (있을 때만)"
if (Has-Command scoop) {
    scoop update
    scoop update *
    Write-OK "scoop update / update *"
} else {
    Write-Skip "scoop 미설치"
}
 
# 4. npm globals
Step-Header "npm globals"
if (Has-Command npm) {
    npm update -g
    if ($LASTEXITCODE -eq 0) { Write-OK "npm update -g" } else { Write-Fail "npm update -g" }
} else {
    Write-Skip "npm 미설치"
}
 
# 5. Rust toolchain
Step-Header "Rust toolchain (rustup)"
if (Has-Command rustup) {
    rustup update
    if ($LASTEXITCODE -eq 0) { Write-OK "rustup update" } else { Write-Fail "rustup update" }
} else {
    Write-Skip "rustup 미설치"
}
 
# 6. Cargo binaries
Step-Header "Cargo binaries (cargo install-update -a)"
if (Has-Command cargo) {
    cargo install-update --version 2>$null | Out-Null
    if ($LASTEXITCODE -eq 0) {
        cargo install-update -a
        if ($LASTEXITCODE -eq 0) { Write-OK "cargo install-update -a" }
        else { Write-Fail "cargo install-update -a" }
    } else {
        Write-Warn "cargo-update 미설치 (설치: cargo install cargo-update)"
    }
} else {
    Write-Skip "cargo 미설치"
}
 
# 7. pipx
Step-Header "pipx (Python global tools)"
if (Has-Command pipx) {
    pipx upgrade-all
    if ($LASTEXITCODE -eq 0) { Write-OK "pipx upgrade-all" } else { Write-Fail "pipx upgrade-all" }
} else {
    Write-Skip "pipx 미설치"
}
 
# 8. Flutter SDK
Step-Header "Flutter SDK (flutter upgrade)"
if (Has-Command flutter) {
    flutter upgrade
    if ($LASTEXITCODE -eq 0) { Write-OK "flutter upgrade" } else { Write-Fail "flutter upgrade" }
} else {
    Write-Skip "flutter 미설치"
}
 
Write-Host ""
Write-Host "━━━ 완료 ━━━" -ForegroundColor Cyan
Write-Host "점검: winget upgrade  /  npm outdated -g  /  pacman -Qu (MSYS2)" -ForegroundColor DarkGray

update-system.bat (더블클릭 진입점):

@echo off
title System Update
 
echo ============================================
echo   System Update (Windows)
echo   MSYS2 + winget + npm + rustup + cargo + pipx
echo ============================================
echo.
 
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0update-system.ps1" %*
 
if %errorlevel% neq 0 (
    echo.
    echo [ERROR] Update failed. Check log above.
) else (
    echo.
    echo [DONE] System update complete.
)
 
pause

PS1 파일은 UTF-8 with BOM으로 저장하세요. Windows PowerShell 5.1에서 한글 출력이 깨지지 않으려면 BOM 필요. VS Code는 우하단 인코딩 클릭 → "Save with Encoding" → "UTF-8 with BOM".

실행 결과 예시

update-system.bat 더블클릭 (UAC 승인) → 첫 실행은 MSYS2 + winget 갱신이 5-10분, 두 번째부터는 1-3분.

━━━ 시스템 업데이트 (Windows) ━━━

[1/8] MSYS2 (pacman -Syuu) — 핵심
  → 사용 경로: C:\msys64\usr\bin\bash.exe
:: Synchronizing package databases...
:: Starting core system upgrade...
...
  OK pacman -Syuu 완료 (core 업데이트가 있었다면 한 번 더 권장)

[2/8] winget (시스템 패키지)
  Microsoft.VisualStudioCode 1.99.2 → 1.100.0
  GitHub.cli 2.65.0 → 2.66.1
  ...
  OK winget upgrade --all

[3/8] Scoop (있을 때만)
  SKIP scoop 미설치

[4/8] npm globals
  OK npm update -g

...

━━━ 완료 ━━━
점검: winget upgrade  /  npm outdated -g  /  pacman -Qu (MSYS2)

자동화 — 작업 스케줄러로 알림만

전체 자동 실행은 비추한다. winget이 가끔 대화형 EULA를 띄우거나, MSYS2 core 업데이트는 셸 재시작이 필요한데 무인 실행 시 멎는다. "잊지 않게 알림만".

작업 스케줄러 PowerShell:

$action = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument '-NoProfile -Command "[System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\"); [System.Windows.Forms.MessageBox]::Show(\"주간 update-system 점검 시간\", \"Dev Maintenance\")"'
 
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Friday -At 10:00am
 
Register-ScheduledTask -TaskName "Dev Update Reminder" `
    -Action $action -Trigger $trigger `
    -Description "주 1회 update-system 실행 알림"

매주 금요일 오전 10시 메시지박스 한 번. 실행은 사람이 결정.

함정

  • MSYS2 core 패키지 갱신 후엔 셸 재시작 + 재실행 필요: pacman이 자기 자신이나 핵심 라이브러리(libcurl, openssl)를 갱신하면 진행 중인 트랜잭션을 중단하고 재실행을 요구한다. 첫 실행이 끝난 뒤 한 번 더 update-system.bat을 돌리는 게 안전.
  • winget 일부 패키지는 대화형 입력 필요: --silent로 대부분 무인 처리되지만 EULA가 새로 들어간 패키지는 멎는다. 그땐 해당 패키지만 수동.
  • Flutter winget 패키지가 없을 수 있음: winget 리포지토리에 Flutter.Flutter가 등록 안 된 시기에는 docs.flutter.dev에서 zip 받아 PATH 추가.
  • Scoop은 선택: 일부러 winget 또는 scoop 한쪽만 쓰는 정책이라면 다른 쪽은 단계가 SKIP된다. 충돌 위험 없음.
  • -Syuu의 두 번째 u: 다운그레이드까지 동기화. MSYS2 리포가 가끔 패키지를 의도적으로 다운그레이드하는데 -Syu만 쓰면 충돌이 누적된다.

Mac 사용자도?

같은 발상으로 brew·언어 툴체인·Flutter·CocoaPods를 한 번에 갱신하는 셸 스크립트 → Mac 개발 환경 정기 유지관리.

정리

  • Windows 빌드 환경은 MSYS2 갱신이 1순위
  • 도구 1개씩 손으로 갱신 → 잊는다
  • 통합 스크립트 1개 → 잊어도 한 번 돌리면 끝
  • 자동화는 알림까지만, 실행은 사람이
  • 매주 1회면 빌드 깨짐·인증서 만료·SDK drift 모두 막을 수 있다

댓글