Viewer가 작동하는 방식

문서 요청 라이프사이클

Doconut는 ASP.NET Core 미들웨어를 통해 페이지 이미지로 문서를 렌더링합니다. 라이프사이클(열기, 토큰, 페이지 요청, 닫기)을 이해하면 오류 메시지를 포함해 관찰하게 되는 거의 모든 동작을 설명할 수 있습니다.

세 가지 구성 요소

  • Viewer — 주입하는 공개 서비스입니다. 문서를 열고 세션 토큰을 반환합니다.
  • 문서 세션 — 로드된 문서를 보관하는 서버 측 객체이며, IMemoryCache에 토큰을 키로 저장합니다.
  • Doconut 미들웨어 — UseDoconut()에 의해 추가되며, 브라우저 위젯이 만드는 모든 요청(pages, thumbnails, search, annotations 등)에 응답하고, 항상 토큰으로 인증됩니다.

Viewer는 무상태입니다 — 설계상

Viewer는 봉인된 클래스이며, 요청당 문서 상태를 보관하지 않고, 의도적으로 IDisposable을 구현하지 않습니다. 세션은 세션 관리자에서 독립적으로 존재하며, 캐시 만료 또는 명시적인 CloseDocument(token)에 의해 정리됩니다.

이제 직접 생성할 필요가 없습니다. AddDoconut()가 일시적인 서비스로 등록하므로, 필요할 때마다 주입해서 사용합니다:

csharp
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
    var token = await viewer.OpenDocumentAsync($"files/{fileName}");
    return Results.Content(token, "text/plain");
});

MVC 애플리케이션에서는 생성자 매개변수로 받아 사용하고, Razor 뷰에서는 @inject Doconut.Viewer Viewer를 사용합니다. Viewer 인스턴스에 대한 애플리케이션 전용 캐시는 더 이상 필요하지 않으며, 캐시할 가치가 없기 때문에 올바르지도 않습니다.

OpenDocumentAsync 내부에서 일어나는 일

  1. 라이선스 게이트. 거부되었거나 버전이 만료된 라이선스(블랙리스트에 등재되었거나 변조되었거나 라이선스 업데이트 기간 외에 빌드된 경우)는 즉시 LicenseException을 발생시키며, 거부 사유를 메시지로 전달합니다 — 유효하지 않은(부재한 것이 아니라) 라이선스에 대해서는 열기가 조용히 저하되지 않습니다. 캘린더가 만료된 Temporary 또는 구독 라이선스는 예외이며, 예외를 발생시키지 않고 워터마크로 저하됩니다.
  2. 세션 생성. 뷰어 팩토리는 파일 확장자에 맞는 포맷 뷰어를 선택하고 문서를 로드합니다(렌더링 파이프라인 참조). 세션은 새 GUID 토큰과 함께 IMemoryCache에 슬라이딩 만료(DocOptions.TimeOut 분, 기본값 60)로 저장됩니다. 각 페이지 요청마다 타이머가 리셋됩니다.
  3. 보안 등록. UnsafeMode = false(기본값)인 경우, 토큰은 호출자의 ASP.NET 세션에 바인딩됩니다: secure-{token} 마커가 세션에 기록되어, 문서를 연 브라우저 세션만이 페이지를 요청할 수 있습니다.
  4. 토큰이 반환됩니다. 토큰은 이후 모든 작업에 사용되는 단일 자격 증명입니다.

별도의 워밍업 단계는 없습니다. 이전 라이브러리에서는 InitCache()를 제공했지만, 이제는 존재하지 않으며 대체되는 기능도 없습니다.

세 가지 오버로드는 입력만 다릅니다: 파일 경로, 파일 경로와 포맷별 설정(PdfConfig, WordConfig 등), 혹은 확장자를 기반으로 포맷을 감지하는 Stream과 FileInfo.

위젯이 페이지를 가져오는 방법

클라이언트 위젯은 쿼리 문자열에 토큰을 포함하여 Doconut 미들웨어를 호출합니다. 미들웨어가 수행하는 작업은 요청에 따라 달라집니다:

쿼리목적
?token=…&page=N렌더링된 페이지 이미지(PNG)
?token=…&page=N&thumb=1썸네일
?token=…&zoom=…확대된 페이지 렌더링
?token=…&search=term전체 텍스트 검색(라이선스 제한)
?token=…&bookmarks문서 개요/북마크
?token=…&copy / &showlinks / &fileFormat텍스트 복사, 하이퍼링크 및 포맷 정보
?token=…&metaDICOM 기술 메타데이터; 이 패키지의 DICOM 세션에 대해 501 반환
?token=…&action=rotate/flip/close페이지 동작 및 명시적 닫기
?token=…&AnnSave=… / &AnnLoad주석 저장/로드

각 경로는 먼저 검증됩니다:

  • 토큰 없음 → 미들웨어가 404를 반환합니다(ShowDoconutInfo = true인 경우 버전 배너 표시).
  • 알 수 없거나 만료된 토큰 → 문서 세션을 찾을 수 없습니다. 문서를 다시 열어 주세요. 오류 이미지가 반환됩니다.
  • 세션 미들웨어 누락(UnsafeMode = false인 경우) → 세션 미들웨어가 구성되지 않았습니다. UseDoconut() 전에 UseSession()을 호출하십시오.와 함께 HTTP 500 반환.
  • 다른 브라우저 세션에서 토큰이 열림 → 이 페이지를 볼 권한이 없습니다. 오류 이미지가 반환됩니다.

미들웨어가 마운트되는 위치

UseDoconut()는 토큰을 포함한 모든 요청에 응답하며, 마운트 위치에 관계없이 동작합니다. 레퍼런스 애플리케이션은 MapWhen 분기에서 기존 DocImage.axd 요청 형태를 유지하므로 기존 클라이언트는 언제나 그 URL을 호출합니다. 어떤 방식을 선택하든 클라이언트의 BasePath가 일치해야 합니다 — Viewer 구성 참고.

페이지를 열기 노드가 아닌 공유 스토리지에서 제공하는 것은 완전히 다른 구성이며, 분산 배포를 참고하십시오.

문서 닫기

csharp
viewer.CloseDocument(token);

CloseDocument는 캐시에서 세션을 제거하고(기본 문서 엔진을 해제하고 메모리를 즉시 해제), secure-{token} 마커를 삭제하며, 접근 권한을 취소합니다. 호출은 선택 사항이며—슬라이딩 만료가 자동으로 동일한 정리를 수행하지만—대용량 문서의 경우 사용자가 작업을 마치는 즉시 메모리를 해제하는 정중한 방법입니다.

주입된 Viewer에서 호출합니다. 이전 방식인 using 블록에서 단명 Viewer를 생성해 토큰을 닫는 패턴은 이제 해당되지 않으며 필요하지 않습니다.

주요 요점

  • 하나의 열린 문서는 하나의 세션이며 하나의 토큰과 같습니다. 토큰은 브라우저 세션당 존재하며 전역 URL이 아닙니다.
  • 토큰은 슬라이딩 윈도우로 만료되며, DocOptions.TimeOut을 초과해 유휴 상태인 뷰어는 다시 열어야 합니다.
  • Viewer는 자유롭게 주입 및 공유할 수 있으며, 세션이 모든 상태를 보유합니다.

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