파이프라인의 빌드 종속성 계획

완료됨

이 단원에서는 더 쉽게 공유할 수 있도록 코드를 패키징하는 방법에 관해 알아봅니다. 패키지를 만들어야 하는 이유, 만들 수 있는 패키지 종류, 패키지를 호스트할 수 있는 위치 및 호스트되는 패키지에 액세스할 수 있는 방법을 알 수 있습니다. 패키지 버전 관리에 대해서도 알아봅니다.

코드베이스는 항상 더 커지고 복잡해집니다. 팀이 앱에서 사용하는 모든 코드를 작성하는 것은 드문 일입니다. 대신 팀에는 다른 개발자가 작성한 기존 코드가 포함됩니다. 앱에 이러한 패키지나 종속성이 다수 존재할 수 있습니다. 해당 종속성을 적절하게 유지 관리하고 보안 요구 사항을 충족하는지 확인하려면 종속성을 적극적으로 관리하는 것이 중요합니다.

먼저, 팀이 어떻게 하고 있는지 검사하고 확인해 보겠습니다. Andy는 다른 팀에 도움이 되는 코드의 잠재적인 변경에 관해 이야기하기 위해 팀을 소집했습니다.

팀 회의

Andy: 여러분, 안녕하세요. Space Game의 백 엔드 시스템을 작업하는 팀과 이야기하고 있었습니다. 이 팀은 작성하려는 백 엔드 앱에서 웹 사이트에 사용하는 모델을 사용할 수 있었습니다.

Amita: 모델이란 무엇인가요?

Andy: 아시다시피 Space Game 웹 사이트는 ASP.NET Core 애플리케이션입니다. 이 모델은 Model-View-Controller(MVC) 패턴을 사용하여 데이터가 사용자 인터페이스에 표시되는 방식과 데이터를 분리합니다. 모든 앱에서 사용할 수 있도록 모델 클래스를 포함하는 패키지를 만들 수 있다고 생각했습니다.

Amita: 정확히 목표가 무엇인가요?

Andy: 두 팀 모두 동일한 데이터베이스를 공유하게 됩니다. 게임에서 데이터베이스에 높은 점수를 보내고, 사용자가 이 점수를 읽어 순위표에 표시합니다.

Amita: 일리가 있네요. 이 패키지는 어떻게 만들 수 있나요?

Andy: 바로 그것에 대해 당신과 이야기하고 싶었습니다. 몇 가지 옵션이 있으며 아이디어를 찾고 있습니다.

Tim: 도와드리기 전에 몇 가지 질문이 있습니다. 제게는 새로운 개념이기 때문에 모두 어떻게 작동하는지 알고 싶습니다.

패키지란?

패키지에는 다른 개발자가 작성하지 않은 경우에도 고유한 프로젝트에서 사용할 수 있는 재사용 가능한 코드가 포함되어 있습니다.

컴파일된 언어의 경우 패키지에는 일반적으로 .NET의 .dll 파일 또는 Java의 .class 파일과 같이 컴파일된 이진 코드가 포함됩니다. JavaScript 또는 Python과 같이 컴파일된 언어가 아니라 해석된 언어의 경우, 패키지에 소스 코드가 포함될 수 있습니다.

어느 쪽이든 패키지는 일반적으로 ZIP 또는 유사한 형식으로 압축됩니다. 패키지 시스템에서는 종종 .nupkg 또는 .jar와 같은 고유한 파일 확장자를 정의하여 패키지 사용을 명확하게 합니다. 압축하면 다운로드 시간을 줄일 수 있으며 단일 파일을 생성하여 관리를 단순화할 수도 있습니다.

또한 대부분의 패키지에는 패키지에 관한 메타데이터 또는 정보를 제공하는 하나 이상의 파일이 포함됩니다. 이 메타데이터에서는 패키지의 기능을 설명하고 사용 조건, 작성자의 연락처 정보 및 패키지 버전을 지정할 수 있습니다.

패키지를 빌드해야 하는 이유는 무엇인가요?

코드를 복제하는 것과는 반대로 패키지를 빌드하면 이점이 있습니다.

