PCL(이식 가능한 클래스 라이브러리)

PCL(이식 가능한 클래스 라이브러리)은 최신 버전의 Visual Studio에서 더 이상 사용되지 않는 것으로 간주됩니다. 여전히 PCL을 열고 편집하고 컴파일할 수 있지만 새 프로젝트의 경우 .NET Standard 라이브러리를 사용하여 더 큰 API 노출 영역에 액세스하는 것이 좋습니다.

플랫폼 간 애플리케이션을 빌드하는 핵심 구성 요소는 다양한 플랫폼별 프로젝트에서 코드를 공유할 수 있다는 것입니다. 그러나 다른 플랫폼이 종종 다른 BCL(기본 클래스 라이브러리) 하위 집합을 사용하므로 실제로 다른 .NET Core 라이브러리 프로필에 빌드되므로 이 문제는 복잡합니다. 즉, 각 플랫폼은 동일한 프로필을 대상으로 하는 클래스 라이브러리만 사용할 수 있으므로 각 플랫폼에 대해 별도의 클래스 라이브러리 프로젝트가 필요한 것처럼 보입니다.

이 문제를 해결하는 코드 공유에는 .NET Standard 프로젝트, 공유 자산 프로젝트PCL(이식 가능한 클래스 라이브러리) 프로젝트의 세 가지 주요 방법이 있습니다.

  • .NET Standard 프로젝트는 .NET 코드를 공유하기 위한 기본 방법입니다. .NET Standard 프로젝트 및 Xamarin에 대해 자세히 알아보세요.
  • 공유 자산 프로젝트는 단일 파일 집합을 사용하며 솔루션 내에서 코드를 공유하는 빠르고 간단한 방법을 제공하며 일반적으로 조건부 컴파일 지시문을 사용하여 사용할 다양한 플랫폼에 대한 코드 경로를 지정합니다(자세한 내용은 공유 프로젝트 문서 참조).
  • PCL 프로젝트는 알려진 BCL 클래스/기능 집합을 지원하는 특정 프로필을 대상으로 합니다. 그러나 PCL의 단점은 프로필 특정 코드를 자체 라이브러리로 분리하기 위해 추가적인 아키텍처 노력이 필요하다는 것입니다.

이 페이지에서는 특정 프로필을 대상으로 하는 PCL 프로젝트를 만든 다음, 여러 플랫폼별 프로젝트에서 참조할 수 있는 방법을 설명합니다.

이식 가능한 클래스 라이브러리란?

애플리케이션 프로젝트 또는 라이브러리 프로젝트를 만들 때 결과 DLL은 생성되는 특정 플랫폼에서 작업하도록 제한됩니다. 이렇게 하면 Windows 앱에 대한 어셈블리를 작성한 다음 Xamarin.iOS 및 Xamarin.Android에서 다시 사용할 수 없습니다.

그러나 이식 가능한 클래스 라이브러리를 만들 때 코드를 실행할 플랫폼 조합을 선택할 수 있습니다. 이식 가능한 클래스 라이브러리를 만들 때 선택하는 호환성은 라이브러리가 지원하는 플랫폼을 설명하는 "프로필" 식별자로 변환됩니다.

아래 표에서는 .NET 플랫폼에 따라 달라지는 몇 가지 기능을 보여줍니다. 특정 디바이스/플랫폼에서 실행되도록 보장되는 PCL 어셈블리를 작성하려면 프로젝트를 만들 때 필요한 지원을 선택하기만 하면 됩니다.

기능 .NET Framework UWP 앱 Silverlight Windows Phone Xamarin
핵심 Y Y Y Y Y
LINQ Y Y Y Y Y
IQueryable Y Y Y 7.5+ Y
직렬화 Y Y Y Y Y
데이터 주석 4.0.3 + Y Y Y

Xamarin 열은 Xamarin.iOS 및 Xamarin.Android가 Visual Studio와 함께 제공되는 모든 프로필을 지원한다는 사실을 반영하며, 사용자가 만든 라이브러리의 기능 가용성은 지원하도록 선택한 다른 플랫폼에 의해서만 제한됩니다.

여기에는 다음의 조합인 프로필이 포함됩니다.

  • .NET 4 또는 .NET 4.5
  • Silverlight 5
  • Windows Phone 8
  • UWP 앱

Microsoft 웹 사이트에서 다양한 프로필의 기능에 대해 자세히 알아보고 지원되는 프레임워크 정보 및 기타 메모를 포함하는 다른 커뮤니티 멤버의 PCL 프로필 요약을 볼 수 있습니다.

혜택

  1. 중앙 집중식 코드 공유 – 다른 라이브러리 또는 애플리케이션에서 사용할 수 있는 단일 프로젝트에서 코드를 작성하고 테스트합니다.
  2. 리팩터링 작업은 솔루션에 로드된 모든 코드(이식 가능한 클래스 라이브러리 및 플랫폼별 프로젝트)에 영향을 줍니다.
  3. PCL 프로젝트를 솔루션의 다른 프로젝트에서 쉽게 참조하거나 다른 사용자가 솔루션에서 참조할 수 있도록 출력 어셈블리를 공유할 수 있습니다.

