라이선스 설정

Doconut이 라이선스 파일을 찾는 위치

라이선스가 없더라도 Doconut은 문서를 렌더링합니다 — 각 페이지에 평가 워터마크가 표시됩니다. 이 페이지에서는 라이선스를 제공하는 네 가지 방법과 여러 방법이 설정된 경우 정확한 우선순위를 설명합니다.

라이선스는 한 번, AddDoconut() 동안 로드됩니다. 이는 이전 .NET Standard 라이브러리와 달리, 라이선스를 Viewer 인스턴스에 전달하거나 정적 Viewer.DoconutLicense(...) / Viewer.SetLicensePlugin(...) 호출을 통해 설정하던 방식과 다릅니다. 이러한 메서드는 이번 릴리스에서 시작 메커니즘이 아니므로 — 마이그레이션 가이드를 참조하십시오.

라이선스를 제공하는 네 가지 방법

네 가지가 있습니다: DoconutOptions 에서 제공되는 세 가지 명시적 소스 — 스트림, 원시 내용, 또는 파일 경로 —와 아무 것도 설정되지 않았을 때의 자동 검색이 있습니다. 여러 개가 설정된 경우, 우선순위는 정확히 다음과 같습니다:

LicenseStream > LicenseContent > LicensePath > 자동 검색

경로별

LicensePath 은(는) File.Exists 에 그대로 전달됩니다. 상대 경로는 프로세스의 현재 작업 디렉터리를 기준으로 해석되며 — 프로젝트 폴더가 아니고, Program.cs 가 위치한 폴더도 아닙니다. 경로가 해석되지 않으면 Doconut은 예외를 발생시키지 않으며 자동 검색으로 되돌아가지 않습니다 — 단순히 라이선스를 로드하지 않고 뷰어에 워터마크가 표시됩니다. 자동 검색은 LicensePath, LicenseContent, 또는 LicenseStream 중 어느 것도 설정되지 않았을 때만 실행됩니다. 동일 폴더(Doconut.Viewer.<Capability>.lic)에 있는 플러그인별 라이선스 파일도 함께 읽히므로, 플러그인 라이선스가 기본 라이선스와 나란히 있을 때 LicensePath 와 AddPlugin<...>() 가 함께 작동합니다.

절대 경로를 선호하십시오 (예: IWebHostEnvironment.WebRootPath 또는 AppContext.BaseDirectory 로 구성된 경우). 또는 LicensePath 를 완전히 생략하고 아래의 자동 검색에 의존할 수 있습니다.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
});

스트림별

LicenseStream 은(는) 시작 시 한 번 읽혀집니다 — 라이선스가 디스크 파일이 아닌 비밀 저장소에서 제공될 때 유용합니다.

csharp
// 우선순위: LicenseStream > LicenseContent > LicensePath > 자동 검색.
builder.Services.AddDoconut(options =>
{
    options.LicenseStream = licenseStream;
});

내용별

LicenseContent 은(는) 라이선스 텍스트 자체를 받아들입니다 — 환경 변수, 데이터베이스, 또는 비밀 관리자로부터 제공될 수 있습니다:

csharp
// 데이터베이스, 환경 변수 또는 비밀 관리자에서 가져온 License XML —
// 디스크에 파일이 없습니다. LicenseStream에만 능가됩니다.
builder.Services.AddDoconut(options =>
{
    options.LicenseContent = Environment.GetEnvironmentVariable("DOCONUT_LICENSE") ?? "";
});

자동 검색

세 가지 명시적 소스를 모두 설정하지 않으면, Doconut이 스스로 라이선스를 검색합니다:

csharp
// 아무 것도 구성하지 않으며, Doconut이 라이선스를 자체적으로 검색합니다. 이 두 폴더에서만:
//   1. {CurrentDirectory}/wwwroot
//   2. {AppContext.BaseDirectory}/wwwroot   (빌드 출력 폴더 안의 wwwroot)
// 먼저 Doconut.lic을 찾고, 다음으로 Doconut.Viewer.lic을 찾으며, 각 기능별 파일도 포함합니다.
// Doconut.Viewer.<Capability>.lic 파일을 함께 찾습니다.
builder.Services.AddDoconut();

탐색 폴더는 순서대로이며, 각 폴더에서 찾는 파일 이름은 다음과 같습니다:

text
1. {CurrentDirectory}/wwwroot
2. {AppContext.BaseDirectory}/wwwroot

Filenames (checked in each folder above, in order):
  Doconut.lic                          — base viewer license (checked first)
  Doconut.Viewer.lic                   — base viewer license
  Doconut.Viewer.<Capability>.lic      — per-capability license, alongside the base license

wwwroot 폴더 외부의 파일은 읽지 않습니다: 출력 폴더 자체에 있는 .lic 이나 wwwroot/lib 에 있는 파일은 무시됩니다.

이전에 Viewer 생성자에 라이선스 경로의 List<string> 를 전달한 경우(기능당 하나씩) — 해당 보조 파일들을 Doconut.Viewer.lic 옆에 두고 자동 검색이 이를 찾아가도록 하십시오. DoconutOptions 에는 경로 목록 옵션이 없습니다.

라이선스를 출력 폴더에 복사하기

프로세스가 프로젝트 폴더에서 실행되지 않을 때 — 배포된 앱, IIS, 컨테이너, 테스트 러너 등 — 첫 번째 탐색이 실패하고 두 번째 탐색인 {AppContext.BaseDirectory}/wwwroot이 파일을 찾아야 합니다. SDK 자체 테스트 앱은 매 빌드마다 이 MSBuild 대상으로 라이선스를 해당 위치에 복사합니다:

