웹 서비스의 아키텍처 변화와 컨테이너 기술의 등장 과정을 살펴보고 수많은 컨테이너를 효율적으로 관리하는 컨테이너 오케스트레이션(Kubernetes)에 대해서까지 정리해 보죠.
컨테이너, MSA, DevOps, 웹 서비스 아키텍처의 핵심
초기 웹 서비스 구조
초기 웹 서비스는 대부분 모놀리식 아키텍처(Monolithic Architecture)로 구축되었습니다.
- 특징: 웹 서비스의 모든 기능(사용자 인증, 상품 관리, 결제, 추천 등)이 하나의 거대한 애플리케이션으로 묶여 하나의 서버에 배포.
- 서버 구성: Apache나 Nginx 같은 웹 서버가 요청을 받고, Tomcat이나 JBoss 같은 WAS(Web Application Server)에서 Java, Python, PHP 등으로 개발된 애플리케이션 코드를 실행하고, 데이터베이스(DB)와 통신하는 구조.
모놀리식 아키텍처의 한계:
- 배포의 어려움: 작은 기능 하나를 수정해도 전체 애플리케이션을 다시 빌드하고 배포해야 했습니다. 배포 시간이 길어지고, 이 과정에서 예상치 못한 오류가 발생할 위험이 컸습니다.
- 확장의 어려움: 특정 기능(예: 추천 시스템)에만 트래픽이 몰려도 전체 서버를 증설해야 했습니다. 비효율적이고 비용이 많이 들었습니다.
- 기술 스택의 종속성: 하나의 언어나 프레임워크에 종속되어 새로운 기술 도입이 어려웠습니다.
- 개발 환경의 불일치 ("내 컴퓨터에서는 되는데"): 개발자마다 개발 환경이 조금씩 다르고, 개발 환경과 실제 운영 환경 간의 차이 때문에 배포 시 문제가 발생하는 'Dependency Hell(종속성 지옥)' 문제가 빈번했습니다. 특정 라이브러리 버전 문제, OS 환경 설정 문제 등이 대표적입니다.
- 느슨한 결합의 부재: 각 기능이 강하게 연결되어 있어 한 부분의 변경이 다른 부분에 예상치 못한 영향을 미치기 쉬웠습니다.
마이크로서비스 아키텍처(MSA)의 등장과 새로운 요구
모놀리식 아키텍처의 한계를 극복하기 위해 마이크로서비스 아키텍처(Microservices Architecture, MSA)가 대안으로 등장했죠.
- 특징: 하나의 거대한 애플리케이션을 여러 개의 작고 독립적인 서비스로 분리합니다. 각 서비스는 독립적으로 개발, 배포, 운영될 수 있으며, REST API 등을 통해 서로 통신합니다.
- 장점:
- 독립적인 배포: 각 서비스는 독립적으로 배포되므로, 특정 서비스만 수정해도 전체 시스템에 영향을 주지 않고 빠르게 배포할 수 있습니다.
- 탄력적인 확장: 트래픽이 많은 특정 서비스만 독립적으로 확장(스케일 아웃)할 수 있어 효율적입니다.
- 다양한 기술 스택: 각 서비스에 가장 적합한 프로그래밍 언어, 프레임워크, 데이터베이스를 자유롭게 선택하여 사용할 수 있습니다.
- 팀의 자율성: 작은 팀들이 각 서비스를 전담하여 개발 및 운영함으로써 개발 속도를 높일 수 있습니다.
하지만 MSA에도 나타난 문제점
- 배포 복잡성 증가: 수십, 수백 개의 독립적인 서비스를 관리하고 배포하는 것이 매우 복잡해졌습니다. 각 서비스마다 필요한 런타임, 라이브러리 버전 등을 일일이 맞춰주는 것이 큰 부담이었습니다.
- 환경 불일치 문제 심화: MSA는 더 많은 서비스와 더 다양한 기술 스택을 사용하게 되므로, '내 컴퓨터에서는 되는데' 문제는 오히려 더 심각해질 수 있었습니다.
컨테이너 기술의 등장
MSA 환경의 복잡성과 '환경 불일치' 문제를 해결하기 위해 컨테이너 기술(특히 Docker)이 등장했어요. 컨테이너는 웹 서비스 구조에서 다음과 같은 역할을 수행하게 됩니다.
- 애플리케이션 및 종속성 패키징
- 컨테이너는 웹 애플리케이션 코드뿐만 아니라, 해당 코드를 실행하는 데 필요한 모든 런타임(예: JVM, Node.js), 라이브러리, 환경 변수, 시스템 도구 등을 하나의 가볍고 독립적인 패키지(이미지)로 만듭니다.
- 이는 "어디서든 동일하게 실행될 수 있는 실행 단위"를 제공하며, 'Dependency Hell' 문제를 근본적으로 해결합니다. 개발 환경, 테스트 환경, 운영 환경 어디서든 동일한 컨테이너 이미지를 사용하므로, 환경 불일치로 인한 오류를 최소화합니다.
- 격리된 실행 환경 제공
- 각 컨테이너는 호스트 OS의 커널을 공유하지만, 사용자 공간에서는 완전히 격리된 환경을 가집니다. 이는 한 서비스의 문제가 다른 서비스로 전파되는 것을 막아 안정성을 높입니다.
- 웹 서버, WAS, DB 등이 모두 각각의 컨테이너로 실행될 수 있으며, 서로 간섭 없이 독립적으로 운영될 수 있습니다.
- 효율적인 리소스 활용
- 기존의 가상 머신(VM) 방식은 Guest OS를 포함하므로 오버헤드가 컸습니다. 컨테이너는 Guest OS 없이 호스트 OS의 커널을 공유하므로 VM보다 훨씬 가볍고 빠르게 시작되며, 적은 리소스로 더 많은 서비스를 실행할 수 있습니다.
- 웹 서비스 환경에서 수십, 수백 개의 마이크로서비스를 운영해야 할 때, 각 서비스를 컨테이너로 만들면 VM 방식보다 훨씬 효율적으로 서버 리소스를 활용할 수 있습니다.
- 배포 및 확장성 증대
- 컨테이너 이미지는 한 번 만들면 어디서든 빠르게 실행될 수 있습니다. 이는 CI/CD(지속적 통합/지속적 배포) 파이프라인과 결합되어 웹 서비스의 배포 속도를 획기적으로 단축시킵니다.
- 트래픽 증가 시, 필요한 서비스 컨테이너의 복제본(인스턴스)을 빠르고 쉽게 늘릴 수 있습니다(수평 확장). 트래픽 감소 시에는 반대로 줄일 수 있어 비용 효율적입니다.
컨테이너 오케스트레이션 (Kubernetes)
수십, 수백 개의 컨테이너를 수동으로 관리하는 것은 거의 불가능합니다. 여기서 등장하는 것이 컨테이너 오케스트레이션 도구(대표적으로 Kubernetes, 쿠버네티스)입니다.
Kubernetes의 역할
- 배포 자동화: 컨테이너화된 애플리케이션을 여러 서버(노드)에 자동으로 배포합니다.
- 확장 및 축소 자동화: 트래픽에 따라 컨테이너 인스턴스 수를 자동으로 조절합니다.
- 장애 복구: 컨테이너에 문제가 발생하면 자동으로 재시작하거나 다른 서버로 이동시켜 서비스 중단을 최소화합니다.
- 서비스 디스커버리 및 로드 밸런싱: 여러 컨테이너 인스턴스 중 어떤 인스턴스로 요청을 보낼지 자동으로 찾아주고, 트래픽을 분산시킵니다.
- 롤링 업데이트 및 롤백: 서비스 중단 없이 애플리케이션 버전을 업데이트하고, 문제가 발생하면 이전 버전으로 쉽게 되돌릴 수 있습니다.
결과적으로 웹 서비스 구조의 변화
이러한 컨테이너와 컨테이너 오케스트레이션 기술의 등장은 웹 서비스 구조를 모놀리식에서 마이크로서비스 기반의 클라우드 네이티브 아키텍처로 전환하는 데 결정적인 역할을 했습니다.
- 클라이언트 측: 여전히 브라우저나 모바일 앱이 주를 이룹니다.
- 서버 측:
- 더 이상 하나의 거대한 서버 덩어리가 아니라, 수많은 작고 독립적인 컨테이너화된 마이크로서비스들의 집합으로 구성됩니다.
- 이 컨테이너들은 쿠버네티스 클러스터 위에서 관리되며, 웹 서비스 요청은 API 게이트웨이를 통해 각 마이크로서비스로 라우팅 됩니다.
- 데이터베이스도 필요에 따라 독립적인 컨테이너로 운영되거나, 클라우드 제공업체의 관리형 서비스(RDS, DynamoDB 등)를 이용하는 경우가 많습니다.
- 웹 서버(Nginx, Apache)도 컨테이너로 배포되거나, 쿠버네티스 인그레스 컨트롤러(Ingress Controller)가 그 역할을 수행합니다.
이러한 변화는 웹 서비스의 민첩성, 안정성, 확장성을 극대화하여, 오늘날과 같이 방대한 규모의 서비스를 빠르고 효율적으로 개발하고 운영할 수 있게 만들었습니다. 컨테이너는 단순히 도구 하나가 아니라, 현대 웹 서비스 아키텍처의 패러다임을 바꾼 핵심 기술이라고 할 수 있습니다.
2025.04.01 - [프로그래밍 언어/Python] - Django vs Flask 파이썬 웹 프레임워크 비교 - Flask #1
Django vs Flask 파이썬 웹 프레임워크 비교 - Flask #1
Flask와 Django를 비교해 보며 어떤 상황에서 Flask를 선택하는 것이 유리한지 판단해 보고자 하며, 초보 웹 개발자도 쉽게 이해할 수 있는 예제 코드와 구조 설명을 통해 Flask의 학습 장벽을 낮추고,
eco7t.tistory.com