이번에 프록시에 대해 정리하면서, 단순한 개념 설명을 넘어서서 실무에서 Proxy와 ProxySelector를 어떻게 선택하고 적용할지에 대한 전략까지 정리해봤습니다.
Java/Kotlin 기반의 Spring 프로젝트에서 HTTP 요청을 외부 프록시 서버를 거쳐야 하는 환경이라면 필수적으로 알아야 하는 내용입니다.
Proxy vs ProxySelector 실무 기준 비교 분석
개발 경력 5년 차인 제 입장에서 이 둘의 차이는 단순한 API 수준의 차이가 아닙니다. 프록시를 어떻게, 얼마나 유연하게 적용할 수 있는가에 대한 아키텍처적 결정 요소라고 생각합니다.
Proxy – 단순하고 명시적인 설정 방식
java.net.Proxy는 개별 요청에 대해 직접 프록시를 지정할 수 있습니다. 테스트나 제한된 상황에서 매우 간편하게 사용할 수 있는 구조죠.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080));
HttpURLConnection conn = (HttpURLConnection) new URL("http://example.com").openConnection(proxy);
- 장점: 명시적으로 지정하므로 디버깅이나 테스트에 유리
- 단점: 코드 곳곳에 프록시 설정이 흩어지고, URL 조건별 제어가 불가능
ProxySelector – 정책 기반의 프록시 설정
ProxySelector는 URL 패턴에 따라 프록시를 선택할 수 있는 전략 객체입니다. Java 11부터 기본 HttpClient에서도 사용되며, Spring에서는 JdkClientHttpRequestFactory와 함께 사용할 수 있습니다.
val proxySelector = ProxySelector.of(InetSocketAddress("proxy.example.com", 8080))
val httpClient = HttpClient.newBuilder().proxy(proxySelector).build()
val requestFactory = JdkClientHttpRequestFactory(httpClient)
- 장점: 조건 기반 프록시 적용 가능, 정책 분리 용이
- 단점: 구조적 이해 없이 설정하면 적용 범위 오해 소지 있음
또한 전역으로 적용하고 싶다면 다음과 같이 JVM 전체에 적용할 수 있습니다
ProxySelector.setDefault(ProxySelector.of(InetSocketAddress("proxy.example.com", 8080)))
이렇게 하면 모든 HttpClient는 별도로 프록시 설정을 하지 않더라도 해당 프록시를 사용합니다.
실무에서의 선택 기준은?
실제 업무에서는 다음과 같은 기준으로 선택했습니다:
상황 | 적합한 방식 |
테스트 또는 한정된 요청만 프록시 필요 | Proxy 직접 지정 |
외부망 접근이 빈번하고 URL 패턴에 따라 유동적 프록시 필요 | ProxySelector 적용 |
전체 프로젝트 단에서 일괄 적용 필요 | ProxySelector.setDefault(...) 사용 |
Spring Boot에서는 RestClient, WebClient 등 다양한 방식의 HTTP 호출을 사용하는데,
이 중 RestClient에서 JdkClientHttpRequestFactory와 함께 ProxySelector를 적용하면 가장 유연한 설정이 가능합니다.
공식 문서 및 참고 자료
프록시 설정은 단순한 설정 이상의 고민이 필요한 영역입니다.
특히 다양한 외부 API를 호출하거나, 내부망/외부망을 구분해서 프록시를 적용해야 하는 경우라면 ProxySelector의 전략적 사용이 필수적입니다.
개인적으로는 프로젝트 초반에 구조적으로 설정 방향을 정해두는 것이, 장기적으로 안정성과 유지보수 측면에서 훨씬 유리하다고 느꼈습니다.