라이선스 설정

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

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

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

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

LicenseStream 가 LicenseContent 를, LicenseContent 가 LicensePath 를, LicensePath 가 auto-search 를 우선합니다.

경로별

LicensePath 은 File.Exists에 그대로 전달됩니다. 상대 경로는 프로세스의 current working directory를 기준으로 해석됩니다 — 프로젝트 폴더가 아니며, Program.cs 파일이 위치한 폴더도 아닙니다. 경로가 해석되지 않으면 Doconut은 예외를 발생시키지 않으며 auto-search 로 되돌아가지도 않습니다 — 단순히 라이선스를 로드하지 않아 뷰어에 워터마크가 표시됩니다. LicensePath, LicenseContent, LicenseStream 중 어느 것도 설정되지 않은 경우에만 auto-search 가 실행됩니다. 동일 폴더에 있는 플러그인별 라이선스 파일(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 > auto-search.
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();

검색 폴더 순서와 각 폴더에서 찾는 파일 이름은 다음과 같습니다:

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 파일은 auto-search 로는 절대 찾을 수 없습니다. 이 페이지의 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<...>() 호출을 제거하거나, 기능을 부여하는 유료 라이선스 또는 활성화된 Temporary/Demo(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는 현재 활성 재로드 경로가 없는 호환성 속성으로, 라이선스 파일을 교체하려면 애플리케이션을 재시작해야 합니다.

문제 해결 매트릭스

증상가능 원인확인 방법
Viewer가 작동하지만 모든 페이지에 워터마크가 표시됨라이선스가 로드되지 않았거나, 라이선스가 기간 만료됨IDoconutLicenseService를 해결하고, 출력 디렉터리와 프로세스 작업 디렉터리를 확인하십시오
AddDoconut()가 플러그인에서 예외 발생라이선스에 해당 플러그인 기능이 부여되지 않음IsCapabilityGranted(...)를 확인하고 구매하지 않은 등록을 제거하십시오
구성된 상대 경로가 로컬에서는 동작하지만 IIS/컨테이너에서는 동작하지 않음프로세스 작업 디렉터리가 변경됨AppContext.BaseDirectory 또는 절대 경로를 사용하십시오
교체한 .lic 파일이 효과가 없음싱글톤 라이선스 서비스가 이미 생성되어 있음애플리케이션을 재시작하십시오
OpenDocumentAsync가 LicenseException을 발생서명, 도메인, 버전 범위, 블랙리스트, 또는 플러그인 런타임 게이트가 라이선스를 거부함예외/거부 메시지를 읽되 신뢰할 수 없는 클라이언트에 노출하지 마십시오

다음 단계

  • Licensing — 기능, 라이선스 등급, 그리고 런타임에 로드된 내용을 확인하는 방법.
  • Troubleshooting — 워터마크, 거부된 라이선스, 그리고 기능 오류.

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