PDF 문서에서 주석을 지우는 방법 (.NET)

PDF에 검토자 의견, 강조 표시 및 마크업이 가득하면 문서를 읽기 어려워질 수 있습니다. 법률 브리프, 최종 연구 논문 또는 기업 보고서를 준비하든, 게시하거나 보관하기 전에 종종 주석을 지우기 해야 합니다. 이 튜토리얼에서는 GroupDocs.Annotation for .NET을 사용하여 PDF 파일에서 주석을 지우는 방법을 정확히 배우고, 이 라이브러리가 다른 대안보다 뛰어난 이유와 일반적인 함정을 처리하는 방법을 알아봅니다.

빠른 답변

  • PDF 주석을 모두 삭제하는 가장 빠른 방법은 무엇인가요? Call annotator.Save(outputPath, new SaveOptions { AnnotationTypes = AnnotationType.None }).
  • 시작하려면 라이선스가 필요합니까? 아니요 – 무료 체험판은 개발 및 소규모 테스트에 사용할 수 있습니다.
  • 지원되는 .NET 버전은 무엇인가요? .NET Framework 4.5+, .NET Core 3.1+, .NET 5/6/7.
  • 원본 파일을 변경하지 않고 유지할 수 있나요? 예 – API는 항상 새 깨끗한 파일을 작성하여 원본을 그대로 유지합니다.
  • GroupDocs.Annotation이 지원하는 파일 형식은 몇 개인가요? PDF, DOCX, XLSX, PPTX 및 이미지 형식을 포함하여 50개 이상의 입력 및 출력 형식을 지원합니다.

“주석을 지우는 방법”이란 무엇인가요?

주석을 지우는 방법은 PDF에서 모든 주석 객체를 프로그래밍 방식으로 제거하여 결과 파일에 원본 내용과 레이아웃만 포함하도록 하는 것을 의미합니다. 이 작업은 주석 레이어가 없는 새로운 PDF를 생성하여 페이지 순서, 글꼴 및 포함된 이미지를 보존합니다.

왜 .NET용 GroupDocs.Annotation을 사용해야 할까요?

GroupDocs.Annotation은 50개 이상의 파일 형식을 지원하며 전체 문서를 메모리에 로드하지 않고 200 MB까지의 PDF를 처리할 수 있어 멀티스레드 환경에서도 확장 가능한 메모리 효율적인 솔루션을 제공합니다. 일반 PDF 라이브러리와 비교할 때, 내장된 주석 유형 필터링, 배치 처리 및 정리 후 원본 레이아웃을 보존하는 99.9 % 정확도를 제공합니다.

필수 조건

  • GroupDocs.Annotation .NET 라이브러리 (v25.4.0 이상)
  • Visual Studio (모든 에디션) 또는 다른 .NET 호환 IDE
  • C# 구문 및 using 문에 대한 기본 지식
  • 하나 이상의 주석이 포함된 샘플 PDF (Adobe Acrobat, Foxit 또는 무료 Edge PDF 뷰어로 추가할 수 있음)

GroupDocs.Annotation 설정하기

설치 (쉬운 방법)

옵션 1: NuGet 패키지 관리자 콘솔

Install-Package GroupDocs.Annotation -Version 25.4.0

옵션 2: .NET CLI (명령줄을 선호하는 경우)

dotnet add package GroupDocs.Annotation --version 25.4.0

라이선스 질문 처리

프로덕션으로 전환할 때 무료 체험을 시작하고 영구 라이선스로 전환할 수 있습니다.

기본 설정 (첫 5줄)

Annotator 클래스는 메모리에 로드된 PDF 문서를 나타내는 진입점입니다. 주석을 읽고, 편집하고, 저장하는 메서드를 제공합니다.

using GroupDocs.Annotation;

string sourceDocumentPath = "YOUR_DOCUMENT_DIRECTORY/ANNOTATED";
using (Annotator annotator = new Annotator(sourceDocumentPath))
{
    // Your annotation removal magic happens here
}

팁: using 문은 Annotator 인스턴스를 자동으로 해제하여 파일 핸들을 해제하고 루프에서 많은 파일을 처리할 때 메모리 누수를 방지합니다.

GroupDocs.Annotation을 사용하여 PDF에서 모든 주석을 지우는 방법

SaveOptions 클래스는 문서 저장 방식을 사용자 정의할 수 있게 해 주며, 유지하거나 버릴 주석 유형을 지정합니다. AnnotationType은 Highlight, Comment, Strikeout 등 지원되는 모든 주석 카테고리를 나열하는 열거형입니다.

