about_Modules — PowerShell 모듈 사용하기
about_Modules — PowerShell 모듈 사용하기
PowerShell로 작업하다 보면 명령이 다 어디서 나오는지 궁금해질 때가 있어요. 그 명령들을 담아 두고 필요할 때 불러 쓰는 단위가 바로 모듈(module) 이에요. 이 글에서는 PowerShell 모듈을 설치하고, 불러오고, 사용하는 방법을 하나씩 설명해 드릴게요.
본문
짧게 요약하면
PowerShell 모듈을 설치하고 가져오고(import) 사용하는 방법을 다루는 문서예요.
자세히 설명하면
PowerShell은 명령 셸이면서 동시에 스크립트 언어예요. PowerShell의 명령은 스크립트, 함수, cmdlet으로 구현되고요, 여기에 키워드처럼 처리 구조와 흐름을 만드는 요소와 변수, 공급자(provider), 별칭(alias) 같은 리소스가 함께 들어 있어요.
모듈은 cmdlet, provider, 함수, 변수, 그리고 기타 리소스를 담을 수 있는 자족적(self-contained)이고 재사용 가능한 단위예요. 기본적으로 PowerShell은 설치된 모듈의 명령을 처음 사용하는 순간에 그 모듈을 자동으로 불러와요. 이 자동 로딩 동작은 $PSModuleAutoLoadingPreference 변수로 조정할 수 있고요, 자세한 내용은 about_Preference_Variables에서 확인할 수 있어요.
모듈은 세션 중에 직접 불러오거나 내릴 수도 있어요. 불러오거나 다시 불러오려면 Import-Module, 내리려면 Remove-Module을 쓰면 돼요.
PowerShell은 기본 제공되는 모듈 세트를 포함하고 있고, 누구든 C#이나 PowerShell 스크립트 언어 자체로 새 모듈을 만들 수 있어요. C#으로 작성해 컴파일된 .NET 어셈블리 모듈은 네이티브 모듈(native module), PowerShell로 작성한 모듈은 스크립트 모듈(script module) 이라고 불러요.
이 글은 모듈을 사용하는 방법을 다루는 문서예요. 모듈을 만드는 방법이 궁금하다면 Writing a PowerShell Module 문서를 참고하세요.
참고 — PowerShell 3.0 이전에는 cmdlet과 provider가 snap-in이라는 단위로 묶여 있었어요. PowerShell 3.0부터
Microsoft.PowerShell.Coresnap-in이 모든 세션에 기본 추가되는데, 이게 지금 남아 있는 유일한 snap-in이에요. 나머지 snap-in은 전부 모듈로 전환되었고, 새 snap-in은 더 이상 만들 수 없어요.
기본 모듈 위치
PowerShell은 모듈을 다음과 같은 기본 위치에 보관해요.
Windows에서
- 모든 사용자 범위 —
$Env:ProgramFiles\PowerShell\Modules - 현재 사용자 범위 —
$HOME\Documents\PowerShell\Modules - PowerShell과 함께 제공되는 모듈 —
$PSHOME\Modules
Linux와 macOS에서
- 모든 사용자 범위 —
/usr/local/share/powershell/Modules - 현재 사용자 범위 —
$HOME/.local/share/powershell/Modules - PowerShell과 함께 제공되는 모듈 —
$PSHOME/Modules
기본적으로 현재 사용자의 Modules 폴더는 존재하지 않아요. Install-Module이나 Install-PSResource로 CurrentUser 범위에 모듈을 설치하면 그 cmdlet들이 사용자용 Modules 폴더를 만들어 두죠. 폴더가 없다면 직접 만들어도 되고요, 다음 명령으로 현재 사용자용 Modules 폴더를 만들 수 있어요.
$folder = New-Item -Type Directory -Path $HOME\Documents\PowerShell\Modules
이 위치들은 $Env:PSModulePath 환경 변수에 자동으로 포함돼요. 기본 모듈 위치에 대한 자세한 내용은 about_PSModulePath를 보세요.
모듈 자동 로딩
설치된 모듈의 명령을 처음 실행하면 PowerShell이 자동으로 그 모듈을 가져와요(import). 단, 모듈은 $Env:PSModulePath 환경 변수에 지정된 위치에 있어야 해요.
자동 로딩 덕분에 별도 설정이나 프로필 구성 없이도 모듈의 명령을 바로 쓸 수 있어요. 아래 예시들은 각각 Get-CimInstance를 담고 있는 CimCmdlets 모듈을 세션에 가져오는 경우예요.
명령 실행하기:
Get-CimInstance Win32_OperatingSystem
명령 가져오기:
Get-Command Get-CimInstance
명령 도움말 보기:
Get-Help Get-CimInstance
Get-Command에 와일드카드 문자(*)를 쓰면 PowerShell은 어떤 모듈도 가져오지 않아요. 세션에 필요하지 않을 모듈을 불러오지 않고도 와일드카드로 명령을 탐색할 수 있는 거죠.
모듈을 직접 가져오기
모듈이 $Env:PSModulePath 환경 변수에 지정된 위치에 설치되어 있지 않거나, 패키지 형태가 아니라 독립된 .dll·.psm1 파일로 제공될 때는 직접 가져오는 게 필요해요.
또 PowerShell provider를 사용하는 명령은 자동으로 모듈을 가져오지 않아요. 예를 들어 Get-PSSessionConfiguration cmdlet처럼 WSMan: 드라이브가 필요한 명령은 WSMan: 드라이브를 포함한 Microsoft.WSMan.Management 모듈을 Import-Module cmdlet으로 가져와야 할 수 있어요.
가져오는 방식을 바꾸고 싶을 때도 있죠. 예를 들어 Import-Module의 Prefix 매개 변수는 모듈에서 가져온 cmdlet의 명사 부분에 구별되는 접두사를 붙여 주고, NoClobber 매개 변수는 세션의 기존 명령을 숨기거나 대체하는 명령을 추가하지 못하게 막아요. 자세한 내용은 이름 충돌 관리에서 다룰게요.
다음 예시는 BitsTransfer 모듈을 현재 세션으로 가져와요.
Import-Module BitsTransfer
$Env:PSModulePath에 없는 모듈을 가져오려면 모듈 폴더의 전체 경로를 쓰면 돼요. 예를 들어 C:\ps-test 디렉터리의 TestCmdlets 모듈을 세션에 추가하려면 이렇게 입력해요.
Import-Module C:\ps-test\TestCmdlets
모듈 폴더에 들어 있지 않은 모듈 파일을 가져올 때는 명령에 모듈 파일의 전체 경로를 쓰면 돼요. C:\ps-test 디렉터리의 TestCmdlets.dll 모듈을 세션에 추가하려면 이렇게요.
Import-Module C:\ps-test\TestCmdlets.dll
세션에 모듈을 추가하는 방법에 대한 자세한 내용은 Import-Module을 참고하세요.
매 세션 시작 시 모듈 가져오기
Import-Module 명령은 현재 PowerShell 세션에 모듈을 가져와요. 시작하는 모든 세션에 모듈을 가져오고 싶다면 Import-Module 명령을 PowerShell 프로필에 추가하면 돼요.
프로필에 대한 자세한 내용은 about_Profiles를 보세요.
게시된 모듈 설치하기
게시된 모듈(published module)은 PowerShell Gallery 같은 등록된 리포지토리에서 받을 수 있는 모듈이에요. PowerShellGet과 Microsoft.PowerShell.PSResourceGet 모듈은 등록된 리포지토리에서 PowerShell 모듈을 찾고, 설치하고, 게시하는 cmdlet을 제공해요.
PowerShellGet 모듈은 PowerShell 5.0 이상에 포함되어 있고, Microsoft.PowerShell.PSResourceGet 모듈은 PowerShell 7.4 이상에 포함되어 있어요. 후자가 PowerShell의 선호되는 패키지 관리자죠. Microsoft.PowerShell.PSResourceGet은 더 오래된 PowerShell 버전에서 PowerShellGet과 나란히 설치할 수도 있어요. PowerShell Gallery에서 모듈을 설치하려면 Install-Module 또는 Install-PSResource cmdlet을 쓰면 됩니다.
Get-Command Install-Module, Install-PSResource
CommandType Name Version Source
----------- ---- ------- ------
Function Install-Module 2.9.0 PowerShellGet
Cmdlet Install-PSResource 1.0.0 Microsoft.PowerShell.PSResourceGet
자세한 내용은 PowerShellGet Overview를 참고하세요.
모듈을 직접 설치하기
모듈은 다른 폴더에서 모듈 내용을 복사해서 직접 설치할 수도 있어요. 그 폴더는 로컬 머신의 다른 위치거나 다른 머신에 설치된 것일 수 있죠. 직접 설치는 모듈 폴더 전체를 $Env:PSModulePath에 포함된 새 위치로 복사하면 돼요.
PowerShell에서는 Copy-Item cmdlet을 쓰면 되고요, 예를 들어 C:\PSTest의 MyModule 폴더를 복사하려면 다음 명령을 실행하면 돼요.
$modulePath = $HOME\Documents\PowerShell\Modules\MyModule
Copy-Item -Path C:\PSTest\MyModule\* -Destination $modulePath -Recurse
모듈은 어느 위치에나 설치할 수 있지만, 기본 모듈 위치에 설치하면 관리하기가 훨씬 쉬워요.
설치된 모듈 찾기
Get-Module cmdlet은 현재 PowerShell 세션에 로드된 PowerShell 모듈을 가져와요.
Get-Module
나열되는 모듈에는 $Env:PSModulePath뿐 아니라 어느 위치에서든 가져온 모듈이 포함될 수 있어요. $Env:PSModulePath에 설치된 모듈을 모두 나열하려면 다음 명령을 쓰세요.
Get-Module -ListAvailable
이 명령은 $Env:PSModulePath에 설치된 모든 모듈을 가져오지만, 현재 세션에 가져온 모듈만 보여 주는 건 아니에요. 다른 위치에 설치된 모듈은 나열하지 않아요. 자세한 내용은 Get-Module을 보세요.
모듈의 명령 나열하기
Get-Command cmdlet으로 사용 가능한 모든 명령을 찾을 수 있어요. Get-Command의 매개 변수로 모듈, 이름, 명사 등 기준에 따라 명령을 필터링할 수 있고요.
특정 모듈의 모든 명령을 찾으려면 이렇게 입력해요.
Get-Command -Module BitsTransfer
모듈 이름 자리에 <module-name>을 넣으면 돼요.
Get-Command cmdlet에 대한 자세한 내용은 Get-Command를 참고하세요.
모듈 제거하기
모듈을 제거하면 그 모듈이 세션에 추가했던 명령이 세션에서 삭제돼요. 예를 들어 다음 명령은 세션에서 BitsTransfer 모듈을 제거해요.
Remove-Module BitsTransfer
모듈 제거는 모듈 가져오기의 반대 동작이에요. 다만 제거한다고 모듈이 제거(uninstall) 되는 건 아니에요. 자세한 내용은 Remove-Module을 보세요.
명령은 모듈과 snap-in에서 세션으로 추가될 수 있어요. 모듈은 cmdlet, provider, 함수 같은 모든 종류의 명령과 변수, 별칭, PowerShell 드라이브 같은 항목을 추가할 수 있지만, snap-in은 cmdlet과 provider만 추가할 수 있어요.
세션에서 모듈을 제거하기 전에 다음 명령으로 어느 모듈을 제거할지 확인해 보세요. 예를 들어 Get-Date와 Get-Help cmdlet의 출처를 찾으려면 이렇게요.
Get-Command Get-Date, Get-Help -All |
Select-Object -Property Name, CommandType, Module ,PSSnapIn
다음 출력은 Get-Help cmdlet이 Microsoft.PowerShell.Core snap-in에 있다는 걸 보여 줘요. 이 snap-in은 세션에서 제거할 수 없어요.
Name CommandType Module PSSnapIn
---- ----------- ------ --------
Get-Date Function
Get-Date Cmdlet Microsoft.PowerShell.Utility
Get-Help Cmdlet Microsoft.PowerShell.Core
Get-Date에는 두 가지 출처가 있어요. 하나는 함수이고, 다른 하나는 Microsoft.PowerShell.Utility 모듈의 cmdlet이에요. 모듈은 Remove-Module로 제거할 수 있고, 함수는 Function: 드라이브에서 삭제하면 돼요.
Remove-Item Function:Get-Date
Function: 드라이브에 대한 자세한 내용은 about_Function_Provider를 보세요.
이름 충돌 관리
이름 충돌은 세션에 같은 이름을 가진 명령이 둘 이상 있을 때 생겨요. 모듈 가져오기는 모듈의 명령이 세션의 명령이나 항목과 이름이 같을 때 이름 충돌을 일으키죠.
Import-Module은 현재 세션의 명령을 숨기고 대체하는 명령을 추가할 수 있어요. 이름 충돌로 명령이 숨겨지거나 대체될 수 있는데, 명령 대체(command replacement) 는 가져온 모듈에 세션의 기존 명령과 같은 이름의 명령이 들어 있을 때 발생해요. 이때 새로 가져온 명령이 기존 명령보다 우선해요.
예를 들어 세션에 같은 이름의 함수와 cmdlet이 있으면 PowerShell은 기본적으로 함수를 실행해요. 같은 유형의 명령(예: 같은 이름의 cmdlet 두 개)이 세션에 있으면 기본적으로 가장 최근에 추가된 명령을 실행하죠.
우선 순위 규칙 설명과 숨겨진 명령 실행 방법을 포함한 자세한 내용은 about_Command_Precedence를 참고하세요.
숨겨지거나 대체된 명령은 명령 이름을 한정해 실행할 수 있어요. 즉, 실행하려는 명령 버전이 들어 있는 모듈의 이름을 붙이면 되죠. 예를 들어 이렇게요.
Microsoft.PowerShell.Utility\Get-Date
Get-Date 앞에 모듈 이름을 붙이면 Microsoft.PowerShell.Utility 모듈의 버전을 실행하게 돼요.
이름 충돌을 감지하려면 Get-Command cmdlet의 All 매개 변수를 쓰세요. 기본적으로 Get-Command는 명령 이름을 입력했을 때 실행되는 명령만 가져오지만, All 매개 변수는 세션에서 그 이름을 가진 모든 명령을 가져와요.
이름 충돌을 막으려면 Import-Module cmdlet의 NoClobber나 Prefix 매개 변수를 쓰면 돼요. Prefix 매개 변수는 가져온 명령 이름에 접두사를 붙여 세션에서 고유하게 만들고, NoClobber 매개 변수는 세션의 기존 명령을 숨기거나 대체하는 명령은 아예 가져오지 않아요.
Import-Module의 Alias, Cmdlet, Function, Variable 매개 변수로 가져올 명령만 골라서 세션에서 이름 충돌을 일으키는 명령을 배제할 수도 있어요.
모듈 작성자는 모듈 매니페스트의 DefaultCommandPrefix 속성으로 모든 명령 이름에 기본 접두사를 추가해 이름 충돌을 막을 수 있어요. 이때 Prefix 매개 변수의 값이 DefaultCommandPrefix의 값보다 우선해요.