Linux의 .NET: 보기보다 간단합니다.

게시 됨: 2022-08-16

Microsoft의 Visual Studio가 작동하려면 Windows가 필요하기 때문에 Linux에서 .NET 솔루션을 개발하는 것은 항상 어려운 일이었습니다. 여러 .NET 프로젝트에서 작업한 후 Linux에서 .NET 개발의 한계를 테스트하기로 결정했습니다. 이 간단한 자습서는 SQL Server가 포함된 ASP.NET MVC 응용 프로그램에 중점을 두어 내가 선호하는 OS에서 .NET 개발이 얼마나 우아하고 효과적인지 보여줍니다.

개발 환경

먼저 Microsoft의 표준 가이드를 사용하여 특정 Linux 버전과 관련된 .NET 도구 및 SDK가 설치되었는지 확인해야 합니다.

내가 선호하는 개발 환경은 창으로 된 통합 개발 환경(IDE), 강력한 데이터베이스 관리 및 쿼리 도구, 데이터베이스 자체, 구축 및 배포를 위한 도구로 구성됩니다. 다음 도구를 사용하여 견고한 기능을 구현하고 아름다운 코딩 경험을 가능하게 합니다.

  • IDE: 비주얼 스튜디오 코드
  • 데이터베이스 관리 및 쿼리 도구: DBeaver
  • 데이터베이스: Microsoft SQL Server(Linux 설치)
  • 빌드 도구: .NET SDK 명령줄 인터페이스(CLI)
  • 가상 머신 및 컨테이너: Docker

샘플 애플리케이션을 진행하기 전에 이러한 도구가 제대로 설치되었는지 확인하십시오.

프로젝트 비계

이 샘플 응용 프로그램에서는 가상 신발 매장 재고 관리 시스템에 대한 일련의 사용 사례를 통해 ASP.NET 개발 및 기능을 강조합니다. 새 .NET 응용 프로그램과 마찬가지로 솔루션을 만든 다음 여기에 프로젝트를 추가해야 합니다. .NET SDK CLI 도구를 활용하여 새 솔루션을 스캐폴드할 수 있습니다.

 mkdir Shoestore && cd Shoestore dotnet new sln

다음으로 이 프로젝트 구조는 ASP.NET 개발자에게 가장 친숙하므로 단순성을 위해 명시적 기본 클래스를 포함하는 ASP.NET 프로젝트를 만듭니다. MVC 패턴을 사용하여 프로젝트를 생성해 보겠습니다.

 mkdir Shoestore.mvc && cd Shoestore.mvc dotnet new mvc --use-program-main=true

다음으로 솔루션에 프로젝트를 추가합니다.

 # Go to the root of the solution cd .. dotnet sln add Shoestore.mvc/

이제 기본 솔루션과 포함된 ASP.NET 프로젝트가 있습니다. 계속하기 전에 모든 것이 빌드되었는지 확인하십시오.

 cd Shoestore.mvc/ dotnet restore dotnet build

좋은 개발 방법은 배포 및 이식성을 향상시키기 위해 핵심 서비스와 애플리케이션 런타임을 Docker 컨테이너에 넣는 것을 권장합니다. 따라서 애플리케이션을 지원하는 간단한 Docker 컨테이너를 만들어 보겠습니다.

애플리케이션 이식성

Docker 이미지는 일반적으로 OS 및 데이터베이스를 포함한 기본 솔루션과 같은 필수 요구 사항에 대해 허용되는 시작점으로 다른 상위 Docker 이미지를 참조합니다. 이 Docker 모범 사례에 따라 Microsoft에서 게시한 상위 이미지를 참조하면서 적절한 서비스 구성을 위해 Dockerfile과 Docker Compose 파일을 모두 만듭니다. Docker 단계를 사용하여 이미지를 작게 유지합니다. 단계를 통해 응용 프로그램을 빌드하는 동안 .NET SDK를 사용할 수 있으므로 응용 프로그램이 실행되는 동안에만 ASP.NET 런타임이 필요합니다.

