팁 (조언)
이 콘텐츠는 .NET Docs 또는 오프라인으로 읽을 수 있는 무료 다운로드 가능한 PDF로 제공되는 eBook인 'ASP.NET Core와 Azure로 현대 웹 애플리케이션 설계하기'에서 발췌한 내용입니다.
"좋은 아키텍처가 비싸다고 생각되면 나쁜 아키텍처를 시도해 보세요." - 브라이언 푸트와 조셉 요더
대부분의 기존 .NET 애플리케이션은 단일 IIS 앱 도메인 내에서 실행되는 실행 파일 또는 단일 웹 애플리케이션에 해당하는 단일 단위로 배포됩니다. 이 방법은 가장 간단한 배포 모델이며 많은 내부 및 소규모 퍼블릭 애플리케이션을 매우 잘 제공합니다. 그러나 이 단일 배포 단위를 고려할 때도 대부분의 비 사소한 비즈니스 애플리케이션은 몇 가지 논리적 분리를 통해 여러 계층으로 이점을 얻을 수 있습니다.
모놀리식 애플리케이션이란?
모놀리식 애플리케이션은 동작 측면에서 완전히 자체 포함된 애플리케이션입니다. 작업을 수행하는 과정에서 다른 서비스 또는 데이터 저장소와 상호 작용할 수 있지만 동작의 핵심은 자체 프로세스 내에서 실행되며 전체 애플리케이션은 일반적으로 단일 단위로 배포됩니다. 이러한 애플리케이션을 수평적으로 확장해야 하는 경우 일반적으로 전체 애플리케이션이 여러 서버 또는 가상 머신에서 중복됩니다.
올인원 애플리케이션
애플리케이션 아키텍처에 사용할 수 있는 프로젝트 수가 가장 적습니다. 이 아키텍처에서 애플리케이션의 전체 논리는 단일 프로젝트에 포함되고, 단일 어셈블리로 컴파일되고, 단일 단위로 배포됩니다.
Visual Studio 또는 명령줄에서 생성된 새로운 ASP.NET Core 프로젝트는 간단한 "올인원" 모놀리식 구조로 시작됩니다. 여기에는 프레젠테이션, 비즈니스 및 데이터 액세스 논리를 포함하여 애플리케이션의 모든 동작이 포함됩니다. 그림 5-1은 단일 프로젝트 앱의 파일 구조를 보여줍니다.
그림 5-1. 단일 프로젝트의 ASP.NET Core 앱
단일 프로젝트 시나리오에서는 폴더를 사용하여 문제를 분리합니다. 기본 템플릿에는 모델, 뷰 및 컨트롤러의 MVC 패턴 책임을 위한 별도의 폴더와 데이터 및 서비스에 대한 추가 폴더가 포함됩니다. 이 정렬에서 프레젠테이션 세부 정보는 Views 폴더로 최대한 제한되어야 하며 데이터 액세스 구현 세부 정보는 데이터 폴더에 보관된 클래스로 제한되어야 합니다. 비즈니스 논리는 Models 폴더 내의 서비스 및 클래스에 있어야 합니다.
간단하지만 단일 프로젝트 모놀리식 솔루션에는 몇 가지 단점이 있습니다. 프로젝트의 크기와 복잡성이 증가함에 따라 파일 및 폴더의 수도 계속 증가할 것입니다. UI(사용자 인터페이스) 문제(모델, 뷰, 컨트롤러)는 사전순으로 그룹화되지 않는 여러 폴더에 상주합니다. 이 문제는 필터 또는 ModelBinders와 같은 추가 UI 수준 구문이 자체 폴더에 추가되는 경우에만 악화됩니다. 비즈니스 논리는 Models 및 Services 폴더 사이에 분산되어 있으며 어떤 폴더가 어떤 다른 폴더에 의존해야 하는지에 대한 명확한 표시는 없습니다. 프로젝트 수준에서 조직이 부족하면 스파게티 코드가 자주 발생합니다.
이러한 문제를 해결하기 위해 애플리케이션은 종종 각 프로젝트가 애플리케이션의 특정 계층 에 상주하는 것으로 간주되는 다중 프로젝트 솔루션으로 발전합니다.
레이어란?
애플리케이션의 복잡성이 증가함에 따라 이러한 복잡성을 관리하는 한 가지 방법은 해당 책임 또는 문제에 따라 애플리케이션을 분리하는 것입니다. 이 방법은 우려 사항의 분리 원칙을 따르며 개발자가 특정 기능이 구현되는 위치를 쉽게 찾을 수 있도록 증가하는 코드베이스를 구성하는 데 도움이 될 수 있습니다. 하지만 계층화된 아키텍처는 코드 조직 외에 다양한 이점을 제공합니다.
코드를 계층으로 구성하면 애플리케이션 전체에서 일반적인 하위 수준 기능을 다시 사용할 수 있습니다. 이 재사용은 작성해야 하는 코드가 적고 애플리케이션이 직접 반복하지 않음(DRY) 원칙에 따라 단일 구현에서 표준화할 수 있기 때문에 유용합니다.
계층화된 아키텍처를 사용하면 애플리케이션에서 계층이 다른 계층과 통신할 수 있는 제한을 적용할 수 있습니다. 이 아키텍처는 캡슐화를 달성하는 데 도움이 됩니다. 레이어를 변경하거나 바꾸면 레이어와 함께 작동하는 레이어만 영향을 받아야 합니다. 다른 레이어에 따라 달라지는 레이어를 제한하여 단일 변경이 전체 애플리케이션에 영향을 주지 않도록 변경의 영향을 완화할 수 있습니다.
레이어(및 캡슐화)를 사용하면 애플리케이션 내의 기능을 훨씬 쉽게 바꿀 수 있습니다. 예를 들어 애플리케이션은 처음에는 지속성을 위해 자체 SQL Server 데이터베이스를 사용할 수 있지만 나중에 클라우드 기반 지속성 전략 또는 웹 API 뒤에 하나를 사용하도록 선택할 수 있습니다. 애플리케이션이 논리 계층 내에서 지속성 구현을 올바르게 캡슐화한 경우 해당 SQL Server 특정 계층을 동일한 공용 인터페이스를 구현하는 새 계층으로 대체할 수 있습니다.
향후 요구 사항 변경에 대응하여 구현을 교환할 수 있는 가능성 외에도 애플리케이션 계층을 사용하면 테스트 목적으로 구현을 보다 쉽게 교환할 수 있습니다. 애플리케이션의 실제 데이터 계층 또는 UI 계층에 대해 작동하는 테스트를 작성하는 대신, 이러한 계층을 테스트 시 요청에 대한 알려진 응답을 제공하는 가짜 구현으로 바꿀 수 있습니다. 이 접근 방식을 사용하면 일반적으로 애플리케이션의 실제 인프라에 대한 테스트를 실행하는 것과 비교할 때 테스트를 훨씬 쉽게 작성하고 훨씬 더 빠르게 실행할 수 있습니다.
논리적 계층화는 엔터프라이즈 소프트웨어 애플리케이션에서 코드의 구성을 개선하기 위한 일반적인 기술이며 코드를 계층으로 구성할 수 있는 여러 가지 방법이 있습니다.
비고
레이어는 애플리케이션 내의 논리적 분리를 나타냅니다. 애플리케이션 논리가 개별 서버 또는 프로세스에 물리적으로 분산되는 경우 이러한 개별 물리적 배포 대상을 계층이라고 합니다. 단일 계층에 배포되는 N 계층 애플리케이션이 있을 수 있으며 매우 일반적입니다.
기존 "N 계층" 아키텍처 애플리케이션
계층으로 애플리케이션 논리의 가장 일반적인 구성은 그림 5-2에 나와 있습니다.
그림 5-2. 일반적인 애플리케이션 계층.
이러한 계층은 UI, BLL(비즈니스 논리 계층) 및 DAL(데이터 액세스 계층)으로 자주 축약됩니다. 이 아키텍처를 사용하여 사용자는 BLL과만 상호 작용하는 UI 계층을 통해 요청을 수행합니다. BLL은 데이터 액세스 요청에 대해 DAL을 호출할 수 있습니다. UI 계층은 DAL에 직접 요청해서는 안 되며 다른 수단을 통해 직접 지속성과 상호 작용해서는 안 됩니다. 마찬가지로 BLL은 DAL을 통해서만 지속성과 상호 작용해야 합니다. 이러한 방식으로 각 계층에는 잘 알려진 책임이 있습니다.
이 기존 계층화 방법의 한 가지 단점은 컴파일 시간 종속성이 위에서 아래로 실행된다는 것입니다. 즉, UI 계층은 BLL에 따라 달라지며, BLL은 DAL에 따라 달라집니다. 즉, 일반적으로 애플리케이션에서 가장 중요한 논리를 보유하는 BLL은 데이터 액세스 구현 세부 정보(종종 데이터베이스의 존재 여부에 따라 다름)에 따라 달라집니다. 이러한 아키텍처에서 비즈니스 논리를 테스트하는 것은 종종 어렵기 때문에 테스트 데이터베이스가 필요합니다. 다음 섹션에서 볼 수 있듯이 종속성 반전 원칙을 사용하여 이 문제를 해결할 수 있습니다.
그림 5-3은 애플리케이션을 책임(또는 계층)으로 세 개의 프로젝트로 나누는 예제 솔루션을 보여 줍니다.
그림 5-3. 세 개의 프로젝트가 있는 간단한 모놀리식 애플리케이션입니다.
이 애플리케이션은 조직 목적을 위해 여러 프로젝트를 사용하지만 여전히 단일 단위로 배포되며 클라이언트는 단일 웹앱으로 상호 작용합니다. 이렇게 하면 매우 간단한 배포 프로세스가 가능합니다. 그림 5-4는 Azure를 사용하여 이러한 앱을 호스트하는 방법을 보여줍니다.
그림 5-4. Azure Web App의 간단한 배포
애플리케이션 요구 사항이 증가함에 따라 더 복잡하고 강력한 배포 솔루션이 필요할 수 있습니다. 그림 5-5는 추가 기능을 지원하는 보다 복잡한 배포 계획의 예를 보여 줍니다.
그림 5-5. Azure App Service에 웹앱 배포
내부적으로 이 프로젝트의 조직은 책임에 따라 여러 프로젝트로 전환하면 애플리케이션의 유지 관리 효율성이 향상됩니다.
이 유닛은 클라우드 기반의 주문형 확장성을 활용하여, 크기를 늘리거나 범위를 넓힐 수 있습니다. 스케일 업은 앱을 호스팅하는 서버에 CPU, 메모리, 디스크 공간 또는 기타 리소스를 추가하는 것을 의미합니다. 스케일 아웃은 물리적 서버, 가상 머신 또는 컨테이너에 관계없이 이러한 서버의 인스턴스를 추가하는 것을 의미합니다. 앱이 여러 인스턴스에서 호스트되는 경우 부하 분산 장치를 사용하여 개별 앱 인스턴스에 요청을 할당합니다.
Azure에서 웹 애플리케이션의 크기를 조정하는 가장 간단한 방법은 애플리케이션의 App Service 계획에서 수동으로 크기 조정을 구성하는 것입니다. 그림 5-6은 앱을 제공하는 인스턴스 수를 구성하는 적절한 Azure 대시보드 화면을 보여 줍니다.
그림 5-6. Azure에서 앱 서비스 계획 크기 조정
클린 아키텍처
종속성 반전 원칙과 Domain-Driven 디자인(DDD) 원칙을 따르는 애플리케이션은 비슷한 아키텍처에 도달합니다. 이 아키텍처는 수년에 걸쳐 많은 이름으로 불려왔습니다. 이름 중 하나는 육각형 아키텍처였고 포트 및 어댑터가 그 뒤를 따랐습니다. 최근에는 양파 아키텍처 또는 클린 아키텍처로 인용되었습니다. 후자의 이름인 Clean Architecture는 이 전자책에서 이 아키텍처의 이름으로 사용됩니다.
eShopOnWeb 참조 애플리케이션은 클린 아키텍처 접근 방식을 사용하여 코드를 프로젝트로 구성합니다. ardalis/cleanarchitecture GitHub 리포지토리에서 또는 NuGet에서 템플릿을 설치하여 고유한 ASP.NET Core 솔루션의 시작점으로 사용할 수 있는 솔루션 템플릿을 찾을 수 있습니다.
클린 아키텍처는 비즈니스 논리 및 애플리케이션 모델을 애플리케이션의 중심에 배치합니다. 비즈니스 논리가 데이터 액세스 또는 기타 인프라 문제에 종속되는 대신, 이 종속성은 반전됩니다. 인프라 및 구현 세부 정보는 Application Core에 따라 달라집니다. 이 기능은 Application Core에서 추상화 또는 인터페이스를 정의한 다음 인프라 계층에 정의된 형식에 의해 구현됩니다. 이 아키텍처를 시각화하는 일반적인 방법은 양파와 유사한 일련의 동심원을 사용하는 것입니다. 그림 5-7은 이 아키텍처 표현 스타일의 예를 보여줍니다.
그림 5-7. 클린 아키텍처; 오니언 아키텍처 보기
이 다이어그램에서 종속성은 가장 안쪽 원으로 흐릅니다. Application Core는 이 다이어그램의 핵심 위치에서 해당 이름을 사용합니다. 또한 다이어그램에서 Application Core에 다른 애플리케이션 계층에 대한 종속성이 없음을 확인할 수 있습니다. 애플리케이션의 엔터티 및 인터페이스가 중심에 있습니다. Application Core 내에 있지만 바깥쪽에 있는 도메인 서비스는 일반적으로 내부 원에서 정의된 인터페이스를 구현합니다. Application Core 외부에서 UI와 인프라 계층은 모두 Application Core에 의존하지만 서로(반드시) 의존하지는 않습니다.
그림 5-8에서는 UI와 다른 계층 간의 종속성을 더 잘 반영하는 보다 전통적인 가로 계층 다이어그램을 보여 줍니다.
그림 5-8. 클린 아키텍처; 가로 계층 보기
단색 화살표는 컴파일 시간 종속성을 나타내고 파선 화살표는 런타임 전용 종속성을 나타냅니다. 클린 아키텍처에서는 UI 계층이 컴파일 시간에 Application Core에 정의된 인터페이스와 함께 작동하며, 이상적으로는 인프라 계층에 정의된 구현 유형에 대해 알 필요가 없습니다. 그러나 런타임에 앱이 실행되려면 이러한 구현 형식이 필요하므로 종속성 주입을 통해 Application Core 인터페이스에 연결해야 합니다.
그림 5-9에서는 이러한 권장 사항에 따라 빌드될 때 ASP.NET Core 애플리케이션의 아키텍처에 대한 자세한 보기를 보여 줍니다.
그림 5-9. ASP.NET 핵심 아키텍처 다이어그램은 클린 아키텍처를 따르는 것입니다.
Application Core는 인프라에 의존하지 않으므로 이 계층에 대한 자동화된 단위 테스트를 작성하기가 매우 쉽습니다. 그림 5-10 및 5-11은 테스트가 이 아키텍처에 어떻게 적합한지 보여 줍니다.
그림 5-10. Application Core를 개별적으로 단위 테스트하기
그림 5-11. 외부 종속성을 사용하여 인프라 구현을 통합 테스트합니다.
UI 계층은 인프라 프로젝트에 정의된 형식에 대한 직접적인 종속성이 없으므로 테스트를 용이하게 하거나 변화하는 애플리케이션 요구 사항에 대응하여 구현을 교환하기가 매우 쉽습니다. ASP.NET Core의 종속성 주입에 대한 기본 제공 사용 및 지원은 복잡하고 중요한 모놀리식 애플리케이션을 구성하는 가장 적절한 방법입니다.
모놀리식 애플리케이션의 경우 Application Core, 인프라 및 UI 프로젝트는 모두 단일 애플리케이션으로 실행됩니다. 런타임 애플리케이션 아키텍처는 그림 5-12와 유사할 수 있습니다.
그림 5-12. 샘플 ASP.NET Core 앱의 런타임 아키텍처입니다.
클린 아키텍처에서 코드 구성
클린 아키텍처 솔루션에서 각 프로젝트에는 명확한 책임이 있습니다. 따라서 특정 형식은 각 프로젝트에 속하며 적절한 프로젝트에서 이러한 형식에 해당하는 폴더를 자주 찾습니다.
응용 프로그램 핵심
Application Core는 엔터티, 서비스 및 인터페이스를 포함하는 비즈니스 모델을 보유합니다. 이러한 인터페이스에는 데이터 액세스, 파일 시스템 액세스, 네트워크 호출 등 인프라를 사용하여 수행되는 작업에 대한 추상화가 포함됩니다. 경우에 따라 이 계층에 정의된 서비스 또는 인터페이스가 UI 또는 인프라에 대한 종속성이 없는 비 엔터티 형식으로 작업해야 합니다. 이러한 개체는 간단한 DDO(데이터 전송 개체)로 정의할 수 있습니다.
Application Core 타입
- 엔터티(유지되는 비즈니스 모델 클래스)
- 엔터티의 집합(그룹)
- 인터페이스
- 도메인 서비스
- 사양
- 사용자 정의 예외 및 가드 절
- 도메인 이벤트 및 처리기
인프라
인프라 프로젝트에는 일반적으로 데이터 액세스 구현이 포함됩니다. 일반적인 ASP.NET Core 웹 애플리케이션에서 이러한 구현에는 EF(Entity Framework) DbContext, 정의된 EF Core Migration
개체 및 데이터 액세스 구현 클래스가 포함됩니다. 데이터 액세스 구현 코드를 추상화하는 가장 일반적인 방법은 리포지토리 디자인 패턴을 사용하는 것입니다.
인프라 프로젝트에는 데이터 액세스 구현 외에도 인프라 문제와 상호 작용해야 하는 서비스 구현이 포함되어야 합니다. 이러한 서비스는 Application Core에 정의된 인터페이스를 구현해야 하므로 인프라에는 Application Core 프로젝트에 대한 참조가 있어야 합니다.
인프라 유형
- EF Core 형식(
DbContext
,Migration
) - 데이터 액세스 구현 형식(리포지토리)
- 인프라 관련 서비스(예:
FileLogger
또는SmtpNotifier
)
UI 계층
ASP.NET Core MVC 애플리케이션의 사용자 인터페이스 계층은 애플리케이션의 진입점입니다. 이 프로젝트는 Application Core 프로젝트를 참조해야 하며, 해당 형식은 Application Core에 정의된 인터페이스를 통해 인프라와 엄격하게 상호 작용해야 합니다. 인프라 계층 형식에 대한 직접 인스턴스화 또는 정적 호출은 UI 계층에서 허용되지 않아야 합니다.
UI 계층 유형
- 컨트롤러
- 사용자 지정 필터
- 사용자 지정 미들웨어
- 조회수
- 뷰모델 (ViewModels)
- 스타트업
Startup
클래스 또는 Program.cs 파일은 애플리케이션을 구성하고 구현 형식을 인터페이스에 연결합니다. 이 논리가 수행되는 위치를 앱의 컴퍼지션 루트라고 하며 런타임에 종속성 주입이 제대로 작동할 수 있도록 합니다.
비고
앱을 시작하는 동안 종속성 주입을 연결하기 위해 UI 계층 프로젝트는 인프라 프로젝트를 참조해야 할 수 있습니다. 이 종속성은 어셈블리에서 형식 로드를 기본적으로 지원하는 사용자 지정 DI 컨테이너를 사용하여 가장 쉽게 제거할 수 있습니다. 이 샘플의 목적을 위해 가장 간단한 방법은 UI 프로젝트가 인프라 프로젝트를 참조하도록 허용하는 것입니다(그러나 개발자는 인프라 프로젝트의 형식에 대한 실제 참조를 앱의 컴퍼지션 루트로 제한해야 합니다).
모놀리식 애플리케이션 및 컨테이너
단일 및 모놀리식 배포 기반 웹 애플리케이션 또는 서비스를 빌드하고 컨테이너로 배포할 수 있습니다. 애플리케이션 내에서 모놀리식이 아니라 여러 라이브러리, 구성 요소 또는 계층으로 구성될 수 있습니다. 외부적으로 단일 프로세스, 단일 웹 애플리케이션 또는 단일 서비스를 사용하는 단일 컨테이너입니다.
이 모델을 관리하려면 애플리케이션을 나타내는 단일 컨테이너를 배포합니다. 시스템의 확장성을 높이려면 부하 분산 장치 앞에 추가 인스턴스를 복사하기만 하면 됩니다. 단순성은 단일 컨테이너 또는 VM에서 단일 배포를 관리하는 것에서 비롯됩니다.
그림 5-13과 같이 각 컨테이너 내에 여러 구성 요소/라이브러리 또는 내부 계층을 포함할 수 있습니다. 그러나 "컨테이너는 한 가지 작업을 수행하고 한 프로세스에서 수행"이라는 컨테이너 원칙에 따라 모놀리식 패턴이 충돌할 수 있습니다.
이 방법의 단점은 애플리케이션이 확장되면 크기를 조정해야 하는 경우에 발생합니다. 전체 애플리케이션의 크기를 조정하는 경우 실제로 문제가 되지 않습니다. 그러나 대부분의 경우 애플리케이션의 일부 부분은 크기 조정이 필요한 초크 지점이지만 다른 구성 요소는 덜 사용됩니다.
일반적인 전자 상거래 예제를 사용하면 제품 정보 구성 요소의 크기를 조정해야 할 수 있습니다. 제품을 구매하는 것보다 더 많은 고객이 제품을 검색합니다. 결제 파이프라인을 사용하는 것보다 더 많은 고객이 장바구니를 사용합니다. 더 적은 수의 고객이 의견을 추가하거나 구매 기록을 봅니다. 그리고 콘텐츠 및 마케팅 캠페인을 관리해야 하는 소수의 직원만 단일 지역에 있을 수 있습니다. 모놀리식 디자인의 크기를 조정하면 모든 코드가 여러 번 배포됩니다.
"모든 크기 조정" 문제 외에도 단일 구성 요소를 변경하려면 전체 애플리케이션의 전체 재검사 및 모든 인스턴스의 전체 재배포가 필요합니다.
모놀리식 접근 방식은 일반적이며 많은 조직에서 이 아키텍처 접근 방식을 사용하여 개발하고 있습니다. 많은 사람들이 충분한 결과를 가지고 있는 반면, 다른 사람들은 한계에 도달하고 있습니다. 많은 사람들이 도구와 인프라가 SOA(서비스 지향 아키텍처)를 빌드하기가 너무 어려웠기 때문에 이 모델에서 애플리케이션을 설계했으며 앱이 커질 때까지 필요를 못했습니다. 모놀리식 접근 방식의 한계에 도달한 경우 컨테이너 및 마이크로 서비스를 더 잘 활용할 수 있도록 앱을 분리하는 것이 다음 논리적 단계일 수 있습니다.
각 인스턴스에 전용 VM을 사용하여 Microsoft Azure에서 모놀리식 애플리케이션을 배포할 수 있습니다. Azure Virtual Machine Scale Sets를 사용하면 VM의 크기를 쉽게 조정할 수 있습니다. Azure App Services는 VM을 관리할 필요 없이 모놀리식 애플리케이션을 실행하고 인스턴스 크기를 쉽게 조정할 수 있습니다. Azure App Services는 Docker 컨테이너의 단일 인스턴스도 실행하여 배포를 간소화할 수 있습니다. Docker를 사용하여 단일 VM을 Docker 호스트로 배포하고 여러 인스턴스를 실행할 수 있습니다. 그림 5-14와 같이 Azure 분산 장치를 사용하여 크기 조정을 관리할 수 있습니다.
다양한 호스트에 대한 배포는 기존 배포 기술로 관리할 수 있습니다. Docker 호스트는 수동으로 수행되는 docker 실행 과 같은 명령이나 CD(지속적인 업데이트) 파이프라인과 같은 자동화를 통해 관리할 수 있습니다.
컨테이너로 배포된 모놀리식 애플리케이션
컨테이너를 사용하여 모놀리식 애플리케이션 배포를 관리하는 이점이 있습니다. 컨테이너 인스턴스의 크기 조정은 추가 VM을 배포하는 것보다 훨씬 빠르고 쉽습니다. 가상 머신 확장 집합을 사용하여 VM 크기를 조정하는 경우에도 만드는 데 시간이 소요됩니다. 앱 인스턴스로 배포되는 경우 앱의 구성은 VM의 일부로 관리됩니다.
Docker 이미지로 업데이트를 배포하는 것은 훨씬 빠르고 네트워크 효율적입니다. Docker 이미지는 일반적으로 몇 초 만에 시작되어 출시 속도가 빨라집니다. Docker 인스턴스를 분해하는 것은 명령을 실행하는 docker stop
것만큼 쉽으며 일반적으로 1초 이내에 완료됩니다.
컨테이너는 기본적으로 변경할 수 없으므로 손상된 VM에 대해 걱정할 필요가 없습니다. 반면 업데이트 스크립트는 디스크에 남아 있는 특정 구성 또는 파일을 고려하는 것을 잊어버릴 수 있습니다.
더 간단한 웹 애플리케이션의 모놀리식 배포에 Docker 컨테이너를 사용할 수 있습니다. 이 접근 방식은 지속적인 통합 및 지속적인 배포 파이프라인을 개선하고 배포-프로덕션 성공을 달성하는 데 도움이 됩니다. 더 이상 "내 컴퓨터에서 작동하며 프로덕션에서 작동하지 않는 이유는 무엇인가요?"
마이크로 서비스 기반 아키텍처에는 많은 이점이 있지만 이러한 이점은 복잡성을 증가합니다. 경우에 따라 비용이 이점보다 크므로 단일 컨테이너 또는 몇 개의 컨테이너에서 실행되는 모놀리식 배포 애플리케이션이 더 나은 옵션입니다.
모놀리식 애플리케이션은 잘 구분된 마이크로 서비스로 쉽게 분해할 수 없습니다. 마이크로 서비스는 서로 독립적으로 작동하여 복원력 있는 애플리케이션을 제공해야 합니다. 애플리케이션의 독립적인 기능 조각을 제공할 수 없는 경우 분리하면 복잡성이 더해집니다.
애플리케이션은 아직 독립적으로 기능을 확장할 필요가 없을 수 있습니다. 단일 인스턴스 이상으로 확장해야 하는 많은 애플리케이션은 해당 전체 인스턴스를 복제하는 비교적 간단한 프로세스를 통해 이 작업을 수행할 수 있습니다. 애플리케이션을 불연속 서비스로 분리하는 추가 작업은 애플리케이션의 전체 인스턴스를 간단하게 스케일링하는 것이 간단하고 비용 효율적일 때 최소한의 이점을 제공합니다.
애플리케이션 개발 초기에는 자연 기능 경계가 어디에 있는지 명확히 알 수 없습니다. 최소 실행 가능한 제품을 개발할 때 자연 분리는 아직 등장하지 않았을 수 있습니다. 이러한 조건 중 일부는 일시적일 수 있습니다. 모놀리식 애플리케이션을 만드는 것으로 시작하고 나중에 마이크로 서비스로 개발 및 배포할 일부 기능을 분리할 수 있습니다. 다른 조건은 애플리케이션의 문제 공간에 필수적일 수 있습니다. 즉, 애플리케이션이 여러 마이크로 서비스로 분할되지 않을 수 있습니다.
애플리케이션을 여러 개별 프로세스로 분리하면 오버헤드도 발생합니다. 기능을 다른 프로세스로 분리하는 데 더 복잡합니다. 통신 프로토콜은 더 복잡해집니다. 메서드 호출 대신 서비스 간에 비동기 통신을 사용해야 합니다. 마이크로 서비스 아키텍처로 이동하면 이벤트 버스 처리, 메시지 복원력 및 재시도, 최종 일관성 등 eShopOnContainers 애플리케이션의 마이크로 서비스 버전에 구현된 많은 구성 요소를 추가해야 합니다.
훨씬 간단한 eShopOnWeb 참조 애플리케이션 은 단일 컨테이너 모놀리식 컨테이너 사용을 지원합니다. 애플리케이션에는 기존 MVC 보기, 웹 API 및 Razor Pages를 포함하는 하나의 웹 애플리케이션이 포함됩니다. 필요에 따라 별도의 API 프로젝트를 실행해야 하는 애플리케이션의 Blazor 기반 관리 구성 요소를 실행할 수 있습니다.
애플리케이션은 솔루션 루트에서 docker-compose build
및 docker-compose up
명령을 사용하여 시작할 수 있습니다. 이 명령은 웹 프로젝트의 루트에 있는 컨테이너를 사용하여 Dockerfile
웹 인스턴스에 대한 컨테이너를 구성하고 지정된 포트에서 컨테이너를 실행합니다. GitHub에서 이 애플리케이션의 원본을 다운로드하여 로컬로 실행할 수 있습니다. 이 모놀리식 애플리케이션조차도 컨테이너 환경에 배포되는 이점을 누릴 수 있습니다.
즉, 컨테이너화된 배포는 애플리케이션의 모든 인스턴스가 동일한 환경에서 실행된다는 것을 의미합니다. 이 접근 방식에는 초기 테스트 및 개발이 수행되는 개발자 환경이 포함됩니다. 개발 팀은 프로덕션 환경과 일치하는 컨테이너화된 환경에서 애플리케이션을 실행할 수 있습니다.
또한 컨테이너화된 애플리케이션은 더 낮은 비용으로 확장됩니다. 컨테이너 환경을 사용하면 기존 VM 환경보다 리소스를 더 많이 공유할 수 있습니다.
마지막으로 애플리케이션을 컨테이너화하면 비즈니스 논리와 스토리지 서버가 분리됩니다. 애플리케이션이 확장됨에 따라 여러 컨테이너는 모두 단일 물리적 스토리지 매체를 사용합니다. 이 스토리지 매체는 일반적으로 SQL Server 데이터베이스를 실행하는 고가용성 서버입니다.
Docker 지원
프로젝트는 eShopOnWeb
.NET에서 실행됩니다. 따라서 Linux 기반 또는 Windows 기반 컨테이너에서 실행할 수 있습니다. Docker 배포의 경우 SQL Server에 대해 동일한 호스트 유형을 사용하려고 합니다. Linux 기반 컨테이너는 더 작은 공간을 허용하며 선호됩니다.
Visual Studio 2017 이상을 사용하여 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 Docker 지원 추가를 선택하여 기존 애플리케이션에Docker 지원을> 수 있습니다. 이 단계에서는 필요한 파일을 추가하고 사용할 프로젝트를 수정합니다. 현재 eShopOnWeb
샘플에는 이미 이러한 파일이 있습니다.
솔루션 수준 docker-compose.yml
파일에는 빌드할 이미지와 시작할 컨테이너에 대한 정보가 포함되어 있습니다. 이 파일을 사용하면 명령을 사용하여 docker-compose
동시에 여러 애플리케이션을 시작할 수 있습니다. 이 경우 웹 프로젝트만 시작됩니다. 별도의 데이터베이스 컨테이너와 같은 종속성을 구성하는 데 사용할 수도 있습니다.
version: '3'
services:
eshopwebmvc:
image: eshopwebmvc
build:
context: .
dockerfile: src/Web/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "5106:5106"
networks:
default:
external:
name: nat
파일 docker-compose.yml
는 Dockerfile
프로젝트에서 Web
을 참조합니다.
Dockerfile
사용할 기본 컨테이너와 애플리케이션을 구성하는 방법을 지정하는 데 사용됩니다. ' Web
Dockerfile
:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
COPY *.sln .
COPY . .
WORKDIR /app/src/Web
RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/Web/out ./
ENTRYPOINT ["dotnet", "Web.dll"]
Docker 문제 해결
컨테이너화된 애플리케이션을 실행한 후에는 중지할 때까지 계속 실행됩니다.
docker ps
명령을 사용하여 실행 중인 컨테이너를 볼 수 있습니다. 명령을 사용하고 컨테이너 ID를 docker stop
지정하여 실행 중인 컨테이너를 중지할 수 있습니다.
실행 중인 Docker 컨테이너는 개발 환경에서 사용하고자 하는 포트에 바인딩될 수 있습니다. 실행 중인 Docker 컨테이너와 동일한 포트를 사용하여 애플리케이션을 실행하거나 디버그하려고 하면 서버가 해당 포트에 바인딩할 수 없다는 오류가 표시됩니다. 다시 한번 컨테이너를 중지하면 문제가 해결됩니다.
Visual Studio를 사용하여 애플리케이션에 Docker 지원을 추가하려면 Docker Desktop이 실행 중인지 확인합니다. 마법사를 시작할 때 Docker Desktop이 실행되고 있지 않으면 마법사가 제대로 실행되지 않습니다. 또한 마법사는 현재 컨테이너 선택을 검사하여 올바른 Docker 지원을 추가합니다. Windows 컨테이너에 대한 지원을 추가하려면 Windows 컨테이너를 사용하여 Docker Desktop을 실행하는 동안 마법사를 실행해야 합니다. Linux 컨테이너 지원을 추가하려면, Linux 컨테이너가 구성된 상태로 Docker를 실행하는 동안 마법사를 실행하십시오.
기타 웹 애플리케이션 아키텍처 스타일
- Web-Queue-Worker: 이 아키텍처의 핵심 구성 요소는 클라이언트 요청을 제공하는 웹 프런트 엔드 및 리소스 집약적 작업, 장기 실행 워크플로 또는 일괄 작업을 수행하는 작업자입니다. 웹 프런트 엔드는 메시지 큐를 통해 작업자와 통신합니다.
- N 계층: N 계층 아키텍처는 애플리케이션을 논리 계층 및 물리적 계층으로 나눕니다.
- 마이크로 서비스: 마이크로 서비스 아키텍처는 소규모의 자율 서비스 컬렉션으로 구성됩니다. 각 서비스는 독립적이며 제한된 컨텍스트 내에서 단일 비즈니스 기능을 구현해야 합니다.
참조 – 일반적인 웹 아키텍처
-
클린 아키텍처
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html -
양파 아키텍처
https://jeffreypalermo.com/blog/the-onion-architecture-part-1/ -
리포지토리 패턴
https://deviq.com/repository-pattern/ -
클린 아키텍처 솔루션 템플릿
https://github.com/ardalis/cleanarchitecture -
마이크로서비스 아키텍처 e북
https://aka.ms/MicroservicesEbook -
DDD(Domain-Driven 디자인)
https://learn.microsoft.com/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/
.NET