PowerShell 내장 멤버(Intrinsic Members)
PowerShell 내장 멤버(Intrinsic Members)
PowerShell에서 객체를 다루다 보면, 그 객체에 내가 정의하지도 않았는데 어디선가 달려들어온 속성이 보일 때가 있어요. 예를 들어 해시 테이블 하나만 만들어도 Count, Keys, Values 같은 게 그냥 따라붙죠. 그건 PowerShell이 모든 객체에 기본으로 달아 놓는 **내장 멤버(intrinsic members)**라서 그래요. 이 글에선 이 내장 멤버가 뭔지, 각각 어떤 역할을 하는지, 그리고 실제로 어떻게 확인하고 쓸 수 있는지 하나씩 살펴볼게요.
본문
한 줄 요약
모든 PowerShell 객체가 공통으로 갖는 내장 멤버에 대해 설명하는 문서예요.
자세히 보기
PowerShell은 객체가 만들어질 때 그 객체에 몇 가지 "숨겨진" 속성과 메서드를 추가해요. 이 속성과 메서드를 통틀어 **내장 멤버(intrinsic members)**라고 불러요. 내장 멤버는 평소에는 보이지 않게 숨겨져 있는데, Get-Member의 Force 매개 변수를 쓰면 이 숨겨진 멤버들까지 볼 수 있어요.
객체 뷰(Object views)
내장 멤버에는 객체를 서로 다른 관점에서 바라보는 MemberSet 속성 묶음도 들어 있어요. MemberSet 속성이 정확히 뭔지 더 알고 싶다면 PSMemberSet 문서를 함께 보면 돼요.
모든 PowerShell 객체는 다음 네 가지 속성을 기본으로 갖고 있어요.
psbase— 확장이나 적응(adaptation)이 적용되지 않은, 순수한 기본 객체만 담긴 MemberSet이에요. 객체 종류에 따라[psobject]로 감싸진 .NET 인스턴스일 수도 있고, 감싸지지 않았다면 입력받은 객체 그 자체예요.psadapted— 기본 객체에 ETS(Extended Type System)가 추가한 **적응 멤버(adapted members)**까지 합쳐 보여주는 MemberSet이에요. 적응 멤버가 있을 때만 그만큼 더 보여주죠.psextended—Types.ps1xml파일과Add-Membercmdlet으로 추가된 멤버만 보여주는 MemberSet이에요. 어떤 객체든 실행 중에Add-Membercmdlet으로 확장할 수 있어요.psobject— 객체에 대한 메서드, 속성, 각종 정보를 훑어볼 수 있는 반성(reflection)의 보고예요.
예제로 확인하기
예를 들어 $hash가 사용자 정보를 담은 해시 테이블이라고 해볼게요. Get-Member의 Force 매개 변수로 이 객체의 내장 멤버를 직접 확인할 수 있어요.
$hash = @{
Age = 33
Name = 'Bob'
}
$hash | Get-Member -Force -MemberType MemberSet, CodeProperty
실행하면 pstypenames, psadapted, psbase, psextended, psobject 같은 내장 멤버들이 줄줄이 나와요.
TypeName: System.Collections.Hashtable
Name MemberType Definition
---- ---------- ----------
pstypenames CodeProperty System.Collections.ObjectModel.Collection`1[[System.String, System.Private.CoreLib, Version=7…
psadapted MemberSet psadapted {Item, IsReadOnly, IsFixedSize, IsSynchronized, Keys, Values, SyncRoot, Count, Add,…
psbase MemberSet psbase {Item, IsReadOnly, IsFixedSize, IsSynchronized, Keys, Values, SyncRoot, Count, Add, Cl…
psextended MemberSet psextended {}
psobject MemberSet psobject {Members, Properties, Methods, ImmediateBaseObject, BaseObject, TypeNames, get_Membe…
psobject는 쓰는 법이 Get-Member와 비슷하면서도 더 유연해요. 예를 들어 객체의 속성과 그 값을 한 번에 열거할 수 있죠.
$hash.psobject.Properties | Select-Object Name, MemberType, Value
Name MemberType Value
---- ---------- -----
IsReadOnly Property False
IsFixedSize Property False
IsSynchronized Property False
Keys Property {Age, Name}
Values Property {33, Bob}
SyncRoot Property {[Age, 33], [Name, Bob]}
Count Property 2
이번엔 해시 테이블을 PSCustomObject로 바꿔서 만든 객체를 비교해 볼게요.
$user = [pscustomobject]$hash
$user.psobject.Properties | Select-Object Name, MemberType, Value
Name MemberType Value
---- ---------- -----
Age NoteProperty 33
Name NoteProperty Bob
해시 테이블의 키가 PSCustomObject에서는 속성으로 바뀐 게 보이죠. 이렇게 새로 생긴 속성들은 이제 psextended MemberSet에 속하게 돼요.
$user | Get-Member -Force -MemberType MemberSet, CodeProperty
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
pstypenames CodeProperty System.Collections.ObjectModel.Collection`1[[System.String, System.Private.CoreLib, Version=7…
psadapted MemberSet psadapted {ToString, GetType, Equals, GetHashCode}
psbase MemberSet psbase {ToString, GetType, Equals, GetHashCode}
psextended MemberSet psextended {Age, Name}
psobject MemberSet psobject {Members, Properties, Methods, ImmediateBaseObject, BaseObject, TypeNames, get_Membe…
형식 정보(Type information)
pstypenames 코드 속성은 객체의 형식 계층을 상속 순서대로 나열해 줘요. 예를 들어 보면 이렇게 돼요.
$file = Get-Item C:\temp\test.txt
$file.pstypenames
System.IO.FileInfo
System.IO.FileSystemInfo
System.MarshalByRefObject
System.Object
출력은 가장 구체적인 형식인 System.IO.FileInfo에서 시작해서 가장 일반적인 System.Object까지 내려가요.
메서드
PowerShell은 모든 객체에 숨은 메서드 두 개를 추가해요. 이 메서드는 Get-Member -Force 명령이나 탭 완성에서는 보이지 않아요.
ForEach()와 Where()
ForEach()와 Where() 메서드는 모든 PowerShell 객체에서 쓸 수 있어요. 다만 실제로는 컬렉션을 다룰 때 가장 유용하죠. 사용법이 더 궁금하면 about_Arrays 문서를 참고해요.
여기서 한 가지 알아두면 좋은 게 있어요. PowerShell 7.6-preview.5부터는 ForEach()의 별칭으로 PSForEach(), Where()의 별칭으로 PSWhere()가 추가됐어요. 이 별칭을 쓰면 객체의 기본 클래스에 이미 정의되어 있을 수 있는 ForEach()나 Where()와 충돌을 피할 수 있어요. System.Collections.Generic.List 클래스처럼 자기만의 ForEach() 메서드를 정의한 경우에는 PSForEach()로 기본 클래스 메서드 대신 내장 메서드를 호출하는 거죠.
속성(Properties)
모든 스칼라 형식이 기본 형식에 Count나 Length 속성을 갖고 있는 건 아니에요. 그래서 PowerShell은 빠진 속성을 스칼라 형식 전부에 내장 멤버로 추가해 줘요.
참고
초기화되지 않은 변수는 암묵적으로
$null이에요.$null은 스칼라라서 내장Count와Length가 둘 다 0이에요.
Count와 Length는 비슷해 보이지만 데이터 형식에 따라 다르게 동작할 수 있어요. 예를 들어 문자열의 Length는 그 문자열의 문자 개수이고, Count는 객체 인스턴스의 개수를 뜻해요.
PS> $str = 'string'
PS> $str.Length
6
PS> $str.Count
1
이 속성들에 대해 더 보고 싶다면 about_Properties를 확인해요.
스칼라 형식의 배열 인덱싱
객체가 인덱싱 가능한 컬렉션이 아닐 때, 인덱스 연산자로 첫 번째 요소에 접근하면 그 객체 자신이 돌아와요. 첫 번째 요소를 넘어서는 인덱스는 $null을 반환해요.
PS> (2)[0]
2
PS> (2)[-1]
2
PS> (2)[1] -eq $null
True
PS> (2)[0,0] -eq $null
True
원리에 대해 더 알고 싶다면 about_Operators의 인덱스 연산자 부분을 봐요.
형식의 new() 메서드
PowerShell 5.0부터는 모든 .NET 형식에 정적 new() 메서드가 추가됐어요. 아래 두 예시는 결과가 같아요.
$expression = New-Object -TypeName regex -ArgumentList 'pattern'
$expression = [regex]::new('pattern')
new() 메서드를 쓰는 쪽이 New-Object보다 성능이 더 좋아요. 클래스에 대한 자세한 내용은 about_Classes 문서를 참고해요.
더 알아보기
- about_Arrays — 배열과
ForEach()/Where()활용 - about_Properties —
Count/Length속성 자세히 - about_Operators — 인덱스 연산자
- about_Classes —
new()메서드와 클래스 - PSMemberSet — MemberSet 속성
- about_Types.ps1xml — 확장 형식 정의
- 원문(영어) GitHub 소스