brunch

You can make anything
by writing

C.S.Lewis

by 정채상 Oct 03. 2024

클라우드에서 서비스 확장하기

디지털서비스 이슈리포트 2024-09호

이 글은 제가 NIA [한국지능정보사회진흥원]의 < 디지털서비스 이슈리포트 > 2024년 9월호에 기고한 글입니다. 원본 글 '클라우드에서 서비스 확장하'를 이곳 브런치에서도 공유합니다.


들어가며


지난 2024년 8월호에 “클라우드 서비스 개발에서 데이터베이스 사용 최적화하기”라는 주제로 클라우드에서 서비스를 운영하고 있으면서 사용자가 늘어날 때 데이터베이스를 이용하면서 생기는 여러 이슈들에 대해서 어떻게 그 문제들을 다루는지에 대해 여러 가지 방법들을 다루었었다.


마지막 문단에는 서비스를 운영하는 여러분들이 이 단계까지에 오게 되면 많은 사용자들이 이용하고 있다는 증거이므로 먼저 축하의 마음을 전한다는 말과 함께 데이터베이스 이외에도 다양한 문제들이 발생할 것임을 이야기 드렸는데, 이 글에서는 데이터베이스 최적화만으로 해결되지 않는 다양한 이슈들에 대해 각종 클라우드 환경에서 어떤 노력들을 할 수 있는지에 대해 이야기 해 보겠다.


앞 글에서는 데이터베이스의 최적화 기법들에 대해 이야기하기 위해서 게시판을 운영하는 서비스의 예를 들었지만, 이 글에서는 조금 더 일반적인 서비스에 동시에 접속하려는 사용자가 많아져서 발생하는 이슈들에 대해 이야기 해 보겠다. 타임 딜 같은 외부 이벤트 등과 연계해서 사용자들이 늘어나는 것을 예상할 수도 있고, 이른바 바이럴 마케팅에 긍정적 영향을 받아서 예상하지 못하는 상태에서 점진적으로 사용자들이 늘어나는 경우도 있을 수 있겠다.


동시 접속 처리 - 웹 서비스



게임과 같은 앱을 운영하더라도, 클라우드에 있는 서버에 접속해서 서비스를 시작할 것이고, 이는 웹 서비스에 동시에 많은 사용자들이 몰리는 것과 같기에 웹 서비스를 만들 때 어떻게 하면 동시 접속 가능한 사용자를 늘릴 수 있을까와 같은 문제라 하겠다. 사용자가 직접 하나의 기계를 선택해서 거기서 실행되고 있던 웹 서버에 연결해서 요청하던 환경에서 아래와 같이 확장을 고려할 수 있다. 그림 1은 네이버 클라우드에서 레퍼런스로 보여 주는 소규모 웹사이트를 위한 아키텍쳐의 사례이고, 여러 개의 웹 서버가 나눠서 사용자의 요청을 대응하는 모습이다. 그리고 그림 2는 마이크로소프트 애저에서 제공하는 앱 서비스를 이용해서 주 요청을 담당하게 하고, 나머지 필요한 요소들을 주변에 배치함으로써 확장을 구현한 모습의 사례이다.

