about_Functions_Advanced_Methods — 고급 함수가 쓰는 메서드

about_Functions_Advanced_Methods — 고급 함수가 쓰는 메서드

도입 이 문서는 CmdletBinding 특성을 지정한 함수가 컴파일된 cmdlet처럼 동일한 메서드와 속성을 어떻게 활용할 수 있는지 설명해 드릴게요. 고급 함수를 만들 때 $PSCmdlet 변수를 통해 접근할 수 있는 각종 메서드를 정리했으니, 함수를 한 단계 더 다듬고 싶다면 꼭 읽어 보세요.

출처: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_methods

본문

간단한 설명 (Short description)

CmdletBinding 특성을 지정한 함수가 컴파일된 cmdlet이 사용하는 메서드와 속성을 어떻게 활용할 수 있는지 설명해 드릴게요.

자세한 설명 (Long description)

CmdletBinding 특성을 지정한 함수는 $PSCmdlet 변수를 통해 추가적인 메서드와 속성에 접근할 수 있어요. 여기에는 다음과 같은 메서드들이 포함됩니다.

  • 모든 함수가 사용할 수 있는 동일한 입력 처리 메서드
  • 작업을 수행하기 전에 사용자에게 확인을 받기 위한 ShouldProcessShouldContinue 메서드
  • 오류 레코드를 생성하기 위한 ThrowTerminatingError 메서드
  • 서로 다른 종류의 출력을 반환하는 여러 Write 메서드

PSCmdlet 클래스의 모든 메서드와 속성은 고급 함수에서 사용할 수 있어요. 자세한 내용은 System.Management.Automation.PSCmdlet 문서를 참고하세요.

CmdletBinding 특성에 대한 자세한 내용은 about_Functions_CmdletBindingAttribute 문서를, CmdletBindingAttribute 클래스에 대해서는 System.Management.Automation.Cmdlet.CmdletBindingAttribute 문서를 참고하세요.

입력 처리 메서드 (Input processing methods)

이 섹션에서 다루는 메서드를 입력 처리 메서드라고 불러요. 함수의 경우 이 세 가지 메서드가 begin, process, end 블록으로 표현되고, PowerShell 7.3부터는 clean 블록 프로세스 메서드가 추가됐어요.

이 블록들을 함수에 반드시 써야 하는 건 아니에요. 이름이 붙은 블록을 사용하지 않으면 PowerShell이 코드를 함수의 end 블록에 넣어요. 다만 이런 이름 있는 블록 중 하나를 쓰거나 dynamicparam 블록을 정의한다면, 모든 코드를 반드시 이름 있는 블록 안에 넣어야 해요.

다음 예제는 1회성 전처리를 위한 begin 블록, 여러 레코드를 처리하기 위한 process 블록, 1회성 후처리를 위한 end 블록을 가진 함수의 골격을 보여줘요.

Function Test-ScriptCmdlet
{
[CmdletBinding(SupportsShouldProcess=$true)]
    param ($Parameter1)
    begin{}
    process{}
    end{}
    clean{}
}

참고: 이 블록들은 CmdletBinding 특성을 쓰지 않는 함수를 포함해 모든 함수에 적용돼요.

begin

이 블록은 함수의 1회성 전처리를 제공하는 데 사용돼요. PowerShell 런타임은 파이프라인에서 함수 인스턴스 하나당 이 블록의 코드를 한 번만 실행해요.

process

이 블록은 함수의 레코드 단위 처리를 제공하는 데 사용돼요. 다른 블록 없이 process 블록만 정의해도 괜찮아요. process 블록이 실행되는 횟수는 함수를 어떻게 사용하느냐, 함수가 어떤 입력을 받느냐에 따라 달라져요.