코드를 복제하는 대신 패키지를 만드는 한 가지 이유는 드리프트를 방지하기 위해서입니다. 코드가 복제되면 특정 앱의 요구 사항을 충족하도록 각 복사본이 빠르게 분기될 수 있습니다. 한 복사본에서 다른 복사본으로 변경 사항을 마이그레이션하기가 어려워집니다. 즉, 모든 사용자에게 혜택을 주는 방식으로 코드를 개선하는 기능을 잃게 됩니다.

또한 패키지는 관련된 기능을 하나의 재사용 가능한 구성 요소로 그룹화합니다. 프로그래밍 언어에 따라 패키지는 특정 유형 및 함수에 대한 액세스 권한을 앱에 부여하고 구현 세부 정보에 대한 액세스 권한을 제한할 수 있습니다.

패키지를 빌드하는 또 다른 이유는 해당 패키지의 기능을 빌드하고 테스트하는 일관된 방법을 제공하기 위해서입니다. 코드가 복제되면 각 앱이 여러 다른 방식으로 코드를 빌드하고 테스트할 수 있습니다. 한 테스트 세트에는 다른 세트가 활용할 수 있는 검사가 포함될 수 있습니다.

한 가지 단점은 패키지를 사용하면 또 다른 코드베이스를 테스트하고 유지 관리해야 한다는 것입니다. 기능을 추가할 때도 주의해야 합니다. 일반적으로 패키지에는 다양한 종류의 앱을 활용하는 기능이 포함되어 있어야 합니다. 예를 들어 Json.NET은 JSON 파일에 관해 작업하는 데 사용할 수 있는, 널리 사용되는 .NET용 NuGet 패키지입니다. Json.NET은 오픈 소스이므로 커뮤니티에서 개선 사항을 제안하고 문제를 보고할 수 있습니다.

여러 앱이 동일한 코드를 활용할 수 있으면 장점이 단점보다 훨씬 큽니다. 코드베이스 하나, 테스트 세트 하나, 관리할 빌드 프로세스가 하나만 있습니다.

종속성을 식별하려면 어떻게 해야 하나요?

목표가 코드를 개별 구성 요소로 재구성하는 것이라면 제거하고, 재사용할 수 있도록 패키징하고, 중앙 위치에 저장하고, 버전을 지정할 수 있는 앱의 부분을 식별해야 합니다. 자신의 코드를 오픈 소스이거나 라이선스가 부여된 타사 구성 요소로 바꿀 수도 있습니다.

코드베이스에서 잠재적 종속성을 식별하는 방법에는 여러 가지가 있습니다. 여기에는 코드에서 재사용 패턴 검사와 솔루션의 아키텍처 분석이 포함됩니다. 종속성을 식별하는 몇 가지 방법은 다음과 같습니다.

  • 중복 코드.

    코드 특정 부분이 여러 위치에 표시된다면, 이 코드를 재사용할 수 있다는 뜻입니다. 이러한 중복 코드를 중앙 집중화하고 적절하게 다시 패키징합니다.

  • 높은 응집력 및 낮은 결합.

    두 번째 접근 방식은 서로 응집력이 높고, 코드의 다른 부분과 결합이 낮은 코드 요소를 찾는 것입니다. 기본적으로 높은 응집력은 서로 관련된 코드베이스의 파트를 단일 위치에 유지하는 것을 의미합니다. 동시에 낮은 결합은 코드베이스에서 관련 없는 부분을 최대한 분리하는 것입니다.

  • 개별 수명 주기.

    수명 주기가 비슷하고 개별적으로 배포 및 릴리스할 수 있는 코드 부분을 찾습니다. 이 코드를 별도의 팀에서 유지 관리할 수 있는 경우, 솔루션 외부의 구성 요소로 패키징할 수 있습니다.

  • 안정적인 부분.

    코드베이스의 일부는 안정적이고 자주 변경되지 않을 수 있습니다. 코드 리포지토리를 확인하여 변경 빈도가 낮은 코드를 찾습니다.

  • 독립 코드 및 구성 요소.

    코드와 구성 요소가 독립적이고 시스템의 다른 파트와 관련이 없다면, 별도의 종속성으로 격리할 수 있습니다.

코드베이스를 검사하고 검토하는 데 도움이 되는 다양한 도구를 사용할 수 있습니다. 여기에는 중복 코드를 검사하고 솔루션 종속성 그래프를 그리는 도구부터 결합 및 응집력의 메트릭을 계산할 수 있는 도구까지 다양합니다.