그림 1. 소규모 웹사이트를 위한 아키텍쳐 ( https://www.ncloud.com/intro/architecture/3 )


그림 2. 기본 Azure 앱 Service 아키텍처 

이는 하나의 물리적 기계 서비스에 몰려 있던 것들을 각 기능에 맞게 나누어 쓰는 것에 해당하는데, 먼저 데이터베이스를 별도의 기계 혹은 서비스로 놓고, 서비스에 필요한 파일들을 다른 곳에 놓음으로서 웹서비스는 주어진 트래픽의 처리를 전담하게 한다. 


웹 서비스의 성능 개선을 위해서는 트래픽 분산을 담당하는 로드밸런서를 사용자와 웹 서버 사이에 놓으며, 유사시에 같은 기능을 하는 웹서버를 여러 개 놓아서 동시에 운영할 수 있도록 하고, 캐시를 사용하는 등 여러 기법들을 사용함으로써 성능 개선을 기대한다. 참고로 데이터베이스를 사용하지 않는 작업들은 분산되는 효과를 기대할 수 있지만, 사용자들의 요구가 모두 데이터베이스를 읽고 쓴다면 병목은 다시 데이터베이스 내에서 생기게 된다. 


로드 밸런서 사용하기


로드 밸런서는 여러 대의 서버에 걸쳐 있는 네트워크 트래픽을 효과적으로 분산시키는 장치로, 주요 기능은 다음과 같다.   

    트래픽 분산: 클라이언트의 요청을 여러 대의 서버에 분산시켜 서버 부하를 균형있게 조절할 수 있고, 이를 통해 서버 리소스를 효율적으로 활용할 수 있다.  

    서버 가용성 관리: 서버의 상태를 모니터링하고, 서버가 오프라인이 되면 해당 서버를 제외하고 나머지 서버로 트래픽을 전달하는데, 이를 통해 시스템의 가용성과 신뢰성을 높일 수 있다.  

    확장성 지원: 서버 용량을 동적으로 늘리거나 줄일 수 있어, 시스템의 확장성을 높일 수 있다.  

    보안 기능: SSL 종단 암호화, 웹 어플리케이션 방화벽(WAF, Web Application Firewall) 등 다양한 보안 기능을 제공하여 시스템의 보안을 강화할 수 있다.  

    세션 관리: 사용자 세션을 관리하여 동일한 클라이언트 요청이 동일한 서버로 전달되도록 할 수 있다.  


이와 같은 기능을 통해 로드 밸런서는 웹 서버와 사용자 사이 뿐 아니라 API 서비스, 데이터베이스 등 다양한 분야에서 활용되고 있고, 대규모 트래픽을 처리하는 시스템에서 로드 밸런서는 매우 중요한 역할을 한다. 클라우드 환경에서는 아래와 같은 다양한 로드밸런서 솔루션들을 사용할 수 있다.

    AWS ELB(Elastic Load Balancing) : AWS 에서 제공하는 기본 로드 밸런서로, 다양한 유형을 선택 가능하고 글로벌 네트워크 및 강력한 보안 기능들을 통합할 수 있다.  

    Azure Load Balancer : Azure 에서 제공하는 기본 로드밸런서로 L4 로드 밸런싱 외에 웹 어플리케이션 방화벽(WAF)과 통합된 보안 기능을 제공한다.   

    GCP Load Balancing : 구글 클라우드에서 제공하는 관리형 로드 밸런서로, 단일 글로벌 IP로 전 세계에서 트래픽 처리가 가능하고, 자동으로 확장과 트래픽 최적화를 지원한다. .  

    NCP Load Balancer :  네이버 클라우드에서 제공하는 로드 밸런서로, 비용 효율적이며, 사용자가 정의 가능한 로드 밸런싱 정책을 제공한다. 

 NGINX  / HAProxy  : 오픈 소스 웹 서버이자 리버스 프록시로, 트래픽을 분산시키는 로드 밸런서로 사용할 수 있다. 설치형으로 주로 이용한다.


캐시 사용하기


먼저 캐시는 컴퓨터 과학에서 일반적으로 쓰이는 개념으로 자주 사용하는 데이터 혹은 앞으로 사용할 거 같은 데이터를 빠르게 접근할 수 있는 곳에 준비하는 방법론을 이야기한다. 하드웨어부터 응용 소프트웨어까지 널리 쓰이는 기법으로 시스템의 성능을 높이고 응답 시간을 단축시키기 위해 광범위하게 사용된다. 


하나의 웹 서비스를 사용자들이 실행함에 있어 네트워크를 통해서 여러 서비스들을 이용하게 될 때에도 같은 개념을 다양한 계층에서 사용할 수 있다. 각 계층에서 메모리를 소비하고 임시적인 데이터 일관성을 비용으로 지불하면서 전체 응답 시간 단축, 서버의 부하 감소를 기대하고, 그에 따른 비용 절감의 효과까지도 이룰 수 있다. 아래는 각 계층 별로 자주 캐시를 사용하는 방법들의 예제들이다.  

    브라우저 캐시 : 사용자 브라우저에서 캐시를 설정해서 이미지, CSS, JS 파일 등을 저장해 두어 다음 번 요청 시 네트워크를 이용하지 않고 빠르게 로드할 수 있게 할 수 있다.   

    리버스 프록시 캐시 : 로드 밸런서로 사용하는 리버스 프록시의 경우 각 클라이언트에서의 요청과 백앤드 서버의 응답을 저장해 두고 같은 요청에 같은 결과를 네트워크를 이용하지 않고 사용할 수 있다.  

    서버 사이드 캐시 : 서버 내에서 자주 사용하는 데이터를 매 번 연산하지 않고, 메모리 등에 저장하여 사용한다.  

    데이터베이스 쿼리 캐시 : 데이터베이스에서 자주 조회되는 쿼리 결과를 저장해서 데이터베이스의 추가적인 열람을 하지 않고 성능을 높인다.  

이들 중 클라우드 환경에서 동작하는 서비스에서 사용하는 캐시는 서버 사이드 캐시에 해당하고, 서버에서의 다양한 지원을 위해서는 레디스(Redis)와 멤캐시드(Memcached)를 인메모리(in-memory) 데이터 저장소로 주로 사용한다. 다양한 데이터 구조와 보조 장치에 기록해야 할 경우 혹은 메시지 전송 기능이 필요할 때는 레디스 계열이 주로 이용되고, 단순한 키-값 캐시가 필요하고 상대적으로 더 빠른 성능이 필요할 때는 맴캐시드 계열 서비스를 사용한다. 

그림 3. 레디스 OSS와 멤캐시드 중에서 선택하기

캐시 서비스를 설치해서 사용할 수도 있지만,  클라우드 서비스들에서는 아래와 같이 관리형 서비스들을 사용할 수 있다.  

    AWS  : 아마존 엘라스티캐시(Amazon ElastiCache)는 관리형 캐시 서비스로, 레디스와 멤캐시드를 지원한다.   

    구글 클라우드 : 구글 클라우드 메모리스토어(Google Cloud Memorystore)는 관리형 캐시 서비스로, 레디스와 멤캐시드, 발키(Valkey), 레디스 클러스터 등을 지원한다  

    애저: 애져 캐시 포 레디스2(Azure Cache for Redis®2)는 관리형 캐시 서비스로 레디스를 지원한다. 

네이버 클라우드  : 클라우드DB 포 레디스(Cloud DB for Redis)는 관리형 캐시 서비스로 레디스를 지원한다.


CDN 사용


앞에서 이야기한 사용자와 서비스 사이의 캐시를 구현하는 방법 들 중 하나로 CDN(콘텐츠 전송 네트워크, Content Delivery Network)이 많이 쓰인다. 이는 콘텐츠를 더 빠르고 효율적으로 전달하기 위한 분산 네트워크이고, 이 CDN은 여러 서버로 구성된 네트워크를 통해 웹사이트의 정적 자원(이미지, 비디오, CSS, JavaScript 파일 등)을 사용자와 가장 가까운 서버에서 제공함으로써 웹사이트의 성능과 가용성을 향상시킨다.


클라우드 서비스들이 실제 사용자에게 쓰일 때 영향이 큰 부분이기도 하고, 퍼블릭 클라우드가 널리 쓰이기 이전부터 중요하게 쓰였으며, 현재 아래와 같은 여러 서비스들이 있다.  

    아카마이(Akamai) : 업계에서 가장 오래된 CDN 중 하나로, 전 세계적으로 분산된 데이터 센터를 보유하고 있다. 높은 가용성과 안정성을 제공하며, 광범위한 보안 기능(DDoS 방어, WAF 등)들을 제공한다.

    클라우드플레어(Cloudflare) : 무료 플랜을 제공하는 인기 있는 CDN으로, 설정이 간편하다. DDoS 방어, SSL, WAF 등 다양한 보안 기능을 포함하고 있으며, 빠른 속도와 안정성을 제공해서 중소기업, 스타트업 혹은 개인 웹사이트에도 많이 사용된다.

    아마존 클라우드프론트(Amazon CloudFront) : AWS 생태계에 통합된 CDN 서비스로, AWS의 다양한 서비스와 원활하게 연결된다. 유연한 요금 체계와 높은 확장성을 제공하며, 글로벌 엣지 로케이션을 통해 빠른 속도를 보장한다.

    구글 클라우드 CDN(Google Cloud CDN) : 구글 클라우드 플랫폼에 통합되어 제공되는 CDN으로, 구글 클라우드의 인프라를 활용한다. 자동화된 캐싱, HTTPS 지원을 비롯한 구글 클라우드 서비스와의 원활한 통합이 가능하다.

    애저 CDN : 애저 플랫폼과 통합된 CDN 서비스로, 다양한 콘텐츠 전송 및 캐싱 기능을 제공한다. 애저의 보안 및 데이터 관리 기능과 함께 사용하여 안정성을 높일 수 있다.

    CDN+ : 네이버 클라우드 플랫폼에 통합되어 제공되는 CDN이다. 한국 내 사용자에게 최적화된 성능을 제공하며, DDoS 방어와 자동 캐시 관리 기능이 뛰어나다.


그 밖의 기법들


이제까지 더 많은 동시 접속 사용자를 지원하기 위해 클라우드에서 지원하는 서비스를 이용해서 해결하려는 방법들에 대해 알아 보았고, 그 이외에도 몇가지 방법들을 소개한다. 어떤 방법을 적용하기 전에 이미 끊임 없는 모니터링과 최적화 등을 고민해야 하고, 병목이 일어나고 있는 건 아닌지, 네트워크 전송 속도와 CPU의 부하 등을 계속 체크해야 한다. 


먼저 해당 기계들의 물리적인 위치를 고려한다. 넓게는 나라, 조금 좁게는 데이터센터의 위치, 더 좁게는 네트워크 장비까지 클라우드 내에서 서비스들의 위치들까지 불필요한 낭비가 없는지 확인한다. 흔히 하는 실수로, 잘 동작하고 있던 서비스가 몇명의 사용자가 쓰지 않는 기능을 위해 작은 새로운 서비스가 연동이 되면서 병목이 되어 전반적으로 느려지는 경우가 있곤 한다. 클라우드 내에서라도 네트워크 대역이 충분히 활용되고 있는지 확인하도록 한다.


그리고, 개발자들 사이에서 종종 이슈로 오가는 CSR(클라이언트 측 렌더링, Client-Side Rendering)과 SSR(서버 측 렌더링, Server-Side Rendering) 사이의 선택도 고려할 수 있다. 사용자의 여러 행동들을 매번 서버에 물을 것인가, 미리 받아 놓은 코드로 해결할 것인가의 선택지로, 사용자와 서비스 사이의 불필요한 통신을 줄이는 요소가 될 수 있지만, 검색 엔진에 노출되기를 원하는 페이지의 경우 검색 엔진에게 잘못된 정보를 전해 줄 수가 있어 장단점을 비교할 수 있어야 한다.


마지막으로 하나의 요청과 응답을 주고 받게 될 때 더 많은 동시 접속을 지원하려면 시간이 많이 걸리는 작업들을 비동기 처리를 이용해서 구현할 수 있다. 카프카(kafka)나 펍섭(pubsub) 등의 메시징 시스템을 이용해서 서비스를 재구성을 해야 하지만, 시간이 오래 걸리는 작업들을 시스템의 부하가 적을 때 몰아서 할 수 있으므로 시스템의 효율도 높일 수 있다. 다만, 실제 작업이 끝나기 전에 대기중이라는 화면을 보여 주는 등 사용자를 대상으로 하는 기능이 추가되어야 한다면 설계를 다시 해야 하는 경우가 생기기도 하니, 여건을 고려해서 적절한 방법을 선택해야 한다.


아래는 이제까지의 기법들이 적용된 서비스의 조금 복잡한 설계 예제이다. 가운데 웹 서버를 중심으로 이 글을 시작할 때보다 많은 고려할 것들이 추가되어 있음을 알 수 있다.


그림 4. AWS 클라우드에서의 웹 애플리케이션 호스팅


동시 접속 처리 - 컨테이너를 이용한 배포


클라우드에 만들어진 서비스들은 여러 개의 논리적인 애플리케이션 서비스에서 처리가 되는데 아래 그림에서처럼 이전의 전통적인 방식에서는 하나의 운영체제 위에 여러 개의 서비스들이 동작하는 방식이었다면, 이후 데이터센터 혹은 클라우드를 사용하는 지금은 가상화된 배포 시대를 지나 컨테이너를 개발해서 배포하는 시대로 바뀌어 가고 있다. 중간에 VM 이라 부르는 가상화된 하드웨어 상에서 자체 운영체제를 포함한 형태로 자원을 나누어 쓰는 시도들이 있었지만, 운영 체제를 여러 계층으로 운영하는 것보다 하나의 운영 체제에 런타임 환경을 나누고 공유할 수 있게 하는 컨테이너 방식이 지금은 대세로 자리잡고 있다.

그림 5. 어플리케이션 배포 환경의 변화

컨테이너는 아래와 같은 이유들로 널리 쓰이게 되었다.  

    기민한 애플리케이션 생성과 배포: VM 이미지를 사용하는 것에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적이다.  

    지속적인 개발, 통합 및 배포: 안정적이고 주기적으로 컨테이너 이미지를 빌드해서 배포할 수 있고 빠르고 효율적으로 롤백할 수 있다.  

    개발과 운영의 관심사 분리: 배포 시점이 아닌 빌드/릴리스 시점에 애플리케이션 컨테이너 이미지를 만들기 때문에, 애플리케이션이 인프라스트럭처에서 분리된다.  

    가시성(observability): 운영체제 수준의 정보와 메트릭에 머무르지 않고, 각 애플리케이션의 상태와 그 밖의 시그널을 모아서 볼 수 있다.  

    클라우드 및 OS 배포판 간 이식성: 우분투, RHEL, CoreOS, 온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.  

    분산되고, 유연하며, 자유로운 마이크로서비스: 애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고 보다 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.  


이 때 하나의 서비스를 앱으로, 배포와 운영의 단위로는 컨테이너, 그들이 공유하는 전통적인 하드웨어와 OS를 접근하게 해 주는 컨테이너 런타임을 사용하고, 이들을 아울러서 함께 운영하는 방식으로 쿠버네티스(kubernetes)를 널리 쓴다. 이는 오래 전 구글의 보그(borg) 라는 관리 프로그램이 오픈소스로 세상에 공개된 후 일반적으로 쓰이게 된 것으로 아래 그림처럼 컨테이너화된 애플리케이션을 실행하는 역할을 하는 노드, 이들이 모여 있는 노드 클러스터, 하나 이상의 컨테이너가 모여 구성된 파드(Pod) 등의 개념으로 일들을 수행할 서버들을 조율한다. 그래서 쿠버네티스는 가장 유명한 컨테이너 오케스트레이션 서비스라고 부른다. 

그림 7. 쿠버네티스 개요 

쿠버네티스를 이용하면, 계획적으로 혹은 동적으로 서비스들을 관제할 수 있고, 자원 분배도 효율적으로 할 수 있다. 특히 클라우드 환경에서 자원의 구매 방식에 따라 다양한 전략을 구사할 수 있기에 클라우드 고객들은 직접 쿠버네티스 클러스터 등을 운영할 수도 있고, 반대로 각 클라우드 서비스들은 이런 편의를 위해 각각 아래와 같은 관리형 서비스들을 운영한다.   

    AWS EKS(Elastic Kubernetes Service)  

          AWS에서 제공하는 완전 관리형 쿠버네티스 서비스    

          AWS 의 EC2와 Fargate와 통합하여 다양한 워커 노드 옵션 사용 가능    

        다양한 AWS의 서비스들과 깊이 있게 통합되어 있음    

    GCP GKE(Google Kubernetes Engine)  

        구글 클라우드가 제공하는 완전 관리형 쿠버네티스 서비스    

        최신 쿠버네티스 기술이 빠르게 반영    

        구글 클라우드 로드 밸런서, 클라우드 모니터링, 클라우드 로깅과 통합되어 있음    

        앤토스와의 통합을 통해 온프레미스 및 멀티 클라우드에서 일관된 관리 가능    

    애저 AKS(Azure Kubernetes Service)  

        애저에서 제공하는 완전 관리형 쿠버네티스 서비스    

        애저의 VM, ACI(Azure Container Instance)와의 통합으로 유연한 워커 노드 배포 가능    

    네이버 클라우드 쿠버네티스 서비스  

        네이버 클라우드에서 제공하는 쿠버네티스 관리형 서비스로, 한국 기반의 로컬 클라우드 환경에서 최적화된 솔루션    

        국내 클라우드 환경에 최적화되어 있어 한국에서 법적 요구 사항을 충족하는 데 유리함    

    IBM 클라우드 쿠버네티스 서비스  

          IBM 클라우드에서 제공하는 완전 관리형 쿠버네티스 서비스    

        하이브리드 클라우드 및 멀티 클라우드 전략에 특화되어 있음.    


아이러니하게 클라우드에 독립적인 환경을 더 잘 사용하기 위해 특정 클라우드와의 종속성을 늘어나는 방향으로 진행되는데, 로깅 같은 클라우드 내의 다른 서비스들과 연결이 쉽다거나 자동으로 자원을 할당하거나 하는 등의 장점이 있고, 이로 인한 자원의 효율성 향상으로 인해 비용이 절감되기도 한다.


컨테이너 혹은 컨테이너 클러스터를 운영할 때 가장 흔하게 하는 실수는 할당받아 놓고 쓰지 않는 유휴 자원들로 인한 낭비와 손실인데, 클라우드 단위의 관리형 서비스들은 개별 업체가 아니라 전체 클라우드 상에서 쓰지 않는 리소스들을 미리 반납하는 형태로 클라우드 업체가 얻는 이득을 나눠 갖는 방식으로 구현된다. 다만 자원의 사용률이 이미 어느 정도 이상으로 이미 쓰고 있다면 거꾸로 다양한 방법으로 자원들을 선점해서 싸게 선구매한 후에 쿠버네티스 클러스터를 직접 운영하는 식으로 비용 절감을 구현하기도 한다. 서비스가 장기적인 성장이 예상이 될 때 고민과 결정이 필요한 순간이 오게 될 것이다.


맺으며


지금까지 클라우드에서 만든 서비스들이 사용자가 늘어 확장할 때 발생하는 이슈들 중에서 어플리케이션 단에서 일어나는 일들과 이들을 대응하기 위한 여러 시도들, 그 중에서 클라우드 서비스들에서 사용 가능한 방법들을 위주로 정리하여 보았다. 데모 시스템을 간단하게 운영하던 시작에 비해서 아주 많은 부가적인 서비스들을 익히고 이용해야 하지만, 안정적인 서비스로 가는 필연적인 과정들이다. 


시스템을 확장하는 과정에서 새로운 역할들을 하는 서비스들이 필요한데, 많은 경우 각 퍼블릭 클라우드 혹은 로컬 클라우드에서 제공을 하고 있거나 서드파티의 형태로 사용을 할 수 있다. 그리고 여러 신기술들을 적용하는 새로운 서비스들이 생기고 가끔씩 없어지기도 한다. 기술책임자의 시각에서는 각 클라우드 내에서 사용 가능한 서비스들의 기능, 제약, 가격, 락인 효과, 심지어 직원들의 친숙도 등을 고려해서 결정을 끊임없이 내려야 하겠고, 다시 한 번 그 무게와 책임을 응원한다.

매거진의 이전글 클라우드 서비스 개발에서 데이터베이스 사용 최적화 하기
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari