라이선스 설정

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

라이선스가 없으면 Doconut은 여전히 문서를 렌더링하지만, 모든 페이지에 평가용 워터마크가 표시됩니다. 이 페이지에서는 라이선스를 제공하는 네 가지 방법과 여러 방법이 동시에 설정될 경우 적용되는 정확한 우선순위를 설명합니다.

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

네 가지가 있습니다: 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
// 데이터베이스, 환경 변수 또는 비밀 관리자에서 가져온 라이선스 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();

The probe folders, in order, and the filenames looked for in each:

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-plugin license, alongside the base license

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

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

프로세스가 프로젝트 폴더에서 실행되지 않을 때(게시된 앱, 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을 발생시킵니다서명, 도메인, 버전 윈도우, 블랙리스트, 또는 플러그인 런타임 게이트가 라이선스를 거부했습니다예외/거부 메시지를 읽되 신뢰할 수 없는 클라이언트에 노출하지 마십시오

다음 단계

  • 라이선스 — 기능, 라이선스 등급, 런타임에 로드된 내용 확인.
  • 문제 해결 — 워터마크, 거부된 라이선스, 기능 오류.

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