단점

  1. 동일한 이식 가능한 클래스 라이브러리가 여러 애플리케이션 간에 공유되므로 플랫폼별 라이브러리를 참조할 수 없습니다(예: Community.CsharpSqlite.WP7).
  2. 이식 가능한 클래스 라이브러리 하위 집합에는 Android용 MonoTouch 및 Mono(예: DllImport 또는 System.IO.File)에서 사용할 수 있는 클래스가 포함되지 않을 수 있습니다.

참고 항목

이식 가능한 클래스 라이브러리는 최신 버전의 Visual Studio에서 사용되지 않으며 대신 .NET 표준 라이브러리 를 사용하는 것이 좋습니다.

어느 정도는 공급자 패턴 또는 종속성 주입을 사용하여 이식 가능한 클래스 라이브러리에 정의된 인터페이스 또는 기본 클래스에 대해 플랫폼 프로젝트의 실제 구현을 코딩하는 두 가지 단점을 피할 수 있습니다.

이 다이어그램은 이식 가능한 클래스 라이브러리를 사용하여 코드를 공유하는 플랫폼 간 애플리케이션의 아키텍처를 보여 주지만 종속성 주입을 사용하여 플랫폼 종속 기능을 전달합니다.

This diagram shows the architecture of a cross-platform application using a Portable Class Library to share code, but also using Dependency Injection to pass in platform-dependent features

Mac용 Visual Studio 연습

이 섹션에서는 Mac용 Visual Studio 사용하여 이식 가능한 클래스 라이브러리를 만들고 사용하는 방법을 안내합니다. 전체 구현은 PCL 예제 섹션을 참조하세요.

PCL 만들기

솔루션에 이식 가능한 클래스 라이브러리를 추가하는 것은 일반 라이브러리 프로젝트를 추가하는 것과 매우 유사합니다.

  1. 새 프로젝트 대화 상자에서 다중 플랫폼 > 라이브러리 이식 가능한 라이브러리> 옵션을 선택합니다.

    Create a new PCL project

  2. PCL이 Mac용 Visual Studio 만들어지면 Xamarin.iOS 및 Xamarin.Android에 대해 작동하는 프로필로 자동으로 구성됩니다. PCL 프로젝트는 다음 스크린샷과 같이 표시됩니다.

    PCL project in the solution pad

이제 PCL에서 코드를 추가할 준비가 되었습니다. 다른 프로젝트(애플리케이션 프로젝트, 라이브러리 프로젝트 및 기타 PCL 프로젝트)에서도 참조할 수 있습니다.

PCL 설정 편집

이 프로젝트의 PCL 설정을 보고 변경하려면 프로젝트를 마우스 오른쪽 단추로 클릭하고 옵션 > 빌드 > 일반을 선택하여 여기에 표시된 화면을 확인합니다.

PCL Project Options to set the profile

변경...을 클릭하여 이 이식 가능한 클래스 라이브러리의 대상 프로필을 변경합니다.

코드가 PCL에 이미 추가된 후 프로필이 변경된 경우 코드가 새로 선택한 프로필의 일부가 아닌 기능을 참조하는 경우 라이브러리가 더 이상 컴파일되지 않을 수 있습니다.

PCL 작업

코드가 PCL 라이브러리에 기록되면 Mac용 Visual Studio 편집기에서 선택한 프로필의 제한 사항을 인식하고 그에 따라 자동 완성 옵션을 조정합니다. 예를 들어 이 스크린샷은 Mac용 Visual Studio 사용되는 기본 프로필(Profile136)을 사용하는 System.IO 대한 자동 완성 옵션을 보여 줍니다. 사용 가능한 클래스의 절반 정도가 표시되는 스크롤 막대를 확인합니다(실제로 사용 가능한 클래스는 14개만 있음).

Intellisense list of 14 classes in the System.IO class of a PCL

Xamarin.iOS 또는 Xamarin.Android 프로젝트의 System.IO 자동 완성과 비교합니다. 일반적으로 사용되는 클래스와 PCL FileDirectory 프로필에 없는 클래스를 포함하여 40개의 클래스를 사용할 수 있습니다.

Intellisense list of 40 classes in .NET Framework System.IO namespace

이는 PCL 사용의 기본 장단성을 반영합니다. 여러 플랫폼에서 코드를 원활하게 공유하는 기능은 가능한 모든 플랫폼에서 비슷한 구현이 없기 때문에 특정 API를 사용할 수 없음을 의미합니다.

PCL 사용

PCL 프로젝트가 만들어지면 일반적으로 참조를 추가하는 것과 동일한 방식으로 호환되는 애플리케이션 또는 라이브러리 프로젝트에서 참조를 추가할 수 있습니다. Mac용 Visual Studio 참조 노드를 마우스 오른쪽 단추로 클릭하고 참조 편집을 선택한 다음 다음과 같이 프로젝트 탭으로 전환합니다.

