PowerShell 스크립트나 함수를 작성할 때는 종종 매개변수를 통해 사용자 입력을 받고자 합니다. 이러한 매개변수가 받아들일 값의 범위를 제한하지 않으면 부적절한 값이 제공될 수 있는 상황이 발생할 수 있습니다. 이 문서에서는 PowerShell의 ValidateSet 매개변수 유효성 검사 속성을 사용하여 정의한 값만 허용하도록 제한하는 방법을 알아보겠습니다.
PowerShell 스크립트나 함수를 작성할 때는 다양한 유효성 검사 속성을 사용하여 매개변수에 제공된 값이 허용 가능한지 확인하고, 그렇지 않은 경우 사용자에게 알릴 수 있습니다.
이 문서에서는 ValidateSet 유효성 검사 속성에 초점을 맞추어 설명합니다. ValidateSet의 기능, 코드에서 ValidateSet을 사용해야 하는 이유, 그리고 사용자가 유효한 매개변수 값을 제공할 수 있도록 도와주는 탭 완성 기능에 대해 알아보겠습니다.
PowerShell ValidateSet: 간략한 개요
ValidateSet은 매개변수 속성으로, 해당 매개변수의 값을 정의한 요소들로 제한할 수 있습니다.
예를 들어, Active Directory 도메인 컨트롤러와 작업하는 스크립트가 있다고 가정해보겠습니다. 이 스크립트에는 도메인 컨트롤러의 이름을 지정하는 매개변수가 있습니다. 스크립트가 필요한 값들을 미리 알고 있을 때 사용자가 “foobar”와 같은 값을 사용할 이유는 없습니다. ValidateSet을 사용하면 이러한 가능성을 제한할 수 있습니다.
요구 사항
이 문서는 학습 안내서가 될 것입니다. 따라하기를 계획한다면 다음이 필요합니다:
- Visual Studio Code 또는 다른 코드 편집기. 저는 Visual Studio Code를 사용할 것입니다.
- 이 문서에서 대부분의 코드에는 최소한 PowerShell 5.1이 필요합니다. 한 섹션에서는 PowerShell 6.1 이상이 필요하며, 해당 부분에 도달하면 식별하겠습니다.
이 문서의 모든 코드는 다음 환경에서 테스트되었습니다:
Operating System | PowerShell Versions |
---|---|
Windows 7 SP1 | 5.1, Core 6.2 |
Windows 10 1903 | 5.1, Core 6.2 |
Linux Mint 19.2 | Core 6.2 |
ValidateSet 주변 개념을 설명하기 위해 Get-PlanetSize.ps1이라는 작은 스크립트를 작성할 것입니다. 이 스크립트는 태양계의 행성 크기에 관한 정보를 반환합니다.
처음에는 간단한 스크립트로 시작하여 사용자의 입력을 처리하고 가능한 매개변수 값을 쉽게 찾을 수 있도록 기능을 점진적으로 개선할 것입니다.
시작하기
시작하려면 먼저 아래의 PowerShell 코드를 좋아하는 텍스트 편집기에 복사하여 Get-PlanetSize.ps1로 저장하십시오.
PowerShell 프롬프트에서 스크립트를 실행하면 다음과 같은 결과가 출력됩니다:
정보는 제공되지만 유연성은 부족합니다. 모든 행성의 정보가 반환되며, Mars의 정보만 필요한 경우에도 마찬가지입니다.
어쩌면 당신은 모든 행성을 반환하는 대신 단일 행성을 지정할 수 있는 기능을 원할지도 모릅니다. 이를 위해 매개변수를 도입하여 이를 실현하는 방법을 살펴보겠습니다.
매개변수를 사용하여 입력 받기
스크립트가 매개변수를 받을 수 있도록 하려면 스크립트 상단에 Param()
블록을 추가하세요. 매개변수의 이름을 Planet
으로 지정하세요. 적절한 Param()
블록은 아래와 같습니다.
아래 예시에서 [Parameter(Mandatory)]
라인은 스크립트에 항상 행성 이름이 제공되도록 보장합니다. 행성 이름이 누락된 경우 스크립트에서 입력을 요구합니다.
이제 이 Planet
매개변수를 스크립트에 통합하기 위해 $planets.keys | Foreach-Object {
라인을 $Planet | Foreach-Object {
로 변경하는 것이 가장 간단합니다. 이제 이전에 정적으로 정의된 해시테이블에 의존하는 대신 Planet
매개변수의 값을 읽어옵니다.
이제 스크립트를 실행하고 Planet
매개변수를 사용하여 특정 행성에 대한 정보만 확인할 수 있습니다.
훌륭합니다. 스크립트 완료? 아마도 그렇지 않을 수도 있습니다.
선택 옵션이 너무 개방되어 있습니다.
Get-PlanetSize.ps1을 사용하여 행성 Barsoom의 지름을 찾으려고 하면 어떻게 될까요?
음, 이상합니다. Barsoom은 행성 목록에 없지만 스크립트가 실행됩니다. 이를 어떻게 해결할 수 있을까요?
문제는 스크립트가 유효한 값인지 여부에 관계없이 모든 입력을 수용하고 사용한다는 것입니다. 스크립트는 Planet
매개변수에 어떤 값이 허용되는지 제한할 방법이 필요합니다. ValidateSet을 사용해보세요!
특정한 값만 사용하도록 보장하기
A ValidateSet list is a comma-separated list of string values, wrapped in single or double-quotes. Adding a ValidateSet attribute to a script or function parameter consists of adding a line of text to the Param()
block, as shown below. Replace the Param()
block in your copy of Get-PlanetSize.ps1 with the one below and save the file.
다시 Planet 매개변수에 Barsoom
을 사용하여 스크립트를 실행해보세요. 이제 유용한 오류 메시지가 반환됩니다. 이 메시지는 무엇이 잘못되었는지 구체적으로 알려주며, 매개변수에 대한 가능한 값 목록도 제공합니다.
PowerShell의 ValidateSet을 대소문자 구분하도록 만들기
기본적으로 ValidateSet 속성은 대소문자를 구분하지 않습니다. 즉, 허용된 목록에 대소문자 구분 없이 어떤 문자열이든 허용합니다. 예를 들어, 위의 예제는 Mars
와 mars
를 모두 쉽게 허용합니다. 필요한 경우, ValidateSet을 대소문자 구분하도록 강제할 수 있습니다.
ValidateSet의 IgnoreCase
옵션은 유효한 값 목록과 매개변수에 제공된 값이 정확히 일치하는지를 확인하는 유효성 검사 속성입니다. 기본적으로 IgnoreCase
는 $True
로 설정됩니다(대소문자 구분 안 함). 이 값을 $False
로 설정하면 Get-PlanetSize.ps1
의 Planet
매개변수에 mars를 값으로 제공하는 경우 오류 메시지가 생성됩니다.
아래의 예시처럼 유효한 값 목록의 끝에 IgnoreCase
옵션에 $true
값을 할당하여 IgnoreCase
옵션을 사용할 수 있습니다.
이제 Planet
에 대한 값으로 목록에 있는 값과 정확히 일치하지 않는 값을 사용하려고 시도하면 유효성 검사가 실패합니다.
탭 완성 사용하기
ValidateSet을 사용하는 또 다른 장점은 탭 완성 기능을 제공한다는 것입니다. 이는 TAB 키를 사용하여 매개변수의 가능한 값들을 순환할 수 있다는 것을 의미합니다. 이는 스크립트나 함수의 사용성을 크게 향상시킵니다. 특히 콘솔에서 사용할 때 말이죠.
아래 예제에서 주목해야 할 몇 가지 사항이 있습니다:
- 탭 완성은 마지막 값을 표시한 후에 첫 번째 값으로 돌아갑니다.
- 값들은 알파벳 순서로 표시되지만, ValidateSet에 알파벳 순으로 나열되어 있지 않습니다.
- 첫 글자를 입력하고 TAB 키를 누르면 탭 완성에 제공되는 값들이 해당 글자로 시작하는 값들로 제한됩니다.


또한 아래 예제에서 보여지듯이 PowerShell 통합 스크립팅 환경(ISE)에서도 ValidateSet 탭 완성 기능을 활용할 수 있습니다. ISE Intellisense 기능을 사용하면 가능한 값 목록이 멋진 선택 상자로 표시됩니다.
Intellisense는 그 글자를 포함하는 모든 값들을 반환하며, 해당 글자로 시작하는 값들만 반환하지 않습니다.

이제 Windows 5.1에서 ValidateSet 유효성 검사 속성을 다루었으니 PowerShell Core 6.1에서 추가된 내용을 살펴보고 스크립트에 더 많은 유효성 검사 기능을 제공할 수 있는지 알아봅시다.
PowerShell 6.1에서 ValidateSet의 변경 사항 이해하기
PowerShell Core 6.1의 도입으로 ValidateSet 검증 속성에 두 가지 새로운 기능이 추가되었습니다:
- ErrorMessage 속성
- System.Management.Automation.IValidateSetValuesGenerator에 대한 액세스를 통해 ValidateSet에서 클래스 사용
ErrorMessage 속성
Get-PlanetSize.ps1에 잘못된 행성 이름을 제공하면 생성되는 기본 오류 메시지는 도움이 되지만 다소 장황합니다:
아래 예시에서와 같이 ValidateSet
검증 속성의 ErrorMessage
속성을 사용하여 다른 오류 메시지를 설정할 수 있습니다. {0}
은 제출된 값으로 자동으로 대체되고 {1}
은 허용된 값 목록으로 자동으로 대체됩니다.
스크립트 파일의 Param()
블록을 대체하고 저장한 다음 Get-PlanetSize.ps1 -Planet Barsoom
을 다시 시도하십시오. 아래에서 오류가 훨씬 간결하고 설명적임을 알 수 있습니다.
다음으로, PowerShell 클래스를 통해 ValidateSet에서 허용되는 값 정의하는 새로운 방법을 살펴보세요.
PowerShell 클래스
PowerShell에서 클래스로 알려진 사용자 정의 유형은 버전 5부터 사용 가능했습니다. PowerShell Core 6.1의 도입으로 ValidateSet에 값을 제공하기 위해 클래스를 사용할 수 있는 새로운 기능이 추가되었습니다.
클래스를 사용하면 ValidateSet의 주요 제한 사항을 해결할 수 있습니다 – 정적입니다. 즉, 함수 또는 스크립트의 일부로 포함되어 있으며 스크립트 자체를 편집하여만 변경할 수 있습니다.
ValidateSet
과 함께 작동하는 새로운 기능은 System.Management.Automation.IValidateSetValuesGenerator 클래스를 사용하는 기능입니다. 우리는 이를 상속을 사용하여 자체 클래스의 기반으로 사용할 수 있습니다. ValidateSet
과 함께 작동하기 위해서는 클래스가 System.Management.Automation.IValidateSetValuesGenerator에 기반하고 GetValidValues()
라는 메서드를 구현해야 합니다.
GetValues()
메서드는 수락하려는 값 목록을 반환합니다. 정적 행성 목록이 [Planet]
클래스로 대체된 Param()
블록은 아래와 같이 보일 것입니다. 이 예제는 아직 작동하지 않습니다. 계속 읽어보면 어떻게 구현하는지 알 수 있습니다.
ValidateSet 값 목록에 클래스 사용: 실제 예제
클래스를 사용하여 ValidateSet 값 목록을 보여주기 위해 이전에 사용한 정적 행성 목록을 CSV 텍스트 파일에서 로드된 목록으로 대체할 것입니다. 이제 더 이상 스크립트 자체에서 정적 값 목록을 유지할 필요가 없습니다!
클래스의 데이터 소스 만들기
먼저, 각 유효한 값이 포함된 CSV 파일을 만들어야 합니다. 이를 위해 이 데이터 세트를 새 텍스트 파일로 복사하여 planets.csv로 저장하고 Get-PlanetSize.ps1 스크립트와 동일한 폴더에 저장하십시오.
스크립트에 클래스 추가하기
ValidateSet에서 사용하는 클래스는 이미 정의되어 있어야 합니다. 따라서 Get-PlanetSize.ps1의 현재 구조는 작동하지 않습니다.
[Planet] 클래스는 사용되기 전에 정의되어야 하므로 스크립트의 시작 부분에 위치해야 합니다. 적합한 뼈대 클래스 정의는 다음과 같습니다.
클래스의 GetValidValues() 메서드 내에서 Import-CSV
cmdlet을 사용하여 이전에 생성한 텍스트 파일 planets.csv을 가져옵니다. 파일은 전역 범위에서 변수인 $planets
로 가져와 스크립트에서 나중에 액세스할 수 있습니다.
GetValidValues()
를 통해 행성 이름 목록을 반환하기 위해 return
문을 사용합니다. 이러한 변경 후 클래스는 다음과 같아야 합니다.
다음으로 스크립트에서 $planets
해시 테이블 선언을 아래와 같이 제거합니다. [Planet]
클래스에서 채워진 전역 변수 $planets
에 행성 데이터가 포함되어 있습니다.
이제 남은 원본 코드를 함수로 래핑하고 이름을 Get-PlanetDiameter
로 지정하여 스크립트의 이름과 구분합니다. 함수 내에 있던 Param()
블록을 함수 내부로 이동합니다. 아래와 같이 정적인 행성 목록을 [Planet]
클래스에 대한 참조로 대체합니다.
$output = "행성 {0}의 지름은 {1} km입니다" -f $_, $planets[$_]
라인을 다음의 두 줄로 대체하세요. 이렇게 하면 스크립트가 이전에 만든 해시 테이블이 아닌 Import-CSV
로 생성된 객체 배열에서 행성을 찾을 수 있습니다. 스크립트에서 제거한 이전 코드:
이러한 변경 후 최종 스크립트는 다음과 같아야 합니다:
이제부터 스크립트는 PowerShell 6.1 이상에서만 작동합니다
이제 이 스크립트를 어떻게 사용합니까?
스크립트 실행
스크립트를 실행하면 새 버전의 스크립트를 직접 사용할 수 없습니다. 유용한 코드는 이제 함수로 래핑되어 있습니다. PowerShell 세션 내에서 함수에 액세스하려면 파일을 닷 소스해야 합니다.
닷 소스로 실행한 후 PowerShell 세션에서 새로운 Get-PlanetDiameter
함수에 탭 완성 기능을 사용할 수 있습니다.
“그런 작업의 이점은 무엇입니까?”라고 묻는 소리를 듣겠습니다. “스크립트는 같은 방식으로 작동하는 것 같지만 코드 사용이 더 어렵습니다!”
다음을 시도해 보세요:
- 이전에 만든
planets.csv
파일을 엽니다. - 새 이름과 지름이 있는 새 행을 추가합니다.
- CSV 파일을 저장하세요.
원래 스크립트를 닷소스한 동일한 세션에서 Get-PlanetDiameter
를 사용하여 새 행성의 지름을 찾아보세요. 성공했습니다!
이러한 방식으로 클래스를 사용하면 여러 가지 이점이 있습니다:
- 유효한 값 목록이 코드 자체와 분리되지만 파일의 값에 대한 변경 사항은 스크립트에서 인식됩니다.
- 파일은 스크립트에 접근하지 않는 사람에 의해 유지 관리될 수 있습니다.
- A more complex script could look up information from a spreadsheet, database, Active Directory or a web API.
클래스를 사용하여 ValidateSet 값을 제공할 때 가능성은 거의 무한합니다.
요약하면
Get-PlanetSize.ps1
을 구축하면서 많은 내용을 다루었으므로 다시 한번 정리해 보겠습니다.
이 문서에서 다음을 배웠습니다:
- ValidateSet 유효성 검사 속성이 무엇이며 사용해야 할 이유
- ValidateSet을 PowerShell 함수 또는 스크립트에 추가하는 방법
- ValidateSet과 탭 자동 완성의 동작 방식
- ValidateSet이 대소문자를 구분하는지 제어하기 위해
IgnoreCase
속성을 사용하는 방법 - ValidateSet과 PowerShell 6.1에서
ErrorMessage
속성을 사용하는 방법 - PowerShell 6.1에서 동적 ValidateSet을 만들기 위해 클래스를 사용하는 방법
더 기다릴 필요가 있나요? 지금 ValidateSet을 사용해 보세요!
추가 자료
Source:
https://adamtheautomator.com/powershell-validateset/