다음 내용으로 Shoestore.mvc Dockerfile을 만듭니다.

 # Shoestore\Shoestore.mvc\Dockerfile # Build stage FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /shoestore COPY Shoestore.mvc/*.csproj ./ # Restore project packages RUN dotnet restore COPY Shoestore.mvc/* ./ # Create a release build RUN dotnet build -c Release -o /app/build # Run the application and make it available on port 80 FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app EXPOSE 80 # Assets and views COPY Shoestore.mvc/Views ./Views COPY Shoestore.mvc/wwwroot ./wwwroot COPY --from=build /app/build ./ ENTRYPOINT [ "dotnet", "Shoestore.mvc.dll" ]

다음으로 솔루션의 루트 디렉터리에 docker-compose.yml 파일을 만듭니다. 처음에는 애플리케이션 서비스의 .Dockerfile 에 대한 참조만 포함됩니다.

 # Shoestore/docker-compose.yml version: "3.9" services: web: build: context: . dockerfile: Shoestore.mvc/Dockerfile ports: - "8080:80"

또한 빌드 아티팩트만 이미지에 복사되도록 .dockerignore 파일로 환경을 구성하겠습니다.

이제 애플리케이션 서비스가 스텁되고 실행 환경이 실행될 준비가 되었으므로 데이터베이스 서비스를 생성하고 Docker 구성에 연결해야 합니다.

데이터베이스 서비스

Microsoft SQL Server를 Docker 구성에 추가하는 것은 간단합니다. 특히 Microsoft에서 제공한 Docker 이미지를 변경하지 않고 사용하고 있기 때문입니다. docker-compose.yml 파일 하단에 다음 구성 블록을 추가하여 데이터베이스를 구성합니다.

 db: image: "mcr.microsoft.com/mssql/server" environment: SA_PASSWORD: "custom_password_123" ACCEPT_EULA: "Y" ports: - "1433:1433"

여기에서 ACCEPT_EULA 는 설치가 중단되는 것을 방지하고 ports 설정은 기본 SQL Server 포트가 변환 없이 통과할 수 있도록 합니다. 이를 통해 Compose 파일에는 애플리케이션 서비스와 데이터베이스가 모두 포함됩니다.

애플리케이션 코드를 사용자 지정하기 전에 Docker 환경이 작동하는지 확인하겠습니다.

 # From the root of the solution docker compose up --build

시작하는 동안 오류가 나타나지 않는다고 가정하면 불완전한 샘플 응용 프로그램은 로컬 주소 http://localhost:8080 의 웹 브라우저를 통해 사용할 수 있어야 합니다.

코드 생성 도구

이제 재미있는 부분인 응용 프로그램 코드를 사용자 지정하고 응용 프로그램 데이터가 Microsoft SQL Server 데이터베이스에 유지되도록 하는 데 초점을 맞춥니다. EF(Entity Framework) 및 .NET SDK 도구를 모두 사용하여 응용 프로그램을 데이터베이스에 연결하고 응용 프로그램의 모델, 보기, 컨트롤러 및 EF 필수 구성을 스캐폴딩합니다.

필요한 도구를 지정하기 전에 tool-manifest 파일을 만들어야 합니다.

 # From the root of the solution dotnet new tool-manifest

다음과 같은 간단한 명령을 사용하여 이 파일에 EF 및 SDK 도구를 추가합니다.

 dotnet tool install dotnet-ef dotnet tool install dotnet-aspnet-codegenerator

이러한 도구가 제대로 설치되었는지 확인하려면 dotnet ef 를 실행합니다. 유니콘이 나타나면 올바르게 설치된 것입니다. 다음 dotnet aspnet-codegenerator 를 실행하여 ASP.NET 도구를 테스트합니다. 출력은 일반적인 CLI 사용 블록이어야 합니다.

이제 이러한 도구를 사용하여 응용 프로그램을 만들 수 있습니다.

MVC: 모델

애플리케이션 빌드의 첫 번째 작업은 모델을 만드는 것입니다. 이 모델은 나중에 데이터베이스에 추가되므로 프로젝트에 MS SQL Server 및 EF 패키지를 포함합니다.

 cd Shoestore.mvc/ dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools dotnet restore