Annotator 클래스로 소스 PDF를 로드하고, SaveOptions를 구성하여 AnnotationTypes를 AnnotationType.None으로 설정한 뒤 annotator.Save(outputPath, saveOptions)를 호출합니다. 이 한 줄 작업은 전체 주석 레이어를 제거하고 원본 텍스트, 이미지 및 레이아웃을 보존하며, 소스 파일을 수정하지 않고 지정된 위치에 깨끗한 PDF를 작성합니다.

annotator.Save(resultFilePath, new SaveOptions { AnnotationTypes = AnnotationType.None });

주요 단계: 주석 제거 단계별 가이드

문제 이해

주석을 지우면 주석 객체가 포함되지 않은 새 PDF 버전이 생성됩니다. 이는 여러 가지 측정 가능한 효과를 가집니다:

  1. 파일 크기 감소 – 정리 후 일반적으로 5‑15 % 작아집니다.
  2. 무결성 보존 – 페이지 순서, 글꼴 및 이미지가 정확히 동일하게 유지됩니다.
  3. 메타데이터 제거 – 모든 주석 관련 메타데이터가 삭제됩니다.
  4. 원본에 영향 없음 – 소스 파일은 변경되지 않아 감사 추적에 필수적입니다.

1단계: 파일 경로 설정 (올바른 방법)

올바른 경로 처리는 가장 흔한 “파일을 찾을 수 없음” 오류를 방지합니다. Path.Combine은 OS에 구애받지 않는 경로를 생성하므로 동일한 코드가 Windows, macOS 및 Linux에서 작동합니다.

inputFilePath 변수는 주석이 달린 PDF의 위치를 보관하고, resultFilePath는 정리된 PDF가 저장될 위치를 가리킵니다.

using System.IO;

string documentDirectory = "YOUR_DOCUMENT_DIRECTORY";
string outputDirectory = "YOUR_OUTPUT_DIRECTORY";

// Define paths for source and result documents
string annotatedPdfPath = Path.Combine(documentDirectory, "ANNOTATED");
string resultFilePath = Path.Combine(outputDirectory, "result.pdf");

왜 Path.Combine을 사용하나요? 올바른 디렉터리 구분자(\ 또는 /)를 자동으로 삽입하고, 런타임 예외를 일으키는 이중 구분자 버그를 방지합니다.

2단계: 문서 로드

Annotator 클래스는 PDF를 파싱하고 주석 컬렉션을 노출하는 GroupDocs.Annotation의 핵심 객체입니다.

using GroupDocs.Annotation;
using GroupDocs.Annotation.Options;

using (Annotator annotator = new Annotator(annotatedPdfPath))
{
    // The next step happens here
}

내부 동작: Annotator를 인스턴스화하면 라이브러리가 파일을 스트리밍하고 각 주석의 메모리 내 표현을 구축하여 수정 준비를 합니다. 100 MB보다 큰 PDF의 경우 이 단계에 몇 초가 걸릴 수 있습니다.

3단계: 마법의 한 줄 (모든 주석 제거)

다음은 모든 주석을 지우고 깨끗한 파일을 작성하는 간결한 호출입니다:

