PowerShell 파이프라인은 PowerShell 쉘 및 스크립팅 언어의 가장 중요하고 유용한 기능 중 하나입니다. 작동 방식과 가능한 기능에 대한 기본적인 이해를 한다면 해당 기능을 사용하여 자신의 함수에서 그 힘을 발휘할 수 있습니다. 이 튜토리얼에서는 바로 그것을 해보겠습니다!
PowerShell 파이프라인을 사용하면 명령을 연결하여 하나의 ‘파이프라인’을 구성할 수 있으며, 코드를 간소화하고 병렬 처리 등을 가능하게 합니다. 파이프라인을 이해하고 파이프라인을 활용하기 위해 자신의 함수를 만들어보려면 시작해봅시다!
사전 요구 사항
이 게시물은 튜토리얼이며, 실습 위주로 진행됩니다. 함께 따라하려면 PowerShell v3+가 필요합니다. 이 튜토리얼은 Windows PowerShell v5.1을 사용합니다.
PowerShell 파이프라인 이해하기
대부분의 PowerShell 명령은 매개 변수를 통해 일부 입력을 받습니다. 명령은 일부 객체를 입력으로 받아 내부에서 작업을 수행한 다음 선택적으로 일부 객체를 출력으로 반환합니다.
파이프라인의 명령은 릴레이 경주에서 인간 러너처럼 작동합니다. 첫 번째와 마지막 러너를 제외한 모든 러너는 이전 러너로부터 배턴(객체)을 받아 다음 러너로 전달합니다.
예를 들어, Stop-Service
cmdlet에는 InputObject
라는 매개변수가 있습니다. 이 매개변수를 사용하면 Stop-Service
에 특정 유형의 개체를 전달하여 중지하려는 Windows 서비스를 나타낼 수 있습니다.
InputObject
매개변수를 사용하려면 Get-Service
를 통해 서비스 개체를 검색한 다음 아래에 표시된대로 개체를 InputObject
매개변수에 전달할 수 있습니다. InputObject
매개변수를 통해 입력을 제공하는이 Stop-Service
cmdlet의 방법은 훌륭하게 작동하며 작업을 완료합니다.
이 Stop-Service
명령에 입력을 전달하는이 방법은 두 가지 다른 단계가 필요합니다. PowerShell은 먼저 Get-Service
를 실행하고 출력을 변수에 저장한 다음 그 값을 InputObject
매개변수를 통해 Stop-Service
에 전달해야 합니다.
이제 위의 코드 일부를 아래의 코드 일부와 비교하면 같은 작업을 수행합니다. $services
변수를 만들거나 InputObject
매개변수를 사용할 필요가 없기 때문에 훨씬 간단합니다. 대신 PowerShell은 InputObject
매개변수를 사용할 것으로 인식합니다. 이것은 매개변수 바인딩이라는 개념을 통해 수행됩니다.
이제 |
연산자를 사용하여 명령을 연결했습니다. 여기에 파이프라인을 만들었습니다.
하지만 파이프라인을 만들려면 두 개의 명령만 사용할 필요는 없으며 (명령 매개변수가 지원하는 경우) 원하는 만큼 많이 연결할 수 있습니다. 예를 들어, 아래 코드 스니펫을 참조하십시오:
- 모든 객체를
Get-Service
cmdlet이 반환하는Where-Object
cmdlet에 전달합니다. Where-Object
cmdlet은 각 객체의Status
속성을 확인한 다음 값이Running
인 객체만 반환합니다.- 그런 다음 해당 객체들은
Select-Object
로 전송되며 해당 객체의Name
및DisplayName
속성만 반환합니다.
Select-Object
이 출력하는 객체를 수용하는 다른 cmdlet이 없으므로 해당 명령은 객체를 직접 콘솔로 반환합니다.Where-Object
및Select-Object
cmdlet은 매개변수 바인딩이라는 개념을 통해 파이프라인 입력을 처리하는 방법을 이해합니다.
파이프라인에 대한 추가 정보는 명령을 실행하십시오
Get-Help about_pipelines
.
파이프라인 매개변수 바인딩
처음 보면 파이프라인은 사소한 것처럼 보일 수 있습니다. 어쨌든 단지 명령에서 객체를 다른 명령으로 전달하는 것뿐입니다. 그러나 실제로는 파이프라인이 훨씬 더 복잡합니다. 명령은 매개변수를 통해서만 입력을 수용합니다. 파이프라인은 명시적으로 정의하지 않아도 사용할 매개변수를 어떻게 찾아야 할지 어떻게 알아야 할지 결정해야 합니다.
파라미터 바인딩은 파이프라인을 통해 입력을 받을 때 어떤 매개변수를 사용해야 하는지 결정하는 작업입니다. 파이프라인으로 들어오는 객체를 매개변수에 바인딩하려면, 들어오는 명령의 매개변수가 이를 지원해야 합니다. 명령 매개변수는 두 가지 방법 중 하나로 파이프라인 매개변수 바인딩을 지원합니다. ByValue
와/또는 ByPropertyName
.
ByValue
명령 매개변수는 전체 들어오는 객체를 매개변수 값으로 받습니다. ByValue
매개변수는 들어오는 객체 중 특정 유형의 객체를 찾습니다. 해당 객체 유형이 일치하는 경우, PowerShell은 해당 매개변수에 바인딩되어야 한다고 가정하고 수락합니다.
Get-ChildItem
cmdlet에는Path
라는 매개변수가 있으며, string 객체 유형과ByValue
를 통해 파이프라인 입력을 받습니다. 따라서'C:\Windows' | Get-ChildItem
과 같은 명령을 실행하면 C:\Windows 디렉토리의 모든 파일이 반환됩니다. 왜냐하면C:\Windows
는 문자열이기 때문입니다.
ByPropertyName
명령 매개변수는 객체 전체를 받는 것이 아니라 해당 객체의 단일 속성을 받습니다. 이는 객체 유형이 아닌 속성 이름을 보고 수행됩니다.
Get-Process cmdlet에는
Name
매개변수가 있으며, 이는 파이프라인 입력ByPropertyName
을 수락하도록 설정되어 있습니다.[pscustomobject]@{Name='firefox'} | Get-Process
와 같이Name
속성이 있는 개체를Get-Process
cmdlet에 전달할 때 PowerShell은 들어오는 개체의Name
속성을Name
매개변수에 매핑하고 해당 값을 사용합니다.
파이프라인 입력을 지원하는 명령 매개변수 찾기
앞서 언급했듯이 모든 명령이 파이프라인 입력을 지원하는 것은 아닙니다. 명령의 작성자는 이 기능을 개발해야 합니다. 명령은 파이프라인을 지원하는 매개변수가 하나 이상 있어야 합니다. ByValue
또는 ByPropertyName
을 사용합니다.
어떻게 하면 어떤 명령과 해당 매개변수가 파이프라인 입력을 지원하는지 알 수 있을까요? 시행착오로 시도할 수 있지만 Get-Help
명령을 사용하여 PowerShell 도움말 시스템을 사용하는 것이 더 나은 방법입니다.
Get-ChildItem
cmdlet의 Path
매개변수를 살펴보겠습니다. 이것이 두 종류의 파이프라인 입력을 지원하는 것을 볼 수 있습니다.