다음으로, 데이터베이스에 추가할 모델을 결정하고 코드가 데이터베이스에서 해당 데이터에 쉽게 액세스하고 쿼리할 수 있도록 하는 EF 데이터베이스 컨텍스트 개체를 만듭니다.

EF 관련 코드를 저장할 Data 디렉터리를 만들고 다음 콘텐츠로 Data/ApplicationDBContext.cs 파일을 만듭니다.

 // Shoestore/Shoestore.mvc/Data/ApplicationDBContext.cs using Microsoft.EntityFrameworkCore; namespace Shoestore.mvc.Data; public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options):base(options){} }

다음으로 Dockerfile 에서 구성한 자격 증명과 일치해야 하는 데이터베이스 연결 문자열을 구성합니다. Shoestore/Shoestore.mvc/appsettings.json 의 내용을 다음과 같이 설정합니다.

 { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "Shoestore": "Server=db;Database=master;User=sa;Password=custom_password_123;" } }

데이터베이스 연결 문자열이 구성되고 데이터베이스 컨텍스트가 코딩되었으므로 애플리케이션의 Main 함수를 코딩할 준비가 되었습니다. 시스템 디버깅을 단순화하기 위해 데이터베이스 예외 처리를 포함할 것입니다. 또한 생성된 코드의 .NET 버그로 인해 Docker 컨테이너가 보기를 잘못 제공하기 때문에 보기 서비스 구성에 특정 코드를 추가해야 합니다. 이렇게 하면 Docker 이미지의 보기 위치에 대한 파일 경로가 명시적으로 설정됩니다.

 using Microsoft.EntityFrameworkCore; using Shoestore.mvc.Data; namespace Shoestore.mvc; // ... public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Associate our EF database context and configure it with our connection string var connectionString = builder.Configuration.GetConnectionString("Shoestore"); builder.Services.AddDbContext<ApplicationDBContext>( options => options.UseSqlServer(connectionString)); // Middleware to catch unhandled exceptions and display a stack trace builder.Services.AddDatabaseDeveloperPageExceptionFilter(); // Add services to the container. // ASP.NET has a known issue where the final built app doesn't know where the view // files are (in the Docker container). // The fix is to specifically add view locations. builder.Services .AddControllersWithViews() .AddRazorOptions(options => { options.ViewLocationFormats.Add("/{1}/{0}.cshtml"); options.ViewLocationFormats.Add("/Shared/{0}.cshtml"); });

개발 모드에 있을 때 시스템에 데이터베이스 마이그레이션 끝점을 추가하려면 동일한 파일 내의 IsDevelopment if 문으로 건너뜁니다. 다음 코드를 사용하여 else 문을 추가합니다.

 // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { // Leave the contents of the if block alone. These are hidden for clarity. } else { app.UseMigrationsEndPoint(); }

다음으로 빠른 테스트를 실행하여 새 패키지와 소스 코드 편집이 올바르게 컴파일되는지 확인합니다.

 // Go to mvc directory cd Shoestore.mvc dotnet restore dotnet build

이제 Shoestore.mvc\Models\Shoe.cs 파일을 만들어 모델을 필수 필드로 채우겠습니다.

 namespace Shoestore.mvc.Models; public class Shoe { public int ID { get; set; } public string? Name { get; set; } public int? Price { get; set; } public DateTime CreatedDate { get; set; } }

EF는 연결된 모델, 컨텍스트 파일 및 애플리케이션의 모든 EF 코드를 기반으로 SQL을 생성합니다. 그런 다음 필요에 따라 SQL 결과가 번역되어 코드로 반환됩니다. 데이터베이스 컨텍스트에 Shoe 모델을 추가하면 EF는 MS SQL Server와 애플리케이션 간에 변환하는 방법을 알게 됩니다. 데이터베이스 컨텍스트 파일인 Shoestore/Shoestore.mvc/Data/ApplicationDBContext.cs 에서 이 작업을 수행해 보겠습니다.

 using Microsoft.EntityFrameworkCore; using Shoestore.mvc.Models; namespace Shoestore.mvc.Data; public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options) { } private DbSet<Shoe>? _shoe { get; set; } public DbSet<Shoe> Shoe { set => _shoe = value; get => _shoe ?? throw new InvalidOperationException("Uninitialized property" + nameof(Shoe)); } }

