현재 프로젝트를 진행하고 있으면서 제가 만들고 있는 서비스의 흥행으로 사용자 이용량이 증가하게 되면 시스템의 확장이 필요해집니다. 그렇다면 그 때, 시스템의 확장을 위한 방법에는 어떤 것이 있을지 그리고 어떤 방식을 채택하는게 좋을지 알아보도록 하겠습니다.
먼저 서버의 확장이 왜 필요할지에 대해 알아보도록 하겠습니다.
간단한 사이드 프로젝트를 진행하게 되면, 위 그림과 같이 사용자 단말에서 웹 서버를 바로 조회하는 형식으로 프로젝트를 진행하게 됩니다. 이러한 단일 서버 형태의 단점은 사용자의 데이터를 웹 서버에 보관한다는 점, 그리고 그로인해 웹 서버가 사용자 단말과의 트래픽 처리와 함께 데이터 처리도 관여 하기 때문에, 전체적으로 웹 서버의 트래픽이 증가 해 장애 가능성이 높아진다는 점이 있습니다.
따라서 데이터베이스 서버를 두어, 웹/모바일 트래픽 처리 서버(웹 계층)와 데이터베이스 서버(데이터 계층)를 분리하여 웹 서버에 집중되는 트래픽을 분리할 수 있으며, 추후 서버를 확장하게 되면 웹 서버 또는 데이터베이스 서버를 개별적으로 확장해 나갈 수 있다는 장점이 있습니다.
Scale Up
스케일 업(Scale-Up) 은 쉽게 말하면 서버의 사양을 보다 높은 사양으로 업그레이드 하는 것 입니다. 하드웨어 적인 부분의 예를 들면, 서버의 성능이나 용량 증강을 목적으로 디스크를 추가하거나 CPU나 메모리를 업그레이드 시키는 것을 말합니다.
서버 하나의 능력을 증강시키기 때문에 수직 규모 확장법(vertical Scaling)이라고도 합니다.
수직 규모 확장법의 소프트웨어 적인 예로는 AWS의 EC2인스턴스 사양을 micro에서 → small, small→medium등으로 높이는 것으로 생각할 수 있습니다. 또한 수직 규모 확장법의 하드웨어 적인 예시로는 서버의 사양을 올리는 것으로 생각할 수도 있습니다.
스케일 업은 한 대의 서버의 사양을 확장 시키기 때문에, 데이터 갱신이 빈번하게 일어나는 데이터베이스 서버에 적합한 방식이라 볼수도 있습니다.
스케일 업 방식의 가장 큰 장점으로는 서버를 구축하기 단순하다는 점이 있습니다.
하지만 스케일 업의 경우, 서버 한대에 모든 부하가 집중되므로 서버 장애 시 전체 시스템에 장애가 생길 수도 있는 위험성이 있습니다(SPOF). 그렇기에 장애에 대한 자동 복구(failover)방안이나 다중화(re-dundancy)을 제시하지 않습니다.
스케일 아웃(Scale-Out)
스케일 아웃(Scale-Out)은 기존의 하드웨어는 그대로 두고 장비를 추가해서 확장하는 방식을 말합니다.
서버의 수를 늘리기 때문에 수평적 규모 확장법(horizontal scaling)이라고도 합니다.
기존 서버만으로 용량이나 성능의 한계에 도달했을 때, 비슷한 사양의 서버를 추가로 연결해 처리할 수 있는 데이터 용량이 증가할 뿐만 아니라 기존 서버의 부하를 분담해 성능 향상의 효과를 기대할 수도 있습니다.
스케일 아웃의 경우, 스케일 업과 달리 서버 한 대가 장애로 다운되더라도 다른 서버로 서비스 제공이 가능하다는 장점이 있습니다(High Availability). 이러한 High Availability를 제공하기 위해서는 스케일 아웃 방식에서는 서버가 여러 대가 되기 때문에 각 서버에 걸리는 부하를 균등하게 처리 해주는 로드밸런서 가 시스템 구조에 도입되어야 합니다.
로드 밸런서(Load Balancer)
로드 밸런서는 부하 분산 집합(load balancing set)에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할을 합니다.
사용자는 로드밸런서를 통해 서버의 Private IP 주소에 직접 접근하는 것이 아닌 로드 밸런서의 Public IP 주소로 접속합니다. 웹 서버는 클라이언트의 접속을 직접 처리하지 않게 됩니다. Private IP 주소는 로드 밸런서가 서버와 통신하기 위해 사설 주소를 사용합니다.
그림 처럼 로드 밸런서를 사용하고, 부하 분산 집합을 설정하고, 부하 분산 집합에 또 하나의 웹 서버를 추가하고 나면 장애를 자동복구하지 못하는 문제(no failover)는 해소되며, 그에 따라앞서 살펴보았던 웹 계층(사용자의 웹/모바일 트래픽을 처리하는 서버)의 가용성이 향상됩니다.
위 그림에서 로드 밸런서가 트래픽을 처리하는 과정을 좀 더 자세히 설명해보자면,
- 서버 1이 장애가 발생해 다운되면 서버 1이 받고 있던 모든 트래픽은 서버 2로 전송된다. 이때 서버 2로 트래픽이 몰리는것을 방지하기 위해 새로운 서버를 추가할 수도 있다.
- 그림 처럼 서버 두대로는 대규모 트래픽을 감당할 수 없는 시점이 오게 되는데, 이 때 로드밸런서가 로드 밸런서의 부하 분산 집합에 속한 웹 서버들에게 트래픽을 자동으로 분산 해주기 때문에, 웹 서버 계층에 더 많은 서버를 추가하기만 하면 됩니다.
그리고, 이런 로드 밸런서의 종류로는 ELB(Elastic Load Balancer)와 Nginx를 대표적인 예시로 들 수 있습니다. 두 제품의 장단점을 알아보고, 현재 진행중인 프로젝트에서는 어떤 제품을 선택해야 할지 또는 두 제품을 동시에 사용할지에 대해 얘기해보겠습니다.
ELB(Elastic Load Balancer)
먼저 ELB는 AWS상에 여러 대상에 애플리케이션의 트래픽을 자동으로 분산시켜 안정적인 AWS 서버 환경을 운용하는데에 도움을 주는 서비스 입니다. ELB는 서로다른 EC2 인스턴스에 대한 하나의 진입점을 제공합니다. 그래서 사용자는 실제 요청이 처리되는 EC2 인스턴스가 어느 곳인지 알 필요 없이, ELB를 통해 동일한 진입점으로 요청을 전송할 수 있습니다.
(앞서 설명한 내용을 다시 인용하자면, 사용자는 로드밸런서(ELB)를 통해 서버의 Private IP 주소(EC2 Instance의 IP 주소)에 직접 접근하는 것이 아닌 로드 밸런서의 Public IP 주소(ELB의 진입점 엔드포인트 라고도 합니다)로 접속합니다.)
ELB는 이런 부하분산 처리 기능만 갖고 있는것이 아닌, 부하 분산 대상에 대한 헬스 체크, 고정 세션(Sticky Session),SSL 암복호화(SSL Offload), 헬스 체크를 통한 장애가 발생한 다운 서버 제외 등의 기능이 제공됩니다.
또한 ELB는 AWS에서 제공하는 기능인 오토 스케일링과 함께 조합해서 사용합니다. 오토 스케일링은 우리가 구축해놓은 AWS 환경에 트래픽이 몰릴 때, AWS 인스턴스(컴퓨터) 수를 자동으로 늘림으로서 서버 갯수를 조절 해 서비스가 고가용성을 유지할수 있도록 합니다. 또한 트래픽이 적을 경우 인스턴스를 감소시켜 AWS 사용자의 비용 낭비를 막아줍니다.
그렇기 때문에 ELB와 오토 스케일링을 함께 사용하면, 트래픽 분산 처리시에 EC2를 보다 효과적이게 이용할 수 있습니다.
Nginx
Nginx는 비동기 이벤트 기반(Event-Loop) 구조의 경량화 웹 서버 프로그램 입니다. 사용자로부터 요청을 받았을 때, 요청에 맞는 정적 파일(HTML,CSS등)을 응답해주는 HTTP Web Server로 활용되기도 하고, Reverse Proxy Server로 활용하여 WAS 서버의 부하를 줄일 수 있는 로드 밸런서로 활용되기도 합니다.
Nginx 의 특징중 비동기 이벤트 기반의 구조라는 말을 앞서 하였는데. 이에 대해 더 자세히 설명 하자면, Apache와 같은 쓰레드 기반의 WAS는 하나의 쓰레드가 하나의 요청을 처리하는 구조이기 때문에, 사용자의 매 요청마다 쓰레드를 생성 및 할당해야 하기 때문에 메모리 리소스를 많이 점유한다는 문제가 있습니다. 반면 Nginx는 이벤트 중심 접근방식으로 하나의 스레드 내에서 여러 요청을 처리하는 구조 입니다. 이때 사용된 이벤트 중심 접근 방식(Even-Driven 구조)은 Event Handler에서 비동기 방식으로 먼저 처리되는 요청을 진행한다는 것을 의미합니다.
비동기 이벤트 루프 방식에 대해 명쾌한 비유를 들어주신 분의 말을 인용해 이어서 설명하도록 하겠습니다.
(식당에 비유하자면...손님들에게 일단 당장 음식은 내오지 못하더라도 메뉴는 주방에 전달하고 손님을 앉히게해서 한꺼번에 많은 손님들을 받을 수 있는 그런 구조다.) 원문 링크
이런 Nginx의 특성을 이용하면 사용자의 요청에 의해 생기는 다수의 연결을 효과적으로 처리할 수 있다는 장점이 있습니다.
그렇다면 이런 Nginx의 단점은 무엇일까요? 먼저 Nginx는 동적 컨텐츠(js나, php등)를 기본적으로 처리할 수 없기 때문에 외부 자원과 연계를 해야 합니다 이 과정에서 외부 자원과의 통신을 해야하기 때문에 프로세스 속도가 저하된다는 단점이 있습니다.
현재 진행중인 프로젝트에서는 로드밸런서를 어떤걸 써야 할까?
현재 진행중인 프로젝트에서는 ELB의 헬스 체크, SSL 암복호화 와 같은 다양한 기능들을 사용해, 프로젝트 생산성을 높일 수 있지만, ELB를 사용함에 있어 비용 문제가 발생하고, ELB의 다양한 기능보다는 현재 프로젝트의 목표중 하나인 대용량 트래픽 처리에 중점을 두고 생각해 보았을 때도, Nginx의 비동기 이벤트 기반의 구조를 이용해 대규모 트래픽을 분산 처리해주는 로드 밸런서의 역할로 활용하려 합니다.
그렇다면 이런 수평적 규모 확장법(Horizontal Scailing)은 서버를 확장하고, 로드 밸런서가 고르게 트래픽을 분배해줌에 따라 서버 가용성을 증가 시킬 수 있어, 좋은 점만 있는 것일까요?
아닙니다. 웹 애플리케이션 서비스의 특성상, 로그인 과 같은 정보를 서버에 저장해야할 경우가 생기는데, 이때 서버 다중화 환경에서 발생하는 세션 불일치 현상이 발생할 수도 있습니다. 이를 해결하기 위한 방법에 관련된 내용은 다른 포스트에서 설명하도록 하겠습니다.
마무리
제가 현재 진행중인 프로젝트는 웹 서버를 기반으로한 프로젝트입니다. 추후 사용자가 계속해서 증가함에 따라 서버가 받는 부하가 증가한다고 가정할 때, 스케일 업 방식을 채택한다면 서버의 성능 향상을 통해 사용자 개개인의 사용자 경험은 향상 시킬 수 있을지도 모르겠으나, 사용자의 수가 늘어나게 된다면 1대의 서버에 트래픽이 집중되게 되어 결국 전체 애플리케이션 장애로 까지 이어지게 될 것 입니다. 따라서 서버의 부하 분산 처리와, 서버 장애에 따른 다중화 된 서버로 서비스 제공이 가능한 스케일 아웃 방식을 채택하고, 서버 다중화에 따른 트래픽 분산처리를 위해 로드밸런서(Nginx)를 도입하는게 진행중인 프로젝트에서 채택할 수 있는 서버 확장 전략이라고 생각합니다.
+ 또한 서버의 고 가용성이 아닌 서버의 성능 향상 관점에서는, 수직적 규모 확장법 뿐만 아니라 CDN이나 캐싱을 이용하는 듯 접근을 달리하여, 서버의 성능 개선을 노려볼 수 있을 것 같습니다. 해당 내용 관련하여 추후 포스팅에서 설명하도록 하겠습니다 감사합니다😊
참고 자료
https://library.gabia.com/contents/infrahosting/1222/
https://tecoble.techcourse.co.kr/post/2021-10-12-scale-up-scale-out/