모놀리식 앱을 모듈화하고 컨테이너화하는 방법을 안내하는 학습 과정의 두 번째 튜토리얼입니다.
학습 과정은 다음 튜토리얼로 구성됩니다.
- 개요
- 모놀리식 이해하기
- 모놀리식 모듈화(이 튜토리얼)
- 컨테이너화를 위한 모듈식 앱 준비
- 모듈식 앱 컨테이너화
- GKE 클러스터에 앱 배포
이전 튜토리얼인 모놀리식 이해하기에서는 Cymbal Books라는 모놀리식 앱에 대해 알아봤습니다. 로컬 머신에서 모놀리식을 실행해 보고 모놀리식의 여러 부분이 엔드포인트를 통해 서로 통신한다는 사실을 배웠습니다.
이 튜토리얼에서는 모놀리식을 모듈로 나누어 컨테이너화를 준비하는 방법을 알아봅니다. 코드가 이미 업데이트되었으므로 모듈화 단계를 직접 수행할 필요는 없습니다. 튜토리얼을 따라 저장소에서 앱의 모듈식 버전을 살펴보고 원래 모놀리식과 어떻게 다른지 확인해 보겠습니다.
비용
이 튜토리얼은 무료로 완료할 수 있습니다. 하지만 이 시리즈의 마지막 튜토리얼에 나온 단계를 따르면Google Cloud 계정에 비용이 청구됩니다. GKE를 사용 설정하고 Cymbal Books 앱을 GKE 클러스터에 배포하면 비용이 청구되기 시작합니다. 이 비용에는 가격 책정 페이지에 설명된 대로 GKE의 클러스터당 요금과 Compute Engine VM 실행 요금이 포함됩니다.
불필요한 요금이 청구되지 않도록 이 튜토리얼을 완료한 후 GKE를 중지하거나 프로젝트를 삭제하세요.
시작하기 전에
이 튜토리얼을 시작하기 전에 첫 번째 튜토리얼인 모놀리식 이해하기를 완료해야 합니다. 이 튜토리얼에서는 로컬 머신에서 Cymbal Books의 모듈식 버전을 실행합니다. 이를 위해서는 이미 환경을 설정한 상태여야 합니다. 첫 번째 튜토리얼을 이미 완료했다면 GitHub 저장소를 클론한 상태입니다. Cymbal Books 앱의 세 가지 버전은 모두 이 저장소의 다음 폴더에 있습니다.
monolith/
modular/
containerized/
계속하기 전에 이러한 폴더가 머신에 있는지 확인합니다. 또한 가상 환경 book-review-env
가 활성 상태인지 확인합니다. 활성화 방법을 다시 확인하려면 첫 번째 튜토리얼의 가상 환경 만들기 및 활성화를 참조하세요. 환경을 활성화하면 앱의 모듈식 버전에 실행에 필요한 모든 것이 포함됩니다.
모듈화란?
이 튜토리얼에서는 모놀리식 앱을 모듈화하여 컨테이너화를 준비하는 방법을 알아봅니다. 모듈화는 모놀리식을 모듈식 앱으로 전환하는 프로세스입니다. 이전 튜토리얼에서 배웠듯이 모놀리식의 특징은 구성요소를 독립적으로 실행하거나 확장할 수 없다는 점입니다. 모듈식 앱은 다릅니다. 기능이 독립적으로 실행하고 확장할 수 있는 모듈로 분할됩니다.
모듈화와 컨테이너화는 종종 함께 실행되지만 각 개념을 명확하게 이해할 수 있도록 이 튜토리얼 시리즈에서는 별도의 단계로 취급합니다. 이 튜토리얼에서는 모놀리식을 모듈화하는 방법을 설명하고, 이후 튜토리얼에서는 모듈식 앱을 컨테이너화하는 방법을 설명합니다.
증분 모듈화
프로덕션 환경에서는 일반적으로 한 번에 하나의 구성요소를 모듈화합니다. 구성요소를 모듈화하고 모듈을 모놀리식과 통합하며 다음 구성요소를 작업하기 전에 모두 정상적으로 작동하는지 확인합니다. 일부 구성요소는 모듈화되고 다른 구성요소는 모놀리식의 일부로 남아 있는 이 하이브리드 상태를 마이크로리스(microlith)라고 합니다. 그러나 이 튜토리얼에서는 앱을 모듈화하는 방법의 전체 예시를 제공하기 위해 모든 앱 구성요소를 동시에 모듈화합니다.
모놀리식을 모듈화하는 방법
이 섹션에서는 Cymbal Books 모놀리식이 별도의 모듈로 분할된 방법을 알아봅니다. 자체 앱에 적용할 수 있도록 모듈화 프로세스를 이해하는 데 도움이 되는 단계가 제공됩니다. 그러나 클론된 저장소에 이미 앱의 모듈식 버전이 포함되어 있으므로 이 튜토리얼에서는 이러한 단계를 실행할 필요가 없습니다.
앱의 고유한 기능 식별
Cymbal Books 모놀리식을 모듈화하는 첫 번째 단계는 기본 기능을 식별하는 것입니다. Cymbal Books 샘플 애플리케이션의 경우 모놀리식에 다음과 같은 네 가지 고유한 기능이 있습니다.
- 홈페이지 제공
- 도서 세부정보 제공
- 도서 리뷰 제공
- 책 표지 이미지 제공
모듈 만들기
이전 튜토리얼에서 본 것처럼 모놀리식은 이전 섹션에서 식별된 네 가지 기능을 경로 핸들러로 구현하는 단일 Flask 앱입니다. 앱을 모듈화하려면 각 경로 핸들러를 가져와 자체 Flask 앱에 배치합니다. 경로 핸들러가 4개인 Flask 앱 1개가 아니라 각 앱에 경로 핸들러가 1개씩 있는 Flask 앱 4개를 얻게 됩니다.
다음 다이어그램은 단일 Flask 앱에서 4개의 개별 Flask 앱으로의 변환을 보여줍니다.
모듈식 앱에서 각 Flask 앱은 독립적으로 실행되며 다이어그램과 같이 다른 포트(8080, 8081, 8082, 8083)에서 리슨합니다. 이 설정은 이 튜토리얼의 뒷부분에서 모듈식 앱을 테스트할 때 동일한 머신에서 모든 모듈을 실행하기 때문에 필요합니다. 충돌을 방지하려면 각 앱에 서로 다른 포트 번호가 필요합니다.
홈페이지 모듈은 두 가지 역할을 합니다. 홈페이지를 제공하고 다른 모듈과 통신하여 웹페이지에 표시해야 하는 데이터를 수집합니다. 다른 각 모듈은 리뷰, 세부정보 또는 이미지를 제공하는 단일 기능에 중점을 둡니다. 이러한 모듈은 서로 통신하지 않으며 홈페이지 모듈의 요청에만 응답합니다.
홈페이지 모듈에 추가 조정 역할이 있지만 다른 모듈에 영향을 주지 않고 모듈을 업데이트할 수 있으므로 이 앱은 여전히 모듈식입니다. 단일 대규모 Flask 애플리케이션이 각각 특정 부분의 애플리케이션 기능을 처리하는 4개의 요소로 분할되었습니다.
모듈 간 통신 사용 설정
모듈을 만든 후에는 모듈이 서로 통신할 수 있는지 확인해야 합니다. Cymbal Books 앱에서는 이 통신 로직이 이미 구현되어 있습니다. 다운로드한 코드의 modular/
폴더에서 홈페이지, 도서 세부정보, 리뷰, 이미지를 제공하는 각 앱의 기본 기능이 별도의 Flask 앱으로 구현되어 있음을 확인할 수 있습니다. 이러한 각 앱은 자체 HTTP 엔드포인트를 정의하며 모듈은 이러한 엔드포인트에 HTTP 요청을 전송하여 통신합니다.
Cymbal Books 모놀리식을 간단하게 모듈화했습니다. 모놀리식에는 경로 핸들러로 구현된 잘 정의된 구성요소가 있으며 각 경로 핸들러에는 잘 정의된 엔드포인트가 있습니다. 이러한 경로 핸들러가 별도의 Flask 애플리케이션에 배치되면 엔드포인트를 통해 통신하는 기능을 유지합니다. 경로 핸들러를 별도의 Flask 앱에 배치하는 간단한 작업으로 모듈이 생성되고 모듈이 서로 통신할 수 있게 됩니다.
모듈 간 통신의 일반적인 접근 방식은 모듈이 서로 HTTP 요청을 전송할 수 있는 REST API를 구현하는 것입니다. Cymbal Books에서는 다음과 같이 작동합니다. 각 모듈은 Flask의 내장 도구를 사용하여 REST 엔드포인트를 정의합니다. 또 다른 인기 있는 접근 방식은 모듈이 서로의 기능을 직접 호출할 수 있는 gRPC입니다.
Cymbal Books에서 통신이 간단한 이유
모듈식 앱의 각 모듈은 웹 서버 내에서 실행되는 별도의 Flask 애플리케이션입니다. 예를 들어 홈페이지 모듈은 홈페이지를 제공하고 도서 세부정보 모듈은 도서 세부정보를 제공합니다. 웹 서버는 HTTP 요청과 응답을 처리하도록 설계되었으므로 모듈 간의 통신이 간단합니다. 각 모듈은 다른 모듈에서 데이터를 요청하는 데 사용할 수 있는 엔드포인트를 노출합니다.
각 모듈에 필요한 데이터에 대한 액세스 권한만 부여
모놀리식을 적절하게 모듈화하려면 각 모듈이 필요한 데이터에만 액세스할 수 있도록 해야 합니다. 데이터 격리라고 하는 이 원칙은 진정한 모듈식 아키텍처를 만드는 데 중요한 요소입니다.
모듈화 중에 자주 저지르는 실수는 여러 모듈이 단일 데이터베이스와 같은 동일한 데이터에 액세스하도록 허용하는 것입니다. 이러한 유형의 구현은 다음과 같은 문제를 일으킵니다.
- 긴밀한 결합: 공유 데이터의 구조가 변경되면(예: 데이터베이스 테이블 이름이 변경되거나 열이 추가됨) 이 데이터를 사용하는 모든 모듈을 업데이트해야 합니다. 적절한 모듈화를 통해 이 문제를 방지할 수 있습니다.
- 내결함성 문제: 여러 모듈에서 동일한 데이터 소스를 사용하는 경우 하나의 모듈에서 발생한 런타임 오류(예: 잘못된 쿼리 또는 과도한 트래픽)로 인해 다른 모듈이 중단될 수 있습니다. 시스템의 한 부분에서 장애가 발생하면 시스템의 다른 부분으로 장애가 확산될 수 있습니다.
- 성능 병목 현상: 단일 공유 데이터 소스로 인해 병목 현상이 발생할 수 있습니다. 즉, 여러 모듈이 한 데이터 소스와 상호작용하려고 하면 전체 애플리케이션 속도가 느려질 수 있습니다.
이러한 문제를 방지하려면 각 모듈에 자체 데이터 소스가 있어야 합니다.
Cymbal Books에서 데이터베이스를 사용하여 데이터를 저장했다면 데이터베이스를 복제하거나 파티셔닝하여 데이터 격리를 적용하고 각 모듈이 필요한 데이터에만 액세스하도록 해야 합니다. 복제에는 모듈마다 데이터베이스의 별도 사본을 유지하는 것이 포함되며, 파티셔닝은 특정 테이블 또는 행에 대한 액세스를 제한합니다. 두 접근 방식 모두 모듈이 서로의 데이터를 방해하지 못하도록 합니다.
다음 다이어그램에서는 모놀리식 도서 앱 아키텍처와 도서 앱의 모듈식 아키텍처를 비교합니다.
모놀리식의 기능이 단일 data/
디렉터리에 액세스하므로 모놀리식의 구현은 데이터 격리의 원칙을 따르지 않습니다.
반면 모듈식 앱은 데이터를 별도의 디렉터리로 분할하고 각 모듈이 지정된 데이터와만 상호작용하도록 하여 어느 정도의 데이터 격리를 달성합니다.
- 도서 세부정보 모듈은
details_data/
디렉터리에서만 데이터를 가져옵니다. - 도서 리뷰 모듈은
reviews_data/
디렉터리에서만 데이터를 가져옵니다. - 이미지 모듈은
images/
디렉터리에서만 데이터를 가져옵니다.
후속 튜토리얼에서는 앱을 컨테이너화하여 데이터 격리를 더욱 향상하는 방법을 알아봅니다.
용어 설명
소프트웨어 개발 업계에서는 마이크로서비스 및 분산 시스템이라는 용어를 자주 접하게 됩니다. 이 섹션에서는 이러한 용어가 Cymbal Books의 모듈식 구현과 어떤 관련이 있는지 설명합니다.
Microservices
마이크로서비스는 특정 태스크를 실행하는 자율적인 모듈입니다. 이러한 모듈은 엔드포인트와 같은 인터페이스를 통해 다른 모듈과 통신합니다.
Cymbal Books의 모듈식 버전의 각 모듈은 이 정의에 적합하므로 마이크로서비스라고 할 수 있습니다. 후속 튜토리얼에서 모듈식 앱이 컨테이너화되면 컨테이너 내에서 실행되는 코드도 모듈 내에서 실행되는 동일한 코드이므로 마이크로서비스라고 할 수 있습니다.
분산 시스템
분산 시스템은 네트워크를 통해 통신하여 공통 목표를 달성하는 독립적인 모듈로 구성됩니다. 이러한 모듈은 서로 다른 머신에서 실행될 수 있지만 단일 시스템으로 함께 작동합니다.
모듈식 Cymbal Books 앱도 이 정의에 적합합니다. 모듈은 독립적으로 실행되고 HTTP를 통해 데이터를 교환하지만 함께 단일 시스템으로 작동합니다. 다음 섹션에서는 편의상 모든 모듈을 단일 머신에서 실행하지만, 이는 필수가 아닙니다. 각 모듈은 다른 서버에서 쉽게 실행할 수 있습니다. 따라서 Cymbal Books 앱의 모듈식 버전을 분산 시스템으로 분류할 수 있습니다.
모듈식 구현 테스트
이제 Cymbal Books 모놀리식이 모듈이 Flask 앱인 모듈식 앱으로 변환되는 방식을 확인했으므로 애플리케이션을 테스트하고 각 모듈이 독립적으로 실행되는지 확인할 수 있습니다.
이 튜토리얼에서는 동일한 머신에서 모듈을 실행합니다. 하지만 각 모듈을 별도의 서버에서 실행할 수도 있습니다. 각 모듈은 자율적이므로 엔드포인트를 통해 다른 모듈과 통신할 수 있습니다.
환경 설정
테스트를 준비하려면 다음 단계를 따르세요.
터미널에서 클론된 저장소의
modular
디렉터리로 이동합니다.cd modular
가상 환경
book-review-env
가 활성 상태인지 확인합니다. 활성화 단계를 다시 확인하려면 가상 환경 만들기 및 활성화를 참조하세요.
Flask 앱 시작
/modular
폴더에는 모든 Flask 애플리케이션을 동시에 시작하는 bash 스크립트가 포함되어 있습니다. 앱의 각 모듈은 8080 또는 8081과 같은 고유한 포트를 리슨합니다.
- 홈페이지 Flask 앱(home.py): 포트 8080
- 도서 세부정보 Flask 앱(book_details.py): 포트 8081
- 책 리뷰 Flask 앱(book_reviews.py): 포트 8082
- 이미지 Flask 앱(images.py): 포트 8083
모듈은 모두 동일한 머신에서 실행되므로 각 모듈은 고유한 포트 번호를 리슨해야 합니다. 각 모듈이 다른 서버에 있으면 각 모듈은 포트 충돌을 일으키지 않고 동일한 포트 번호를 리슨할 수 있습니다.
다음 명령어를 사용하여 bash 스크립트를 실행합니다.
bash ./start_services.sh
이 스크립트는 시작 문제를 식별하는 데 도움이 되도록 Flask 앱(예: home.py.log
, book_details.py.log
)마다 별도의 로그 파일을 만듭니다.
스크립트가 성공적으로 완료되면 다음 메시지가 표시됩니다.
All services have been started. Access the app at http://localhost:8080/
각 Flask 앱 테스트
브라우저에서 다음 URL을 방문하여 모듈을 테스트합니다.
- 홈페이지:
http://localhost:8080/
은 모듈화된 Cymbal Books 애플리케이션의 홈페이지를 표시합니다. 이 페이지는 다른 모듈에 요청하여 도서 세부정보, 리뷰, 이미지를 가져옵니다. - 도서 세부정보:
http://localhost:8081/book/1
은 ID가 1인 도서의 세부정보를 반환합니다. 이 응답은 JSON 데이터이며 앱에서 형식을 지정하고 인간이 읽을 수 있는 방식으로 표시합니다. - 도서 리뷰:
http://localhost:8082/book/1/reviews
는 ID가 1인 도서의 리뷰를 가져와 반환합니다. 리뷰는 JSON 형식입니다. 홈페이지 모듈은 이 데이터를 요청하고 도서 세부정보 페이지에 통합합니다. - 이미지:
http://localhost:8083/images/fungi_frontier.jpg
는 Fungi Frontier의 도서 표지 이미지를 제공합니다. URL이 올바르면 이미지가 브라우저에 직접 로드됩니다.
Flask 앱 중지
테스트를 완료하면 다음 명령어로 모든 Flask 앱을 중지합니다.
kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)
요약
이 튜토리얼에서는 Cymbal Books 모놀리식을 모듈화하는 방법을 설명했습니다. 이 프로세스는 다음 단계로 구성됩니다.
- 앱의 고유한 구성요소를 식별합니다.
- 모듈을 만듭니다.
- 각 모듈이 필요한 데이터에만 액세스할 수 있도록 합니다.
그런 다음 로컬 머신에서 모듈식 구현을 테스트했습니다.
다음 단계
다음 튜토리얼인 컨테이너화를 위한 모듈식 앱 준비에서는 localhost
대신 Kubernetes 서비스 이름을 사용하도록 엔드포인트를 업데이트하여 컨테이너화를 위해 모듈식 앱을 준비하는 방법을 알아봅니다.