인터넷 통신 기술의 발달과 함께 정적인 웹 콘텐츠 뿐만 아니라 점차 동적으로 생성된 리소스를 공유하려는 시도가 생겨났다. 이에 따라 서로 다른 프로토콜을 연결하거나, HTTP만 허용하는 방화벽을 통과하여 다른 프로토콜로 통신하는 등의 다양한 상황들이 생겨났다.
이 장에서는 다양한 리소스에 접근하거나 서로 다른 프로토콜, 애플리케이션 간의 통신에 HTTP를 어떻게 사용하는지 알아본다.
게이트웨이는 HTTP 프로토콜과 다른 프로토콜을 연결시켜준다. 혹은 서버가 게이트웨이 역할을 함으로써 데이터베이스와 통신한다.
두 번째 그림은 HTTP 트래픽을 다른 프로토콜로 자동 변환시켜주는 게이트웨이의 역할을 나타낸다.
위와 같은 다양한 종류의 게이트웨이를 알아본다.
게이트웨이는 클라이언트 측 프로토콜과 서버 측 프로토콜을 빗금(/)으로 구분하여 기술한다.
<클라이언트 프로토콜>/<서버 프로토콜>
이 때, 게이트웨이가 어느 쪽 역할을 하고 있는가에 따라서 구분된다.
클라이언트가 브라우저 설정을 통해서 HTTP 요청을 서버가 아닌 게이트웨이에 바로 보낼 수 있다.
위의 그림처럼 일반적인 HTTP 통신에는 아무런 영향을 주지 않지만, FTP 프로토콜인 경우에는 지정된 게이트웨이로 HTTP 요청을 한다. 게이트웨이는 해당 요청을 받아 FTP 서버에 전달한다.
서버 측 웹 게이트웨이는 클라이언트로부터 HTTP 요청을 받아, 서버 영역으로 들어오는 시점에 다른 프로토콜로 전환한다.
클라이언트가 일반 HTTP를 사용하여 웹을 탐색할 수 있지만, 게이트웨이가 자동으로 사용자의 모든 세션을 암호화하여 웹 서버로 전달한다.
해당 게이트웨이는 보안 가속 게이트웨이
라고 한다. 웹 서버의 앞단에 위치하며, 리버스 프록시 역할을 한다. HTTPS 트래픽을 받아서 복호화하고 웹 서버로 HTTP 요청을 보낸다. 서버보다 더 효율적으로 복호화하는 암호화 하드웨어를 내장하여 서버의 부하를 줄여주기도 한다.
그러나 게이트웨이와 서버 간의 트래픽은 암호화되어 있지 않기 때문에 네트워크가 안전한지 확인 후에 사용해야 한다.
그 동안은 클라이언트와 서버를 연결하는 게이트웨이에 관한 내용이었다면, 가장 일반적인 게이트웨이의 형태인 애플리케이션 서버는 목적지 서버와 게이트웨이를 한 개의 서버로 결합한다.
애플리케이션 서버 : HTTP를 통해서 클라이언트와 통신하고, 서버 측에 있는 애플리케이션 프로그램에 연결하는 서버 측 게이트웨이다.
클라이언트의 HTTP 요청을 받은 애플리케이션 서버는 API를 통해서 서버에서 동작하는 애플리케이션에 해당 요청을 전달한다.
최초의 애플리케이션 서버(게이트웨이)의 API는 공용 게이트웨이 인터페이스(CGI)이다. CGI는 특정 URL에 대한 HTTP 요청에 따라 프로그램을 실행하고, 출력된 결과를 수집하고, HTTP 응답을 회신하는데 웹 서버가 사용하는 표준화된 인터페이스 집합(정의)이다.
웹 서버로부터 외부 프로그램을 호출함으로써 웹 서버의 동적인 역할을 가능하도록 정의해 놓은 것이 CGI라고 볼 수 있다. Python 에서는 WSGI(Web Server Gateway Interface) 가 그 역할을 한다고 볼 수 있다. 클라이언트로부터 들어오는 HTTP 요청을 받은 웹 서버(ex.nginx)는 내장된 WSGI module을 통해 WSGI 프로토콜로 WSGI Server(middleware) 인 gunicorn과 통신한다. gunicorn은 이를 다시 wsgi를 지원하는 애플리케이션(ex. django) 에 연결시켜준다.
CGI는 모든 요청마다 새로운 프로세스를 만들어내고 그로 인해 부하가 발생한다. 또한 서버의 성능을 제한하며 서버 장비에 부담을 준다. 이러한 단점을 보완하고자 나온 것이 Fast CGI다. Fast CGI는 데몬으로 동작하여 요청마다 새로운 프로세스를 만들고 제거하면서 생기는 성능 저하 문제를 해결하였다.
웹 애플리케이션이 개발이 활발해짐에 따라, 두 애플리케이션 사이에서 프로토콜 인터페이스를 맞추는 일이 문제가 되었다. HTTP 헤더로는 표현하기 힘든 복잡한 정보를 교환해야 할 수도 있기 때문이다. 이에, 웹 애플리케이션이 서로 통신하는데 사용할 표준과 프로토콜 집합을 개발하였다.
SOAP 은 HTTP 메시지에 XML 데이터를 담는 프로토콜이다. 현대 웹 서비스의 데이터 교환 방식은 REST 방식에 JSON 포맷의 데이터를 주고 받는 방식을 주로 사용한다.
터널은 HTTP 프로토콜을 지원하지 않는 애플리케이션에 HTTP 애플리케이션을 사용해 접근하는 방법이다. 따라서 터널을 사용하면 HTTP 트래픽만 허용하는 방화벽이 있더라도 그렇지 않은 트래픽을 전송할 수 있다.
웹 터널은 CONNECT 메서드를 사용하여 커넥션을 맺는다. CONNECT 메서드는 터널 게이트웨이가 목적 서버와 포트에 TCP 커넥션을 맺고 클라이언트와 서버 간의 데이터를 무조건 전달할 것을 요청한다.
웹 터널은 원래 방화벽을 통해 암호화된 SSL 트래픽을 전달하기 위해 개발되었다. 많은 기업들이 더 강력한 보안을 위해 모든 트래픽이 패킷을 필터링하는 라우터와 프록시를 거쳐가도록 했다. 이 때, 기술적으로 오래된 프록시는 암호화된 SSL을 인지하지 못하고 차단한다. 터널을 사용하면 SSL 트래픽을 HTTP 커넥션으로 전송하여 80번 포트만을 허용하는 방화벽을 통과시킬 수 있다.
아래의 그림은 클라이언트와 서버가 직접 SSL 커넥션을 맺은 경우(a)와 HTTP 터널을 통한 SSL 커넥션(b)를 비교한 것이다. 이처럼 터널은 보안 트래픽이 방화벽을 통과하도록 하는데에 유용하게 사용될 수 있다. 하지만 터널을 이용한 악의적인 트래픽이 유입되는 경로로써 활용될 수도 있기 때문에 유의할 필요가 있다.
방금 봤던 SSL 터널링을 게이트웨이를 통해서도 가능하게 할 수 있다. 하지만 몇 가지 단점이 있다.
그러나 SSL 터널링을 사용하면, 게이트웨이에 SSL을 구현할 필요가 없다. SSL 세션은 클라이언트가 생성한 요청과 웹 서버 간에 생성된다. 게이트웨이는 트랜잭션의 보안에는 관여하지 않고 암호화된 데이터를 그대로 터널링한다.
게이트웨이는 클라이언트의 터널 사용 인증에 대한 허가를 내리기 전에 프록시 인증을 할 수 있다.
일반적으로 터널 게이트웨이는 통신하고 있는 프로토콜이 터널을 올바른 용도로 사용하고 있는지를 검증할 방법이 없다. 따라서 터널의 오용을 최소화하기 위해 게이트웨이는 HTTPS 전용 포트인 443 같이 잘 알려진 특정 포트만을 터널링할 수 있도록 허용하는 것이 좋다.
HTTP 릴레이는 커넥션을 맺기 위한 HTTP 통신을 한 다음, 헤더와 메서드에 대한 로직을 수행하지 않고 맹목적으로 데이터를 전달하는 간단한 형태의 프록시이다. 단순 필터링이나 콘텐츠 변환을 하는데 사용되기도 한다. 그러나 앞서 4장 TCP 커넥션에서 지속 커넥션을 유지할 때, 멍청한 프록시로 인해 발생하는 문제와 마찬가지로 행(hang)에 걸릴 수 있다.