PowerShell에서 프록시 사용하기: 시작하기 전에 알아야 할 것
Windows 자동화 스크립트를 작성하다 보면 외부 API 호출이 갑자기 차단되는 상황을 겪게 됩니다. Azure나 AWS 데이터센터 IP 대역이 차단되는 경우가 흔하며, 이때 PowerShell 프록시 설정이 필수적입니다. Invoke-WebRequest와 Invoke-RestMethod는 기본적으로 -Proxy 파라미터를 지원하지만, 실무에서는 지역 타겟팅, 세션 유지, 재시도 로직까지 고려해야 합니다.
이 가이드에서는 ProxyHat 게이트웨이(gate.proxyhat.com:8080)를 기준으로 PowerShell 환경에서 프록시를 안정적으로 사용하는 방법을 코드 중심으로 다룹니다. 모든 예제는 PowerShell 5.1과 PowerShell 7에서 동작하도록 작성되었습니다.
왜 데이터센터 IP가 차단되는가: 기술적 배경
많은 웹 서비스와 API 엔드포인트는 Cloudflare, Akamai, PerimeterX 같은 WAF/봇 방지 시스템을 통해 들어오는 요청의 IP를 검사합니다. 이 시스템들은 IANA가 할당한 데이터센터 IP 대역을 식별하고, 비정상적인 패턴으로 판단되면 HTTP 403이나 429 응답을 반환합니다.
PowerShell 스크립트가 Azure VM이나 AWS EC2에서 실행되는 경우, 아웃바운드 IP는 해당 클라우드 제공자의 대역에 속합니다. 예를 들어 Azure East US의 아웃바운드 IP 대역은 Microsoft가 공개하는 Azure IP Range JSON에서 확인할 수 있으며, 이 대역들은 주요 봇 방지 서비스에서 자동 차단 대상으로 등록되어 있습니다.
반면 레지덴셜 프록시는 실제 ISP가 부여한 가정용 IP에서 트래픽을 중계하므로, 일반 사용자의 요청과 구별하기 어렵습니다. 이것이 PowerShell 웹 스크래핑 작업에서 레지덴셜 프록시가 필요한 핵심 이유입니다.
기본 프록시 연결: -Proxy와 -ProxyCredential
가장 간단한 형태는 -Proxy 파라미터에 ProxyHat 게이트웨이 URL을 전달하는 것입니다. 인증이 필요한 경우 -ProxyCredential과 함께 사용합니다.
# 기본 프록시 연결 (대화형 자격증명)
$response = Invoke-WebRequest `
-Uri 'https://httpbin.org/ip' `
-Proxy 'http://gate.proxyhat.com:8080' `
-ProxyCredential (Get-Credential)
Write-Host $response.Content
# { "origin": "198.51.100.42" }
매번 자격증명을 입력하는 것은 자동화에 부적합하므로, PSCredential 객체를 스크립트 내에서 생성하는 것이 일반적입니다.
# 프록시 자격증명을 코드로 생성
$proxyUser = 'myuser'
$proxyPass = 'mypass'
$securePass = ConvertTo-SecureString $proxyPass -AsPlainText -Force
$proxyCred = New-Object System.Management.Automation.PSCredential($proxyUser, $securePass)
$response = Invoke-WebRequest `
-Uri 'https://httpbin.org/ip' `
-Proxy 'http://gate.proxyhat.com:8080' `
-ProxyCredential $proxyCred `
-UseBasicParsing
$response.Content
Windows 통합 인증을 사용하는 환경이라면 -ProxyUseDefaultCredentials 스위치를 사용할 수 있지만, ProxyHat과 같은 외부 프록시 서비스에서는 사용자명/비밀번호 방식이 표준입니다.
지역 타겟팅과 세션 유지: 사용자명에 플래그 인코딩
ProxyHat은 사용자명에 플래그를 인코딩하여 지역 타겟팅과 세션 제어를 지원합니다. 예를 들어 user-country-US는 미국 IP를, user-session-abc123은 고정 세션을 의미합니다. 이를 PSCredential에 담아 전달하면 됩니다.
# 국가별 지역 타겟팅 (미국)
$geoUser = 'user-country-US'
$securePass = ConvertTo-SecureString 'mypass' -AsPlainText -Force
$geoCred = New-Object System.Management.Automation.PSCredential($geoUser, $securePass)
$usResponse = Invoke-RestMethod `
-Uri 'https://httpbin.org/ip' `
-Proxy 'http://gate.proxyhat.com:8080' `
-ProxyCredential $geoCred
Write-Host "US IP: $($usResponse.origin)"
# 독일 베를린 + 세션 고정
$stickyUser = 'user-country-DE-city-berlin-session-abc123'
$stickyCred = New-Object System.Management.Automation.PSCredential($stickyUser, $securePass)
$deResponse = Invoke-RestMethod `
-Uri 'https://httpbin.org/ip' `
-Proxy 'http://gate.proxyhat.com:8080' `
-ProxyCredential $stickyCred
Write-Host "Berlin sticky IP: $($deResponse.origin)"
세션 ID를 변경하면 새 IP가 할당되므로, IP 로테이션은 세션 ID를 변경하면서 루프를 돌면 됩니다. 세션 유지 시간은 일반적으로 10~30분이며, 이 시간 내에는 동일한 IP가 유지됩니다.
System.Net.WebProxy로 더 세밀한 제어
PowerShell 7의 Invoke-WebRequest는 내부적으로 .NET HttpClient를 사용합니다. 더 세밀한 제어가 필요하다면 [System.Net.WebProxy] 객체를 직접 구성할 수 있습니다.
# WebProxy 객체를 사용한 세밀한 제어
$webProxy = New-Object System.Net.WebProxy('http://gate.proxyhat.com:8080', $false)
$webProxy.Credentials = New-Object System.Net.NetworkCredential('user-country-UK', 'mypass')
# HttpClientHandler에 프록시 적용 (PowerShell 7)
$handler = New-Object System.Net.Http.HttpClientHandler
$handler.Proxy = $webProxy
$handler.UseProxy = $true
$client = New-Object System.Net.Http.HttpClient($handler)
$response = $client.GetAsync('https://httpbin.org/ip').Result
$content = $response.Content.ReadAsStringAsync().Result
Write-Host $content
쿠키와 헤더 유지: WebRequestSession 활용
여러 요청에 걸쳐 쿠키와 헤더를 유지해야 하는 경우 -SessionVariable과 -WebSession을 사용합니다. 이는 로그인 후 인증이 필요한 페이지를 스크랩할 때 필수적입니다.
# 세션 변수로 쿠키/헤더 유지
$securePass = ConvertTo-SecureString 'mypass' -AsPlainText -Force
$proxyCred = New-Object System.Management.Automation.PSCredential('user-country-US', $securePass)
$proxy = 'http://gate.proxyhat.com:8080'
# 첫 번째 요청 - 세션 생성
$firstResponse = Invoke-WebRequest `
-Uri 'https://httpbin.org/cookies/set?sessionid=test123' `
-Proxy $proxy `
-ProxyCredential $proxyCred `
-SessionVariable session `
-UseBasicParsing
# User-Agent 및 헤더 설정
$headers = @{
'Accept' = 'application/json'
'X-Custom-Header' = 'MyApp/1.0'
}
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
# 두 번째 요청 - 세션 재사용
$secondResponse = Invoke-WebRequest `
-Uri 'https://httpbin.org/cookies' `
-Proxy $proxy `
-ProxyCredential $proxyCred `
-WebSession $session `
-Headers $headers `
-UserAgent $userAgent `
-UseBasicParsing
Write-Host $secondResponse.Content
# { "cookies": { "sessionid": "test123" } }
-SessionVariable로 생성된 $session 객체는 Microsoft.PowerShell.Commands.WebRequestSession 타입이며, 내부에 CookieContainer와 헤더 정보를 보존합니다. -WebSession으로 이 객체를 후속 요청에 전달하면 쿠키가 자동으로 재전송됩니다.
레지덴셜 프록시로 JSON API 페이징: 재시도와 백오프 포함
이제 실제 시나리오를 다뤄보겠습니다. 봇 방지 시스템이 활성화된 API를 페이징하면서 세션을 로테이션하고, 실패 시 지수 백오프로 재시도하는 완전한 예제입니다.
# JSON API 페이징 + 세션 로테이션 + 재시도/백오프
function Invoke-ProxiedApiCall {
param(
[string]$Uri,
[int]$MaxRetries = 3,
[int]$BaseDelaySec = 2
)
$proxyUrl = 'http://gate.proxyhat.com:8080'
$baseUser = 'user-country-US'
$securePass = ConvertTo-SecureString 'mypass' -AsPlainText -Force
for ($attempt = 1; $attempt -le $MaxRetries; $attempt++) {
# 세션 ID를 매번 변경하여 IP 로테이션
$sessionId = [System.Guid]::NewGuid().ToString('N').Substring(0, 8)
$userName = "$baseUser-session-$sessionId"
$cred = New-Object System.Management.Automation.PSCredential($userName, $securePass)
try {
$response = Invoke-RestMethod `
-Uri $Uri `
-Proxy $proxyUrl `
-ProxyCredential $cred `
-MaximumRetryCount 3 `
-RetryIntervalSec $BaseDelaySec `
-ErrorAction Stop
return $response
}
catch [System.Net.Http.HttpRequestException] {
$statusCode = $_.Exception.Response.StatusCode.value__
Write-Warning "Attempt $attempt failed with HTTP $statusCode on $Uri"
if ($statusCode -eq 403 -or $statusCode -eq 429) {
# 봇 방지 또는 rate limit - 더 긴 대기
$delay = [Math]::Pow(2, $attempt) * $BaseDelaySec
Write-Host "Backing off for $delay seconds..."
Start-Sleep -Seconds $delay
}
}
catch {
Write-Warning "Attempt $attempt failed: $($_.Exception.Message)"
if ($attempt -lt $MaxRetries) {
Start-Sleep -Seconds ($BaseDelaySec * $attempt)
}
}
}
throw "Failed after $MaxRetries attempts: $Uri"
}
# 사용 예: 페이지별로 API 호출
$baseUrl = 'https://api.example.com/items'
$allItems = @()
for ($page = 1; $page -le 50; $page++) {
$uri = "$baseUrl?page=$page&per_page=100"
$data = Invoke-ProxiedApiCall -Uri $uri -MaxRetries 4 -BaseDelaySec 2
$allItems += $data.items
Write-Host "Page $page: retrieved $($data.items.Count) items (total: $($allItems.Count))"
# 요청 간 500ms 대기
Start-Sleep -Milliseconds 500
}
Write-Host "Total items retrieved: $($allItems.Count)"
-MaximumRetryCount와 -RetryIntervalSec는 PowerShell 5.1 이상에서 기본 지원되는 파라미터입니다. 하지만 이 파라미터는 5xx 오류에만 자동으로 반응하므로, 403/429 응답은 try/catch 내에서 별도로 처리해야 합니다.
프록시 유형 비교: 레지덴셜 vs 데이터센터 vs 모바일
| 프록시 유형 | IP 출처 | 차단 확률 | 평균 응답 시간 | 비용 | 적합한 용도 |
|---|---|---|---|---|---|
| 레지덴셜 | ISP 가정용 IP | 낮음 | 200~800ms | 중간~높음 | 봇 방지 회피, SERP 스크래핑 |
| 데이터센터 | 클라우드/호스팅 IP | 높음 | 50~200ms | 낮음 | 공개 API, 차단 없는 엔드포인트 |
| 모바일 | 4G/5G 통신사 IP | 매우 낮음 | 500~2000ms | 높음 | 소셜 미디어, 고도 보호 사이트 |
ProxyHat은 세 가지 유형을 모두 지원하며, 프록시 가격 페이지에서 각 유형별 요금을 확인할 수 있습니다. PowerShell 자동화에서는 레지덴셜 프록시가 가장 균형 잡힌 선택입니다.
프로덕션 팁: 환경 변수, TLS, 병렬 처리
환경 변수로 자식 프로세스에 프록시 전달
PowerShell에서 실행하는 자식 프로세스(curl, .NET 앱 등)에 프록시를 전달하려면 환경 변수를 설정합니다.
# 환경 변수로 프록시 설정 (자식 프로세스에 상속됨)
$env:HTTP_PROXY = 'http://user-country-US:mypass@gate.proxyhat.com:8080'
$env:HTTPS_PROXY = 'http://user-country-US:mypass@gate.proxyhat.com:8080'
# 이제 curl이나 .NET HttpClient가 자동으로 프록시 사용
curl.exe https://httpbin.org/ip
# 작업 완료 후 환경 변수 제거
Remove-Item Env:HTTP_PROXY
Remove-Item Env:HTTPS_PROXY
TLS 버전 강제 설정
PowerShell 5.1은 기본적으로 TLS 1.0을 사용하려 할 수 있으므로, 최신 API와 통신하려면 TLS 1.2 이상을 강제해야 합니다.
# TLS 1.2 강제 (PowerShell 5.1)
[Net.ServicePointManager]::SecurityProtocol = `
[Net.SecurityProtocolType]::Tls12 -bor `
[Net.SecurityProtocolType]::Tls13
# PowerShell 7에서는 별도 설정 불필요 - 기본적으로 TLS 1.2+ 사용
# 단, Invoke-WebRequest -SslProtocol Tls12 로 명시 가능
$response = Invoke-WebRequest `
-Uri 'https://httpbin.org/get' `
-Proxy 'http://gate.proxyhat.com:8080' `
-ProxyCredential $proxyCred `
-SslProtocol Tls12
PowerShell 7 ForEach-Object -Parallel로 병렬 요청
PowerShell 7의 -Parallel 스위치를 사용하면 여러 요청을 동시에 실행할 수 있습니다. 각 런스페이스(runspace)는 독립적이므로 세션 변수를 공유할 수 없지만, 프록시 자격증명은 안전하게 전달할 수 있습니다.
# PowerShell 7 병렬 처리 - 10개 URL 동시 요청
$urls = 1..50 | ForEach-Object { "https://httpbin.org/delay/1?id=$_" }
$securePass = ConvertTo-SecureString 'mypass' -AsPlainText -Force
$results = $urls | ForEach-Object -Parallel {
$proxyUrl = 'http://gate.proxyhat.com:8080'
$sessionId = [System.Guid]::NewGuid().ToString('N').Substring(0, 8)
$userName = "user-country-US-session-$sessionId"
$cred = New-Object System.Management.Automation.PSCredential($userName, $using:securePass)
try {
$response = Invoke-WebRequest `
-Uri $_ `
-Proxy $proxyUrl `
-ProxyCredential $cred `
-UseBasicParsing `
-TimeoutSec 15 `
-ErrorAction Stop
[PSCustomObject]@{
Url = $_
Status = $response.StatusCode
Length = $response.Content.Length
}
}
catch {
[PSCustomObject]@{
Url = $_
Status = $_.Exception.Message
Length = 0
}
}
} -ThrottleLimit 10
$results | Format-Table -AutoSize
-ThrottleLimit 10은 동시에 최대 10개 요청을 실행합니다. ProxyHat 레지덴셜 프록시는 100개 이상의 동시 세션을 지원하지만, 대상 서비스의 rate limit을 고려하여 적절히 조정해야 합니다.
윤리와 법적 고려사항
프록시를 사용한 데이터 수집은 강력한 도구지만, 윤리적·법적 경계를 반드시 지켜야 합니다.
- 공개 데이터만 수집: 로그인 없이 접근 가능한 페이지나 API만 대상으로 합니다.
- robots.txt 준수: 웹사이트의 크롤링 정책을 확인하고 존중합니다.
- 미국 CFAA: Computer Fraud and Abuse Act는 무단 접근을 금지하며, ToS 위반 시 법적 위험이 있습니다.
- EU GDPR: 개인정보가 포함된 데이터를 수집할 경우 GDPR 적용 대상이 될 수 있습니다.
- 공식 API 우선: 대상 서비스가 공식 API를 제공한다면 프록시 기반 스크래핑보다 API를 사용하는 것이 안전하고 효율적입니다.
ProxyHat은 공식 문서를 통해 프록시 사용 가이드라인을 제공하며, 지원 위치 목록에서 전 세계 190개국 이상의 IP를 확인할 수 있습니다.
주요 요약: Key Takeaways
- 기본 연결:
-Proxy 'http://gate.proxyhat.com:8080'과-ProxyCredential로 즉시 시작 가능합니다.- 지역 타겟팅: 사용자명에
user-country-US형식으로 인코딩하여 원하는 국가의 IP를 사용합니다.- 세션 제어:
user-session-abc123으로 고정 IP를 유지하거나, 세션 ID를 변경하여 IP를 로테이션합니다.- 쿠키 유지:
-SessionVariable/-WebSession으로 인증 상태를 여러 요청에 걸쳐 유지합니다.- 재시도/백오프:
-MaximumRetryCount+try/catch로 403/429 응답에 대한 지수 백오프를 구현합니다.- 병렬 처리: PowerShell 7의
ForEach-Object -Parallel로 동시 요청을 실행하고-ThrottleLimit로 제어합니다.- 윤리 준수: 공개 데이터만, 공식 API 우선, robots.txt 및 법적 규제 존중.
ProxyHat SDK는 동일한 게이트웨이 엔드포인트를 공유하므로, PowerShell 스크립트에서 설정한 연결 방식을 다른 언어의 SDK에서도 동일하게 적용할 수 있습니다. 웹 스크래핑 사용 사례와 SERP 추적 사용 사례 페이지에서 더 많은 실전 예제를 확인하세요.