xml
<Target Name="CopyLicensesToOutput" AfterTargets="Build">
  <ItemGroup>
    <DoconutLicenseFiles Include="$(MSBuildProjectDirectory)\wwwroot\*.lic" />
    <StaleOutputLicenses Include="$(OutDir)wwwroot\*.lic" />
  </ItemGroup>
  <!-- 먼저 삭제하면 wwwroot의 .lic 파일을 이름 바꾸거나 제거할 때도 출력에서 제외됩니다. -->
  <Delete Files="@(StaleOutputLicenses)" />
  <Copy SourceFiles="@(DoconutLicenseFiles)" DestinationFolder="$(OutDir)wwwroot" />
</Target>

대상은 반드시 $(OutDir)wwwroot이어야 합니다: 출력 루트에 복사된 .lic은 자동 검색으로 절대 찾을 수 없습니다. 이 페이지의 LicensePath 예제들은 동일한 위치를 가리킵니다.

소스 제어에 .lic 파일을 포함하지 마세요 — 앱과 함께 배포하거나 비밀 저장소에서 LicenseContent 또는 LicenseStream을 통해 라이선스를 주입하세요.

라이선스가 없을 때 발생하는 일

라이선스가 없다고 예외가 발생하지 않습니다. AddDoconut()이 성공하고, 앱이 시작되며, 뷰어가 실행됩니다 — 하지만 모든 페이지에 평가 워터마크가 표시되고 선택적 기능이 부여되지 않습니다.

찾았지만 거부된 라이선스 파일은 다릅니다. 잘못된 서명, 변조, 블랙리스트, 혹은 라이선스 버전 창을 벗어난 빌드가 OpenDocumentAsync이 LicenseException을 License.RejectionMessage와 함께 발생하게 합니다. 거부 메시지가 없는 캘린더 만료 라이선스는 워터마크 모드로 계속 동작합니다.

플러그인에는 기능이 필요합니다

해당 권한이 없는 플러그인을 등록하는 것은 다릅니다: 라이선스가 없거나, 레거시 TRIAL 파일이 있거나, 해당 기능이 없는 유료 라이선스인 경우, AddDoconut()이 InvalidOperationException을 발생시켜 앱이 시작되지 않습니다. 예를 들어, Converter을 부여하는 라이선스 없이 Converter 플러그인을 등록하는 경우:

text
InvalidOperationException: The Converter plugin is registered via AddPlugin but no active
license grants Converter. Remove the AddPlugin<...>() call or install a license (or
trial/demo) that includes Converter.

메시지는 해결 방법을 직접 알려줍니다: 해당 플러그인에 대한 options.AddPlugin<...>() 호출을 제거하거나, 기능을 부여하는 유료 라이선스 또는 활성 임시/데모(NFR) 라이선스를 설치하십시오. 임시 등록은 만료 날짜가 지나도 유지될 수 있어, 이미 구성된 앱이 재시작 중에 충돌하는 대신 런타임에 기능이 감소하도록 합니다; 만료되면 해당 기능은 여전히 취소됩니다.

로드된 라이선스 확인

IDoconutLicenseService을 사용하여 SDK가 사용하는 동일한 진실 소스로 인증된 진단 엔드포인트를 노출하거나 기능 플래그를 제어하십시오. 라이선스 내용이나 키를 반환하지 마세요.

csharp
app.MapGet("/api/doconut/license", (IDoconutLicenseService license) => Results.Ok(new
{
    viewer = license.IsViewerLicensed || license.IsTemporary,
    temporary = license.IsTemporary,
    search = license.IsCapabilityGranted(LicenseCapability.Search),
    annotation = license.IsCapabilityGranted(LicenseCapability.Annotation),
    converter = license.HasConverter,
    dicom = license.HasDicom
}));

라이선스는 AddDoconut() 등록 중에 읽혀집니다. ResetLicense은 현재 활성 재로드 경로가 없는 호환성 속성으로, 라이선스 파일을 교체하려면 애플리케이션을 재시작해야 합니다.

문제 해결 매트릭스

증상가능한 원인확인
뷰어는 작동하지만 모든 페이지에 워터마크가 표시됩니다라이선스가 로드되지 않았거나, 라이선스가 캘린더 만료되었습니다IDoconutLicenseService을 해결하고; 출력 디렉터리와 프로세스 작업 디렉터리를 확인하세요
AddDoconut()이 플러그인에 대해 예외를 발생시킵니다라이선스가 해당 플러그인 기능을 부여하지 않습니다IsCapabilityGranted(...)을 확인하고 구매하지 않은 등록을 제거하세요
구성된 상대 경로가 로컬에서는 작동하지만 IIS/컨테이너에서는 작동하지 않습니다프로세스 작업 디렉터리가 변경되었습니다AppContext.BaseDirectory 또는 절대 경로를 사용하세요
교체된 .lic 파일이 영향을 주지 않습니다싱글톤 라이선스 서비스가 이미 생성되었습니다애플리케이션을 재시작하세요
OpenDocumentAsync이 LicenseException을 발생시킵니다서명, 도메인, 버전 창, 블랙리스트, 혹은 플러그인 런타임 게이트가 라이선스를 거부했습니다신뢰할 수 없는 클라이언트에 노출하지 않고 예외/거부 메시지를 읽으세요
기능별 라이선스가 이전에는 작동했지만 현재는 작동하지 않습니다이전 코드가 명시적인 라이선스 경로를 Viewer 생성자에 전달했습니다동반 .lic 파일을 Doconut.Viewer.lic 옆으로 이동하고 자동 검색이 로드하도록 하세요

다음 단계

  • 라이선스 — 기능, 라이선스 티어, 그리고 런타임에 로드된 것을 확인합니다.
  • 문제 해결 — 워터마크, 거부된 라이선스, 그리고 기능 오류.

이 페이지가 도움이 되었나요?