어떤 종류의 패키지가 있나요?

각 프로그래밍 언어 또는 프레임워크에서는 패키지를 빌드하는 고유한 방법을 제공합니다. 널리 사용되는 패키지 시스템은 프로세스 작동 방식에 관한 문서를 제공합니다.

다음과 같이 널리 사용되는 패키지 시스템에 이미 익숙할 것입니다.

  • NuGet: 패키지 .NET 라이브러리
  • NPM: JavaScript 라이브러리 패키지
  • Maven: 패키지 Java 라이브러리
  • Docker: 컨테이너라고 하는 격리된 단위에 소프트웨어 패키지

패키지는 어디서 호스트되나요?

고유한 네트워크에서 패키지를 호스트하거나 호스팅 서비스를 사용할 수 있습니다. 호스팅 서비스는 종종 패키지 리포지토리 또는 패키지 레지스트리라고도 합니다. 이러한 서비스 중 다수는 오픈 소스 프로젝트를 위한 무료 호스팅을 제공합니다.

위에서 설명한 패키지 유형에 널리 사용되는 호스팅 서비스는 다음과 같습니다.

  • NuGet 갤러리

    NuGet 패키지는 .NET 코드 아티팩트에 사용됩니다. 이 아티팩트에는 .NET 어셈블리와 관련 파일, 도구가 포함되어 있으며 메타데이터가 포함된 경우도 있습니다. NuGet은 패키지를 만들고 저장하고 사용하는 방법을 정의합니다. NuGet 패키지는 기본적으로 ZIP 형식의 파일이 포함된 압축 폴더 구조이며 확장자는 .nupkg입니다.

  • NPM

    NPM 패키지는 JavaScript에 사용됩니다. NPM 패키지는 JavaScript 파일과 패키지의 메타데이터를 설명하는 package.json 파일이 포함된 파일 또는 폴더입니다. node.js의 경우 패키지에는 일반적으로 패키지를 사용한 다음 로드할 수 있는 하나 이상의 모듈이 포함되어 있습니다.

  • Maven 중앙 리포지토리

    Maven은 Java 기반 프로젝트에 사용됩니다. 각 패키지는 프로젝트의 메타데이터를 설명하는 프로젝트 개체 모델 파일을 포함하고 있으며, 패키지를 정의하고 작업하기 위한 기본 단위입니다.

  • Docker Hub

    Docker 패키지는 이미지라고 하며, 완전한 자체 포함 배포를 포함합니다. 가장 일반적으로 Docker 이미지는 다른 이미지에 대한 종속성 없이 자체적으로 호스트되고 실행될 수 있는 소프트웨어 구성 요소를 나타냅니다. Docker 이미지는 계층화되어 있으며 다른 이미지에 종속될 수 있습니다.

패키지 피드는 패키지 리포지토리 서버를 나타냅니다. 이 서버는 인터넷에 있거나 네트워크의 방화벽 뒤에 있을 수 있습니다. 예를 들어 Azure Artifacts나 MyGet 같은 호스트 제품을 사용하여 고유 NuGet 피드를 호스트할 수 있습니다. 또한 파일 공유에서 패키지를 호스트할 수 있습니다.

방화벽 뒤에서 패키지를 호스트할 때 자체 패키지에 피드를 포함할 수 있습니다. 또한 시스템에서 인터넷에 연결할 수 없는 경우 네트워크에서 신뢰하는 패키지를 캐시할 수 있습니다.

바람직한 종속성 관리 전략을 구성하는 요소는 무엇인가요?

좋은 종속성 관리 전략은 다음과 같은 세 가지 요소에 따라 다릅니다.

  • 표준화.

    종속성을 선언하고 해결하는 방법을 표준화하면 자동화된 릴리스 프로세스를 반복할 수 있고 예측 가능한 상태를 유지하는 데 도움이 됩니다.

  • 패키지 형식과 소스.

    각 종속성은 해당 형식을 사용하여 패키징하고 중앙 위치에 저장해야 합니다.

  • 버전 관리.

    자신의 코드를 사용할 때와 마찬가지로, 시간이 지남에 따라 발생하는 종속성의 변경 내용을 추적해야 합니다. 즉, 종속성의 버전을 지정해야 합니다.

