PowerShell
Step 9. 실행 정책과 첫 스크립트 — 확인하고 실행하고 원래대로 복원하기
Level 0 — 컴퓨터 조작과 구조의 이해 | 난이도 ★★☆☆☆ | 예상 소요 시간 2–3시간
선수 학습: Step 8. Windows PowerShell 5.1 또는 Windows의 PowerShell 7에서 진행합니다. 인터넷 연결은 필요 없습니다.
- 준비물: 개인 실습용 Windows PC, PowerShell, 텍스트 편집기. 관리자 권한은 필요 없습니다.
- 작업 범위: 새 실습 폴더의 파일과 현재 PowerShell 창의 Process 정책만 변경합니다. 회사·학교의 관리 정책이 설정되어 있으면 승인된 개인 실습 환경을 사용하세요.
- 오늘의 핵심: 실행 정책은 스크립트 실행 조건을 정하는 보조 장치이며 보안 경계가 아닙니다. 허용되거나 서명되었다는 이유만으로 파일을 신뢰하지 않습니다.
스크립트는 명령을 저장한 프로그램입니다. 실행하면 현재 사용자 권한으로 파일 변경이나 네트워크 요청도 할 수 있습니다. 오늘은 날짜와 PC 상태를 조회하는 짧은 파일을 직접 작성하고, 동일한 파일이 정책에 따라 차단되거나 실행되는 과정을 비교합니다. 기존 설정을 “당연히 Restricted일 것”이라고 가정하지 않습니다.
1. 학습 목표
- .ps1 파일을 저장하고 정확한 경로로 실행한다.
- 정책과 적용 범위를 읽고 차단 오류의 원인을 구분한다.
- 현재 창에서만 정책을 바꾸고 기록한 원래 값으로 복원한다.
- 한글을 포함한 파일의 인코딩과 주석을 이해한다.
- checkup.ps1을 실행하고 실제 출력으로 완료 여부를 판단한다.
2. 배경 지식 — 파일, 정책, 범위
2-1. 명령을 파일로 저장하기
명령을 한 줄씩 입력해도 기록 파일이나 변경한 파일은 남을 수 있습니다. 스크립트는 그 명령 자체를 .ps1 파일로 보관하여 다시 읽고 실행하게 합니다. 파일이 같아도 현재 시각, 프로세스 수, 실행 권한에 따라 결과는 달라집니다. 재사용·공유·자동화에 유용하지만 내용을 먼저 읽어야 합니다.
2-2. 정책은 무엇을 판단하나
| 정책 | 의미 |
|---|---|
| Restricted | 대화형 명령은 허용하지만 .ps1 등 스크립트 파일 실행을 제한합니다. |
| RemoteSigned | 인터넷 출처 표시가 있는 스크립트는 신뢰되는 서명이 필요합니다. 그런 표시가 없는 로컬 파일은 작성자가 누구든 서명 없이 실행될 수 있습니다. |
| AllSigned | 로컬에서 직접 만든 스크립트도 신뢰되는 서명이 필요합니다. |
| Unrestricted | 서명 없는 파일도 실행할 수 있으나 출처에 따른 경고가 있을 수 있습니다. |
| Bypass | 실행 정책에 의한 차단·경고를 생략합니다. 오늘은 사용하지 않습니다. |
| Undefined | 해당 범위에 값을 지정하지 않은 상태입니다. 실제 적용값은 별도로 조회합니다. |
디지털 서명은 서명자와 서명 후 변경 여부를 확인하는 데 쓰입니다. 악성 동작이 없다는 보증은 아닙니다. 인터넷 출처 표시는 다운로드 방법과 파일 시스템에 따라 달라집니다. USB에 있다는 이유만으로 자동으로 인터넷 파일이 되거나 안전해지는 것도 아닙니다.
2-3. 범위와 우선순위
MachinePolicy → UserPolicy → Process → CurrentUser → LocalMachine 순으로 우선합니다. 가장 엄격한 값이 무조건 이기는 구조가 아닙니다. Process는 현재 프로세스에만 적용되며 그 환경을 상속하는 자식 프로세스에 전달될 수 있습니다. 그 창을 닫으면 해당 프로세스의 설정은 사라집니다. 이미 실행 중인 다른 창은 별도입니다.
CurrentUser와 LocalMachine 변경은 창을 닫아도 유지됩니다. Scope를 생략하면 LocalMachine을 대상으로 하므로 관리자 권한 오류가 날 수 있습니다. 오늘은 두 범위를 바꾸지 않습니다. Windows PowerShell 5.1과 PowerShell 7의 설정도 따로 관리되므로 사용 중인 창에서 확인하세요.
3. 따라 하기
3-1. 현재 상태를 먼저 기록하기
새 PowerShell 창을 열고 아래 명령을 입력하세요. 이후 복원할 때까지 같은 창을 사용합니다. $previousProcessPolicy에는 원래 Process 값을 보관합니다. 전체 표와 마지막 적용값을 메모해 두세요. 그룹 정책이 감지되면 명령이 중단되며 설정은 바뀌지 않습니다.
$previousProcessPolicy = Get-ExecutionPolicy -Scope Process
Get-ExecutionPolicy -List
Get-ExecutionPolicy
if ((Get-ExecutionPolicy -Scope MachinePolicy) -ne 'Undefined' -or
(Get-ExecutionPolicy -Scope UserPolicy) -ne 'Undefined') {
throw 'Group Policy is configured. Use an approved personal lab.'
}
표는 범위별 설정이고 마지막 단일 값은 실제 적용 정책입니다. 이미 RemoteSigned일 수도 있습니다. 모든 범위가 Undefined여도 실행 정책이 없다는 뜻은 아닙니다. 버전·설정에 따른 기본값을 추측하지 말고 마지막 조회 결과를 기준으로 판단하세요.
3-2. 새 실습 폴더와 hello.ps1 만들기
$scriptlab = Join-Path $HOME ('infosec-step09-' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $scriptlab -ErrorAction Stop
Set-Location -LiteralPath $scriptlab
pwd
표시된 경로를 기록하세요. 무작위 이름의 새 폴더여서 기존 파일을 덮어쓰지 않습니다. 아래 한 줄은 터미널 명령이 아니라 hello.ps1에 저장할 파일 내용입니다.
Get-Date
- 메모장에서 새 문서를 열고 내용을 붙여 넣습니다. 다른 이름으로 저장에서 위 실습 폴더, 파일 이름
hello.ps1, 파일 형식 모든 파일, 인코딩 UTF-8(BOM 포함)을 선택합니다. 편집기에 따라 메뉴 이름은 다를 수 있습니다. - 다른 텍스트 편집기나 파일 작성 도구를 사용해도 됩니다. 아래 확인에서 확장자, 내용, 인코딩이 같은 .ps1 파일이면 됩니다.
- ASCII만 있는 Get-Date는 BOM 없이도 읽히지만, 뒤에서 한글을 추가할 때 5.1과 7 모두에서 읽히도록 UTF-8 BOM을 선택합니다. 파일 저장과 파일 실행은 서로 다른 단계입니다.
Get-Item -LiteralPath .\hello.ps1 | Select-Object Name, FullName, Extension
Get-Content -LiteralPath .\hello.ps1 -Raw -Encoding UTF8
Name이 hello.ps1이고 Extension이 .ps1이어야 합니다. hello.ps1.txt라면 이름부터 고치세요. 내용은 Get-Date 한 줄입니다. 이 확인은 파일을 실행하지 않습니다.
3-3. 의도한 차단을 현재 창에서 재현하기
처음부터 실패한다고 가정하지 않고, 현재 Process만 잠시 Restricted로 설정하여 비교합니다. 아래 블록 전체를 터미널에 붙여 넣으세요. try에서 시도하고, 오류가 나도 finally가 원래 값을 복원합니다. -Force는 여기서 확인 질문을 생략하며 관리자 권한이나 그룹 정책을 우회하지 않습니다.
try {
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Restricted -Force -ErrorAction Stop
Get-ExecutionPolicy
.\hello.ps1
} finally {
Set-ExecutionPolicy -Scope Process -ExecutionPolicy $previousProcessPolicy -Force -ErrorAction Stop
}
Restricted가 출력되고, 스크립트를 실행할 수 없다는 메시지와 PSSecurityException, 흔히 UnauthorizedAccess가 나타납니다. 날짜는 출력되지 않아야 합니다. 오류 문장·경로·표시 언어는 환경에 따라 다릅니다. 같은 오류 ID가 다른 원인에도 쓰일 수 있으므로 전체 메시지와 정책을 함께 확인하세요.
3-4. 현재 창에서 허용하고 실제 파일 실행하기
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force -ErrorAction Stop
Get-ExecutionPolicy -List
Get-ExecutionPolicy
.\hello.ps1
Process가 RemoteSigned이고 적용값도 RemoteSigned인지 확인하세요. 이어서 날짜가 출력됩니다. 같은 파일을 실행했지만 적용 정책이 달라졌습니다. 이후 실습은 이 창에서 진행하고, 끝나면 5장의 복원을 수행합니다. 중간에 그만두면 이 실습 창을 닫아도 Process 설정은 사라집니다.
경로 읽기: .\hello.ps1의 .\는 현재 폴더를 가리킵니다. .hello.ps1은 다른 이름이라 실행 명령이 아닙니다. 단순히 hello.ps1만 입력하면 현재 폴더가 기본 명령 검색 대상이 아니므로 보통 찾지 못합니다. PATH에 등록된 경우 등은 예외입니다. 공백이 있는 경로 문자열은 & 호출 연산자로 실행할 수 있습니다. . .\hello.ps1처럼 점 뒤에 공백을 넣는 dot sourcing은 현재 범위에 변수를 남기는 별도 기능입니다.
3-5. 파일을 여러 줄로 확장하기
hello.ps1의 내용을 아래로 교체하고 UTF-8 BOM으로 저장하세요. 다음 코드 블록 두 개는 각각 파일 내용과 터미널 실행 명령입니다.
$today = Get-Date
"오늘은 $today"
"이 스크립트는 파일에서 실행되었습니다."
.\hello.ps1
세 줄의 코드 중 첫 줄은 변수에 저장하고, 뒤 두 줄이 문자열을 출력합니다. 결과는 두 줄입니다. 시각과 날짜 형식은 환경에 따라 달라집니다. 파일을 다시 실행하면 그때의 날짜를 새로 구합니다.
3-6. 주석을 남기기
hello.ps1을 아래 내용으로 저장하고 이어지는 명령으로 실행하세요. 주석에는 작성일·목적·실행 전 확인 사항을 적었습니다.
# 작성일: 2026-09-10
# 용도: 현재 시각 출력
# 실행 전 확인: 실습 폴더의 hello.ps1
$today = Get-Date
"오늘은 $today" # 화면에 날짜 출력
.\hello.ps1
일반 코드 위치에서 # 뒤는 줄 끝까지 주석입니다. 따옴표 안의 #은 문자열 문자입니다. 아래는 터미널에서 실행하며 출력은 tag#value 한 줄입니다.
"tag#value" # comment
3-7. 미션 — checkup.ps1
새 checkup.ps1에 현재 시각, 실행 중인 프로세스 수, C: 드라이브 여유 공간을 출력하세요. 프로세스가 200개를 초과할 때만 안내 한 줄을 추가합니다. 이 숫자는 조건문 연습용 기준이며 악성 프로세스나 PC 이상을 판정하는 값이 아닙니다. 결과는 화면 출력이며 보고서 파일을 따로 저장하지 않습니다.
4. 연습문제
- Restricted에서도 터미널에서 Get-Date가 실행되는 이유는 무엇인가요?
- hello.ps1이 있는데 명령을 못 찾는다면 어떤 경로·확장자를 확인해야 하나요?
- Scope 없이 Set-ExecutionPolicy를 실행했을 때 권한 오류가 날 수 있는 이유는 무엇인가요?
- RemoteSigned인데 인터넷에서 받은 파일이 차단되는 이유와 먼저 해야 할 확인은 무엇인가요?
- 원래 Process가 Undefined였다면 어떻게 복원해야 하나요?
해설과 완료 기준 · 펼치기/접기
5. 모범 답안과 완료 기준
미션 모범 답안 — 파일 내용
아래를 실습 폴더의 checkup.ps1에 UTF-8 BOM으로 저장합니다.
# checkup.ps1 - 현재 PC의 시각, 프로세스 수, 디스크 여유 공간 조회
"지금 시각: $(Get-Date)"
$proc = @(Get-Process -ErrorAction Stop).Count
"실행 중인 프로세스: $proc 개"
if ($proc -gt 200) { "프로세스가 많습니다 (연습 기준: 200 초과)" }
$drive = Get-PSDrive -Name C -PSProvider FileSystem -ErrorAction Stop
if ($null -eq $drive.Free) { throw 'C: 여유 공간을 조회할 수 없습니다.' }
$freeGiB = [math]::Round($drive.Free / 1GB, 1)
"C: 드라이브 여유 공간: $freeGiB GiB"
같은 PowerShell 창에서 실행합니다.
.\checkup.ps1
출력 확인: 날짜·프로세스 수·여유 공간의 세 줄, 그리고 프로세스 수가 200 초과일 때만 안내 한 줄이 나와야 합니다. @(...).Count는 결과를 배열로 셉니다. 1GB는 PowerShell에서 1,073,741,824이므로 표시는 GiB입니다. C:가 없거나 여유 공간 조회가 실패하면 오류로 중단하며, 모르는 값을 0으로 표시하지 않습니다.
같은 hello.ps1을 전체 경로 문자열로도 실행해 보세요. 앞에서 주석 버전으로 저장했으므로 날짜 문자열 한 줄이 나옵니다.
& "$scriptlab\hello.ps1"
실습 마무리 — 기록한 원래 값으로 복원하기
Set-ExecutionPolicy -Scope Process -ExecutionPolicy $previousProcessPolicy -Force -ErrorAction Stop
Get-ExecutionPolicy -List
Get-ExecutionPolicy
처음 기록한 표와 비교하세요. Process는 원래 값으로, CurrentUser·LocalMachine은 처음 그대로여야 합니다. Undefined였으면 Undefined로 복원합니다. 무조건 Restricted로 바꾸는 것은 원상 복원이 아닙니다. 원래 변수를 잃었거나 어느 창인지 모르겠다면, 다른 업무가 없는 이 실습 창을 닫고 새 창에서 다시 조회하세요. 생성한 .ps1 파일은 창을 닫아도 남습니다.
연습문제 해설
- 1. Restricted는 대화형 명령까지 모두 차단하는 정책이 아닙니다. .ps1 파일 실행 조건과 명령 직접 입력을 구분합니다.
- 2. pwd로 현재 폴더를 보고 Get-Item의 FullName·Extension을 확인합니다. 현재 폴더 파일은 .\hello.ps1처럼 경로를 명시합니다.
- 3. Scope 기본값은 LocalMachine입니다. 권한 오류를 만났다고 무조건 관리자 창을 열지 말고, 오늘의 목적에 맞게 Process인지 확인합니다.
- 4. 인터넷 출처 표시와 서명 요구가 원인일 수 있습니다. 메시지·내용·출처·서명을 확인하세요. 신뢰 근거가 없는 파일은 실행하지 않습니다. 승인된 파일만 차단 해제를 검토하며, 다운로드 폴더를 통째로 해제하지 않습니다.
- 5. 저장한 $previousProcessPolicy로 복원하면 됩니다. Process 변경은 창을 닫아도 소멸합니다. 조직 관리 정책을 다른 범위로 덮어쓰려 하지 않습니다.
완료 체크리스트
- [ ] 두 .ps1 파일의 실제 확장자와 내용을 확인했다.
- [ ] Restricted에서 실제 파일 실행이 차단되고 원래 값이 복원됨을 확인했다.
- [ ] RemoteSigned에서 날짜 및 checkup.ps1 출력이 나왔다.
- [ ] 주석과 문자열 안의 #을 구분한다.
- [ ] 실행 정책이 보안 경계나 안전성 보증이 아님을 설명할 수 있다.
- [ ] 처음과 끝의 정책을 비교했고 영구 범위는 바꾸지 않았다.
6. 자주 막히는 지점
1. 파일이 안 보임
hello.ps1.txt로 저장했거나 다른 폴더에 있을 수 있습니다. 파일 탐색기에서 확장자 표시를 켜고, 터미널의 실제 경로도 확인하세요.
2. 명령을 못 찾음
점만 붙이지 말고 .\hello.ps1을 입력합니다. 경로 오류는 실행 정책을 완화해도 해결되지 않습니다.
3. 정책 변경 권한 오류
Scope Process인지 확인하고 Get-ExecutionPolicy -List로 조직 정책 여부를 봅니다. 그룹 정책이 있으면 승인된 실습 환경을 사용합니다.
4. 바꿨는데 다른 창에서는 실패
Process 값은 해당 프로세스용입니다. 별도 창과 5.1·7은 각각 조회해야 합니다. RemoteSigned도 인터넷 출처가 표시된 미서명 파일은 차단할 수 있습니다.
5. 한글이 깨지거나 파싱 오류
Windows PowerShell 5.1은 BOM 없는 스크립트를 시스템의 기본 ANSI 코드 페이지로 해석합니다. UTF-8과 다르면 문자 깨짐이나 파싱 오류가 생길 수 있습니다. PowerShell 7은 BOM 없는 UTF-8을 지원하므로 항상 오류가 나는 것은 아닙니다. 원래 문자가 보이는 편집기에서 UTF-8 BOM으로 저장하고 다시 확인하세요. 이미 깨진 문자열을 저장하면 BOM만 추가해도 내용이 복구되지는 않습니다.
6. 더블클릭했더니 편집기가 열림
더블클릭 동작은 파일 연결 설정에 따라 다릅니다. “절대로 실행되지 않는다”는 보장은 없습니다. 오늘은 파일을 확인한 다음 PowerShell에서 경로를 명시해 실행합니다.
7. 정리
오늘 만든 것은 재사용할 수 있는 두 스크립트와 설정 전후를 확인하는 습관입니다. 파일 확인 → 현재 정책 기록 → Process만 변경 → 실제 .ps1 실행 → 원래 값 복원 순서를 설명할 수 있어야 합니다. 설정이 허용한다는 사실과 코드가 의도대로 동작한다는 사실은 각각 확인해야 합니다.
실습 검증 기록
2026-09-10, Windows PowerShell 5.1.26100.9444와 PowerShell 7.6.5에서 한·영 파일을 각각 저장하고 실제 .ps1 경로로 실행했습니다. Restricted 차단, RemoteSigned 실행, 한글 UTF-8 BOM, 주석, checkup.ps1 출력과 정책 복원을 확인했습니다. 파일은 자동 작성 도구로 저장했으며 메모장 저장 대화상자의 조작을 검증한 것은 아닙니다. CurrentUser·LocalMachine은 변경하지 않았습니다.
Microsoft: Execution policies · Set-ExecutionPolicy · Scripts and scope · Character encoding
한 단계 더 가까이
수업을 마쳤나요?
본문의 완료 기준을 확인한 뒤 직접 표시하세요.