한 번 파이프라인 입력을 지원하는 명령 매개변수를 알게 되면 아래에 표시된 것처럼 해당 기능을 활용할 수 있습니다.
그러나 반면에, Get-Service
에서의 DisplayName
매개변수는 파이프라인 입력을 지원하지 않습니다.

자체 파이프라인 기능 만들기
표준 PowerShell cmdlet이 파이프라인 입력을 지원한다고 해서 해당 기능을 활용할 수 없는 것은 아닙니다. 다행히도, 파이프라인 입력을 수용하는 함수를 만들 수 있습니다.
이를 설명하기 위해, 기존 함수인 Get-ConnectionStatus
로 시작해 보겠습니다.
- 이 함수에는 단일 매개변수(
[Parameter()]
로 정의되지 않은)인ComputerName
이 있습니다. 이를 통해 하나 이상의 문자열을 전달할 수 있습니다.ComputerName
매개변수가 파이프라인 입력을 수용하지 않는다는 것을 알 수 있습니다. - 그런 다음 함수는 각 문자열을 읽고 각각에 대해
Test-Connection
cmdlet을 실행합니다. - 각 문자열 컴퓨터 이름이 전달되면
ComputerName
및Status
속성이 있는 객체를 반환합니다.
그런 다음 다음과 같이 하나 이상의 호스트 이름 또는 IP 주소를 ComputerName
매개변수로 전달하여 Get-ConnectionStatus
를 호출합니다.
단계 1: 파이프라인 입력 허용
이 함수가 파이프라인 입력을 허용하려면 먼저 적절한 매개변수 속성을 정의해야 합니다. 이 속성은 ValueFromPipeline
으로 파이프라인 입력 ByValue를 허용하거나 ValueFromPipelineByPropertyName
로 파이프라인 입력 ByPropertyName을 허용할 수 있습니다.
이 예에서는 다음과 같이 [Parameter()]
정의의 괄호 안에 ValueFromPipeline
매개변수 속성을 추가합니다.
이 시점에서 기술적으로 이것이 전부입니다. Get-ConnectionStatus
함수는 이제 전달된 모든 문자열 객체를 ComputerName
매개변수에 바인딩합니다. 그러나 매개변수 바인딩이 진행 중이라고 해서 함수가 의미 있는 작업을 수행한다는 것은 아닙니다.
단계 2: 프로세스 블록 추가
파이프라인에서 들어오는 모든 객체를 처리하려면 다음으로 Process
블록을 추가해야 합니다. 이 블록은 PowerShell에게 파이프라인에서 들어오는 각 객체를 처리하라고 알려줍니다.
Process
블록이 없으면 PowerShell은 파이프라인에서 오는 첫 번째 객체만 처리합니다.Process
블록은 PowerShell에게 계속해서 객체를 처리하도록 알려줍니다.
다음과 같이 Process
블록을 추가하여 함수의 모든 기능을 묶어주세요.
Process
블록 내에서 항상 출력을 보내세요.Process
블록 내에서 출력을 보내면 객체가 파이프라인을 통해 스트리밍되어 다른 명령에서 해당 객체를 파이프라인에서 받을 수 있게 됩니다.
PowerShell 파이프라인으로 객체 전달
위의 함수에서 Process
블록을 정의한 후, 아래에 표시된 대로 파이프라인을 통해 ComputerName
매개변수에 값 전달하여 함수를 호출할 수 있습니다.
이 시점에서 파이프라인의 실제 장점을 활용하여 더 많은 명령을 조합할 수 있습니다. 예를 들어, 아래와 같이 새 줄로 구분된 IP 주소의 텍스트 파일인 C:\Test\computers.txt가 있다고 가정해보겠습니다.
그런 다음 Get-Content
cmdlet을 사용하여 텍스트 파일에서 각 IP 주소를 읽고 이를 Get-ConnectionStatus
함수에 직접 전달할 수 있습니다.
이 설정을 한 단계 더 나아가서 Get-ConnectionStatus
가 반환하는 객체를 직접 ForEach-Object
cmdlet에 파이프하여 사용할 수 있습니다.
다음 코드:
- 컴퓨터 이름을 모두 텍스트 파일에서 읽어와
Get-ConnectionStatus
함수에 전달합니다. Get-ConnectionStatus
는 각 컴퓨터 이름을 처리하고ComputerName
및Status
속성이 있는 객체를 반환합니다.Get-ConnectionStatus
는 이후에 각 객체를ForEach-Object
cmdlet에 전달하며 이는 사람이 읽을 수 있는 Cyan으로 색상이 지정된 단일 문자열을 반환합니다.
ComputerName
매개변수에서 파이프라인 입력이 활성화되지 않았거나Get-ConnectionStatus
가Process
블록 내에서 객체를 반환하지 않았다면 PowerShell은 모든 객체(IP 주소)가 처리될 때까지 콘솔에 어떤 상태도 반환하지 않을 것입니다.
속성 이름에 의한 파이프라인 바인딩
Get-ConnectionStatus
cmdlet은 지금까지 '127.0.0.1', '192.168.1.100'
과 같은 문자열 배열을 허용하여 파이프라인 입력 ByValue(ValueFromPipeline
)을 수락하도록 설정되어 있습니다. 입력이 텍스트 파일 대신 CSV 파일에서 받아진 경우 이 기능도 예상대로 작동할까요?
아마도 C:\Test\pc-list.csv에서 아래와 같이 보이는 CSV 파일이 있을 것입니다.
CSV 파일의
ComputerName
필드가Get-ConnnectionStatus
ComputerName
매개변수와 동일한 이름임을 주의하세요.
CSV를 가져와 파이프라인을 통해 Get-ConnectionStatus
에 전달하려고 시도하면 함수가 ComputerName
열에서 예상치 못한 결과를 반환합니다.
무엇이 잘못되었는지 추측할 수 있나요? 결국 매개변수 이름은 일치하기 때문에 PowerShell 파이프라인이 Import-CSV
에서 반환한 출력을 Get-ConnectionStatus
의 ComputerName
매개변수에 바인딩하지 않은 이유는 무엇일까요? 왜냐하면 매개변수 속성 ValueFromPipelineByPropertyName
이 필요하기 때문입니다.
현재 함수의 ComputerName
매개변수는 다음과 같은 매개변수 정의를 가지고 있습니다: [Parameter(ValueFromPipeline)]
. 따라서 아래와 같이 ValueFromPipelineByPropertyName
을 추가하여 ComputerName
매개변수를 ByPropertyName 입력을 지원하도록 설정해야 합니다.
ByPropertyName을 파이프라인 지원으로 추가하면 PowerShell에게 객체 속성 이름과 객체 유형을 살펴보라고 알립니다. 이 변경 사항을 수행한 후에는 예상한 출력이 표시됩니다.
요약
이 튜토리얼에서는 PowerShell 파이프라인의 작동 방식, 매개변수 바인딩 방법 및 PowerShell 파이프라인을 지원하는 자체 함수를 생성하는 방법을 배웠습니다.
함수는 파이프라인 없이 작동할 수 있지만, 객체를 한 명령에서 다른 명령으로 “스트리밍”하고 코드를 단순화할 수는 없습니다.
파이프라인을 준비할 수 있는 함수에 대해 작성한 것이나 작성할 예정인 함수에 대해 생각해 볼 수 있나요?