수정 이력(4건, 최종 수정 2026년 09월 03일)
이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.
- Codex 리뷰에 따라 상담·문의 링크에 /ko/ 로케일 접두를 붙였습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
- 기사 맨 앞에 「이 글의 지식 맵」 절을 추가했습니다. 본문에서 다루는 개념과 그 관계를 요약·그림·상세 페이지 링크로 정리한 것입니다. 본문의 주장은 바꾸지 않았습니다.
- 외부 리뷰(1283건)에 대응해 본문을 업데이트했습니다. 개별 변경 내용은 아래 이력을 참고하십시오.
- 인벤토리 CSV 열의 의미와 형식 예 표를 추가해, 무엇을 보기 위해 만드는 표인지를 명시했습니다. 7의 프로세스와 `WinPSCompatSession`의 관계도를 추가해 「7에 있는 것은 진입점뿐」임을 보이고, ISE 취급(신기능 개발은 종료, 삭제 예정은 없음)과 이전 대상, 어느 7을 넣을지의 판단표, 마이그레이션 완료의 합격 기준과 대조 코드를 추가했습니다.
- 최초 공개
이 글을 인용하기(DOI(등록된 아카이브): 10.5281/zenodo.22174644)
아래 DOI는 이전에 등록된 아카이브를 가리키며 현재 본문과 다를 수 있습니다. 현재 본문을 참조할 때는 이 페이지의 URL을 사용하세요.
Go Komura (2026). 「Windows PowerShell 5.1과 PowerShell 7의 차이 ── 사내 스크립트 마이그레이션 실무 가이드」. 합동회사 코무라소프트. https://comcomponent.com/ko/blog/windows-powershell-5-vs-powershell-7-migration/
- DOI(등록된 아카이브)
- 10.5281/zenodo.22174644
- DOI(마지막 등록 버전)
- 10.5281/zenodo.22174645
「서버에 PowerShell 7을 넣으면 지금 쓰는 스크립트가 깨지지 않나요」「5.1 그대로 두면 안 되는 건가요」── 사내 운영 스크립트를 가진 고객에게서 이런 질문을 받는 일이 늘었습니다. Windows에 처음부터 들어 있는 PowerShell(5.1)과, 따로 설치하는 PowerShell 7. 이름이 같아서 「버전을 올리면 교체된다」고 오해하기 쉽지만, 실제로는 공존하는 별개 제품입니다.
이 관계를 이해하지 못한 채 7을 넣으면, 「설치했는데 아무것도 안 바뀐다(작업은 여전히 5.1로 돈다)」거나, 반대로 「옮겼더니 일본어 파일 연동이 깨졌다」 중 하나를 겪게 됩니다. 특히 후자는 일본어 환경에서 잘 나는 사고이고, 원인은 기본 문자 인코딩의 차이입니다.
이 글에서는 사내 스크립트를 다루는 정보시스템·운영 담당자를 대상으로, 5.1과 7의 관계와 차이를 구조부터 정리하고, 실제로 마이그레이션을 진행하는 절차를 판단표와 함께 정리합니다.
1. 먼저 결론
- Windows PowerShell 5.1과 PowerShell 7은 별개 제품이며, side-by-side로 공존합니다. 5.1은 Windows에 기본 포함되어 .NET Framework 위에서, 7은 별도 설치로 .NET 위에서 동작합니다. 7을 넣어도 5.1은 사라지지 않습니다.12
- Microsoft는 5.1에 신기능을 추가하지 않습니다. 5.1 지원은 Windows 본체의 수명 주기에 묶여 있고, 개발의 중심은 7입니다. 새로 작성하는 스크립트는 7을 기준으로 삼아야 합니다.13
- 실행 파일이 다릅니다. 5.1은
powershell.exe, 7은pwsh.exe입니다. 작업 스케줄러 등의 시작 명령을 바꾸지 않는 한, 기존 구성은 5.1로 계속 동작합니다.45 - 기본 문자 인코딩이 다릅니다. 5.1은 cmdlet마다 제각각이고(Out-File은 UTF-16LE, Get-Content는 ANSI 등), 7은 모두 BOM 없는 UTF-8입니다. 일본어 환경 마이그레이션에서 가장 먼저 걸리는 함정입니다.6
- 7에서 동작하지 않는 모듈에는 Windows 호환 기능이 있습니다.
Import-Module -UseWindowsPowerShell로 백그라운드 5.1 프로세스에 로드한 뒤 remoting으로 사용할 수 있지만, 돌아오는 것은 직렬화된 객체이며 메서드는 호출할 수 없습니다.7 #Requires -Version과$PSVersionTable로 「어느 쪽에서 동작해야 하는 스크립트인지」를 코드에 명시합니다. 의도하지 않은 버전에서 실행되어 조용히 깨지는 사고를, 실행 전에 막을 수 있습니다.89- 마이그레이션은 인벤토리 → 7에서 실행 테스트 → 시작 명령 업데이트의 단계 방식으로 진행합니다. 7 설치는 MSI 또는 winget으로 하고, 업데이트 배포(Microsoft Update를 경유할지)도 처음에 정해 둡니다.524
그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 26건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle
2. 5.1과 7은 어떤 관계인가 ── 대체가 아니라 공존
먼저 전체 그림을 표로 잡습니다.
| 항목 | Windows PowerShell 5.1 | PowerShell 7 |
|---|---|---|
| 제공 방식 | Windows에 기본 포함1 | 별도 설치(MSI/winget 등)2 |
| 기반 | .NET Framework 4.x5 | .NET(7.4는 .NET 8.0 등)54 |
| 실행 파일 | powershell.exe | pwsh.exe4 |
| 설치 위치 | $Env:windir\System32\WindowsPowerShell\v1.05 | $Env:ProgramFiles\PowerShell\75 |
| 이후 개발 | 신기능 추가 없음1 | 개발의 중심. LTS/Stable 릴리스가 있음3 |
| 지원 기간 | Windows 본체의 수명 주기를 따름3 | 기반 .NET의 지원 정책을 따름3 |
7은 5.1을 대체하지 않고, 다른 디렉터리에 설치되어 side-by-side로 동작합니다. 모듈 경로(PSModulePath)도 프로필도 이벤트 로그도 따로 관리됩니다. 7 쪽 PSModulePath에는 5.1의 모듈 경로도 포함되므로, 7에서 기존 모듈의 상당수를 로드할 수 있습니다.52
「지금 어느 쪽에 있는지」는 다음 두 줄로 언제든 확인할 수 있습니다. $PSVersionTable은 PowerShell 버전 정보를 담는 자동 변수입니다.9
# 자신이 어느 PowerShell에 있는지 확인한다
$PSVersionTable.PSVersion # 5.1.x이면 Windows PowerShell, 7.x이면 PowerShell 7
$PSVersionTable.PSEdition # Desktop = Windows PowerShell / Core = PowerShell 7
공식 입장도 분명합니다. Windows PowerShell은 Windows에 기본 포함되는 제품으로, Microsoft는 신기능으로 업데이트하지 않으며, 지원은 사용 중인 Windows 버전에 묶입니다. 한편 PowerShell(7 계열)은 새로운 .NET 위에 구축되고, 릴리스마다 기반 .NET의 지원 정책에 따른 지원 기간이 정해집니다.13 5.1이 내일 당장 사라지는 것은 아니지만, 「앞으로 작성할 것」「앞으로 오래 쓸 것」의 기준은 7에 두어야 한다는 것이 실무 결론입니다.
3. 가장 먼저 걸리는 함정 ── 기본 인코딩 차이와 문자 깨짐
일본어 환경 마이그레이션에서 가장 흔한 문제가 문자 깨짐입니다. 원인은 분명합니다. 기본 문자 인코딩이 둘에서 다릅니다.6
| 작업 | 5.1의 기본값 | 7의 기본값 |
|---|---|---|
Out-File·리다이렉트(>) |
UTF-16LE(BOM 포함)6 | BOM 없는 UTF-86 |
| Set-Content / Add-Content | ANSI(일본어 환경에서는 Shift_JIS)6 | BOM 없는 UTF-8 |
| Get-Content(BOM 없는 파일) | ANSI6 | BOM 없는 UTF-8 |
| Export-Csv | ASCII(일본어가 사라짐)6 | BOM 없는 UTF-8 |
| 스크립트 자체의 해석(BOM 없음) | ANSI 코드 페이지6 | UTF-8 |
# 같은 한 줄이라도, 5.1과 7에서는 만들어지는 파일의 바이트열이 다르다
'こんにちは' | Out-File -FilePath C:\temp\hello.txt
# 5.1에서 실행 → UTF-16LE(BOM 포함) 파일
# 7에서 실행 → BOM 없는 UTF-8 파일
이것이 실무에서 의미하는 바는 두 가지입니다.
첫째, Shift_JIS를 전제로 한 파일 연동은 7로 옮긴 순간 읽기와 쓰기 모두 깨질 수 있습니다. 5.1의 Get-Content는 BOM 없는 파일을 ANSI(일본어 환경에서는 Shift_JIS)로 읽지만, 7은 UTF-8로 읽기 때문입니다. 대책은 파일 입출력 모두에서 -Encoding을 명시하는 것입니다. 7에서는 코드 페이지 번호(-Encoding 932)나 등록 이름으로 지정할 수 있고, 7.4부터는 ansi라는 값도 쓸 수 있습니다.6 CSV 처리의 구체적인 작성법은 같이 공개한 「PowerShell로 Excel·CSV 업무 처리를 자동화하기」에 정리했습니다.
둘째, 스크립트 파일 자체의 저장 형식입니다. BOM 없는 UTF-8로 저장된, 일본어 주석이 들어간 스크립트를 5.1이 읽으면 ANSI로 잘못 해석해 문자 깨짐이나 구문 오류가 납니다. 공식 문서 권장대로 비ASCII 문자가 들어간 스크립트는 BOM 포함 UTF-8로 저장하면, 5.1과 7 모두에서 올바르게 해석됩니다.6
4. 호환성 ── 7에서 동작하지 않는 것과 Windows 호환 기능의 실력
4.1. 무엇이 동작하지 않게 되는가
7은 기존 모듈의 상당수를 그대로 로드할 수 있지만5, 로드되지 않는 것도 있습니다. 공식에서 드는 대표적인 예입니다.
- 더 이상 포함되지 않는 모듈: PSWorkflow/PSWorkflowUtility(워크플로), PSScheduledJob, ISE용 모듈, Microsoft.PowerShell.LocalAccounts 등은 7에 들어 있지 않습니다.4
- 스냅인: 모듈 이전의 오래된 확장 형식인 스냅인은 7에서 지원되지 않습니다.4
- .NET Framework에 밀착된 코드: 7은 기반 .NET이 다르므로, .NET 메서드를 직접 호출하는 스크립트는 동작이 달라질 수 있습니다.54
- 세부 동작 변경:
Export-Csv는#TYPE행을 기본으로 출력하지 않게 되었고,Group-Object는 그룹이 정렬되어 돌아오는 등, 출력에 의존하는 스크립트가 영향을 받는 변경이 있습니다.4
반대 방향의 비호환도 있습니다. 삼항 연산자나 ForEach-Object -Parallel처럼 7에서 추가된 구문·기능을 쓴 스크립트는 5.1에서 동작하지 않습니다.5 「양쪽에서 돌아가게 쓸지」「어느 쪽에서 실행할지를 명시할지」를 스크립트마다 정해야 합니다.
Microsoft 모듈의 지원 상황은 공식 모듈 호환성 페이지에서 확인할 수 있습니다.10
편집 환경(ISE)의 이전 대상도 같이 정해 둡니다. Windows PowerShell ISE는 Windows에서 삭제될 예정이 없고, 보안과 우선순위가 높은 수정도 이어지지만, 신기능 개발은 끝났고 대응하는 것은 PowerShell 5.1 이전뿐입니다.11 즉 7에서 돌릴 스크립트를 ISE에서 작성·실행하는 운영은 성립하지 않습니다. 공식이 안내하는 이전 대상은 Visual Studio Code와 PowerShell 확장입니다. 확장을 넣으면 통합 콘솔에서 사용할 PowerShell 버전을 전환할 수 있습니다(추가 경로도 설정으로 넣을 수 있습니다). ISE에 익숙한 사람을 위해 「ISE 조작감을 VS Code에서 재현하는」 가이드도 있으므로, 전환 안내는 거기서 시작하는 편이 빠릅니다.11 정보시스템 현장은 ISE 사용자가 많으니, 스크립트 마이그레이션 계획과 편집 환경 전환은 같은 타이밍에 안내하십시오.
4.2. Windows 호환 기능(-UseWindowsPowerShell)의 구조와 제약
7에는 5.1에서만 동작하는 모듈을 위한 Windows 호환 기능이 있습니다.
# 7에 대응하지 않는 모듈을 호환 기능을 통해 로드한다(공식 문서의 예)
Import-Module -Name ScheduledTasks -UseWindowsPowerShell
구조는 remoting의 응용입니다. 백그라운드에서 Windows PowerShell 5.1 프로세스가 뜨고, WinPSCompatSession이라는 세션에 모듈이 로드되며, 7 쪽에는 암묵적 remoting으로 생성된 프록시 모듈이 import됩니다. System32 아래의 5.1 전용 모듈은 이름 지정이나 명령 자동 검색에서도 암묵적으로 이 경로로 로드됩니다.7
그림으로 보면 두 프로세스의 관계가 분명해집니다.
flowchart LR
subgraph PS7["pwsh.exe ── PowerShell 7 프로세스"]
SCRIPT["스크립트 본체"]
PROXY["프록시 모듈<br/>암묵적 remoting으로 생성된 진입점.<br/>본체가 아님"]
end
subgraph PS51["powershell.exe ── 뒤에서 뜨는 5.1 프로세스"]
SESSION["WinPSCompatSession<br/>호환 기능으로 로드한 모든 모듈이<br/>하나의 runspace를 공유한다"]
MOD["5.1에서만 동작하는 모듈 본체"]
end
SCRIPT --> PROXY
PROXY -->|"명령 호출을 전달"| SESSION
SESSION --> MOD
MOD -->|"결과"| SESSION
SESSION -.->|"직렬화된 값의 사본만 돌아온다<br/>메서드는 호출할 수 없다"| SCRIPT
그림대로, 7 쪽에 있는 것은 모듈 본체가 아니라 진입점뿐입니다. 「7을 넣으면 전부 7에서 돈다」가 아니라 「7이 5.1에 맡기고, 결과의 사본을 받는다」가 실상이며, 뒤에서 말할 제약은 모두 이 구조에서 나옵니다.
편리하지만, 제약을 모르고 쓰면 조용히 깨집니다. 공식에 적힌 제약은 다음과 같습니다.7
- 주고받는 것은 직렬화된 값이며, 생 객체가 아닙니다. 돌아온 객체의 메서드는 호출할 수 없고, 속성의 스냅샷만 손에 들어옵니다.
- 로컬 Windows에서만 동작하며, Windows PowerShell 5.1이 필요합니다.
- 호환 기능으로 로드한 모든 모듈이 하나의 runspace(하나의 5.1 프로세스)를 공유합니다.
- 일부 모듈(PSScheduledJob 등)은 기본으로 로드가 거부됩니다.
「가져온 결과의 메서드를 호출한다」「파이프라인 도중에 생 객체가 필요하다」 같은 처리는 호환 기능으로는 성립하지 않습니다. 이 경우 파이프라인 전체를 5.1 쪽에서 실행하고 최종 결과만 받는 작성법도 가능하지만7, 복잡해질 정도라면 그 처리만 5.1에 남겨 두는 편이 유지보수하기 쉽다는 것이 실무 감각입니다.
5. 방어적으로 작성하기 ── #Requires와 버전 분기
마이그레이션 기간에는 「어느 쪽에서 실행될지 모르는」 상태가 반드시 생깁니다. 의도하지 않은 버전에서 돌다가 중간에 깨지는 것이 최악이므로, 스크립트 쪽에 방어를 넣습니다.
#Requires 문을 적어 두면, 조건을 충족하지 않는 PowerShell에서는 스크립트가 실행되기 전에 거부됩니다.8
#Requires -Version 7.0
# 이 스크립트는 7 전용(ForEach-Object -Parallel 등을 사용).
# powershell.exe(5.1)로 시작된 경우, 여기서부터는 일절 실행되지 않는다
반대로 5.1 전용 스크립트에는 #Requires -PSEdition Desktop을 적습니다. Desktop이 5.1 계열, Core가 7 계열의 에디션 이름입니다.89
양쪽에서 동작하는 스크립트에서 일부만 동작을 바꾸고 싶을 때는 $PSVersionTable로 실행 시점에 분기합니다.9
# 5.1과 7 양쪽을 지원하는 스크립트에서, 버전 차가 있는 처리만 분기한다
if ($PSVersionTable.PSVersion.Major -ge 6) {
$enc = 932 # 7: 코드 페이지 번호로 Shift_JIS를 지정할 수 있다
} else {
$enc = 'Default' # 5.1: Default = 시스템의 ANSI 코드 페이지
}
Get-Content -LiteralPath $path -Encoding $enc
핵심은 이 명시를 「마이그레이션이 끝난 뒤」가 아니라 「인벤토리 시점」에 넣는 것입니다. #Requires 행이 한 줄 있으면, 그 스크립트가 어느 쪽 환경의 것인지 누구나 알 수 있습니다.
6. 마이그레이션 진행 방법 ── 인벤토리부터 작업 스케줄러 업데이트까지
실제 마이그레이션은 다음 순서로 진행합니다. 한 번에 바꾸는 것은 사고의 원인이므로, 단계 마이그레이션이 원칙입니다.
절차 1: 인벤토리. 스크립트 보관 위치와 작업 스케줄러에서, 동작 중인 .ps1과 시작 명령을 모두 끌어냅니다.
# 작업 스케줄러에서, PowerShell을 시작하는 작업을 모두 끌어낸다
Get-ScheduledTask | ForEach-Object {
foreach ($action in $_.Actions) {
# cmd.exe /c powershell ... 같은 간접 실행도 잡기 위해, 실행 파일과 인수 양쪽을 본다
if ("$($action.Execute) $($action.Arguments)" -match 'powershell|pwsh') {
[pscustomobject]@{
TaskPath = $_.TaskPath # 작업 이름은 폴더 안에서만 고유하므로, 경로도 적어 둔다
TaskName = $_.TaskName
Execute = $action.Execute # powershell.exe인지 pwsh.exe인지
Arguments = $action.Arguments
}
}
}
} | Export-Csv -Path .\ps-tasks.csv -NoTypeInformation -Encoding UTF8
만들어지는 ps-tasks.csv는 4열입니다. 열의 의미와 형식 예를 듭니다(값은 형식의 예이며, 실제 내용은 환경마다 다릅니다).
| 열 | 내용 | 값의 예 |
|---|---|---|
| TaskPath | 작업의 폴더. 작업 이름은 폴더 안에서만 고유함 | \ 또는 \Contoso\Batch\ |
| TaskName | 작업 이름 | DailyReport |
| Execute | 시작할 실행 파일 | powershell.exe / C:\Program Files\PowerShell\7\pwsh.exe / cmd.exe |
| Arguments | 인수 문자열 | -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1 |
이 CSV는 다음 세 가지를 보기 위해 만듭니다. Execute가 powershell.exe인 행은 아직 5.1로 도는 작업, 즉 마이그레이션 대상입니다. Execute가 cmd.exe인 행은 Arguments 안에 PowerShell 시작이 묻혀 있으므로 내용을 열어 확인합니다. 그리고 Arguments에 -File도 -Command도 나오지 않는 행은 위치 지정 그대로 넘기는 호출이므로, 절차 5에서 pwsh로 바꿀 때 해석이 달라집니다(이유는 절차 5). 이 셋을 구분해 두기만 해도 마이그레이션 계획의 분모가 정해집니다.
절차 2: 7 설치. MSI 패키지(배포 관리 도구로 배포하기에 적합) 또는 winget으로 설치합니다.52
어느 판을 어떻게 넣을지는 다음 기준으로 정합니다.32
| 논점 | 선택지 | 판단 기준 |
|---|---|---|
| 어느 판인가 | LTS / Stable | 업무 서버는 LTS. LTS는 .NET LTS에 대응하는 판으로, 업데이트는 중대한 보안 수정과 유지 관리로 한정되어 기존 워크로드에 대한 영향이 최소가 되도록 설계되어 있습니다. Stable은 신기능을 포함하는 대신, 다음 LTS가 나온 뒤 약 6개월이면 지원이 끝납니다3 |
| 클라이언트 PC | winget | 공식이 Windows 클라이언트에서의 권장 방법으로 들고 있습니다2 |
| 서버·다수 배포 | MSI 패키지 | Windows Server와 기업 배포에 최적이라고 명시되어 있습니다. 명령줄 속성으로 업데이트 경로까지 지정할 수 있습니다2 |
| MSIX(스토어) 판 | 주의 | 사용자 단위 설치라 전체 사용자용으로 만들 수 없고, 앱 샌드박스 때문에 WSMan 경유 PowerShell Remoting을 쓸 수 없는 등의 제한이 있습니다. 서버에는 맞지 않습니다2 |
# winget으로 설치. 업데이트도 winget upgrade로 같은 경로를 탄다
winget install --id Microsoft.PowerShell --source winget
# MSI 패키지로 넣고 싶은 경우(서버·배포 관리 도구용)
winget install --id Microsoft.PowerShell --source winget --installer-type wix
winget 자체에도 전제가 있습니다. 7.6.0 winget 패키지부터 winget install --id Microsoft.PowerShell은 기본으로 MSIX 패키지를 넣는 동작으로 바뀌었으므로, MSI가 필요하면 위처럼 --installer-type wix를 붙입니다. 또한 winget은 Windows Server 2022 이전에서는 쓸 수 없습니다(Windows Server 2025의 Desktop Experience 판에는 기본 포함). 서버 군에 대한 배포는 MSI를 전제로 계획하는 편이 무난합니다.2
업데이트 운영도 처음에 정합니다. 7.2 이후 MSI에는 Microsoft Update로 업데이트를 받는 옵션(기본 사용)이 있어, WSUS나 구성 관리 도구의 일반 업데이트 흐름에 태울 수 있습니다.4 관리되지 않은 설치를 방치해 오래된 7이 남는 것이 가장 나쁜 패턴입니다.
절차 3: 7에서 실행 테스트. 인벤토리한 각 스크립트를 pwsh로 실행해, 도는지·출력 파일이 깨지지 않았는지를 확인합니다. 7은 5.1과 공존하므로, 운영 중인 작업을 멈추지 않고 테스트할 수 있는 것이 side-by-side 설계의 이점입니다.2 오류가 나면 4장의 호환성 문제(모듈, .NET API, 동작 변경)를 나눠 봅니다.
「됐다」의 기준을 정해 두지 않으면 테스트가 끝나지 않으므로, 합격 조건을 체크리스트로 만들어 둡니다.
pwsh -NoProfile -File <스크립트>가 끝까지 돌고,$LASTEXITCODE가 0으로 끝난다- 오류 스트림에 아무것도 나오지 않는다(예상된 경고는 내용을 확인하고 허용한다)
- 의존 모듈이 모두 7에서 로드된다(
Import-Module이 통과한다. 호환 기능으로 넘어가지 않았는지도 본다) - 출력 파일 내용이 5.1 판과 일치한다(아래 Compare-Object)
- 출력 파일 인코딩이 수신 측 기대와 같다(3장. Shift_JIS를 전제로 한 연동 대상이 있으면 필수)
- 변경을 수반하는 처리는
-WhatIf로 대상이 5.1일 때와 같은지 확인했다 - 실행 시간이 극단적으로 늘지 않았다(호환 기능을 타면 느려지는 경우가 있다)
출력 비교는 같은 스크립트를 5.1과 7 양쪽에서 돌려 차이를 보는 것이 확실합니다.
# 5.1과 7에서 같은 스크립트를 실행하고, 출력 파일을 비교한다
& "$Env:windir\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -File .\daily-report.ps1
Move-Item .\report.csv .\report-51.csv -Force
& "$Env:ProgramFiles\PowerShell\7\pwsh.exe" -NoProfile -File .\daily-report.ps1
Move-Item .\report.csv .\report-7.csv -Force
# 행 단위 차이. 실행 일시처럼 매번 바뀌는 열이 있으면, 그 열을 빼고 비교한다
Compare-Object (Get-Content .\report-51.csv) (Get-Content .\report-7.csv)
# 바이트 단위로 일치하는지도 본다(BOM이나 줄바꿈 코드 차이는 여기서 드러난다)
(Get-FileHash .\report-51.csv).Hash -eq (Get-FileHash .\report-7.csv).Hash
차이가 나면 먼저 「값이 다른지」「겉모습은 같고 바이트열만 다른지」를 가릅니다. Compare-Object에서는 차이가 없고 Get-FileHash만 불일치라면, 원인은 인코딩 또는 줄바꿈 코드 차이(3장)입니다. 마이그레이션 완료의 정의는 「7에서 예외 없이 끝나는 것」이 아니라, 「5.1일 때와 같은 결과물이 나오는 것」에 두십시오.
절차 4: 어느 쪽에서 실행할지 명시. 테스트에 통과한 것에는 #Requires -Version 7.0을, 5.1에 남길 것에는 #Requires -PSEdition Desktop을 추가합니다(5장).
절차 5: 시작 명령 업데이트. 작업 스케줄러의 동작을 바꿉니다. 여기를 빼먹으면 「7로 옮겼다고 생각했는데 5.1로 계속 돈다」가 발생합니다.
# 변경 전(5.1에서 실행된다):
# powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1
# 변경 후(7에서 실행된다):
# "C:\Program Files\PowerShell\7\pwsh.exe" -NoProfile -File C:\scripts\daily-report.ps1
참고로 pwsh.exe는 첫 번째 위치 지정 매개변수가 -Command에서 -File로 바뀌었습니다. powershell.exe -Command "..."에 해당하는 호출을 기계적으로 치환하면 해석이 달라지므로, -File / -Command를 반드시 명시하십시오.4
실행 정책과 스크립트 서명 취급은 같이 공개한 「PowerShell의 실행 정책과 스크립트 서명」을, 배치 파일(.bat)에서의 이전 판단은 「배치를 PowerShell로 옮겨야 하는가」를 참고하십시오.
7. 실무의 정석(판단표)
| 논점 | 선택지 | 판단 기준 |
|---|---|---|
| 신규 스크립트의 기준 | 5.1 / 7 | 원칙은 7. 5.1은 신기능 추가 없는 현상 유지이고, 개발의 중심은 713 |
| 기존 스크립트 마이그레이션 | 한 번에 전환 / 단계 마이그레이션 | 인벤토리 → 7에서 테스트 → 통과한 것부터 시작 명령 업데이트. side-by-side이므로 단계 마이그레이션이 가능5 |
| 5.1 전용 모듈이 있다 | 이전을 포기 / -UseWindowsPowerShell / 그 처리만 5.1에 남긴다 | 호환 기능은 직렬화 제약(메서드 불가)을 이해한 뒤에. 복잡해지면 5.1에 남기는 편이 유지보수하기 쉬움7 |
| 버전 명시 | 아무것도 하지 않음 / #Requires | 모든 스크립트에 #Requires 또는 실행 시 점검을 넣는다. 의도하지 않은 버전에서의 실행을 실행 전에 막는다8 |
| 파일 입출력 | 기본값에 맡김 / -Encoding 명시 | 항상 명시. 5.1과 7의 기본값 차이로 인한 문자 깨짐을 구조적으로 막는다6 |
| 7의 업데이트 운영 | 수동으로 다시 설치 / MSI의 Microsoft Update 연동 또는 winget | 업데이트 경로를 정한 뒤 배포한다. 방치된 오래된 7이 가장 위험함42 |
8. 정리
- 5.1과 7은 별개 제품이며, side-by-side로 공존합니다. 7을 넣어도 기존 구성은 깨지지 않지만, 반대로 시작 명령을 바꾸지 않는 한 마이그레이션은 전혀 되지 않습니다.
- 5.1은 신기능 추가 없음·지원은 Windows 본체에 묶인 현상 유지 모드이고, 7이 개발의 중심입니다. 신규는 7 기준으로 작성합니다.
- 일본어 환경에서 가장 큰 함정은 기본 인코딩 차이(5.1은 제각각, 7은 BOM 없는 UTF-8)입니다. 입출력의 -Encoding 명시와, 스크립트의 BOM 포함 UTF-8 저장으로 막습니다.
- 7에서 동작하지 않는 모듈은 Windows 호환 기능으로 살릴 수 있지만, 직렬화된 값만 돌아오는 제약이 있습니다. 무리가 되면 해당 처리만 5.1에 남깁니다.
- #Requires와 $PSVersionTable로 「어느 쪽에서 동작하는 스크립트인지」를 코드에 명시하고, 의도하지 않은 버전에서의 실행을 막습니다.
- 마이그레이션은 인벤토리 → 7 설치(MSI/winget) → 실행 테스트 → #Requires 부여 → 작업 스케줄러의 시작 명령 업데이트, 의 단계 방식으로 진행합니다.
관련 글
- PowerShell 명령의 기본 ── 먼저 익힐 조작과 안전한 사용법
- PowerShell 스크립트 응용 ── 로그 조사·아카이브·리포트화를 안전하게 자동화하기
- PowerShell로 Excel·CSV 업무 처리를 자동화하기 ── 집계·대조·장표 출력의 실무 레시피
- VBScript 폐지에 대비하는 VBA·사내 도구 점검 가이드
- .NET Framework에서 .NET으로 이전하기 전 체크리스트
- 배치를 PowerShell로 옮겨야 하는가
관련 상담 영역
합동회사 코무라소프트는 사내 스크립트 자산의 인벤토리와 PowerShell 7로의 단계 마이그레이션 계획·실시, 5.1 전용 모듈에 의존하는 처리의 분리, 「옮겼더니 문자가 깨졌다·동작하지 않게 됐다」 같은 장애 조사를 다룹니다.
참고 링크
-
Microsoft Learn, What is Windows PowerShell?. Windows PowerShell과 PowerShell이 별개 제품인 점, Windows PowerShell은 Windows에 기본 포함되어 .NET Framework 위에 구축되고 최신판이 5.1인 점, Microsoft가 신기능으로 업데이트하지 않으며 지원이 사용 중인 Windows 버전에 묶이는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Install PowerShell 7 on Windows. PowerShell 7이 Windows PowerShell 5.1을 대체하지 않고 새 디렉터리에 설치되어 side-by-side로 실행되는 점, 기본 설치 위치가 $Env:ProgramFiles\PowerShell\7인 점, winget·MSI 등의 설치 방법에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
Microsoft Learn, PowerShell Support Lifecycle. PowerShell 7에 LTS와 Stable 릴리스 구분이 있고 지원 종료일이 기반 .NET의 지원 정책을 따르는 점, Windows PowerShell은 Windows 구성 요소로서 Windows 지원 수명 주기를 따르는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. 실행 파일 이름이 powershell.exe에서 pwsh.exe로 바뀌어 side-by-side를 뒷받침하는 점, 첫 번째 위치 지정 매개변수가 -Command에서 -File로 바뀐 점, PSWorkflow·PSScheduledJob·LocalAccounts 등의 모듈과 스냅인이 7에 포함되지 않는 점, Export-Csv의 #TYPE 기본 생략이나 Group-Object의 정렬된 출력 같은 동작 변경, 각 버전의 기반 .NET, 7.2 이후 MSI의 Microsoft Update 연동 옵션에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11
-
Microsoft Learn, Migrating from Windows PowerShell 5.1 to PowerShell 7. PowerShell 7이 5.1과의 side-by-side 공존을 전제로 설계된 점(다른 설치 경로·PSModulePath·프로필·이벤트 로그), 5.1의 설치 위치와 7의 설치 위치, 기존 모듈의 상당수가 7에서 동작하고 UseWindowsPowerShell로 호환을 보완할 수 있는 점, 삼항 연산자나 ForEach-Object -Parallel 같은 신기능, MSI/ZIP 배포에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
Microsoft Learn, about_Character_Encoding. Windows PowerShell 5.1의 기본 인코딩이 cmdlet마다 일관되지 않은 점(Out-File과 리다이렉트는 UTF-16LE, Set-Content/Get-Content는 ANSI, Export-Csv는 ASCII 등), PowerShell 6 이후가 모두 BOM 없는 UTF-8을 기본으로 하는 점, BOM 없는 스크립트를 5.1이 ANSI로 잘못 해석하므로 비ASCII 문자가 들어간 스크립트는 BOM 포함 UTF-8로 저장해야 하는 점, 코드 페이지 번호 지정이나 7.4의 ansi 값에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11
-
Microsoft Learn, about_Windows_PowerShell_Compatibility. 호환 기능이 백그라운드 Windows PowerShell 5.1 프로세스(WinPSCompatSession)에 모듈을 로드하고 암묵적 remoting으로 프록시 모듈을 생성하는 구조인 점, UseWindowsPowerShell에 의한 명시적 로드와 자동 로드가 모두 있는 점, 직렬화된 값으로 동작하며 생 객체가 아닌 점·로컬 Windows 한정·단일 runspace 공유·기본 로드 거부 목록이라는 제약에 대해. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, about_Requires. #Requires 문이 지정한 PowerShell 버전(-Version), 에디션(-PSEdition Core 또는 Desktop), 모듈 등의 전제 조건을 충족하지 않으면 스크립트 실행 자체를 거부하는 점에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, about_Automatic_Variables. $PSVersionTable이 현재 세션의 PowerShell 버전 상세를 담는 읽기 전용 해시 테이블인 점, PSEdition 속성이 5.1(전체 기능 Windows)에서는 Desktop, 6 이후에서는 Core 값을 가지는 점에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, PowerShell 7 module compatibility. Microsoft 각 모듈(Windows 관리 계열 모듈 포함)의 PowerShell 7 지원 상황이 정리되어 있는 점에 대해. ↩
-
Microsoft Learn, Using Visual Studio Code for PowerShell Development. Windows PowerShell ISE가 Windows에 남지만 신기능 개발은 끝났고 PowerShell 5.1 이전에서만 동작하는 점, Windows에서 삭제될 예정이 없으며 보안과 우선순위가 높은 수정은 이어지는 점, PowerShell 개발에는 Visual Studio Code와 PowerShell 확장을 쓰는 점, 세션 메뉴에서 사용할 PowerShell을 전환하거나 경로를 추가 설정할 수 있는 점, ISE 조작감을 VS Code에서 재현하는 가이드가 있는 점에 대해. ↩ ↩2
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
PowerShell 스크립트의 인수 설계와 모듈화 ── 「돌아가는 스크립트」에서 「남에게 넘길 수 있는 스크립트」로
PowerShell 스크립트를 다른 사람에게 넘길 수 있는 품질로 끌어올리는 절차를 정리합니다. param 블록과 [CmdletBinding()], 입력 검증, 파이프라인 입력, -WhatIf 지원, .psm1 모듈화, 사내 공유와 Git 관리의...
PowerShell 스크립트가 느릴 때 볼 곳 ── 배열·파이프라인·매칭의 핵심
PowerShell 스크립트가 느려지는 대표적인 원인을 정리합니다. 배열의 +=가 O(n^2)가 되는 이유, 파이프라인과 foreach의 차이, 매칭의 해시 테이블화, 파일 I/O 개선, 올바른 측정 방법까지 실무 관점에서 설명합니다.
Write-Host를 그만두기 ── PowerShell의 출력 스트림과 로그 설계
PowerShell 6가지 출력 스트림의 구분 사용, Write-Host가 가진 문제와 올바른 쓰임새, 함수 반환값이 오염되는 원인, -Verbose와 -InformationVariable로 호출 측에서 제어하는 방법, 구조화 로그를 남기는 방법...
PowerShell의 병렬 처리 ── ForEach-Object -Parallel과 Job의 구분
ForEach-Object -Parallel·Start-ThreadJob·Start-Job의 차이와 구분, $using:와 스레드 안전성, ThrottleLimit 정하는 법, 오히려 느려지는 경우까지 실무 관점에서 정리합니다.
PowerShell에서 외부 exe를 올바르게 호출하기 ── 인자의 따옴표·종료 코드·문자 깨짐의 함정
PowerShell에서 robocopy나 사내 EXE를 호출하면 인자가 깨지고, 종료 코드를 얻지 못하며, 출력이 깨집니다. PowerShell 7.3의 인자 전달 변경, 구문 분석 중지 토큰 --%, Start-Process의 용도 나누기까지 ...
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
기존 자산 활용 & 이관 지원
COM / ActiveX / OCX 자산, 네이티브 코드, 32비트 의존성을 유지하면서 단계적인 이관 계획을 지원합니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- Windows PowerShell 5.1과 PowerShell 7은 무엇이 다른가요?
- 별개 제품입니다. 5.1은 Windows에 기본 포함되어 .NET Framework 위에서 동작하며, Microsoft는 신기능 추가를 종료했고 지원은 Windows 본체의 수명 주기를 따릅니다. 7은 .NET(구 .NET Core) 위에서 동작하는 별도 설치 제품으로, 현재 개발의 중심입니다. 7은 5.1을 대체하지 않고 다른 디렉터리에 설치되어 side-by-side로 공존하며, 실행 파일 이름도 powershell.exe와 pwsh.exe로 구분됩니다.
- PowerShell 7을 설치하면 기존 5.1 스크립트가 깨지나요?
- 깨지지 않습니다. 7은 다른 디렉터리(기본값은 Program Files\PowerShell\7)에 설치되고, 모듈 위치와 프로필도 5.1과 따로 관리됩니다. 작업 스케줄러 등에서 powershell.exe를 실행하는 기존 구성은 이전과 같이 5.1로 계속 동작합니다. 그래서 반대로, 7을 넣기만 해서는 마이그레이션이 전혀 되지 않는다는 점에 주의해야 합니다. 7에서 실행하려면 시작 명령을 pwsh.exe로 명시적으로 바꿔야 합니다.
- PowerShell 7에서 기존 스크립트의 문자가 깨지는 이유는 무엇인가요?
- 기본 문자 인코딩이 달라졌기 때문입니다. 5.1은 cmdlet마다 기본값이 다르고(Out-File은 UTF-16LE, Get-Content는 ANSI 등), 7은 모두 BOM 없는 UTF-8입니다. 일본어 환경에서는 Shift_JIS를 전제로 한 파일 연동이 많아서, 기본값 그대로 옮기면 읽기와 쓰기 모두에서 깨질 수 있습니다. 파일 입출력에 -Encoding을 명시하고, 비ASCII 문자가 들어간 스크립트 자체는 BOM 포함 UTF-8로 저장하면 거의 막을 수 있습니다.
- PowerShell 7에서 동작하지 않는 모듈은 어떻게 하면 되나요?
- 먼저 7에서 그대로 Import-Module 해서 동작하는지 확인합니다. 동작하지 않으면 Windows 호환 기능(Import-Module -UseWindowsPowerShell)으로 백그라운드 5.1 프로세스에 모듈을 로드한 뒤, remoting을 통해 7에서 사용할 수 있습니다. 다만 돌아오는 것은 직렬화된 객체라 메서드를 호출할 수 없고, 로컬 Windows에서만 동작하는 제약이 있습니다. 제약에 걸리는 처리는 무리하지 말고 그 부분만 5.1에 남겨 두는 편이 현실적입니다.
- 사내 스크립트를 5.1에서 7로 어떻게 옮기면 되나요?
- 한 번에 바꾸지 말고 단계적으로 마이그레이션합니다. 먼저 작업 스케줄러와 스크립트 보관 위치에서 .ps1을 인벤토리하고, 각각을 7(pwsh)로 실행해 봅니다. 통과한 것부터 #Requires -Version 7을 넣고, 작업 스케줄러의 시작 명령을 powershell.exe에서 pwsh.exe로 바꿉니다. 5.1에서만 동작하는 것은 무리하게 옮기지 않고, 어느 쪽에서 실행해야 하는지를 명시한 채 남겨 둡니다. 7 자체는 MSI 또는 winget으로 설치하고, 업데이트 배포 방법도 함께 정해 둡니다.