티스토리 뷰
1. 프록시 서버 (Proxy Server)
프록시 서버는 클라이언트와 서버를 연결해 주는 서버다. 프록시 서버는 서로 다른 두 네트워크 서비스 사이에 존재한다. 프록시 서버가 존재하는 이유는 바로 인터넷 속도의 향상이다. 이는 특히 제공하는 프로토콜이 다른 두 서버의 데이터 송수신에서 빛을 발한다. 각자 서버에 맞는 데이터로 변형하는 과정을 분리해 놓아 전송 속도를 높일 뿐 아니라 많은 트래픽에 하나의 서버에 몰려 서버가 다운 될 가능성을 낮출 수 있게 된다. 다수의 사용자가 같은 페이지로 요청을 할 때 매번 서버에 접근하는 것 보단 미리 프록시 서버에 받아 놓은 자료를 다시 수신하게 된다면 속도의 향상을 가져온다.
또, 프록시 서버를 통해 서버의 보안성을 높인다. 네트워크의 사적인 정보를 외부 노출을 방지하기 위해 사용하기도 한다. 프록시는 인터넷 검열의 수단이 되기도 하고 검열을 피하는 방법이 되기도 한다. 성인 불법 사이트를 막는데 이 프록시를 사용한다.
프록시 사용을 위해서는 시스템 속성이 로컬 프록시 서버의 주소를 가리키도록 설정하면 된다. 예를 들어 HTTP 프록시를 사용한다면 http.proxyHost 설정을 프록시 서버의 도메인 이름이나 IP 주소로 설정하고 http.proxyPort 설정을 프록시 서버의 포트로 설정하면 된다. 아래 방법은 자바에서 프록시 서버를 구성한 방법이다.
2. 프록시 사용
프록시는 위와 같은 특성으로 인해 매우 쓰임이 다양하다. 서버 앞쪽에 위치하고 있는 특성을 지니고 있어 중심 서버에서 하지 못하는 많은 일들을 대신 해주는 기능을 갖고 있다. 프록시 서버는 아래와 같은 일들을 한다.
- 보안성 증가 : 서버 앞에 위치해 메인 서버의 정보를 노출 되지 않도록 도와준다.
- 캐시 사용 : 프록시 서버에 캐시 정보를 사용하여 반복된 정보를 요청하는 경우 속도를 높일 수 있다.
- 서버 정책 부여 : 서버에 필요한 다양한 정책을 지정 해줄 수 있다.
- IP 추적 방지 : 앞서 보안성과 비슷한 방법으로 나의 IP정보를 노출하지 않기 위해 사용한다.
- 보안 뚥기 : 반대로 서버의 보안 정책을 뚫기 위한 목적으로도 사용한다.
- 우회 목적 : 지역이나 IP 제한이 걸려있는 서버에 접근하기 위해 우회 목적으로 사용한다.
3. 프록시 클래스 (Proxy Class)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketAddress; public class Solution { public static void main(String[] args) { // TODO Auto-generated method stub SocketAddress address = new InetSocketAddress("Proxy.example.com",80); Proxy proxy = new Proxy(Proxy.Type.HTTP,address); } } | cs |
프록시 클래스 생성 자체는 매우 단순하게 만들어 낼 수 있다. 만약 proxy.example.com 호스트에 80 Port Number를 가지는 HTTP에 대한 객체는 위와 같은 방식으로 생성 할 수 있다. 우선 호스트와 Port Number정보를 가진 Address 클래스를 생성한다.
SocketAddress address = new InetSocketAddress("Proxy.example.com",80);
그리고 프록시 클래스 생성을 위해서는 3가지 타입 중 하나를 지정해야 하는데, Java 에선 아래 3가지 타입을 제공하고 있다.
- Proxy.Type.DIRECT : 직접 연결 (프록시 사용하지 않음)
- Proxy.Type.HTTP : HTTP 타입
- Proxy.Type.SOCKS : SOCKS 타입
이 중 HTTP 타입을 사용하여 연결하고 싶으면 아래 방법으로 프록시 클래스 생성이 가능하다.
Proxy proxy = new Proxy(Proxy.Type.HTTP,address);
이런 방식으로 프록시 생성이 가능하다. 물론 현재 프록시 클래스에 대한 어떠한 정의도 이루어지지 않았기 때문에 지금은 아무 기능을 안하는 텅빈 프록시를 앞에 세워 놓은 것과 같다. 다음 장에서 프록시에 기능을 추가하는 방법에 대해 알아보자.
4. 프록시 클래스 응용
JVM은 서로 다른 네트워크 연결에 필요한 프록시 서버를 찾기위해 java.net.ProxySelector를 사용한다. 시스템 설정과 프로토콜을 통해 다른 호스트에 대한 연결 방법을 찾는 방식이다. 그리고 ProxySelector의 서브클래스를 작성해 기본 셀렉터를 변경할 수도 있다.
이 클래스를 구현하기 위해서는 2가지를 기억해야 하는데, 바로 select() 메소드와 connectFailed()메소드이다.
4-1. Select()
Select 메소드는 추상메소드로 ProxySelector 클래스에 구현되어있다. 그러므로 프록시 선택을 위해선 select 메소드에 대한 정의가 필요하다. select 메소드의 경우 연결할 호스트에 대한 URI 정보를 전달해 주어야 한다. 이를 전달해주면 해당 메소드는 URI 타입에 따라 적절한 프록시를 선택해 List<Proxy> 타입으로 반환 하게 된다.
4-2. connectFailed()
해당 클래스는 connectFailed() 역시 추상 메소드로 구성되어 있다. 만약 연결이 실패할 경우 해당 메소드를 통해 연결 실패를 사용자에게 다시 알려 줄 것이다. 이 메소듣 콜백 메소드 이므로 연결 실패되면 프로그램에서 자동으로 반환 해줄 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class LocalProxySelector extends ProxySelector { private List<URI> failed = new ArrayList<URI>(); public List<Proxy> select(URI uri) { List<Proxy> result = new ArrayList<Proxy>(); if(failed.contains(uri)|| !"http".equalsIgnoreCase(uri.getScheme())) { result.add(Proxy.NO_PROXY); } else { SocketAddress proxyAddress = new InetSocketAddress("Proxy.example.com",8000); Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress); result.add(proxy); } return result; } public void connectFailed(URI uri, SocketAddress address, IOException ex){ failed.add(uri); } } | cs |
(출처 : 자바 네트워크 프로그래밍 - O'Reilly)
위 클래스는 프록시를 통한 연결 가능여부를 기억하는 proxySelector 클래스 이다. 앞서 설명한 대로 두개의 추상 메소드가 정의되어 있다. 우선 클래스 최상위에 URI 연결이 실패 했을 시 결과 값을 담을 수 있는 Proxy 타입 ArrayList가 정의되어 있다.
private List<URI> failed = new ArrayList<URI>();
그 다음 select 메소드를 살펴보면, URI 객체를 받아 연결 가능한 프록시를 찾아야 하므로, 파라미터 변수로 URI 객체가 선언되어 있음을 확인 할 수 있다. URL이 아니라 URI이다.
public List<Proxy> select(URI uri)
그리고 그 안에 성공 시 프록시 리스트가 담기는 ArrayList가 또 선언 되어있다.
List<Proxy> result = new ArrayList<Proxy>();
그리고 이 클래스에선 실패하는 Case를 정의해 실패시와 성공시를 조건문으로 나눴다. 해당 클래스에 나온 실패 조건은 2가지 인데, 앞쪽에 선언된 성공 조건은 uri 연결을 실패하는 조건이고, 뒤에 나온 조건은 입력한 uri가 http의 형식을 갖추지 않은 Case이다. 이 2가지 경우인 경우 result List에 NO_PROXY를 추가하면 된다.
if (failed.contains(uri) || ! "http".equalsIgnoreCase(uri.getScheme())) {
result.add(Proxy.NO_PROXY);
}
else 문에는 성공조건이 들어가게 되어 있는데, proxy.example.com 호스트의 PortNumber 8000으로 가정하고 선언하면 아래와 같이 개발하면 된다.
SocketAddress proxyAddress = new InetSocketAddress("proxy.example.com",8000);
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
result.add(proxy);
마지막으로 connectFailed메소드는 아래와 같이 선언하면 된다.
public void connectFailed(URI uri, SocketAddress address, IOException ex) {
failed.add(uri);
}
'Skill > Programming - Network' 카테고리의 다른 글
13. HTTP 요청 (0) | 2019.07.21 |
---|---|
12. HTTP 연결 (0) | 2019.07.16 |
10. URI Class (0) | 2019.06.30 |
9. URLConnection 클래스 (0) | 2019.06.16 |
8.인터넷 주소 클래스 (InetAddress Class) (0) | 2019.06.02 |