웹 서비스를 만들다 보면 CDN이나 리버스 프록시 같은 단어를 자주 만나게 된다. 이 글에서는 해당 개념들을 사용자의 요청이 브라우저를 떠나 데이터베이스에 닿기까지의 과정을 따라가며 설명하고자 한다.
온프레미스는 기업이 IT 인프라를 직접 소유하면서 관리하고 운영하는 방식이다. 서버를 사옥이나 자체 데이터센터에 두는 걸 떠올리면 된다.
클라우드는 인터넷을 통해 CSP로부터 컴퓨팅 자원을 빌려 쓰는 방식이다. 빌리는 자원의 추상화 수준에 따라 IaaS와 PaaS, SaaS로 나뉜다. IaaS는 가상 서버나 스토리지 같은 인프라 자체를 빌려준다. PaaS는 애플리케이션을 올리면 바로 돌아가는 실행 환경까지 제공한다. SaaS는 완성된 소프트웨어를 서비스 형태로 제공한다.
CSP는 Cloud Service Provider의 약자로, AWS와 Microsoft Azure, Google Cloud가 대표적이다.
기업이 온프레미스 대신 클라우드를 선택하는 이유는 비용 효율성, 확장성, 가용성, 신뢰성 때문이다. 장비를 미리 사두지 않고 쓴 만큼만 지불하면 되므로 초기 투자 부담이 줄어들고 트래픽에 따라 서버를 늘리고 줄일 수 있다. 또한, CSP는 여러 지역에 데이터센터를 운영하므로 한 데이터센터에 불이 나더라도 다른 데이터센터로 백업이 가능해 가용성과 신뢰성이 좋다.
초기에는 UI, 비즈니스 로직 처리, 데이터 저장을 하나의 머신 내에 전부 담았다. (물리 서버 혹은 가상 머신 등)
이 방식은 배포가 단순하다. 머신 한 대만 갱신하면 되기 때문이다. 구성 요소 사이에 네트워크 호출이 없기에 지연도 적고 문제를 추적하기도 쉽다.
하지만 부하가 커진다고 해서 머신을 나눠서 늘릴 수 없고, SPoF에 해당한다는 한계점이 있다. 추가로, 무중단 배포가 불가했다. 서비스를 잠시 내려야 하기 때문에 다운타임도 필수적이었다.
그래서 애플리케이션 서버와 데이터베이스 서버를 분리한 2-Tier 구조가 생겨났다. 데이터를 다루는 책임이 별도의 서버로 옮겨가면서 둘을 따로 관리하게 됐다.
이 무렵 스마트폰이 보급되면서 화면을 클라이언트가 직접 그리는 SPA가 늘어났다. 오픈소스 문화가 퍼지면서 백엔드를 더 유연하게 가져갈 필요가 생겨 서버는 점차 API를 제공하는 형태로 바뀌었다. 정적 파일을 빠르게 전달하기 위해 CDN을 쓰는 일도 흔해졌다.
그러면서 3-Tier 구조가 생겨났다. 화면 담당, 로직 담당, 데이터 담당이 3개로 분리된 것이다. 이것을 각각 프리젠테이션 계층과 애플리케이션 계층과 데이터 계층이라 부른다.
Browser → CDN → Load Balancer → Web Server → WAS → DB Server
웹 브라우저에서 발생한 요청은 위와 같은 순서로 이동하게 된다.
CDN(Content Delivery Network)은 전 세계 여러 지역의 엣지 서버에 콘텐츠를 캐싱해 둔다. 사용자가 요청을 보내면 가장 가까운 엣지 서버에서 응답한다. 주로 정적 콘텐츠(이미지, CSS 등)을 다룬다.
사용자와 가까운 엣지 서버에서 응답하기 때문에, 사용자와 서버 사이의 물리적 거리가 가까워 응답이 빠르다. 그리고 원본 서버에게 요청이 가지 않으므로 원본 서버에 가해지는 부하가 줄어든다.
대표적인 서비스로 AWS CloudFront와 Cloudflare, Akamai가 있다.
로드 밸런서는 들어오는 요청을 여러 대의 서버로 분산한다. 한 서버에 부하가 몰리지 않게 하고 일부 서버가 죽어도 나머지가 요청을 받아준다.
로드 밸런서가 트래픽을 분배할 때 어떤 정보를 확인하느냐에 따라 두 종류로 나뉜다. L4 로드 밸런서는 IP 주소, 포트 번호를 기준으로 분배한다. 패킷 내의 내용은 확인하지 않기 때문에 처리가 가볍고 빠르다. L7 로드 밸런서는 HTTP 요청 내 내용도 확인한다. URL 경로가 무엇으로 시작하느냐에 따라 다른 서버로 보내기도 하여 더 정밀한 분배가 가능하다. 하지만 내용을 해석하기 때문에 처리 부담이 좀 더 크다.
요청을 중계하는 중간 서버이다.
포워드 프록시는 클라이언트 앞단에 존재한다. 클라이언트를 대신해 외부 서버에 요청을 보내므로 서버는 실제 요청자가 누구인지 알기 어렵다. 사내망에서 직원들의 외부 접속을 통제하거나 자주 쓰는 자원을 캐싱하는 데 사용된다.
리버스 프록시는 서버 앞단에 존재하며 클라이언트의 요청을 받아서 실제 서버로 넘겨준다. TLS 암호화를 복호화해 서버의 부담을 줄이거나 요청 분배, 응답 캐싱, 보안성을 높이는 게(백엔드 서버를 클라이언트가 알지 못하므로) 가능하다. Nginx, AWS의 ALB가 이에 해당한다.
웹 서버는 HTTP 요청을 받아 주로 정적 콘텐츠(미리 만들어진 HTML이나 이미지처럼 가공이 필요 없는 파일)를 응답한다. 동적인 처리가 필요한 요청은 직접 처리하지 않고 WAS로 전송한다. 이 때의 웹 서버는 리버스 프록시 역할을 겸한다고 할 수 있다. Nginx와 Apache HTTP Server로 예를 들 수 있겠다.
WAS(Web Application Server)는 비즈니스 로직을 실행하여 동적인 결과를 만들어내는 서버이다. 데이터베이스와 연동하고 트랜잭션을 처리하며 세션을 관리한다. Apache Tomcat 등이 해당된다.
웹 서버와 WAS를 나누면 성능, 확장, 보안 면에서 이점이 있다. 정적인 응답은 웹 서버가 처리하므로 WAS는 동적인 응답만 처리할 수 있어 성능이 향상되며 WAS를 외부에 노출하지 않아도 되므로 보안에도 유리하다. 그리고 필요한 서버만을 증설할 수 있어 확장 면에서도 이점이 있다.
퍼블릭 IP는 인터넷 전역에서 식별되는 주소이다. 전 세계에서 유일하며 외부에서 직접 찾아올 수 있다.
프라이빗 IP는 사내망이나 VPC 내부에서만 통하는 주소이다. 같은 내부망 안에서는 유일하지만, 전 세계적으로는 유일하지 않기 때문에 인터넷에서는 사용 불가하며 외부 컴퓨터가 직접 통신할 수 없다. 따라서 내부 장비는 NAT를 거쳐야 인터넷과 통신할 수 있다.
| 항목 | 퍼블릭 IP | 프라이빗 IP |
|---|---|---|
| 통하는 범위 | 인터넷 전역 | 내부망 안에서만 |
| 유일성 | 전 세계에서 유일 | 해당 네트워크 안에서만 유일 |
| 인터넷 접속 | 직접 가능 | NAT를 거쳐야 가능 |
프라이빗 IP로 쓸 수 있는 주소 범위는 RFC 1918이라는 표준이 있다.
| 대역 | 범위 |
|---|---|
| 10.0.0.0/8 | 10.0.0.0 부터 10.255.255.255 까지 |
| 172.16.0.0/12 | 172.16.0.0 부터 172.31.255.255 까지 |
| 192.168.0.0/16 | 192.168.0.0 부터 192.168.255.255 까지 |
이 대역들은 CIDR 표기로 나타내며 인터넷에서 라우팅되지 않으므로 어떤 조직이든 내부 용도로 자유롭게 쓸 수 있다.
VPC는 클라우드 안에 만드는 사용자 전용의 격리된 가상 네트워크다. AWS 같은 CSP의 인프라는 수많은 고객이 함께 사용하기 때문에, 고객의 자원들이 네트워크 내에 섞여있으면 곤란하다. CSP는 고객마다 논리적으로 분리된 VPC를 제공하여 사용자가 어떤 사설 IP 대역을 쓸지 정하고 그 대역을 서브넷으로 나누고, 그 서브넷이 각각 어떻게 인터넷과 통신할지를 설계한다.
보통 VPC 안에서는 서브넷을 나눌 때 성격에 따라 세 구역으로 나누어 사용한다.
Public 구역은 인터넷에 직접 접속할 수 있는 서브넷이다. 외부 사용자가 직접 요청을 보내야 하는 자원을 여기에 배치한다.
DMZ에는 외부 요청을 가장 먼저 받지만 내부를 직접 노출하지는 않는 자원을 둔다. (웹 서버나 리버스 프록시)
Private 구역에는 내부 이용자만 접근할 수 있는 자원을 둔다. WAS와 데이터베이스처럼 외부에 직접 노출되면 안 되는 것들이 해당된다.
VPC 내 자원들이 외부 인터넷과 통신할 대 사용하는 게이트웨이는 IGW와 NAT가 있다.
Public 구역의 자원은 IGW(Internet Gateway)를 사용한다. IGW는 사설 IP 주소와 퍼블릭 IP 주소를 일대일로 짝 지어주는 일대일 NAT 방식을 사용한다. 예를 들어 특정 인스턴스의 사설 IP가 10.0.1.5이고 퍼블릭 IP가 부여되어 있다면 그 인스턴스가 밖으로 보내는 패킷은 출발지 주소가 퍼블릭 IP로 바뀌고 밖에서 그 퍼블릭 IP로 들어오는 패킷은 다시 10.0.1.5로 바뀌어 전달된다.
NAT(Network Address Translation)은 Private 서브넷의 인스턴스가 VPC 외부로 나가는 통신을 시작할 수 있게 해준다. 하지만 나가는 요청만 처리하고 인터넷에서 들어오는 요청은 처리하지 않는다. 덕분에 Private 구역의 WAS가 OS 업데이트를 받거나 외부 API를 호출하는 일은 할 수 있지만 외부에서 직접 접근은 할 수 없게 된다.
NAT은 다대일 방식으로 동작하기 때문에 이가 가능하다. Private 서브넷 내에 인스턴스가 여러 대 있어도(=사설 IP가 여러 개) 퍼블릭 IP는 하나로, 요청이 나갈 때 출발지 주소는 해당 퍼블릭 IP를 사용한다. 요청이 들어오는 경우에는 내부 사설 IP를 모르기 때문에 정상적인 요청이 불가능하다.
추가로, NAT Gateway를 거친 트래픽도 결국 IGW를 지나야 인터넷으로 나갈 수 있다.