annotator.Save(resultFilePath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
  • annotator.Save – 현재 상태를 기반으로 새 PDF 파일을 작성합니다.
  • new SaveOptions() – 저장 과정을 조정할 수 있으며, 기본값은 대부분의 시나리오에 적합합니다.
  • AnnotationTypes = AnnotationType.None – 엔진에 모든 주석 객체를 제외하도록 지시하는 핵심 플래그입니다.

대체 접근법 (특정 유형만 제거)

댓글은 유지하고 강조 표시만 제거하려면, 제외하려는 유형을 비트 OR 연산으로 결합한 AnnotationTypes 플래그를 조정합니다.

// Remove only highlights and text annotations, keep others
annotator.Save(resultFilePath, new SaveOptions() { 
    AnnotationTypes = AnnotationType.Highlight | AnnotationType.Text 
});

전체 작업 예제

모든 내용을 종합하면, 아래 메서드는 .NET 콘솔 또는 웹 프로젝트에 바로 삽입할 수 있는 전체 엔드‑투‑엔드 정리 루틴을 보여줍니다.

using System.IO;
using GroupDocs.Annotation;
using GroupDocs.Annotation.Options;

public void RemoveAllAnnotations()
{
    string documentDirectory = "YOUR_DOCUMENT_DIRECTORY";
    string outputDirectory = "YOUR_OUTPUT_DIRECTORY";
    
    string annotatedPdfPath = Path.Combine(documentDirectory, "ANNOTATED");
    string resultFilePath = Path.Combine(outputDirectory, "result.pdf");
    
    using (Annotator annotator = new Annotator(annotatedPdfPath))
    {
        annotator.Save(resultFilePath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
    }
    
    Console.WriteLine($"Clean document saved to: {resultFilePath}");
}

문제 해결: 오류가 발생했을 때

“File Not Found” 오류를 어떻게 해결하나요?

Annotator를 생성하기 전에 소스 PDF가 존재하는지 확인하십시오. 이렇게 하면 생성자가 예외를 발생시키는 것을 방지할 수 있습니다.

if (!File.Exists(annotatedPdfPath))
{
    throw new FileNotFoundException($"Source document not found: {annotatedPdfPath}");
}

“No Annotations Found” 결과를 어떻게 처리하나요?

먼저 주석 개수를 확인하십시오. 문서에 실제로 주석이 없으면 정리 단계에서 동일한 복사본이 생성됩니다.

using (Annotator annotator = new Annotator(annotatedPdfPath))
{
    var annotations = annotator.Get();
    Console.WriteLine($"Found {annotations.Count} annotations");
    
    if (annotations.Count == 0)
    {
        Console.WriteLine("No annotations to remove");
        return;
    }
    
    // Proceed with removal...
}

대용량 파일의 성능을 어떻게 향상시킬 수 있나요?

수백 개의 주석이 있는 150페이지 PDF를 처리하면 메모리를 많이 사용합니다. 배치 처리를 사용하거나 애플리케이션 메모리 제한을 늘리거나 비동기적으로 작업을 실행하십시오.

// For multiple files, process asynchronously
public async Task ProcessMultipleFiles(string[] filePaths)
{
    var tasks = filePaths.Select(async filePath => 
    {
        await Task.Run(() => RemoveAnnotationsFromFile(filePath));
    });
    
    await Task.WhenAll(tasks);
}

실제 적용 사례

법률 문서 준비

법률 사무소는 종종 여러 검토자 의견이 달린 계약서를 받습니다. 법원에 최종 사본을 제출하기 전에 모든 마크업을 제거하고 정확한 법적 문구와 페이지 순서를 보존해야 합니다.

팁: 규정 준수를 위해 원본 주석 버전을 보관하고, 제출할 때는 정리된 버전을 사용하십시오.

학술 출판

연구자들은 광범위한 동료 검토 메모가 포함된 초안을 교환합니다. 학술지는 깨끗한 원고를 요구하므로, 제출 전에 강조 표시, 댓글 및 스티키 노트를 자동으로 제거할 수 있습니다.

기업 보고서 최종화

임원 요약은 여러 검토 단계를 거칩니다. 이해관계자에게 제공되는 최종 PDF는 내부 댓글이 없어야 전문성을 유지할 수 있습니다.

콘텐츠 관리 시스템

문서 포털을 구축한다면 주석을 표시하는 “리뷰 모드”와 주석을 숨기는 “게시 모드”가 필요할 수 있습니다. 위 코드는 필요에 따라 정리된 복사본을 생성하여 원활한 전환을 가능하게 합니다.

고급 기술 및 최적화

선택적 주석 제거

때때로 특정 주석 유형(예: 강조 표시)만 삭제해야 할 때가 있습니다. AnnotationTypes 속성은 플래그 조합을 허용합니다.

// Remove only highlights and strikethrough, keep comments
var saveOptions = new SaveOptions() 
{ 
    AnnotationTypes = AnnotationType.Highlight | AnnotationType.Strikeout 
};

annotator.Save(resultFilePath, saveOptions);

다수 문서 배치 처리

폴더에 수십 개의 주석이 달린 PDF가 있는 경우, 각 파일을 순회하면서 동일한 정리 로직을 적용하고 결과를 로그에 기록합니다.

public void CleanAllDocumentsInFolder(string inputFolder, string outputFolder)
{
    var pdfFiles = Directory.GetFiles(inputFolder, "*.pdf");
    
    foreach (var file in pdfFiles)
    {
        var fileName = Path.GetFileName(file);
        var outputPath = Path.Combine(outputFolder, $"clean_{fileName}");
        
        using (var annotator = new Annotator(file))
        {
            annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
        }
        
        Console.WriteLine($"Processed: {fileName}");
    }
}

대용량 문서 메모리 최적화

200 MB보다 큰 PDF의 경우 메모리 사용량을 모니터링하고 각 파일 처리 후 GC.Collect()를 호출하여 관리되지 않는 리소스를 해제하십시오.

public void ProcessLargeDocument(string inputPath, string outputPath)
{
    GC.Collect(); // Clean up before starting
    
    using (var annotator = new Annotator(inputPath))
    {
        var initialMemory = GC.GetTotalMemory(false);
        
        annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
        
        var finalMemory = GC.GetTotalMemory(false);
        Console.WriteLine($"Memory used: {(finalMemory - initialMemory) / 1024 / 1024} MB");
    }
    
    GC.Collect(); // Clean up after processing
}

프로덕션 사용을 위한 모범 사례

견고한 오류 처리를 어떻게 구현하나요?

특정 예외를 잡고, 자세한 정보를 로그에 기록하며, 전체 배치를 중단하지 않고 다른 파일 처리를 계속합니다.

try
{
    using (var annotator = new Annotator(inputPath))
    {
        annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
    }
}
catch (FileNotFoundException ex)
{
    Console.WriteLine($"Input file not found: {ex.Message}");
    // Log the error, notify user, etc.
}
catch (UnauthorizedAccessException ex)
{
    Console.WriteLine($"Permission denied: {ex.Message}");
    // Handle permission issues
}
catch (Exception ex)
{
    Console.WriteLine($"Unexpected error: {ex.Message}");
    // Log full exception details
}

구성을 안전하게 관리하려면 어떻게 해야 하나요?

파일 경로, 라이선스 키 및 기타 설정을 하드코딩하지 말고 appsettings.json이나 환경 변수에 저장하십시오.

// In appsettings.json
{
    "DocumentSettings": {
        "InputDirectory": "C:\\Documents\\Input",
        "OutputDirectory": "C:\\Documents\\Output",
        "BackupOriginals": true
    }
}

// In your code
var config = Configuration.GetSection("DocumentSettings");
var inputDir = config["InputDirectory"];
var outputDir = config["OutputDirectory"];

로깅 및 모니터링을 어떻게 추가하나요?

ILogger 또는 서드파티 모니터링 서비스(예: Serilog, Application Insights)와 통합하여 처리 시간, 성공률 및 메모리 사용량을 캡처합니다.

public void RemoveAnnotationsWithLogging(string inputPath, string outputPath)
{
    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
    
    try
    {
        using (var annotator = new Annotator(inputPath))
        {
            var annotationCount = annotator.Get().Count;
            Console.WriteLine($"Processing {inputPath} - Found {annotationCount} annotations");
            
            annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
            
            stopwatch.Stop();
            Console.WriteLine($"Successfully processed in {stopwatch.ElapsedMilliseconds}ms");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Failed to process {inputPath}: {ex.Message}");
        throw;
    }
}

다음 단계

이제 PDF에서 주석을 지우는 작업을 안정적으로 수행할 수 있으므로, 워크플로를 다음과 같이 확장할 수 있습니다:

  • 주석이 포함된 버전과 정리된 버전을 모두 보관하는 자동 문서 검토 파이프라인 구축.
  • SharePoint 또는 기타 DMS 플랫폼과 통합하여 정리된 사본 정책을 적용.
  • 최종 사용자가 주석을 제거하기 전에 미리 볼 수 있는 UI 도구 제작.

두 줄 정리의 간단함과 GroupDocs.Annotation의 강력한 형식 지원이 결합되어, 깨끗한 문서 보관이 필요한 모든 기업에 이상적인 접근 방식이 됩니다.

자주 묻는 질문

Q: PDF 외의 파일 유형에서도 주석을 제거할 수 있나요?
A: 예. GroupDocs.Annotation은 Word, Excel, PowerPoint 및 이미지 형식도 지원하므로 입력 파일 확장자를 변경하면 동일한 API 호출을 사용할 수 있습니다.

Q: 주석을 제거하면 원본 레이아웃이 변경되나요?
A: 아니요. 라이브러리는 주석 레이어만 제거하므로 텍스트, 이미지 및 페이지 구조는 그대로 유지됩니다.

Q: 특정 주석 유형만 삭제하려면 어떻게 해야 하나요?
A: 제외하려는 유형을 비트 OR 조합으로 AnnotationTypes에 설정합니다. 예: AnnotationType.Highlight | AnnotationType.Strikeout.

Q: 이 과정이 원본 PDF를 수정하나요?
A: 원본 파일은 절대 덮어쓰지 않으며, 정리된 PDF는 Save에 지정한 경로에 작성됩니다.

Q: 문서 크기에 따라 성능은 어떻게 변하나요?
A: 200 MB 이하 PDF의 경우 표준 2.5 GHz CPU에서 정리 작업이 5 초 미만에 완료됩니다. 더 큰 파일은 배치 처리 및 비동기 실행을 통해 성능을 향상시킬 수 있습니다.

추가 자료

마지막 업데이트: 2026-06-01
테스트 환경: GroupDocs.Annotation 25.4.0 for .NET
작성자: GroupDocs

관련 튜토리얼