자동 변수 $_ 또는 $PSItem에는 파이프라인에서의 현재 객체가 담겨 있어 process 블록에서 바로 사용할 수 있어요. $input 자동 변수에는 함수와 스크립트블록에서만 사용할 수 있는 열거자(enumerator)가 들어 있어요. 자세한 내용은 about_Automatic_Variables 문서를 참고하세요.

  • 파이프라인 밖에서, 또는 파이프라인 시작 부분에서 함수를 호출하면 process 블록이 한 번 실행돼요.
  • 파이프라인 안에서는 함수에 도달하는 입력 객체 하나마다 process 블록이 한 번씩 실행돼요.
  • 함수에 도달하는 파이프라인 입력이 비어 있으면 process 블록은 실행되지 않아요.
  • 그 경우에도 begin, end, clean 블록은 실행돼요.

중요: 파이프라인 입력을 받도록 설정한 함수에 process 블록이 정의되어 있지 않으면 레코드 단위 처리가 실패해요. 이 경우 함수는 입력과 관계없이 한 번만 실행될 뿐이에요.

파이프라인 입력을 받고 CmdletBinding을 사용하는 함수를 만들 때는 process 블록에서 $_$PSItem 대신 파이프라인 입력으로 정의한 매개변수 변수를 사용해야 해요. 예를 들어:

function Get-SumOfNumbers {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, Position=0, ValueFromPipeline)]
        [int[]]$Numbers
    )

    begin { $retValue = 0 }

    process {
       foreach ($n in $Numbers) {
           $retValue += $n
       }
    }

    end { $retValue }
}

PS> Get-SumOfNumbers 1, 2, 3, 4
10
PS> 1,2,3,4 | Get-SumOfNumbers
10

end

이 블록은 함수의 1회성 후처리를 제공하는 데 사용돼요.

clean

clean 블록은 PowerShell 7.3에서 추가됐어요.

clean 블록은 begin, process, end 블록에 걸쳐 사용한 리소스를 정리하기 좋은 방법이에요. 스크립트 함수나 스크립트 cmdlet의 다른 모든 이름 있는 블록을 덮는 finally 블록과 비슷한 의미를 가져요. 리소스 정리는 다음 시나리오에서 강제로 수행돼요.

  • 파이프라인 실행이 종료 오류 없이 정상적으로 끝났을 때
  • 종료 오류 때문에 파이프라인 실행이 중단됐을 때
  • Select-Object -First에 의해 파이프라인이 중지됐을 때
  • Ctrl+C 또는 StopProcessing()으로 파이프라인이 멈췄을 때

clean 블록은 Success 스트림에 기록된 모든 출력을 버려요.

주의: clean 블록을 추가하는 것은 호환성을 깨뜨리는 변경이에요. clean이 키워드로 해석되기 때문에, 사용자가 스크립트블록의 첫 번째 문장으로 clean이라는 이름의 명령을 직접 호출할 수 없게 됩니다. 다만 실제로 문제가 될 가능성은 낮아요. 해당 명령은 여전히 호출 연산자(& clean)로 호출할 수 있어요.

확인 메서드 (Confirmation methods)

ShouldProcess

이 메서드는 함수가 시스템을 변경하는 작업을 수행하기 전에 사용자에게 확인을 요청할 때 호출해요. 함수는 이 메서드가 반환하는 Boolean 값에 따라 계속 진행할지 결정할 수 있어요. 이 메서드는 함수의 process {} 블록 안에서만 호출할 수 있고, CmdletBinding 특성이 함수가 ShouldProcess를 지원한다고 선언해야 해요(앞의 예제에서 본 것처럼요).

이 메서드에 대한 자세한 내용은 System.Management.Automation.Cmdlet.ShouldProcess 문서를 참고하세요.

확인 요청에 대한 자세한 내용은 Requesting Confirmation 문서를 참고하세요.

ShouldContinue

이 메서드는 두 번째 확인 메시지를 요청할 때 호출해요. ShouldProcess 메서드가 $true를 반환했을 때 호출하면 됩니다. 이 메서드에 대한 자세한 내용은 System.Management.Automation.Cmdlet.ShouldContinue 문서를 참고하세요.

오류 메서드 (Error methods)