마지막으로 데이터베이스 마이그레이션 파일을 사용하여 모델을 데이터베이스로 가져옵니다. EF 도구는 데이터베이스 컨텍스트 및 관련 모델(예: Shoe )을 기반으로 MS SQL Server와 관련된 마이그레이션 파일을 생성합니다.

 cd Shoestore.mvc/ dotnet ef migrations add InitialCreate

컨트롤러와 보기가 준비될 때까지 마이그레이션 실행을 보류합시다.

MVC: 컨트롤러와 뷰

ASP.NET 코드 생성 도구를 사용하여 컨트롤러를 만듭니다. 이 도구는 매우 강력하지만 특정 도우미 클래스가 필요합니다. 기본 컨트롤러 구조 및 EF 통합을 위해 Design 스타일 패키지를 사용합니다. 다음 패키지를 추가해 보겠습니다.

 cd Shoestore.mvc\ dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design && \ dotnet add package Microsoft.EntityFrameworkCore.Design && \ dotnet restore

이제 기본 컨트롤러를 만드는 것은 다음 명령을 호출하는 것만 큼 간단합니다.

 cd Shoestore.mvc\ dotnet dotnet-aspnet-codegenerator controller \ -name ShoesController \ -m Shoe \ -dc ApplicationDBContext \ --relativeFolderPath Controllers \ --useDefaultLayout \ --referenceScriptLibraries

코드 생성기가 컨트롤러를 생성할 때 해당 컨트롤러에 대한 간단한 보기도 생성합니다. MVC 기반이 완성되면 모든 것을 실행할 준비가 되었습니다.

마이그레이션 및 애플리케이션 테스트

EF 마이그레이션은 일반적으로 간단한 일이지만 Docker가 관련되면 프로세스가 더 복잡해집니다. 시리즈의 다음 기사에서는 이러한 마이그레이션이 Docker 솔루션에서 작동하도록 하는 놀랍도록 꼬인 경로를 탐색하지만 지금은 마이그레이션이 실행되기를 원합니다.

모든 구성 및 마이그레이션 파일은 저장소에 포함되어 있습니다. 전체 프로젝트를 로컬 시스템에 복제하고 마이그레이션을 수행해 보겠습니다.

 git clone https://github.com/theZetrax/dot-net-on-linux.git cd ./dot-net-on-linux docker composer up

docker composer 작업은 애플리케이션을 빌드하고 마이그레이션을 실행하며 .NET 런타임으로 ASP.NET 애플리케이션을 시작합니다. 실행 중인 솔루션에 액세스하려면 http://localhost:8080/Shoes 를 방문하세요.

우리의 애플리케이션 인터페이스는 단순하지만 보기에서 데이터베이스에 이르기까지 모든 계층에서 기능을 보여줍니다.

Linux의 .NET은 작동합니다.

솔루션에 대한 개요는 전체 리포지토리를 참조하세요. 다음 기사에서는 마이그레이션과 Docker 이미지를 간결하게 만드는 팁과 요령에 대해 자세히 설명합니다.

Linux의 .NET은 단순한 꿈 그 이상입니다. 실행 가능한 언어, 런타임 및 OS 조합입니다. Visual Studio에서 성장한 많은 개발자는 .NET CLI를 최대한 사용해 본 경험이 없을 수 있지만 이러한 도구는 효과적이고 강력합니다.

Toptal 엔지니어링 블로그에 대한 추가 정보:

  • ASP.NET Core를 사용하여 ASP.NET Web API 빌드
  • Microsoft Stack이 여전히 실행 가능한 선택인 8가지 이유
  • 캐싱을 사용하여 웹 팜에서 ASP.NET 앱 성능을 개선하는 방법
  • .NET 개발자를 위한 Elasticsearch 튜토리얼
  • 쿠버네티스란? 컨테이너화 및 배포 가이드

Toptal Engineering Blog는 이 기사에 제공된 코드 샘플을 검토해 준 Henok Tsegaye에게 감사의 말을 전합니다.