개요
Invoke-WebRequest와 Invoke-RestMethod는 PowerShell에서 HTTP·HTTPS 요청을 보내는 두 개의 핵심 cmdlet이다. 지금까지 Part 16에서 ping·포트·DNS로 “연결이 되는가"를 확인했다면, 이 장은 그 연결 위에서 실제로 “데이터를 주고받는” 단계로 넘어간다 — curl이나 웹 브라우저의 역할을 PowerShell 객체 파이프라인 안에서 수행하는 것이다.
정신 모델은 “Invoke-WebRequest가 HTTP 응답을 있는 그대로(상태 코드, 헤더, 원본 본문, 링크·폼 목록) 객체로 포장해 돌려주는 범용 웹 클라이언트라면, Invoke-RestMethod는 그 본문이 JSON이나 XML이라는 것을 알고 있다고 가정하고 곧바로 PowerShell 객체로 역직렬화해 주는 REST API 전용 클라이언트"라는 것이다. 둘 다 같은 내부 엔진을 쓰지만, “응답을 파싱해서 쓸 것인가, 원본 그대로 다룰 것인가"에 따라 선택이 갈린다.
실무에서는 어느 API를 처음 다룰 때 응답 구조를 모르는 상태에서 Invoke-RestMethod를 먼저 호출했다가 예상과 다른 형태의 객체가 나와 당황하는 경우가 흔한데, 이럴 때는 Invoke-WebRequest로 원본 Content 문자열을 먼저 눈으로 확인한 뒤 Invoke-RestMethod로 전환하는 순서가 안전하다.
사용법
| |
종류
| cmdlet | 반환 값 | 적합한 상황 |
|---|---|---|
Invoke-WebRequest | BasicHtmlWebResponseObject(StatusCode, Content, Headers, Links, Forms 등) | HTML 페이지 크롤링, 파일 다운로드, 응답 헤더·상태 코드 자체를 검사해야 할 때 |
Invoke-RestMethod | JSON/XML을 역직렬화한 PSCustomObject(또는 배열) | REST API 호출, 응답 본문을 곧바로 PowerShell 객체로 다뤄야 할 때 |
| 공통 매개변수 | 의미 |
|---|---|
-Method | Get(기본)/Post/Put/Delete/Patch 등 HTTP 메서드 |
-Body | 요청 본문(문자열, 해시테이블, 또는 ConvertTo-Json한 객체) |
-Headers | 요청 헤더를 담은 해시테이블(Authorization, Accept 등) |
-ContentType | 요청 본문의 MIME 타입(예: application/json) |
-OutFile | 응답 본문을 화면 대신 파일로 저장 |
예시
| |
주의사항·함정
Invoke-RestMethod가 응답 헤더나 상태 코드에 직접 접근할 방법이 기본적으로 없다는 것을 놓치기 쉽다: Invoke-RestMethod는 본문을 곧바로 객체로 반환하기 때문에, Invoke-WebRequest처럼 .StatusCode나 .Headers에 자연스럽게 접근할 수 없다. PowerShell 7.4부터는 -ResponseHeadersVariable로 헤더를 별도 변수에 담을 수 있지만, 이를 모르면 REST API 호출 결과에서 상태 코드를 확인하려다 막힐 수 있다.
PowerShell 7.4부터 요청 인코딩 기본값이 ASCII에서 UTF-8로 바뀌었다: 이전 버전 스크립트를 최신 pwsh로 옮길 때, 비ASCII 문자(한글 등)가 포함된 요청 본문의 인코딩 방식이 달라져 API 서버가 다르게 해석할 수 있다. 다른 인코딩이 필요하면 -Headers의 Content-Type에 charset 속성을 명시적으로 지정해야 한다.
-Body에 해시테이블을 그냥 넘기면 JSON이 아니라 폼 인코딩(application/x-www-form-urlencoded)으로 전송된다: REST API 대부분은 JSON 본문을 기대하므로, JSON을 보내려면 $body | ConvertTo-Json으로 명시적으로 변환한 뒤 -ContentType "application/json"을 함께 지정해야 한다. 이 변환을 빠뜨리면 서버가 요청 본문을 파싱하지 못해 400 오류가 돌아온다.
대량의 페이지네이션된 API 응답을 반복 호출할 때 매번 새 TCP 연결을 맺는 비용을 간과하기 쉽다: -SessionVariable로 세션을 만들어 재사용하면(Invoke-WebRequest -SessionVariable session 이후 -WebSession $session으로 후속 요청에 전달) 쿠키·연결을 유지할 수 있어, 로그인 세션이 필요한 API를 반복 호출할 때 효율적이다.
이식성: curl(Linux/macOS 및 Windows 10+ 기본 포함)은 명령줄 옵션이 훨씬 세분화돼 있고 원시 텍스트 응답을 그대로 출력하는 반면, Invoke-RestMethod는 JSON을 자동으로 객체로 바꿔줘 jq 같은 별도 파싱 도구가 필요 없다. 다만 curl은 사실상 모든 유닉스 계열 시스템의 표준 도구라 이식성 자체는 더 넓고, 셸 스크립트 간 공유가 쉽다는 장점이 있다 — PowerShell 환경 안에서 객체로 후처리할 계획이 없다면 curl이 더 간결할 수 있다.
![Featured image of post [PowerShell] 113. Invoke-WebRequest/Invoke-RestMethod](/post/powershell/invoke-webrequest-invoke-restmethod-powershell/wordcloud_hu_980f1601d1b98530.webp)
![[PowerShell] 111. Resolve-DnsName — DNS 질의](/post/powershell/resolve-dnsname-dns-query-powershell/wordcloud_hu_979b25d1d2bad2ef.webp)
![[PowerShell] 112. Get-NetIPConfiguration/Get-NetAdapter](/post/powershell/get-netipconfiguration-get-netadapter-powershell/wordcloud_hu_52dd3e956ba2b525.webp)
![[PowerShell] 113. Invoke-WebRequest/Invoke-RestMethod](/post/powershell/invoke-webrequest-invoke-restmethod-powershell/wordcloud_hu_d83d75f2879b9315.webp)
![[PowerShell] 114. New-Guid/Get-Random — 유틸리티 모음](/post/powershell/new-guid-get-random-utility-powershell/wordcloud_hu_e9ded1c7c447f201.webp)
![[PowerShell] 115. ActiveDirectory 모듈 개요와 Get-ADUser](/post/powershell/activedirectory-module-get-aduser-powershell/wordcloud_hu_975c1aa2fa88b4a7.webp)
![[PowerShell] 48. ConvertTo-Json/ConvertFrom-Json](/post/powershell/convertto-convertfrom-json-powershell/wordcloud_hu_a8973bead7a830f9.webp)
![[PowerShell] 109. Test-Connection — ping 대응](/post/powershell/test-connection-ping-powershell/wordcloud_hu_5dcd5e1b70095610.webp)
![[PowerShell] 110. Test-NetConnection — 포트·경로 진단](/post/powershell/test-netconnection-port-diagnostic-powershell/wordcloud_hu_4ef96a3f0e037e64.webp)