Add a reference to a PCL via Edit References option

다음 스크린샷은 아래의 PCL 라이브러리와 Xamarin.iOS 프로젝트의 해당 PCL 라이브러리에 대한 참조를 보여 주는 TaskyPortable 샘플 앱의 솔루션 패드를 보여줍니다.

TaskyPortable sample solution showing PCL project

PCL의 출력(즉, 결과 어셈블리 DLL)을 대부분의 프로젝트에 대한 참조로 추가할 수도 있습니다. 따라서 PCL은 플랫폼 간 구성 요소 및 라이브러리를 배송하는 이상적인 방법입니다.

PCL 예제

TaskyPortable 샘플 애플리케이션은 이식 가능한 클래스 라이브러리를 Xamarin과 함께 사용하는 방법을 보여 줍니다. iOS 및 Android에서 실행되는 결과 앱의 몇 가지 스크린샷은 다음과 같습니다.

Here are some screenshots of the resulting apps running on iOS, Android and Windows Phone

순수하게 이식 가능한 코드인 여러 데이터 및 논리 클래스를 공유하며 SQLite 데이터베이스 구현에 종속성 주입을 사용하여 플랫폼별 요구 사항을 통합하는 방법도 보여 줍니다.

솔루션 구조는 아래와 같습니다(각각 Mac용 Visual Studio 및 Visual Studio에서).

The solution structure is shown here in Visual Studio for Mac and Visual Studio respectively

SQLite-NET 코드에는 데모용으로 플랫폼별 조각(각 운영 체제의 SQLite 구현과 함께 작동)이 있으므로 이식 가능한 클래스 라이브러리로 컴파일할 수 있는 추상 클래스 및 iOS 및 Android 프로젝트에서 하위 클래스로 구현된 실제 코드로 리팩터링되었습니다.

TaskyPortableLibrary

이식 가능한 클래스 라이브러리는 지원할 수 있는 .NET 기능으로 제한됩니다. 여러 플랫폼에서 실행되도록 컴파일되므로 SQLite-NET에서 사용되는 기능을 사용할 [DllImport] 수 없습니다. 대신 SQLite-NET은 추상 클래스로 구현된 다음 나머지 공유 코드를 통해 참조됩니다. 추상 API의 추출은 다음과 같습니다.

public abstract class SQLiteConnection : IDisposable {

    public string DatabasePath { get; private set; }
    public bool TimeExecution { get; set; }
    public bool Trace { get; set; }
    public SQLiteConnection(string databasePath) {
         DatabasePath = databasePath;
    }
    public abstract int CreateTable<T>();
    public abstract SQLiteCommand CreateCommand(string cmdText, params object[] ps);
    public abstract int Execute(string query, params object[] args);
    public abstract List<T> Query<T>(string query, params object[] args) where T : new();
    public abstract TableQuery<T> Table<T>() where T : new();
    public abstract T Get<T>(object pk) where T : new();
    public bool IsInTransaction { get; protected set; }
    public abstract void BeginTransaction();
    public abstract void Rollback();
    public abstract void Commit();
    public abstract void RunInTransaction(Action action);
    public abstract int Insert(object obj);
    public abstract int Update(object obj);
    public abstract int Delete<T>(T obj);

    public void Dispose()
    {
        Close();
    }
    public abstract void Close();

}

공유 코드의 re기본der는 추상 클래스를 사용하여 데이터베이스에서 개체를 "저장"하고 "검색"합니다. 이 추상 클래스를 사용하는 모든 애플리케이션에서는 실제 데이터베이스 기능을 제공하는 완전한 구현을 전달해야 합니다.

TaskyAndroid 및 TaskyiOS

iOS 및 Android 애플리케이션 프로젝트에는 PCL에서 공유 코드를 연결하는 데 사용되는 사용자 인터페이스 및 기타 플랫폼별 코드가 포함되어 있습니다.

이러한 프로젝트에는 해당 플랫폼에서 작동하는 추상 데이터베이스 API의 구현도 포함됩니다. iOS 및 Android에서 Sqlite 데이터베이스 엔진은 운영 체제에 기본 제공되므로 구현은 표시된 대로 데이터베이스 연결의 구체적인 구현을 제공하는 데 사용할 [DllImport] 수 있습니다. 플랫폼별 구현 코드의 발췌 내용은 다음과 같습니다.

[DllImport("sqlite3", EntryPoint = "sqlite3_open")]
public static extern Result Open(string filename, out IntPtr db);

[DllImport("sqlite3", EntryPoint = "sqlite3_close")]
public static extern Result Close(IntPtr db);

전체 구현은 샘플 코드에서 볼 수 있습니다.

요약

이 문서에서는 이식 가능한 클래스 라이브러리의 이점과 단점에 대해 간략하게 설명하고, Mac용 Visual Studio 및 Visual Studio 내부에서 PCL을 만들고 사용하는 방법을 설명했으며, 마지막으로 PCL이 작동하는 전체 샘플 애플리케이션인 TaskyPortable을 소개했습니다.