누가 패키지에 액세스할 수 있나요?

많은 패키지 피드에서 패키지에 대한 무제한 액세스 권한을 제공합니다. 예를 들어 로그인하거나 인증할 필요 없이 nuget.org에서 Json.NET을 다운로드할 수 있습니다.

다른 패키지 피드에 인증이 필요합니다. 몇 가지 방법으로 피드에 대한 액세스 권한을 인증할 수 있습니다. 예를 들어 일부 피드 종류에는 사용자 이름 및 암호가 필요합니다. 다른 피드에는 액세스 토큰이 필요합니다. 액세스 토큰은 일반적으로 사용자와 사용자가 액세스할 수 있는 리소스를 식별하는 일련의 긴 문자입니다. 액세스 토큰은 지정된 기간이 지나면 만료되도록 설정할 수 있습니다.

패키지의 버전을 지정하는 방법

버전 관리 체계는 사용하는 패키징 시스템에 따라 달라집니다.

예를 들어 NuGet 패키지에서는 유의적 버전 관리를 사용합니다.

유의적 버전 관리는 널리 사용되는 버전 관리 체계입니다. 형식은 다음과 같습니다.

Major.Minor.Patch[-Suffix]

각 매개 변수의 의미는 다음과 같습니다.

  • 새로운 버전에는 호환성이 손상되는 변경이 도입되었습니다. 일반적으로 앱은 패키지를 사용하여 새로운 주 버전에서 작업하는 방법을 업데이트해야 합니다.
  • 새로운 버전에는 새로운 기능이 도입되어 있지만, 이전 버전과 호환됩니다.
  • 새로운 패치에는 이전 버전과 호환되는 버그 수정이 도입되었지만, 새로운 기능을 제공하지는 않습니다.
  • -Suffix 파트는 선택적이며 패키지를 시험판 버전으로 식별합니다. 예를 들어 1.0.0-beta1은 패키지를 1.0.0 릴리스의 첫 번째 베타 시험판 빌드로 식별할 수 있습니다.

패키지를 참조할 때 버전 번호로 참조합니다.

다음은 PowerShell 및 특정 버전 번호를 사용하여 패키지를 설치하는 예시입니다.

Install-Package Newtonsoft.Json -Version 13.0.1

패키지가 변경되면 어떻게 되나요?

앱에서 패키지를 참조할 때는 대부분의 경우 사용할 패키지의 버전을 지정하거나 고정합니다.

많은 프레임워크에서는 설치할 패키지 버전의 허용 범위를 지정할 수 있습니다. 프레임워크에서는 부동 버전이라고 부르는 와일드카드를 지정할 수 있습니다.

예를 들어 NuGet에서 “1.0” 버전은 1.0보다 크거나 같은 첫 번째 버전을 의미합니다. “[1.0]”은 최신 버전이 아니라 버전 1.0만 설치하도록 지정합니다.

다음은 몇 가지 다른 예입니다.

이 표기법은 다음과 같습니다. Selects:
(1.0,) 1보다 큰 첫 번째 버전
[1.0,2.0] 1.0보다 크거나 같고 2.0보다 작거나 같은 첫 번째 버전
(1.0,2.0) 1.0보다 크고 2.0보다 작은 첫 번째 버전
[1.0,2.0) 1.0보다 크거나 같고 2.0보다 작은 첫 번째 버전

각 유지 관리자가 새 패키지 버전을 릴리스할 때 변경된 항목을 평가하고 해당 버전에 대해 앱을 테스트할 수 있습니다. 준비가 끝나면 구성에서 패키지의 버전 번호를 업데이트하고 변경 내용을 빌드 파이프라인에 제출할 수 있습니다.

다음은 C# 애플리케이션의 프로젝트(.csproj) 파일에 Newtonsoft.Json 패키지를 포함하는 방법의 예입니다. 이 예에서는 해당 패키지의 버전 13.0.1을 지정합니다.

<ItemGroup>
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

지식 점검

1.

패키지란?

2.

공개적으로 공유하려는 패키지를 빌드했다고 가정합니다. 이 작업을 수행하는 가장 쉬운 방법은 무엇인가요?