수정 이력(1건, 최종 수정 2026년 09월 03일)
이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.
- 한국어 전면 재작성에 맞춰 본문 표현을 바로잡았습니다. 기술적인 주장은 일본어판과 같습니다.
- 최초 공개
이 글을 인용하기(DOI(등록된 아카이브): 10.5281/zenodo.22176228)
아래 DOI는 이전에 등록된 아카이브를 가리키며 현재 본문과 다를 수 있습니다. 현재 본문을 참조할 때는 이 페이지의 URL을 사용하세요.
Go Komura (2026). 「사내 프록시와 Windows 앱 ── WinINET·WinHTTP·.NET의 프록시 해석을 정리한다」. 합동회사 코무라소프트. https://comcomponent.com/ko/blog/windows-proxy-wininet-winhttp-dotnet/
- DOI(등록된 아카이브)
- 10.5281/zenodo.22176228
- DOI(마지막 등록 버전)
- 10.5281/zenodo.22176229
「브라우저에서는 외부 사이트를 열 수 있는데, 업무 앱만 외부 API에 연결되지 않는다」「개발 컴퓨터에서는 동작하는데, 고객사 네트워크에서는 타임아웃한다」「수동으로 실행하면 통신할 수 있는데, Windows 서비스로 만드는 순간 실패한다」── 사내 프록시가 있는 환경에서 업무 앱을 돌릴 때, 이런 상담은 단골 중의 단골입니다.
원인 대부분은 프록시 서버 쪽 장애도, 앱의 버그도 아닙니다. Windows에는 「프록시 설정」이라고 부르는 것이 여러 계열로 나뉘어 있고, 어느 설정을 누가 읽는지는 앱(이 쓰는 HTTP 스택)과 실행 계정마다 다르다── 이 불일치입니다. 브라우저가 읽는 설정과, 서비스가 읽는 설정과, .NET의 HttpClient가 읽는 설정은 각각 다른 것이 될 수 있습니다. 이 구조만 파악하면, 「브라우저에서는 연결되는데」라는 증상의 원인 분리가 놀랄 만큼 빨라집니다.
이 글에서는 중소기업 IT 담당자와 Windows 앱 개발자를 대상으로, WinINET·WinHTTP·환경 변수라는 세 계열의 프록시 설정, PAC와 WPAD에 의한 자동 구성, .NET Framework와 .NET(Core 이후)의 프록시 해석 차이, 인증 프록시(407), TLS 검사, 그리고 실무의 원인 분리 절차까지를 한 흐름으로 정리합니다. HttpClient의 생성 패턴이나 타임아웃 설계 자체는 「HttpClient를 using으로 감싸면 안 되는 이유」에서 다루므로, 이 글은 프록시 해석에 집중합니다.
1. 먼저 결론
- Windows의 프록시 설정은 하나가 아니라, 적어도 세 계열이 있습니다. ①WinINET의 사용자별 설정(설정 앱의 「프록시」= 옛 인터넷 옵션), ②WinHTTP의 컴퓨터 설정(
netsh winhttp), ③환경 변수HTTP_PROXY/HTTPS_PROXY입니다. 어느 것을 읽을지는 앱 쪽에서 정해져 있습니다.12 - 설정 앱에서 보이는 「프록시」는 WinINET의 사용자별 설정입니다. 브라우저나 대화형 앱은 이것을 읽지만, Windows 서비스는 읽지 않습니다. WinINET은 서비스에서의 이용이 지원되지 않으며, 서비스 용도는 WinHTTP가 담당합니다.13
- 「수동이면 동작하는데 서비스면 동작하지 않는다」의 가장 흔한 원인은 실행 계정의 차이입니다. LocalSystem이나 서비스 계정에는, 관리자가 자기 화면에서 설정한 사용자별 프록시가 보이지 않습니다.34
netsh winhttp set proxy는 정적 설정이며, PAC·자동 검색·프록시 인증을 다루지 않습니다. PAC나 WPAD를 컴퓨터 단위로 구성하려면netsh winhttp set advproxy쪽 설정이 필요합니다.42- PAC의 결과는 URL마다 달라집니다. PAC 파일의
FindProxyForURL함수는 URL과 호스트를 인자로 받아, 프록시 목록 또는 직접 연결(DIRECT)을 반환합니다. 「저 사이트는 통과하는데 이 API만 통과하지 못한다」는 PAC의 분기가 원인인 경우가 있습니다.56 - .NET(Core 이후)의 HttpClient는 환경 변수 → Windows의 사용자 프록시 설정 순으로 기본 프록시를 초기화합니다.
HTTP_PROXY·HTTPS_PROXY·ALL_PROXY중 하나라도 정의되어 있으면 OS 설정보다 우선하므로, 「누가 환경 변수를 남겨 두었다」는 사고가 일어날 수 있습니다.7 - .NET Framework의 기본은 실행 중인 계정의 인터넷 옵션이며, app.config의
defaultProxy로 덮어쓸 수 있습니다. 구성 파일의 설정이 시스템 설정보다 우선합니다.89 - 407은 프록시 인증의 오류이며, 401(서버 인증)과는 별개입니다. 방식은 Negotiate·NTLM·Basic 등이 있고, .NET에서는
DefaultProxyCredentials나WebProxy.UseDefaultCredentials로 자격 증명을 넘깁니다. 서비스 계정에서는 「기본 자격 증명」의 내용이 바뀐다는 점에 주의합니다.101112 - TLS 검사형 프록시는 사내 CA 인증서의 배포와 세트로 비로소 성립합니다. 배포되지 않은 컴퓨터·런타임에서는 인증서 검증 오류가 됩니다. 앱 쪽에서 검증을 끄는 것이 아니라, 인증서 저장소로의 배포로 해결합니다.134
한 문장으로 정리하면, 「프록시 설정을 확인했다」고 말할 때, 세 계열 중 어느 것을·어느 계정에서 보고 확인했는지를 항상 말할 수 있게 한다── 이것이 이 글의 주제입니다.
그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 19건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle
2. Windows에는 「프록시 설정」이 세 계열 있다
먼저 전체 지도입니다. Windows 위에서 앱이 사내 프록시를 찾는 경로는 크게 다음 세 계열로 나뉩니다.
| 설정 계열 | 설정 위치·명령 | 범위 | 주로 읽는 것 |
|---|---|---|---|
| ① WinINET(인터넷 옵션) | 설정 앱→네트워크 및 인터넷→프록시, inetcpl.cpl |
사용자별(기본) | 브라우저, 대화형 데스크톱 앱, .NET Framework의 기본 |
| ② WinHTTP(컴퓨터 설정) | netsh winhttp set proxy / set advproxy |
컴퓨터 | Windows 서비스, OS 구성 요소의 일부 |
| ③ 환경 변수 | HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY |
프로세스(정의한 곳에 따라 상속) | .NET(Core 이후)의 HttpClient, curl, Node.js·Python 등 크로스 플랫폼 계열 도구 |
①은 「Windows의 프록시 설정」으로 일반적으로 인식되는 것이며, 실체는 WinINET의 구성입니다. 역사적으로는 Internet Explorer의 인터넷 옵션이며, 기본으로는 사용자마다 저장됩니다.4
②는 서비스처럼 「로그온한 사용자가 없는 맥락」을 위한, 컴퓨터 단위의 기본값입니다. ③은 주로 크로스 플랫폼에서 온 도구의 관례이며, Windows에서도 .NET(Core 이후)이나 curl 등이 이것을 읽습니다.7
중요한 점은, 어느 계열을 읽을지를 정하는 것은 설정 쪽이 아니라 앱 쪽이라는 점입니다. 앱이 내부에서 WinINET을 쓰고 있으면 ①, WinHTTP라면 ②(또는 앱 고유의 지정), .NET(Core 이후)라면 ③→①의 순으로, 읽는 곳이 정해져 있습니다. 그래서 「프록시 설정은 맞는데 연결되지 않는다」가 아니라, 「앱이 읽고 있는 계열이, 확인한 계열과 달랐다」가 실상인 경우가 많습니다.
참고로, 그룹 정책 「프록시 설정을 사용자별이 아니라 컴퓨터별로 설정한다」를 켜면 ①을 컴퓨터 단위로 바꿔 모든 사용자에게 같은 설정을 적용할 수 있습니다. MDM(Intune 등)이라면 NetworkProxy CSP로 장치 단위로 구성할 수 있습니다.4
3. WinINET과 WinHTTP ── 대화형 앱용과 서비스용
3.1. 역할의 차이
WinINET과 WinHTTP는 둘 다 Windows 기본 HTTP 클라이언트 스택이지만, 가정하는 쓰임새가 다릅니다.
- WinINET: 대화형 데스크톱 앱용. 사용자의 인터넷 옵션(프록시·Cookie·자격 증명 캐시)을 자동으로 이어받고, 필요하면 자격 증명 입력 UI도 띄울 수 있습니다. 다만 서비스나 서비스에 가까운 프로세스에서의 이용은 지원되지 않습니다.1
- WinHTTP: 서비스·서버 사이드용. 서비스 계정에서의 실행, 스레드의 가장(impersonation), 세션 분리를 지원하는 대신, 사용자의 브라우저 설정·Cookie·자격 증명은 공유하지 않습니다. UI도 띄우지 않습니다.3
Microsoft 자신의 지침도 분명합니다. 「서비스 안에서, 또는 세션 분리와 가장이 필요한 서비스에 가까운 프로세스에서 돌리는 것이 아니면 WinINET을 쓴다」, 거꾸로 말하면 서비스라면 WinHTTP입니다.1
3.2. netsh winhttp의 기본 조작
WinHTTP의 컴퓨터 기본 프록시는 netsh로 조작합니다.2
:: 현재의 WinHTTP 프록시 설정을 표시
netsh winhttp show proxy
:: 정적 프록시를 설정(바이패스 목록 포함)
netsh winhttp set proxy proxy-server="proxy.example.co.jp:8080" bypass-list="*.example.co.jp;<local>"
:: 인터넷 옵션(WinINET)의 설정을 가져오기
netsh winhttp import proxy source=ie
:: 기본(DIRECT)으로 되돌리기
netsh winhttp reset proxy
여기서 잡아 둘 제약은 두 가지입니다.
netsh winhttp set proxy는 정적 설정입니다. 프록시의 자동 검색도, PAC URL 지정도, 프록시 인증도 다루지 않습니다.4import proxy source=ie는 실행 시점의 정적 설정을 복사할 뿐이며, 그 뒤 인터넷 옵션 쪽을 바꿔도 따라가지 않습니다. PAC나 자동 검색을 포함한 컴퓨터 단위 구성이 필요한 경우는netsh winhttp set advproxy로 JSON 형식의 상세 설정(Proxy·ProxyBypass·AutoconfigUrl·AutoDetect)을 구성합니다.2
3.3. 가장 흔한 함정: 서비스는 사용자의 IE 설정을 읽지 않는다
현장에서 가장 많은 패턴을 시간 순으로 쓰면 이렇습니다.
- 개발자가 자기 PC에서 도구를 실행 → 자기 사용자별 프록시 설정(①)이 적용되어 동작한다
- 운영에서는 Windows 서비스(Windows 서비스 만드는 방법과 운영)로 LocalSystem에서 상주시킨다
- LocalSystem에서 보이는 설정은 별개(사용자별 설정은 보이지 않고, WinHTTP 컴퓨터 설정은 미구성=DIRECT) → 외부 API로 직접 연결을 시도해 타임아웃
「같은 컴퓨터인데 동작하지 않는다」가 아니라, 같은 컴퓨터라도 실행 계정이 다르면 보이는 프록시 설정이 다릅니다. 사용자가 로그온하지 않은 상태에서도 통신하는 프로세스에는, 그 프로세스의 HTTP 스택이 실제로 읽는 형태로 컴퓨터 단위 설정을 마련하는 것이 정석입니다. WinHTTP를 쓰는 네이티브 앱이나 Windows 구성 요소라면 netsh의 WinHTTP 설정이 적용됩니다.4 반면 .NET(Core 이후)의 HttpClient는 WinHTTP의 컴퓨터 설정을 읽지 않으므로(5장 참조), .NET으로 만든 서비스에는 시스템 환경 변수(HTTPS_PROXY 등)를 설정하거나, 앱 설정에서 HttpClientHandler.Proxy로 명시합니다.
반대 방향의 사고도 있습니다. 노트북처럼 사내와 사외를 오가는 단말에 netsh winhttp set proxy로 정적 프록시를 고정해 두면, 사외에서는 그 프록시에 도달하지 못해 통신이 전부 실패합니다. 컴퓨터 정적 설정은 네트워크 구성이 바뀌지 않는 서버용 수단으로 생각합니다.4
4. PAC와 WPAD ── 「자동 구성」의 내용
4.1. PAC 파일과 FindProxyForURL
PAC(Proxy Auto-Configuration) 파일은 「이 URL에는 어느 프록시를 쓸지」를 계산하는 JavaScript(ECMAScript)이며, FindProxyForURL(url, host)라는 함수를 반드시 포함합니다. 이 함수는 써야 할 프록시 목록을 반환하거나, 프록시를 쓰지 않고 직접 연결해도 됨을 특별한 반환값(DIRECT)으로 나타냅니다.5
function FindProxyForURL(url, host) {
// 사내 도메인과 사설 주소는 직접 연결
if (dnsDomainIs(host, ".example.co.jp") ||
isInNet(host, "10.0.0.0", "255.0.0.0")) {
return "DIRECT";
}
// 그 밖은 프록시 경유. 앞쪽이 쓰이지 않으면 다음으로 넘어감
return "PROXY proxy1.example.co.jp:8080; PROXY proxy2.example.co.jp:8080; DIRECT";
}
여기서 실무적인 귀결이 두 가지 나옵니다.
- 프록시 해석은 URL마다 수행할 필요가 있습니다. PAC는 URL(호스트)에 따라 다른 프록시나 직접 연결을 반환할 수 있으므로, WinHTTP의 자동 프록시 기능도 요청 대상 URL을 넘겨 그때그때 조회하는 설계입니다.6 「브라우저에서 다른 사이트는 보인다」는 것은, 문제의 API가 같은 경로를 지난다는 증거가 되지 않습니다.
- DIRECT는 「프록시 없이 가라」는 지시입니다. 사내 대상이어야 할 통신이 프록시 로그에 나타나지 않는 경우, PAC가 DIRECT를 반환하고 있거나 바이패스 목록에 일치하고 있을 가능성을 먼저 의심합니다.
4.2. WPAD에 의한 자동 검색
「설정을 자동으로 검색한다」를 켜면, WPAD(Web Proxy Auto-Discovery) 프로토콜로 PAC 파일의 위치를 찾습니다. 일반적인 구성에서는 DHCP에서 PAC URL을 배포하거나, DNS에서 wpad라는 이름의 호스트를 조회해 http://wpad/wpad.dat 같은 URL에서 PAC를 내려받습니다.14
즉 「자동 검색」은 마법이 아니라, DHCP/DNS에 WPAD용 구성이 마련된 네트워크에서만 동작하는 구조입니다. 그런 구성이 없는 네트워크에서 자동 검색만 켜도, 검색 실패의 대기 시간이 늘어날 뿐입니다.
4.3. PAC를 읽지 못하는 클라이언트의 동작
모든 클라이언트가 PAC를 평가할 수 있는 것은 아닙니다.
netsh winhttp set proxy의 정적 설정은 PAC를 평가하지 않습니다.4- 환경 변수
HTTP_PROXY방식의 도구는 원칙적으로 고정 프록시 URL만 쓸 수 있습니다(PAC URL을 쓰는 자리가 없습니다).7 - WinHTTP를 직접 쓰는 네이티브 앱의 경우, 세션을 여는 방식에 따라 달라집니다. Windows 8.1 이후의
WinHttpOpen에서WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY를 지정해 연 앱은 시스템/사용자의 프록시 설정(WPAD/PAC 포함)을 WinHTTP 쪽이 요청마다 자동으로 해석합니다.15 반면 종래의WINHTTP_ACCESS_TYPE_DEFAULT_PROXY(8.1 이후에는 사용이 권장되지 않음) 등으로 연 경우, 자동 프록시는 HTTP 스택에 통합되어 있지 않아, 앱이 스스로WinHttpGetProxyForUrl을 호출해 결과를 요청에 설정해야 합니다. 즉 오래된 구현의 앱에서는 PAC가 있어도 쓰이지 않는 경우가 있습니다.5
「브라우저는 PAC로 올바른 프록시에 가지만, 업무 앱은 PAC를 읽지 않고 직접 연결을 시도해 실패한다」── 이것도 단골의 불일치입니다. PAC로 운영하는 네트워크에서는 PAC를 읽지 못하는 클라이언트를 위해 정적 설정이나 환경 변수로 된 폴백 수단을 정해 둘 필요가 있습니다.
5. .NET의 프록시 해석 ── Framework와 Core 이후는 별개
.NET 앱의 「어느 프록시 설정을 읽는가」는 .NET Framework와 .NET(Core 이후)에서 기본이 다릅니다. 여기를 섞으면 Framework 시절의 지식으로 .NET 8 앱을 조사하다 빗나갑니다.
5.1. .NET Framework ── 기본은 인터넷 옵션, defaultProxy로 덮어쓰기
.NET Framework에서는 HttpWebRequest나(그 위에 올라가는) HttpClient가 Proxy를 명시하지 않는 한 기본 프록시를 씁니다. 기본 프록시는 시스템의 인터넷 설정(실행 중인 계정의 WinINET 설정)과 구성 파일의 조합으로 정해지며, 구성 파일의 설정이 우선됩니다.8
app.config(또는 machine.config)의 system.net/defaultProxy 요소로 이 기본을 제어할 수 있습니다.9
<configuration>
<system.net>
<!-- useDefaultCredentials: 인증 프록시에 기본 자격 증명을 보낼지 -->
<defaultProxy enabled="true" useDefaultCredentials="true">
<proxy usesystemdefault="true"
proxyaddress="http://proxy.example.co.jp:8080"
bypassonlocal="true" />
<bypasslist>
<add address="[a-z]+\.example\.co\.jp$" />
</bypasslist>
</defaultProxy>
</system.net>
</configuration>
defaultProxy 요소를 빈 채로 두면 시스템(인터넷 옵션)의 설정이 쓰이고, proxyaddress 등을 쓰면 그것이 우선됩니다. 프로그램에서는 WebRequest.DefaultWebProxy로 같은 기본을 갈아 끼울 수 있습니다.98
여기에서도 3.3절의 함정이 작용합니다. 「실행 중인 계정의 인터넷 옵션」이 기본이므로, 서비스 계정으로 동작하는 .NET Framework 앱은 관리자의 데스크톱에서 보이는 설정과는 다른(대개 비어 있는) 설정을 읽습니다.
5.2. .NET(Core 이후) ── 환경 변수가 먼저, 다음에 OS의 사용자 설정
.NET(Core 이후)의 HttpClient에는 정적 속성 HttpClient.DefaultProxy가 있습니다. 핸들러에서 프록시를 명시하지 않는 한, 모든 HttpClient 인스턴스가 이것을 씁니다. Windows에서의 초기화 규칙은 「환경 변수를 읽고, 정의되어 있지 않으면 사용자의 프록시 설정을 읽는다」입니다.7
쓰이는 환경 변수는 다음과 같습니다.7
| 환경 변수 | 의미 |
|---|---|
HTTP_PROXY |
HTTP 요청에 쓰는 프록시 |
HTTPS_PROXY |
HTTPS 요청에 쓰는 프록시 |
ALL_PROXY |
위가 미정의일 때의 폴백 |
NO_PROXY |
프록시를 쓰지 않는 호스트의 쉼표 구분 목록 |
주의점은 세 가지입니다.
HTTP_PROXY·HTTPS_PROXY·ALL_PROXY중 하나라도 정의되어 있으면 OS 쪽 프록시 설정보다 우선합니다.NO_PROXY만 정의해도 환경 변수에 의한 프록시는 구성되지 않으며, Windows에서는 계속해서 OS의 사용자 프록시 설정이 쓰입니다. 예전에 검증하면서HTTPS_PROXY를 시스템 환경 변수에 설정한 채 잊어버리거나, CI/CD 템플릿이 주입하고 있는 식의 「보이지 않는 설정」이 사고의 온상입니다.NO_PROXY는 와일드카드(*)를 지원하지 않습니다. 서브도메인에 맞추려면 앞에 점을 붙입니다(.example.com은www.example.com에 일치하지만example.com자체에는 일치하지 않습니다).7- Windows 이외(Linux 컨테이너 등)에서는 환경 변수가 미정의이면 프록시 없음으로 초기화됩니다. 같은 앱이라도 Windows와 Linux에서 기본 동작이 달라지는 점은 컨테이너 마이그레이션 때 확인할 필요가 있습니다.7
5.3. 명시 지정 ── HttpClientHandler.Proxy와 UseProxy
어느 런타임이든 최우선은 핸들러에 대한 명시 지정입니다. HttpClientHandler.Proxy를 지정하면 OS 설정이나 구성 파일보다 우선되고, UseProxy = false로 하면 프록시를 전혀 쓰지 않습니다.14
using System.Net;
// 앱 설정에서 읽은 프록시를 명시적으로 사용
var handler = new HttpClientHandler
{
Proxy = new WebProxy("http://proxy.example.co.jp:8080")
{
BypassProxyOnLocal = true,
BypassList = new[] { @"^intra\.example\.co\.jp$" },
UseDefaultCredentials = true // 인증 프록시라면 실행 계정의 자격 증명으로 응답
},
UseProxy = true
};
var client = new HttpClient(handler);
// 프록시를 전혀 쓰지 않는 클라이언트(사내 API 직접 연결용)
var directHandler = new HttpClientHandler { UseProxy = false };
var directClient = new HttpClient(directHandler);
참고로, 명시 지정이 없고 OS 설정을 따르는 경우, 로컬 대상의 자동 바이패스에는 규칙이 있습니다. 점을 포함하지 않는 평면 이름, 루프백 주소, 자기 컴퓨터의 도메인 접미사와 일치하는 대상 등은 「로컬」로 간주될 수 있습니다.14 「IP 주소를 직접 지정하면 동작이 바뀐다」「FQDN으로 바꿨더니 갑자기 프록시를 통과하기 시작했다」는 현상은 이 판정이 원인인 경우가 있습니다.
우선순위를 정리하면 다음과 같습니다.
| 우선순위(높음→낮음) | .NET Framework | .NET(Core 이후) |
|---|---|---|
| 1 | HttpClientHandler.Proxy 등의 명시 지정 |
왼쪽과 같음 |
| 2 | app.config의 defaultProxy |
HttpClient.DefaultProxy에 대한 대입 |
| 3 | 실행 계정의 인터넷 옵션 | 환경 변수(HTTP_PROXY 등) |
| 4 | ― | Windows의 사용자 프록시 설정 |
6. 인증 프록시 ── 407은 「프록시의」 인증 오류
6.1. 407과 401을 혼동하지 않는다
인증을 요구하는 프록시를 통과하려고 하면, 프록시는 상태 코드 407 (Proxy Authentication Required)와 사용 가능한 인증 방식을 나열한 Proxy-Authenticate 헤더를 반환합니다. 연결 대상 서버의 인증 요구(401과 WWW-Authenticate)와는 별개이며, 자격 증명을 넘기는 상대도 설정하는 위치도 다릅니다.10
인증 방식에는 사용자 이름과 비밀번호를 그대로 보내는 Basic과, Negotiate(Kerberos/NTLM) 같은 챌린지/응답 방식이 있습니다. 챌린지/응답 방식에서는 비밀번호 자체는 네트워크를 흐르지 않고, 여러 차례의 주고받기로 인증이 완료됩니다.10 어느 방식으로 「떨어지는지」의 구조는 「그림으로 이해하는 NTLM과 Kerberos」에서 자세히 다룹니다.
6.2. .NET에서 자격 증명을 넘기는 방법
OS 설정에서 온 기본 프록시를 쓰면서 인증만 통과시키려면 HttpClientHandler.DefaultProxyCredentials를 씁니다. 이것은 UseProxy = true이고 Proxy = null(=시스템 기본 프록시)일 때, 그 기본 프록시에 보낼 자격 증명입니다.11
using System.Net;
var handler = new HttpClientHandler
{
UseProxy = true, // 기본값. null Proxy와 조합하면 시스템 기본 프록시를 사용
Proxy = null,
// 실행 계정(로그온 중인 사용자 또는 서비스 계정)의 자격 증명으로 407에 응답
DefaultProxyCredentials = CredentialCache.DefaultCredentials
};
var client = new HttpClient(handler);
프록시를 명시 지정하는 경우는 WebProxy 쪽에 자격 증명을 둡니다. 많은 클라이언트 시나리오에서는 개별 사용자 이름·비밀번호가 아니라 로그온 중인 사용자의 기본 자격 증명을 쓰는 것이 권장이며, WebProxy.UseDefaultCredentials = true가 그에 해당합니다.12
6.3. 서비스 계정의 407 문제
여기에서도 실행 계정이 작용합니다. 「기본 자격 증명」이란 그 프로세스를 돌리고 있는 계정의 자격 증명입니다. 대화형 사용자로 돌리면 그 사용자로서, LocalSystem 서비스로 돌리면 컴퓨터 계정으로서, 프록시에 대한 인증이 이뤄집니다.
- 프록시가 Active Directory 연동으로 사용자 인증하는 경우, 컴퓨터 계정이나 로컬 계정을 인증하지 못해 서비스로 만드는 순간 407이 계속된다
- 반대로, 프록시 쪽에서 서비스용 인증 제외(출발지 IP나 계정 단위)가 마련된 환경도 있다
즉 407 조사는 「앱의 설정」만으로는 끝나지 않고, 실행 계정을 프록시가 인증할 수 있는가라는 인프라 쪽 설계 확인과 세트가 됩니다. 서비스화하는 앱에서는 도메인의 서비스 계정(gMSA 등)으로 돌리거나, 프록시 쪽에서 인증 제외를 두거나, 인증이 필요 없는 내부 중계 프록시를 세우거나 중 하나를 설계 단계에서 정해 두어야 합니다.
참고로 HTTP_PROXY=http://user:pass@proxy:8080처럼 환경 변수에 자격 증명을 넣는 방식도 있지만7, 평문의 비밀번호가 환경 변수(=프로세스 정보)에 드러나므로 상시 운영에는 권장하지 않습니다.
7. HTTPS와 프록시 ── CONNECT 터널과 TLS 검사
7.1. HTTPS는 프록시를 「터널」로 통과한다
HTTPS 통신에서 프록시를 쓰는 경우, 클라이언트는 먼저 프록시에 CONNECT 대상호스트:443이라는 요청을 보내고, 프록시가 TCP 터널을 열어 줍니다. 성공하면 프록시는 200을 반환하고, 이후 클라이언트와 대상 서버가 그 터널 안에서 TLS 핸드셰이크를 합니다. 터널이 열리지 않으면 프록시는 407(인증 요구)이나 502 등을 반환합니다.16
이 모델에서는 프록시가 터널의 내용(암호화된 HTTPS)을 읽을 수 없습니다. 프록시 로그에 남는 것은 대상 호스트 이름과 연결의 성패까지이며, URL 경로는 보이지 않습니다 ── 이것이 「통과형」 프록시의 동작입니다.
7.2. TLS 검사형 프록시와 인증서 오류
한편 보안 제품 계열 프록시에는 TLS를 일단 종료해 내용을 검사한 뒤 다시 암호화해 전달하는 TLS 검사(SSL 복호화, break and inspect) 형이 있습니다. 이 방식에서는 클라이언트에 제시되는 서버 인증서가 원본이 아니라, 프록시 자신의 CA가 다시 서명한 인증서로 바뀝니다.13
따라서 이 구성이 성립하는 전제는 「프록시의 CA 인증서가 모든 클라이언트의 신뢰된 루트에 배포되어 있을 것」입니다. 배포되지 않은 컴퓨터, 또는 Windows의 인증서 저장소를 보지 않는 런타임(고유의 신뢰 저장소를 가진 도구류)에서는 인증서 검증 오류가 됩니다. .NET에서는 전형적으로 HttpRequestException과 그 내부의 AuthenticationException(원격 인증서가 유효하지 않음, 같은 종류의 메시지)으로 겉으로 드러납니다.
대응 원칙은 다음과 같습니다.
- 사내 CA 인증서를 로컬 컴퓨터의 「신뢰할 수 있는 루트 인증 기관」 저장소에 배포한다. 사용자 저장소와 컴퓨터 저장소의 구분은 「Windows 인증서 저장소 실무 가이드」를 참조합니다.
- 코드에서 인증서 검증을 끄지 않는다.
ServerCertificateCustomValidationCallback에서 항상 true를 반환하는 식의 우회는, 사외 네트워크로 나가는 순간 중간자 공격을 감지하지 못하는 취약한 앱이 됩니다. - 인증서 고정(pinning)을 하는 통신은 애초에 검사가 불가능합니다. 특정 Microsoft 인증서를 검증하는 Windows 구성 요소처럼, 고정된 연결은 프록시가 인증서를 바꾼 시점에 실패하며, 우회책은 없고 제외 설정이 필요합니다.4 Microsoft 365 등 SaaS 대상 트래픽에 대해서는 Microsoft 자신이 네트워크 계층에서의 복호화·검사 대상에서 제외할 것을 권장합니다.13
「사내의 모든 사이트는 보이는데, 특정 클라우드 서비스만 앱이 인증서 오류를 낸다」는 증상은 TLS 검사의 제외 목록과 고정의 조합을 먼저 의심합니다.
8. 원인 분리 절차 ── 5단계로 범인을 특정한다
「연결되지 않는다」의 조사는 다음 순서로 기계적으로 진행합니다.
| 절차 | 할 일 | 알 수 있는 것 |
|---|---|---|
| ① 재현 | 문제의 URL에 curl.exe -v나 Invoke-WebRequest로 접근(가능하면 같은 컴퓨터·같은 계정으로) |
앱 고유의 문제인지, 환경의 문제인지 |
| ② 설정 수집 | netsh winhttp show proxy, 사용자별 설정, 환경 변수의 세 계열을 수집 |
어느 계열에 무엇이 들어 있는지 |
| ③ 계정 특정 | 대상 앱의 실행 계정을 특정(서비스인지, 작업 스케줄러인지, 다른 사용자인지) | 어느 설정·어느 자격 증명으로 동작하는지 |
| ④ 오류 분류 | 407 / 403 / 이름 확인 실패 / 타임아웃 / 인증서 오류를 구분 | 프록시 인증·정책 거부·경로·TLS 검사의 원인 분리 |
| ⑤ 프록시 로그 | 프록시 서버의 액세스 로그에서 해당 시각을 확인 | 애초에 프록시에 도달했는지, 누구로 인증되었는지 |
②의 수집은 PowerShell로 한꺼번에 할 수 있습니다.
# ① 사용자별(WinINET) 설정 ── 실행 계정의 HKCU를 읽는 점에 주의
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' |
Select-Object ProxyEnable, ProxyServer, ProxyOverride, AutoConfigURL
# ② 컴퓨터(WinHTTP) 설정
netsh winhttp show proxy
# ③ 환경 변수
Get-ChildItem env: | Where-Object Name -match 'proxy'
실무상의 요령이 몇 가지 있습니다.
- ①의 재현 테스트에서는 도구가 읽는 설정 계열을 의식합니다. Windows에 포함된
curl.exe는-x http://proxy:8080으로 프록시를 명시할 수 있고, TLS 검증에는 보통 OS의 인증서 저장소(Schannel)를 씁니다. Windows PowerShell 5.1의Invoke-WebRequest는 .NET Framework 쪽(기본으로 인터넷 옵션), PowerShell 7에서는 .NET 쪽(환경 변수 우선)의 해석을 따릅니다. 「curl은 통과하는데 앱은 통과하지 못한다」 자체가 설정 계열의 불일치를 가리키는 힌트입니다. - ③에서 대상이 서비스라면 서비스와 같은 계정으로 ①②를 다시 확인합니다. 관리자 자신의 세션에서의 확인은 LocalSystem이 보는 모습의 증거가 되지 않습니다.
- ④의 오류 분류에서는 407이면 6장(인증), 인증서 오류면 7장(TLS 검사), 타임아웃이면 「프록시에 도달하지 못했다」(경로·이름 확인·방화벽)를 각각 첫 후보로 둡니다. 프록시가 아니라 Windows 방화벽의 수신 규칙이 원인인 패턴은 「Windows 방화벽과 업무 앱」에서 다룹니다.
- ⑤까지 진행해도 프록시 로그에 흔적이 없는 경우, 통신은 프록시에 도달하지 않은 것입니다. PAC의 DIRECT 판정, 바이패스 목록, 환경 변수의 삭제를 잊은 경우를 의심하고, 필요하면 패킷 캡처로 실제 대상을 확인합니다(「Windows의 패킷 캡처 실무 ── pktmon·netsh trace·Wireshark의 구분」).
9. 설계의 권장 ── 프록시를 「설정할 수 있는 앱」으로 만든다
조사 절차를 뒤집으면 앱 쪽의 설계 지침이 됩니다. 사내 프록시가 있는 환경에 납품하는 Windows 앱에서는 다음을 권장합니다.
- 프록시를 앱 설정에서 명시할 수 있게 한다. 기본은 「OS 설정을 따른다」. 많은 환경에서는 기본 그대로로 충분하고, PAC를 읽지 못하거나·서비스로 동작하거나·특수한 프록시 구성인 예외 환경에서만, 설정 파일로 프록시 URL·바이패스 목록·「프록시를 쓰지 않음」을 지정할 수 있게 합니다. 5.3절의
HttpClientHandler.Proxy/UseProxy가 그 구현 지점입니다.14 - 사내 대상(API·DB·라이선스 서버 등)의 통신은 프록시 예외의 취급을 문서로 남긴다. PAC의 DIRECT, 바이패스 목록,
NO_PROXY중 무엇으로 제외하는지를 도입 절차서에 쓸 수 있는 형태로 둡니다.NO_PROXY의 일치 규칙(와일드카드 불가·앞쪽 점의 의미)은 오해가 많으므로 예를 붙입니다.7 - 타임아웃과 재시도를 프록시 경유를 전제로 설계한다. 프록시가 내려가 있거나 인증에서 멈춰 있는 경우, 기본의 긴 타임아웃을 기다리는 구현은 UI도 운영도 굳어집니다. 연결 타임아웃을 짧게 분리하고, 재시도는 멱등한 요청에 한정합니다(설계의 세부는 「HttpClient를 using으로 감싸면 안 되는 이유」).
- 「어느 프록시를 썼는지」를 로그에 남긴다. 장애 조사의 첫 질문에 앱 자신이 답할 수 있게 합니다.
4의 로그는 해석 결과를 기록하는 것만으로도 효과가 있습니다. 핵심은 클라이언트를 실제로 구성한 설정(핸들러)에서 경로를 이끌어 내는 것입니다. HttpClient.DefaultProxy를 직접 로그에 내면, 핸들러에서 Proxy를 명시한 경우나 UseProxy = false로 한 경우에 실제 경로와 어긋난 값을 기록하게 됩니다.
using System.Net.Http;
// handler 는 HttpClient 생성에 쓴 것과 같은 인스턴스
// UseProxy=false 이면 항상 직접 연결. 명시 지정이 있으면 그것이, 없으면 DefaultProxy 가 쓰인다
var effectiveProxy = handler.UseProxy
? handler.Proxy ?? HttpClient.DefaultProxy
: null;
var target = new Uri("https://api.example.com/v1/orders");
var route = effectiveProxy is null || effectiveProxy.IsBypassed(target)
? "DIRECT"
: effectiveProxy.GetProxy(target)?.ToString() ?? "DIRECT";
logger.LogInformation("HTTP 전송 {Target} 경로 {Route} 실행 계정 {User}",
target, route, Environment.UserName);
시작 시 한 번, 주요 대상에 대해 「경로」「실행 계정」을 기록해 두면 8장의 원인 분리 ①〜③이 로그만 보면 끝납니다. 「브라우저에서는 연결되는데」라는 말을 들었을 때, 앱 쪽에서 『나는 이 설정으로, 이 경로를 썼다』고 말할 수 있는 것이 프록시 장애에 강한 앱의 조건입니다.
10. 정리
- Windows의 프록시 설정은 WinINET의 사용자별 설정·WinHTTP의 컴퓨터 설정·환경 변수의 세 계열로 나뉘고, 어느 것을 읽을지는 앱(의 HTTP 스택)과 실행 계정으로 정해집니다.
- WinINET은 대화형 앱용이며 서비스에서의 이용은 지원되지 않고, 서비스 용도는 WinHTTP(
netsh winhttp)가 맡습니다. 「수동이면 동작하는데 서비스면 동작하지 않는다」는 먼저 실행 계정의 차이를 의심합니다. netsh winhttp set proxy는 정적 설정이며 PAC·자동 검색·인증을 다루지 않습니다. PAC로 운영하는 네트워크에서는 PAC를 읽지 못하는 클라이언트의 취급을 정해 둘 필요가 있습니다.- PAC의
FindProxyForURL은 URL마다 프록시 또는 DIRECT를 반환합니다. WPAD는 DHCP/DNS 구성이 있는 네트워크에서만 동작합니다. - .NET Framework의 기본은 실행 계정의 인터넷 옵션(
defaultProxy로 덮어쓰기), .NET(Core 이후)은 환경 변수→사용자 프록시 설정 순입니다. 명시 지정(HttpClientHandler.Proxy)은 항상 최우선입니다. - 407은 프록시 인증의 오류이며, 서비스 계정으로 동작하는 앱에서는 「기본 자격 증명」이 다른 사람이 되는 것이 전형적인 원인입니다.
- TLS 검사형 프록시는 사내 CA 인증서의 배포가 전제이며, 인증서 오류의 정답은 검증을 끄는 것이 아니라 인증서 저장소로의 배포입니다. 고정된 통신은 제외가 필요합니다.
- 원인 분리는 「재현→세 계열의 설정 수집→실행 계정 특정→오류 분류→프록시 로그」의 순으로 기계적으로. 앱 쪽은 「프록시를 설정할 수 있고, 쓴 경로를 로그에 남기는」 설계로 두는 것이 최선의 예방입니다.
다음에 「업무 앱만 연결되지 않는다」는 상담을 받으면, 먼저 이렇게 되묻습니다.
그 앱은 누구의 계정으로 동작하고, 세 계열 중 어느 프록시 설정을 읽는 것입니까.
이 한 질문만으로 조사의 입구는 크게 달라집니다.
관련 기사
- HttpClient를 using으로 감싸면 안 되는 이유 ── C# 업무 앱의 HTTP 통신 실무(생성 패턴·타임아웃·재시도)
- Windows의 패킷 캡처 실무 ── pktmon·netsh trace·Wireshark의 구분
- Windows 방화벽과 업무 앱 ── 수신 규칙은 설치 프로그램에서 등록한다
- Windows 서비스 만드는 방법과 운영 ── 작업 스케줄러와의 구분부터 BackgroundService의 서비스화까지
- 그림으로 이해하는 NTLM과 Kerberos ── 왜 인증은 NTLM으로 「떨어지는가」
- Windows 인증서 저장소 실무 가이드 ── 사용자와 컴퓨터, 어느 쪽에 넣는가
관련 상담 영역
합동회사 코무라소프트에서는 「개발 컴퓨터에서는 동작하는데 고객사 네트워크에서는 통신할 수 없다」「서비스로 만들었더니 외부 API에 연결되지 않게 되었다」와 같은, 사내 프록시·인증 프록시·TLS 검사 환경에서의 Windows 앱 통신 장애 조사와, 프록시 환경을 전제로 한 업무 앱의 통신 설계(설정 항목·타임아웃·로그 설계) 상담을 다룹니다. 현상의 재현 절차와 로그 수집 방법을 정리하는 단계부터여도 됩니다.
참고 링크
-
Microsoft Learn, WinINet vs. WinHTTP. 서비스나 가장·세션 분리가 필요한 프로세스가 아니면 WinINET을 쓴다는 구분 지침, 자격 증명 캐시·자격 증명 프롬프트·서비스 지원·가장·세션 분리 등의 기능 비교표에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, netsh winhttp. netsh winhttp show/set/import/reset의 구문, set proxy의 proxy-server와 bypass-list, import proxy source=ie, set advproxy에 의한 JSON 형식(Proxy·ProxyBypass·AutoconfigUrl·AutoDetect)의 상세 프록시 설정에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, About WinHTTP. WinHTTP가 서비스·서버 사이드 용도로 설계된 HTTP 스택이며, 서비스 계정에서의 실행과 가장을 지원하는 한편 브라우저의 Cookie·캐시·자격 증명·사용자의 인터넷 옵션을 공유하지 않는다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Using a proxy with Delivery Optimization. netsh winhttp set proxy가 자동 검색·PAC URL·프록시 인증을 지원하지 않는 정적 설정이라는 점, 로그온 사용자가 없는 맥락을 위한 장치 단위 프록시 구성(NetworkProxy CSP, 「프록시 설정을 컴퓨터별로 설정한다」 정책), 그리고 인증서 고정을 쓰는 통신이 TLS 검사에서 실패해 제외가 필요해진다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, WinHTTP AutoProxy Support. PAC 스크립트가 FindProxyForURL(url, host) 함수를 포함하고 요청마다 프록시 목록을 계산한다는 점, 직접 연결로 충분한 경우는 특별한 반환값으로 나타낸다는 점, 종래의 AutoProxy API에서는 자동 프록시가 HTTP 스택에 자동 통합되어 있지 않아 앱 쪽에서 WinHttpGetProxyForUrl을 호출해야 한다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, WinHttpGetProxyForUrl function. WPAD 프로토콜의 구현으로서, PAC 파일이 URL마다 다른 프록시를 반환할 수 있으므로 URL 단위로 호출해야 한다는 점, PAC URL의 명시 지정과 네트워크에서의 자동 검색을 모두 지원한다는 점에 대해. ↩ ↩2
-
Microsoft Learn, HttpClient.DefaultProxy Property. Windows에서는 HTTP_PROXY·HTTPS_PROXY·ALL_PROXY·NO_PROXY 환경 변수를 먼저 읽고, 미정의이면 사용자의 프록시 설정을 읽는다는 점, Linux에서는 환경 변수가 없으면 프록시 없이 초기화된다는 점, NO_PROXY가 와일드카드 비대응이며 앞쪽 점에 의한 서브도메인 일치를 쓴다는 점, 프록시 URL에 사용자 이름·비밀번호를 넣을 수 있다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, Configuring Internet Applications. .NET Framework에서 defaultProxy 요소가 기본 프록시를 정의하고, Proxy 속성을 갖지 않는 HttpWebRequest가 기본 프록시를 쓴다는 점, 시스템의 인터넷 설정과 구성 파일의 설정이 조합되며 구성 파일 쪽이 우선된다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, defaultProxy element (network settings). system.net/defaultProxy 요소의 enabled·useDefaultCredentials 특성, proxy·bypasslist·module 자식 요소, 요소가 비어 있는 경우는 시스템의 프록시 설정이 쓰인다는 점, .NET 6 이후로 마이그레이션할 때는 HttpClient.DefaultProxy로 구성한다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Authentication in WinHTTP. 프록시 인증이 필요한 경우에 상태 코드 407과 Proxy-Authenticate 헤더가 반환된다는 점(서버 인증은 401과 WWW-Authenticate), Basic 인증과 Kerberos 등의 챌린지/응답 방식의 차이, 챌린지/응답 방식에서는 사용자 이름과 비밀번호가 네트워크를 흐르지 않는다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, HttpClientHandler.DefaultProxyCredentials Property. UseProxy가 true이고 Proxy가 null이라 시스템 기본 프록시를 쓰는 경우에, 그 기본 프록시에 대한 인증에 쓰는 자격 증명을 설정하는 속성이라는 점에 대해. ↩ ↩2
-
Microsoft Learn, WebProxy.Credentials Property. Credentials 속성이 HTTP 407에 대한 응답으로 프록시에 보내는 자격 증명이라는 점, 많은 클라이언트 시나리오에서는 로그온 중인 사용자의 기본 자격 증명을 쓰기 위해 UseDefaultCredentials를 true로 설정하는 것이 권장이라는 점에 대해. ↩ ↩2
-
Microsoft Learn, Understanding implications when using network intermediation to decrypt or manipulate Microsoft 365 traffic at the network layer. TLS 검사(SSL 복호화)가 프록시나 방화벽에서 TLS를 복호화·검사·재암호화하는 구성이라는 점, 종단 간 TLS를 전제로 하는 서비스에서 오동작이나 성능 저하를 일으킬 수 있다는 점, Microsoft 365 대상 트래픽을 네트워크 계층의 복호화·검사에서 제외하라는 권장에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Make HTTP requests with the HttpClient class. HttpClient.DefaultProxy와 HttpClientHandler.Proxy의 두 구성 방법, Proxy 지정이 구성 파일이나 로컬 컴퓨터의 설정보다 우선된다는 점, WPAD가 DNS의 wpad 이름이나 DHCP를 통해 PAC 파일(wpad.dat 등)을 가져오는 일반적인 구성, 평면 이름·루프백·도메인 접미사 일치에 의한 로컬 대상 바이패스 판정에 대해. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WinHttpOpen function. dwAccessType의 각 값의 의미. WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY(Windows 8.1 이후)가 시스템/사용자의 프록시 설정을 써서 프록시를 자동 결정하고 장애 조치나 인증도 자동 처리한다는 점, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY가 8.1 이후에는 사용이 권장되지 않는다는 점에 대해. ↩
-
Microsoft Learn, Work with existing on-premises proxy servers. 아웃바운드 HTTPS 통신이 프록시에 대한 CONNECT 요청으로 수립된다는 점, 성공 시 HTTP 200이 반환되고 407(인증 요구)이나 502 등의 응답은 프록시가 통신을 허용하지 않았음을 나타내므로 프록시 쪽 팀과의 원인 분리로 나아가야 한다는 점에 대해. ↩
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
HttpClient를 using으로 감싸면 안 됩니다 ── C# 업무 앱의 HTTP 통신 실무(생성 패턴·타임아웃·재시도)
C#의 HttpClient는 매번 using으로 생성하면 소켓이 고갈되고, static으로 두면 DNS 변경을 따라가지 않습니다. PooledConnectionLifetime과 IHttpClientFactory를 쓰는 올바른 생성 패턴, 타임아웃...
Windows의 이름 확인 순서 ── hosts·DNS 캐시·LLMNR/mDNS·DoH
「이름을 확인할 수 없다」「일부 PC만 연결되지 않는다」는 hosts·DNS 캐시·DNS 서버·LLMNR/mDNS 중 어느 층이 답했는지에 따라 결과가 달라집니다. Windows의 이름 확인 순서와 DoH가 바꾸는 것을 구조부터 정리하고, 층별로...
Time Travel Debugging ── 장기 가동에서 재현되지 않는 결함을 「녹화」해서 되감기
한 달에 한 번만 나오는 결함은 크래시 덤프로는 결과밖에 찍히지 않습니다. WinDbg의 Time Travel Debugging(TTD)으로 실행을 녹화해 되감는 방법을 TTD.exe의 녹화 설계, 링 버퍼, TTD.Calls 쿼리, 덤프와의 역...
인수는 왜 깨지는가 ── Windows 명령줄 인수의 규칙
Windows에는 인수의 배열이 존재하지 않으며, CreateProcess에 전달되는 것은 한 줄의 문자열이고 분할은 받는 쪽이 합니다. CommandLineToArgvW·CRT·.NET의 분할 규칙과 .NET의 ArgumentList, C++에...
Windows 프린터 드라이버 제공 종료 ── 업무 앱의 장표·라벨 인쇄는 어떻게 대비할 것인가
Microsoft는 v3/v4 프린터 드라이버의 제공 종료를 단계적으로 진행하고 있으며, 2026년 7월부터는 IPP 클래스 드라이버가 우선됩니다. Windows protected print mode에서 무엇이 사라지는지, 업무 앱의 장표·라벨 ...
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
장애 조사 & 장기 가동 장애
간헐적 장애, 통신 진단, 장기 가동 크래시, 실패 경로 테스트 기반을 정리한 토픽 페이지입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- 브라우저에서는 연결되는데, 업무 앱만 사내 프록시를 통과하지 못하는 이유는 무엇인가요?
- 브라우저는 WinINET의 사용자별 프록시 설정을 읽지만, 업무 앱이 같은 설정을 읽는다고 단정할 수는 없습니다. Windows 서비스로 동작하는 앱이나 다른 계정으로 동작하는 앱은 그 계정에서 보이는 설정, WinHTTP의 컴퓨터 설정, 환경 변수를 참조합니다. 먼저 실행 계정을 특정하고, 그 계정에서 보이는 프록시 설정을 netsh winhttp show proxy와 사용자 설정 양쪽에서 확인합니다. 같은 계정·같은 컴퓨터에서 curl.exe 등으로 재현되면, 앱 고유의 문제가 아니라 설정 계열의 불일치로 판단할 수 있습니다.
- netsh winhttp set proxy를 설정했는데도 앱의 통신이 바뀌지 않는 이유는 무엇인가요?
- netsh winhttp가 설정하는 것은 WinHTTP의 컴퓨터 기본값이며, WinINET을 읽는 브라우저나 대화형 앱, 환경 변수를 우선하는 .NET(Core 이후)의 HttpClient에는 영향을 주지 않습니다. 또한 netsh winhttp set proxy는 정적 설정이라 PAC에 의한 자동 구성이나 자동 검색, 프록시 인증을 다루지 않습니다. 대상 앱이 어떤 HTTP 스택으로, 어느 설정 계열에서 프록시를 해석하는지를 먼저 확인할 필요가 있습니다.
- .NET 앱은 어느 프록시 설정을 읽나요?
- .NET Framework는 기본으로 실행 중인 계정의 인터넷 옵션(WinINET에 해당) 설정을 쓰고, app.config의 system.net/defaultProxy 요소로 덮어쓸 수 있습니다. .NET(Core 이후)의 HttpClient는 HTTP_PROXY·HTTPS_PROXY·NO_PROXY 등의 환경 변수를 먼저 읽고, 정의되어 있지 않으면 Windows의 사용자 프록시 설정으로 넘어갑니다. 어느 쪽이든 HttpClientHandler.Proxy로 명시하면 그것이 최우선입니다. 즉 Framework와 Core 이후는 기본 해석 순서가 다르므로, 마이그레이션 때는 프록시 동작을 다시 확인할 필요가 있습니다.
- 407 Proxy Authentication Required가 돌아올 때는 무엇을 확인해야 하나요?
- 407은 프록시 자체가 인증을 요구한다는 신호이며, 대상 서버의 인증 오류(401)와는 별개입니다. 먼저 프록시가 요구하는 인증 방식(Negotiate·NTLM·Basic)을 Proxy-Authenticate 헤더로 확인하고, .NET이라면 HttpClientHandler.DefaultProxyCredentials나 WebProxy.UseDefaultCredentials로 자격 증명을 넘깁니다. 서비스 계정으로 동작하는 앱에서는 「기본 자격 증명」이 그 서비스 계정의 것이 되므로, 대화형 사용자로는 통과하는데 서비스로 바꾸면 407이 되는 현상이 전형적으로 일어납니다. 프록시 쪽 로그에서 누구로 인증되었는지도 함께 확인합니다.
- TLS 검사형 프록시에서 인증서 오류가 납니다. 인증서 검증을 꺼도 되나요?
- 끄는 것은 권장하지 않습니다. TLS 검사형 프록시는 통신을 일단 복호화한 뒤, 자체 CA로 다시 서명한 인증서를 클라이언트에 제시하므로, 그 CA 인증서가 신뢰된 루트에 들어 있지 않으면 검증 오류가 됩니다. 올바른 대응은 사내 CA 인증서를 Windows의 인증서 저장소(보통 로컬 컴퓨터의 신뢰할 수 있는 루트 인증 기관)에 배포하는 것입니다. 코드에서 검증을 끄면 사외 네트워크에서 쓰일 때 중간자 공격을 감지하지 못하게 되어, 취약점으로 남습니다.