함수는 오류가 발생했을 때 서로 다른 두 메서드를 호출할 수 있어요. 종료되지 않는 오류(non-terminating error)가 발생하면 함수가 WriteError 메서드를 호출해야 하는데, 이 메서드는 Write 메서드 섹션에서 다룰게요. 계속 진행할 수 없는 종료 오류(terminating error)가 발생하면 ThrowTerminatingError 메서드를 호출해야 해요. 종료 오류에는 throw 문을, 종료되지 않는 오류에는 Write-Error cmdlet을 쓸 수도 있어요.

자세한 내용은 System.Management.Automation.Cmdlet.ThrowTerminatingError 문서를 참고하세요.

Write 메서드 (Write methods)

함수는 다음 메서드를 호출해서 서로 다른 종류의 출력을 반환할 수 있어요. 모든 출력이 파이프라인의 다음 명령으로 가는 건 아니라는 점에 주의하세요. Write-Error 같은 다양한 Write cmdlet도 사용할 수 있어요.

WriteCommandDetail

WriteCommandDetail 메서드에 대한 정보는 System.Management.Automation.Cmdlet.WriteCommandDetail 문서를 참고하세요.

WriteDebug

함수 문제를 해결하는 데 쓸 수 있는 정보를 제공하려면 함수에서 WriteDebug 메서드를 호출하게 하세요. WriteDebug 메서드는 디버그 메시지를 사용자에게 표시해요. 자세한 내용은 System.Management.Automation.Cmdlet.WriteDebug 문서를 참고하세요.

WriteError

함수가 종료되지 않는 오류가 발생했고 계속해서 레코드를 처리하도록 설계된 경우 이 메서드를 호출해야 해요. 자세한 내용은 System.Management.Automation.Cmdlet.WriteError 문서를 참고하세요.

참고: 종료 오류가 발생하면 함수는 ThrowTerminatingError 메서드를 호출해야 해요.

WriteObject

WriteObject 메서드를 사용하면 함수가 객체를 파이프라인의 다음 명령으로 보낼 수 있어요. 대부분의 경우 함수가 데이터를 반환할 때는 WriteObject를 쓰는 게 정석이에요. 자세한 내용은 System.Management.Automation.PSCmdlet.WriteObject 문서를 참고하세요.

WriteProgress

완료하는 데 시간이 오래 걸리는 동작이 있는 함수라면 WriteProgress 메서드를 호출해서 진행 상황 정보를 표시하게 할 수 있어요. 예를 들어 완료된 백분율을 표시할 수 있죠. 자세한 내용은 System.Management.Automation.PSCmdlet.WriteProgress 문서를 참고하세요.

WriteVerbose

함수가 무엇을 하고 있는지에 대한 자세한 정보를 제공하려면 WriteVerbose 메서드를 호출해서 자세한(verbose) 메시지를 사용자에게 표시하게 하세요. 기본적으로 자세한 메시지는 표시되지 않아요. 자세한 내용은 System.Management.Automation.Cmdlet.WriteVerbose 문서를 참고하세요.

WriteWarning

예상치 못한 결과를 초래할 수 있는 조건에 대한 정보를 제공하려면 WriteWarning 메서드를 호출해서 경고 메시지를 사용자에게 표시하게 하세요. 기본적으로 경고 메시지는 표시돼요. 자세한 내용은 System.Management.Automation.Cmdlet.WriteWarning 문서를 참고하세요.

참고: $WarningPreference 변수를 설정하거나 Verbose/Debug 명령줄 옵션을 사용해서도 메시지 표시를 제어할 수 있어요. $WarningPreference 변수에 대한 자세한 내용은 about_Preference_Variables 문서를 참고하세요.

기타 메서드와 속성 (Other methods and properties)

$PSCmdlet 변수를 통해 접근할 수 있는 다른 메서드와 속성에 대한 정보는 System.Management.Automation.PSCmdlet 문서를 참고하세요.

예를 들어 ParameterSetName 속성을 사용하면 현재 사용 중인 매개변수 집합(parameter set)을 확인할 수 있어요. 매개변수 집합을 사용하면 함수를 실행할 때 지정된 매개변수에 따라 서로 다른 작업을 수행하는 함수를 만들 수 있답니다.

더 알아보기