개요
모듈은 cmdlet·함수·변수·별칭 등을 하나의 재사용 가능한 단위로 묶은 패키지다. 57장부터 만들어 온 함수들이 지금까지는 세션이나 스크립트 파일 안에만 존재했다면, 이 장부터는 그 함수들을 다른 사람과 공유하거나 여러 스크립트에서 재사용할 수 있는 형태로 포장하는 법을 다루며 Part 9(모듈과 병렬 처리)를 시작한다.
정신 모델은 “스크립트 모듈(.psm1)이 실제 코드를 담는 몸통이고, 모듈 매니페스트(.psd1)는 그 모듈의 이름표이자 설명서"라는 것이다. .psm1만으로도 모듈은 동작하지만, .psd1이 있어야 버전·의존성·작성자 같은 메타데이터를 함께 관리할 수 있다.
사용법
| |
종류
| 파일 | 역할 |
|---|---|
.psm1(스크립트 모듈) | 함수·변수 정의가 담긴 실제 코드 파일 |
.psd1(모듈 매니페스트) | 버전, 작성자, 필요 PowerShell 버전, 내보낼 멤버 목록 등 메타데이터 |
.dll(바이너리 모듈) | C#으로 컴파일된 네이티브 모듈(이 컬렉션은 스크립트 모듈에 집중) |
Export-ModuleMember | .psm1 안에서 어떤 함수·변수·별칭을 외부에 공개할지 명시적으로 선택 |
| 모듈 폴더 구조 | MyModule\MyModule.psm1, MyModule\MyModule.psd1처럼 폴더명과 파일명을 일치시켜야 함 |
예시
| |
| |
| |
주의사항·함정
Export-ModuleMember을 빠뜨리면 .psm1 안의 모든 함수가 기본적으로 전부 공개된다: 의도적으로 내부 헬퍼 함수를 숨기고 싶다면 반드시 Export-ModuleMember -Function으로 공개할 함수를 명시적으로 선택해야 한다. 이 문을 빠뜨리면 “내부용으로만 쓰려던 함수"가 모듈을 가져온 세션에 그대로 노출돼, 62장에서 다룬 스코프 경계가 모듈 수준에서 무의미해진다.
모듈 폴더 이름과 .psm1/.psd1 파일 이름이 정확히 일치해야 한다: MyModule 폴더 안에 MyModule.psm1, MyModule.psd1이 있어야 PowerShell이 이를 하나의 모듈로 인식한다. 폴더명과 파일명이 다르면(예: Utils 폴더 안의 MyModule.psm1) 모듈이 정상적으로 검색·임포트되지 않는다.
모듈이 표준 경로($Env:PSModulePath) 밖에 있으면 자동 임포트되지 않는다: 30장에서 다룬 Env: 프로바이더로 확인할 수 있는 이 경로 목록에 없는 위치의 모듈은, 75장에서 다룰 Import-Module에 전체 경로를 명시적으로 지정해야만 불러올 수 있다.
이식성: Bash에는 표준화된 모듈 시스템이 없어 source 명령으로 여러 스크립트를 이어 붙이는 정도가 최선이고, 이름 충돌이나 버전 관리는 스크립트 작성자가 직접 신경 써야 한다. Python의 패키지(__init__.py)나 Node.js의 package.json이 개념적으로 가장 가깝다 — .psd1 매니페스트가 package.json의 역할을, .psm1이 패키지 진입점 역할을 한다고 보면 비교하기 쉽다.
![Featured image of post [PowerShell] 74. 모듈 개념과 구조(.psm1/.psd1)](/post/powershell/module-structure-psm1-psd1-powershell/wordcloud_hu_9285e5f1ac0ef616.webp)
![[PowerShell] 72. PSScriptAnalyzer — 정적 분석과 코딩 규칙](/post/powershell/psscriptanalyzer-static-analysis-powershell/wordcloud_hu_fb1acde140a2de4f.webp)
![[PowerShell] 73. Measure-Command — 성능 측정과 벤치마킹](/post/powershell/measure-command-benchmark-powershell/wordcloud_hu_b078f0ca79bf08ab.webp)
![[PowerShell] 74. 모듈 개념과 구조(.psm1/.psd1)](/post/powershell/module-structure-psm1-psd1-powershell/wordcloud_hu_7fca0b454a750e2a.webp)
![[PowerShell] 75. Import-Module/Get-Module/Remove-Module](/post/powershell/import-get-remove-module-powershell/wordcloud_hu_f7c6ed2cf0491565.webp)
![[PowerShell] 76. PowerShell Gallery — Install-Module/Find-Module](/post/powershell/powershell-gallery-install-find-module-powershell/wordcloud_hu_68568dc7c4947f25.webp)
![[PowerShell] 77. PowerShell 클래스(class 키워드)](/post/powershell/powershell-class-keyword-powershell/wordcloud_hu_5ff5e6ec1d4f4d49.webp)
![[PowerShell] 78. Start-Job/Get-Job/Receive-Job — 백그라운드 작업](/post/powershell/start-job-get-job-receive-job-powershell/wordcloud_hu_f975cbd44945c564.webp)
![[PowerShell] 79. ForEach-Object -Parallel(PowerShell 7+)](/post/powershell/foreach-object-parallel-threadjob-powershell/wordcloud_hu_30c9034b5b05c027.webp)