PDF Redaction in C#: Remove Sensitive Data and Sanitize Documents with IronPDF

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronPDF를 사용한 C# .NET 기반 PDF 수정은 민감한 콘텐츠를 문서의 내부 구조에서 영구적으로 제거하여 단순히 시각적으로 가리는 것이 아니라, 복사, 검색 또는 포렌식 분석을 통해 원본 데이터를 복구할 수 없도록 합니다. IronPDF는 단순히 텍스트 위에 검은색 사각형을 씌우는 것 이상의 기능을 제공합니다. 정규 표현식 패턴 일치를 이용한 텍스트 수정 , 서명 및 이미지에 대한 영역 기반 수정 , 메타데이터 제거, 내장 스크립트를 제거하는 문서 소독 , 취약점 검사 등을 통해 .NET 개발자에게 HIPAA , GDPRPCI DSS를 준수하는 문서 보호 워크플로를 위한 완벽한 툴킷을 제공합니다.

요약: 빠른 시작 가이드

이 튜토리얼에서는 C# .NET을 사용하여 PDF 문서에서 텍스트 패턴, 이미지 영역, 메타데이터 및 내장 스크립트를 포함한 민감한 콘텐츠를 영구적으로 제거하는 방법을 다룹니다.

  • 이 솔루션은 의료, 법률, 금융 또는 정부 분야에서 민감한 문서를 다루는 .NET 개발자를 위한 것입니다 .
  • 개발할 기능: 정규 표현식 패턴 매칭을 이용한 텍스트 수정(사회보장번호, 신용카드, 이메일), 서명 및 사진에 대한 좌표 기반 영역 수정, 메타데이터 정리, 내장 스크립트 제거를 위한 PDF 파일 검증, YARA 기반 취약점 스캔.
  • 지원 환경: .NET 10, .NET 8 LTS, .NET Framework 4.6.2 이상, .NET Standard 2.0. 모든 작업은 외부 종속성 없이 로컬에서 실행됩니다.
  • 이 방법을 사용하는 경우: 법적 증거 수집, 정보공개법(FOIA) 요청 또는 외부 배포를 위해 문서를 공유해야 하지만 삭제된 콘텐츠가 완전히 제거되었는지 확인해야 할 때 사용합니다.
  • 기술적으로 중요한 이유: 시각적 오버레이를 사용하면 PDF 콘텐츠 스트림에서 원본 텍스트를 복구할 수 있습니다. IronPDF의 문자 삭제 기능은 문서 구조 자체에서 문자 데이터를 삭제하므로 복구가 불가능합니다.

단 몇 줄의 코드로 PDF에서 민감한 텍스트를 삭제할 수 있습니다.

Nuget Icon지금 바로 NuGet을 사용하여 PDF 만들기를 시작하세요.

  1. NuGet 패키지 관리자를 사용하여 IronPDF를 설치하세요.

    PM > Install-Package IronPdf

  2. 다음 코드 조각을 복사하여 실행하세요.

    using IronPdf;
    
    PdfDocument pdf = PdfDocument.FromFile("confidential-report.pdf");
    pdf.RedactTextOnAllPages("CONFIDENTIAL");
    pdf.SaveAs("redacted-report.pdf");
  3. 실제 운영 환경에서 테스트할 수 있도록 배포하세요.

    지금 바로 무료 체험판을 통해 프로젝트에서 IronPDF를 사용해 보세요.
    arrow pointer

IronPDF를 구매하거나 30일 무료 체험판에 가입한 후, 애플리케이션 시작 부분에 라이선스 키를 입력하세요.

IronPdf.License.LicenseKey = "KEY";
IronPdf.License.LicenseKey = "KEY";
$vbLabelText   $csharpLabel

지금 바로 무료 체험판을 통해 IronPDF을 프로젝트에서 사용해 보세요.

첫 번째 단계:
green arrow pointer
!{--010011000100100101000010010100100100000101010010010110010101111101001110010101010001110100010101010100010111110100100101001110010100110101010001000001010011000100110001001100010111110100001001001100010011110100001101001011--}

목차

요약: 빠른 시작 가이드

진정한 수정과 시각적 오버레이의 차이점은 무엇인가요?

민감한 문서를 다루는 사람이라면 누구나 진정한 정보 삭제와 시각적 오버레이의 차이점을 이해하는 것이 매우 중요합니다. 많은 도구와 수동적인 방법들은 실제 데이터를 삭제하지 않고도 마치 삭제한 것처럼 보이게 만듭니다. 이러한 잘못된 안도감은 수많은 대규모 데이터 유출 사고와 규정 준수 실패를 초래했습니다.

시각적 오버레이 방식은 일반적으로 민감한 콘텐츠 위에 불투명한 도형을 그립니다. 텍스트는 PDF 구조 내에서 완전히 그대로 유지됩니다. 문서를 보는 사람은 검은색 사각형을 보지만, 파일의 콘텐츠 스트림에는 원래 문자가 여전히 남아 있습니다. 페이지의 모든 텍스트를 선택하거나, 접근성 도구를 사용하거나, 원본 PDF 데이터를 검토하면 숨겨져 있다고 여겨졌던 모든 내용이 드러납니다. 소송 과정에서 삭제된 서류가 상대측 변호사에 의해 손쉽게 원래대로 복원되면서 소송 결과가 손상된 사례가 있습니다. 정부 기관들이 실수로 기밀 정보를 유출했는데, 해당 정보는 검열된 것처럼 보였지만 완전히 복구 가능한 내용이었다.

진정한 정보 삭제는 다른 방식으로 작동합니다. IronPDF의 텍스트 삭제 기능을 사용하면 라이브러리가 PDF 내부 구조에서 지정된 텍스트를 찾아 완전히 제거합니다. 콘텐츠 스트림에서 문자 데이터가 삭제됩니다. 시각적 표현은 일반적으로 검은색 사각형과 같은 삭제 표시로 대체되지만, 원본 내용은 파일 어디에도 더 이상 존재하지 않습니다. 어떤 선택, 복사 또는 포렌식 분석을 통해서도 영구적으로 삭제된 내용을 복구할 수 없습니다.

IronPDF는 PDF의 구조적 수준을 수정하여 진정한 내용 삭제 기능을 구현합니다. RedactTextOnAllPages 메서드와 그 변형은 페이지 콘텐츠를 검색하고, 일치하는 텍스트를 식별하고, 문서 객체 모델에서 해당 텍스트를 제거하고, 선택적으로 콘텐츠가 이전에 나타났던 위치에 시각적 표시기를 그립니다. 이러한 접근 방식은 안전한 문서 수정을 위한 NIST와 같은 기관의 지침과 일치합니다.

실질적인 의미는 상당합니다. 문서를 외부와 공유하거나, 법적 증거 수집을 위해 파일을 제출하거나, 정보공개 청구에 따라 기록을 공개하거나, 개인 식별 정보를 보호하면서 보고서를 배포해야 하는 경우, 진정한 의미의 정보 삭제만이 적절한 보호책을 제공합니다. 시각적 오버레이는 특정 부분에서 주의를 돌리고 싶을 때와 같은 내부 초안에는 충분할 수 있지만, 실제 데이터 보호를 위해서는 절대 신뢰해서는 안 됩니다. 문서 보안을 강화하려면 PDF 암호화디지털 서명 관련 가이드를 참조하세요.


How do I Redact PDF Text in C# Across an Entire Document?

가장 일반적인 문서 수정 시나리오는 문서 전체에서 특정 텍스트를 모두 제거하는 것입니다. 보고서에서 특정인의 이름을 삭제하거나, 재무제표에서 계좌번호를 제거하거나, 외부 배포 전에 내부 참조 코드를 삭제해야 할 수도 있습니다. IronPDF는 RedactTextOnAllPages 방식을 통해 이를 간단하게 처리합니다.

입력

직원 기록 문서에는 이름, 사회 보장 번호 및 직원 ID를 포함한 개인 정보가 담겨 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-text-all-pages.cs
using IronPdf;

// Load the source document
PdfDocument pdf = PdfDocument.FromFile("employee-records.pdf");

// Redact an employee name from the entire document
pdf.RedactTextOnAllPages("John Smith");

// Redact a Social Security Number
pdf.RedactTextOnAllPages("123-45-6789");

// Redact an internal employee ID
pdf.RedactTextOnAllPages("EMP-2024-0042");

// Save the cleaned document
pdf.SaveAs("employee-records-redacted.pdf");
$vbLabelText   $csharpLabel

이 코드는 직원 정보가 포함된 PDF 파일을 불러와서 각 값에 대해 RedactTextOnAllPages를 호출하여 세 가지 기밀 데이터를 제거합니다. 각 호출은 문서의 모든 페이지를 검색하여 직원의 이름, 사회 보장 번호 및 내부 식별자가 일치하는 모든 항목을 영구적으로 제거합니다.

샘플 출력

기본 동작은 삭제된 텍스트가 나타난 위치에 검은색 사각형을 그리고 문서 구조에서 해당 문자를 별표로 대체합니다. 이는 수정 작업이 실제로 이루어졌음을 시각적으로 확인시켜 줄 뿐만 아니라 원본 콘텐츠가 완전히 삭제되었음을 보장합니다.

문서 길이가 길거나 수정 대상이 여러 개인 경우, 이러한 호출을 효율적으로 연결할 수 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-text-list.cs
using IronPdf;
using System.Collections.Generic;

// Load the document once
PdfDocument pdf = PdfDocument.FromFile("quarterly-report.pdf");

// Define all terms that need redaction
List<string> sensitiveTerms = new List<string>
{
    "Project Titan",
    "Sarah Johnson",
    "Budget: $4.2M",
    "Q3-INTERNAL-2024",
    "sarah.johnson@company.com"
};

// Redact each term
foreach (string term in sensitiveTerms)
{
    pdf.RedactTextOnAllPages(term);
}

// Save the result
pdf.SaveAs("quarterly-report-public.pdf");
$vbLabelText   $csharpLabel

이 패턴은 제거해야 할 민감한 값 목록을 알고 있을 때 효과적입니다. 문서가 한 번 로드되고, 모든 수정 사항이 메모리에 적용된 후 최종 결과가 저장됩니다. 각 용어는 독립적으로 처리되므로 용어 간의 부분 일치 또는 형식 차이는 다른 수정 사항에 영향을 미치지 않습니다.

특정 페이지의 텍스트만 삭제하려면 어떻게 해야 하나요?

때로는 삭제 영역을 보다 정밀하게 제어해야 할 필요가 있습니다. 문서에는 그대로 유지되어야 할 정보가 담긴 표지가 있을 수 있고, 기밀 데이터는 특정 섹션에만 나타난다는 것을 알고 있을 수도 있습니다. IronPDF는 단일 페이지 수정에는 RedactTextOnPage를, 여러 특정 페이지를 대상으로 수정에는 RedactTextOnPages를 제공합니다.

입력

서명 페이지에 고객 이름이 기재되고 재정 조건이 문서 전체의 특정 페이지에 표시되는 여러 페이지로 구성된 계약서 묶음입니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-specific-pages.cs
using IronPdf;

// Load the document
PdfDocument pdf = PdfDocument.FromFile("contract-bundle.pdf");

// Redact text only on page 1 (index 0)
pdf.RedactTextOnPage(0, "Client Name: Acme Corporation");

// Redact text on pages 3, 5, and 7 (indices 2, 4, 6)
int[] financialPages = { 2, 4, 6 };
pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30");

// Other pages remain untouched except for the specific redactions applied

pdf.SaveAs("contract-bundle-redacted.pdf");
$vbLabelText   $csharpLabel

이 코드는 단일 페이지의 경우 RedactTextOnPage를 사용하고 여러 특정 페이지의 경우 RedactTextOnPages를 사용하여 특정 부분을 삭제하는 방법을 보여줍니다. 고객 이름은 1페이지(인덱스 0)에서만 삭제되고, 지불 조건은 3, 5, 7페이지(인덱스 2, 4, 6)에서 삭제되며, 나머지 페이지는 모두 그대로 유지됩니다.

샘플 출력

IronPDF의 페이지 인덱스는 0부터 시작하며, 첫 번째 페이지는 인덱스 0, 두 번째 페이지는 인덱스 1 등으로 이어집니다. 이는 표준 프로그래밍 관례와 일치하며 대부분의 개발자가 배열 접근 방식을 생각하는 방식과도 부합합니다.

대용량 문서를 처리할 때 특정 페이지를 대상으로 하면 성능이 향상됩니다. 몇몇 위치에만 나타나는 텍스트를 찾기 위해 수백 페이지를 스캔하는 대신, 편집 엔진에 정확히 어디를 찾아야 하는지 지정할 수 있습니다. 이는 수천 개의 문서를 처리해야 하는 일괄 처리 시나리오에서 중요한 문제입니다. 최대 처리량을 얻으려면 비동기 및 멀티스레딩 기술을 사용하는 것을 고려하십시오.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-large-document.cs
using IronPdf;

// Process a large document efficiently
PdfDocument pdf = PdfDocument.FromFile("annual-report-500-pages.pdf");

// We know from document structure that:
// - Executive summary with names is on pages 1-3
// - Financial data is on pages 45-60
// - Appendix with employee info is on pages 480-495

// Redact executive names from summary section
for (int i = 0; i <= 2; i++)
{
    pdf.RedactTextOnPage(i, "CEO: Robert Williams");
    pdf.RedactTextOnPage(i, "CFO: Maria Garcia");
}

// Redact specific financial figures from the financial section
int[] financialSection = { 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M");

// Redact employee identifiers from appendix
for (int i = 479; i <= 494; i++)
{
    pdf.RedactTextOnPage(i, "Employee ID:");
}

pdf.SaveAs("annual-report-public-release.pdf");
$vbLabelText   $csharpLabel

이러한 맞춤형 접근 방식은 500페이지 문서에서 관련 섹션만 처리하므로, 모든 페이지를 스캔하여 각 삭제 조항을 찾는 방식에 비해 실행 시간을 크게 단축합니다.

가려진 콘텐츠의 모양을 어떻게 사용자 지정할 수 있나요?

IronPDF는 최종 문서에서 수정 내용이 표시되는 방식을 제어하는 여러 매개변수를 제공합니다. 대소문자 구분, 단어 전체 일치 여부, 시각적 사각형 표시 여부, 삭제된 내용 대신 표시될 대체 텍스트 등을 조정할 수 있습니다.

입력

기밀 분류, 암호, 내부 참조 코드 등 다양한 민감한 용어가 포함된 법률 문서로, 이러한 용어들은 각각 다른 방식으로 삭제 처리되어야 합니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/customize-redaction-appearance.cs
using IronPdf;

// Load the document
PdfDocument pdf = PdfDocument.FromFile("legal-brief.pdf");

// Case-sensitive redaction: only matches exact case
// "CLASSIFIED" will be redacted but "classified" or "Classified" will not
pdf.RedactTextOnAllPages(
    "CLASSIFIED",
    CaseSensitive: true,
    OnlyMatchWholeWords: true,
    DrawRectangles: true,
    ReplacementText: "[REDACTED]"
);

// Case-insensitive redaction: matches regardless of case
// Will redact "Secret", "SECRET", "secret", etc.
pdf.RedactTextOnAllPages(
    "secret",
    CaseSensitive: false,
    OnlyMatchWholeWords: true,
    DrawRectangles: true,
    ReplacementText: "*****"
);

// Whole word disabled: matches partial strings too
// Will redact "password", "passwords", "mypassword123", etc.
pdf.RedactTextOnAllPages(
    "password",
    CaseSensitive: false,
    OnlyMatchWholeWords: false,
    DrawRectangles: true,
    ReplacementText: "XXXXX"
);

// No visual rectangle: text is removed but no black box appears
// Useful when you want seamless removal without obvious redaction marks
pdf.RedactTextOnAllPages(
    "internal-reference-code",
    CaseSensitive: true,
    OnlyMatchWholeWords: true,
    DrawRectangles: false,
    ReplacementText: ""
);

pdf.SaveAs("legal-brief-redacted.pdf");
$vbLabelText   $csharpLabel

이 코드는 RedactTextOnAllPages의 선택적 매개변수를 사용하여 네 가지 다른 수정 구성을 보여줍니다. 이 기능은 대소문자를 구분하여 정확히 일치하는 항목을 "[REDACTED]"로 대체하는 방식, 별표를 사용하여 대소문자를 구분하지 않는 방식, "passwords"와 같은 변형을 포착하기 위한 부분 단어 일치 방식, 그리고 시각적 사각형 없이 콘텐츠를 매끄럽게 제거하는 보이지 않는 방식 등을 보여줍니다.

샘플 출력

매개변수는 요구 사항에 따라 서로 다른 목적을 수행합니다.

CaseSensitive는 문자 대소문자를 고려하여 일치 여부를 결정합니다. 법률 문서에서는 의미를 전달하는 특정 대문자 표기법이 자주 사용되므로 대소문자를 구분하여 정확히 일치하는 항목만 제거합니다. 대소문자가 다양한 일반 텍스트를 처리할 때는 모든 경우를 포착하기 위해 대소문자를 구분하지 않는 매칭이 필요할 수 있습니다.

OnlyMatchWholeWords는 검색 결과가 전체 단어와 일치하는지 아니면 부분 문자열과 일치하는지를 제어합니다. 이름을 가릴 때는 일반적으로 단어 전체가 일치하도록 해야 합니다. 그래야 "Smith"가 "Blacksmith"나 "Smithfield"의 일부를 실수로 가리는 일이 발생하지 않습니다. 계좌번호 접두사와 같은 패턴을 삭제할 때는 변형을 포착하기 위해 부분 일치가 필요할 수 있습니다.

DrawRectangles는 콘텐츠가 제거된 위치에 검은색 상자가 나타날지 여부를 지정합니다. 대부분의 규제 및 법률 환경에서는 내용이 실수로 누락된 것이 아니라 의도적으로 삭제되었음을 입증하기 위해 눈에 띄는 삭제 표시를 요구합니다. 내부 워크플로는 더 깔끔한 출력을 위해 보이지 않는 제거 작업을 선호할 수 있습니다.

ReplacementText는 삭제된 내용 대신 나타날 문자를 정의합니다. 일반적으로 별표, "삭제됨" 레이블 또는 빈 문자열을 사용합니다. 삭제된 영역에서 선택 또는 복사를 시도하면 대체 텍스트가 문서 구조에 나타납니다.


정규 표현식을 사용하여 민감한 패턴을 찾고 삭제하는 방법은 무엇인가요?

알려진 텍스트 문자열을 수정하는 것은 제거할 특정 값이 있을 때 효과적이지만, 많은 기밀 데이터 유형은 고정된 값보다는 예측 가능한 패턴을 따릅니다. 사회보장번호, 신용카드 번호, 이메일 주소, 전화번호, 날짜는 모두 정규 표현식으로 일치시킬 수 있는 인식 가능한 형식을 가지고 있습니다. 패턴 기반 정보 삭제 시스템을 구축하면 모든 특정 값을 사전에 알지 못해도 PDF 콘텐츠에서 개인 정보를 제거할 수 있습니다.

IronPDF의 텍스트 추출 기능 과 수정 방법을 결합하면 강력한 패턴 매칭 워크플로우를 구현할 수 있습니다. 텍스트를 추출하고, .NET 정규 표현식을 사용하여 일치하는 부분을 찾은 다음, 발견된 각 값을 수정합니다.

using IronPdf;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class PatternRedactor
{
    // Common patterns for sensitive data
    private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string>
    {
        // US Social Security Number: 123-45-6789
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },

        // Credit Card Numbers: various formats with 13-19 digits
        { "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },

        // Email Addresses
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },

        // US Phone Numbers: (123) 456-7890 or 123-456-7890
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },

        // Dates: MM/DD/YYYY or MM-DD-YYYY
        { "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" },

        // IP Addresses
        { "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" }
    };

    public void RedactPatterns(string inputPath, string outputPath, params string[] patternNames)
    {
        // Load the PDF
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract all text from the document
        string fullText = pdf.ExtractAllText();

        // Track unique matches to avoid duplicate redaction attempts
        HashSet<string> matchesToRedact = new HashSet<string>();

        // Find all matches for requested patterns
        foreach (string patternName in patternNames)
        {
            if (SensitivePatterns.TryGetValue(patternName, out string pattern))
            {
                Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(fullText);

                foreach (Match match in matches)
                {
                    matchesToRedact.Add(match.Value);
                }
            }
        }

        // Redact each unique match
        foreach (string sensitiveValue in matchesToRedact)
        {
            pdf.RedactTextOnAllPages(sensitiveValue);
        }

        // Save the redacted document
        pdf.SaveAs(outputPath);
    }
}

// Usage example
class Program
{
    static void Main()
    {
        PatternRedactor redactor = new PatternRedactor();

        // Redact SSNs and credit cards from a financial document
        redactor.RedactPatterns(
            "customer-data.pdf",
            "customer-data-safe.pdf",
            "SSN", "CreditCard", "Email"
        );
    }
}
using IronPdf;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class PatternRedactor
{
    // Common patterns for sensitive data
    private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string>
    {
        // US Social Security Number: 123-45-6789
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },

        // Credit Card Numbers: various formats with 13-19 digits
        { "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },

        // Email Addresses
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },

        // US Phone Numbers: (123) 456-7890 or 123-456-7890
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },

        // Dates: MM/DD/YYYY or MM-DD-YYYY
        { "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" },

        // IP Addresses
        { "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" }
    };

    public void RedactPatterns(string inputPath, string outputPath, params string[] patternNames)
    {
        // Load the PDF
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract all text from the document
        string fullText = pdf.ExtractAllText();

        // Track unique matches to avoid duplicate redaction attempts
        HashSet<string> matchesToRedact = new HashSet<string>();

        // Find all matches for requested patterns
        foreach (string patternName in patternNames)
        {
            if (SensitivePatterns.TryGetValue(patternName, out string pattern))
            {
                Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(fullText);

                foreach (Match match in matches)
                {
                    matchesToRedact.Add(match.Value);
                }
            }
        }

        // Redact each unique match
        foreach (string sensitiveValue in matchesToRedact)
        {
            pdf.RedactTextOnAllPages(sensitiveValue);
        }

        // Save the redacted document
        pdf.SaveAs(outputPath);
    }
}

// Usage example
class Program
{
    static void Main()
    {
        PatternRedactor redactor = new PatternRedactor();

        // Redact SSNs and credit cards from a financial document
        redactor.RedactPatterns(
            "customer-data.pdf",
            "customer-data-safe.pdf",
            "SSN", "CreditCard", "Email"
        );
    }
}
$vbLabelText   $csharpLabel

이 패턴 기반 접근 방식은 패턴을 한 번 정의하고 모든 문서에 적용할 수 있기 때문에 확장성이 뛰어납니다. 새로운 데이터 형식을 추가하려면 사전에 새로운 정규 표현식 패턴을 추가하기만 하면 됩니다.

재사용 가능한 민감 데이터 스캐너를 어떻게 구축하나요?

실제 운영 환경에서는 문서를 스캔하고 기밀 정보가 포함되어 있는지 확인한 후 삭제 여부를 결정해야 하는 경우가 많습니다. 이는 규정 준수 감사에 도움이 되며, 정보 삭제 결정에 대한 사람의 검토를 가능하게 합니다. 다음 클래스는 스캔 기능과 함께 수정 기능을 제공합니다.

using IronPdf;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;

public class SensitiveDataMatch
{
    public string PatternType { get; set; }
    public string Value { get; set; }
    public int PageNumber { get; set; }
}

public class ScanResult
{
    public string FilePath { get; set; }
    public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>();
    public bool ContainsSensitiveData => Matches.Count > 0;

    public Dictionary<string, int> GetSummary()
    {
        return Matches.GroupBy(m => m.PatternType)
                      .ToDictionary(g => g.Key, g => g.Count());
    }
}

public class DocumentScanner
{
    private readonly Dictionary<string, string> _patterns;

    public DocumentScanner()
    {
        _patterns = new Dictionary<string, string>
        {
            { "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" },
            { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
            { "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
            { "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
            { "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }
        };
    }

    public ScanResult ScanDocument(string filePath)
    {
        ScanResult result = new ScanResult { FilePath = filePath };
        PdfDocument pdf = PdfDocument.FromFile(filePath);

        // Scan each page individually to track location
        for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++)
        {
            string pageText = pdf.ExtractTextFromPage(pageIndex);

            foreach (var pattern in _patterns)
            {
                Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(pageText);

                foreach (Match match in matches)
                {
                    result.Matches.Add(new SensitiveDataMatch
                    {
                        PatternType = pattern.Key,
                        Value = MaskValue(match.Value, pattern.Key),
                        PageNumber = pageIndex + 1
                    });
                }
            }
        }

        return result;
    }

    // Partially mask values for safe storage
    private string MaskValue(string value, string patternType)
    {
        if (patternType == "Social Security Number" && value.Length >= 4)
        {
            return "XXX-XX-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Credit Card" && value.Length >= 4)
        {
            return "****-****-****-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Email Address")
        {
            int atIndex = value.IndexOf('@');
            if (atIndex > 2)
            {
                return value.Substring(0, 2) + "***" + value.Substring(atIndex);
            }
        }
        return value.Length > 4 ? value.Substring(0, 2) + "***" : "****";
    }

    public void ScanAndRedact(string inputPath, string outputPath)
    {
        // First scan to identify sensitive data
        ScanResult scanResult = ScanDocument(inputPath);

        if (!scanResult.ContainsSensitiveData)
        {
            return;
        }

        // Load document for redaction
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract unique actual values (not masked) for redaction
        string fullText = pdf.ExtractAllText();
        HashSet<string> valuesToRedact = new HashSet<string>();

        foreach (var pattern in _patterns)
        {
            Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
            foreach (Match match in regex.Matches(fullText))
            {
                valuesToRedact.Add(match.Value);
            }
        }

        // Apply redactions
        foreach (string value in valuesToRedact)
        {
            pdf.RedactTextOnAllPages(value);
        }

        pdf.SaveAs(outputPath);
    }
}

// Usage
class Program
{
    static void Main()
    {
        DocumentScanner scanner = new DocumentScanner();

        // Scan only (for audit purposes)
        ScanResult result = scanner.ScanDocument("application-form.pdf");
        var summary = result.GetSummary();

        // Scan and redact in one operation
        scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf");
    }
}
using IronPdf;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;

public class SensitiveDataMatch
{
    public string PatternType { get; set; }
    public string Value { get; set; }
    public int PageNumber { get; set; }
}

public class ScanResult
{
    public string FilePath { get; set; }
    public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>();
    public bool ContainsSensitiveData => Matches.Count > 0;

    public Dictionary<string, int> GetSummary()
    {
        return Matches.GroupBy(m => m.PatternType)
                      .ToDictionary(g => g.Key, g => g.Count());
    }
}

public class DocumentScanner
{
    private readonly Dictionary<string, string> _patterns;

    public DocumentScanner()
    {
        _patterns = new Dictionary<string, string>
        {
            { "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" },
            { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
            { "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
            { "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
            { "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }
        };
    }

    public ScanResult ScanDocument(string filePath)
    {
        ScanResult result = new ScanResult { FilePath = filePath };
        PdfDocument pdf = PdfDocument.FromFile(filePath);

        // Scan each page individually to track location
        for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++)
        {
            string pageText = pdf.ExtractTextFromPage(pageIndex);

            foreach (var pattern in _patterns)
            {
                Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(pageText);

                foreach (Match match in matches)
                {
                    result.Matches.Add(new SensitiveDataMatch
                    {
                        PatternType = pattern.Key,
                        Value = MaskValue(match.Value, pattern.Key),
                        PageNumber = pageIndex + 1
                    });
                }
            }
        }

        return result;
    }

    // Partially mask values for safe storage
    private string MaskValue(string value, string patternType)
    {
        if (patternType == "Social Security Number" && value.Length >= 4)
        {
            return "XXX-XX-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Credit Card" && value.Length >= 4)
        {
            return "****-****-****-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Email Address")
        {
            int atIndex = value.IndexOf('@');
            if (atIndex > 2)
            {
                return value.Substring(0, 2) + "***" + value.Substring(atIndex);
            }
        }
        return value.Length > 4 ? value.Substring(0, 2) + "***" : "****";
    }

    public void ScanAndRedact(string inputPath, string outputPath)
    {
        // First scan to identify sensitive data
        ScanResult scanResult = ScanDocument(inputPath);

        if (!scanResult.ContainsSensitiveData)
        {
            return;
        }

        // Load document for redaction
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract unique actual values (not masked) for redaction
        string fullText = pdf.ExtractAllText();
        HashSet<string> valuesToRedact = new HashSet<string>();

        foreach (var pattern in _patterns)
        {
            Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
            foreach (Match match in regex.Matches(fullText))
            {
                valuesToRedact.Add(match.Value);
            }
        }

        // Apply redactions
        foreach (string value in valuesToRedact)
        {
            pdf.RedactTextOnAllPages(value);
        }

        pdf.SaveAs(outputPath);
    }
}

// Usage
class Program
{
    static void Main()
    {
        DocumentScanner scanner = new DocumentScanner();

        // Scan only (for audit purposes)
        ScanResult result = scanner.ScanDocument("application-form.pdf");
        var summary = result.GetSummary();

        // Scan and redact in one operation
        scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf");
    }
}
$vbLabelText   $csharpLabel

스캐너는 수정이 이루어지기 전에 어떤 기밀 정보가 존재하는지 확인할 수 있도록 해줍니다. 이는 발견 및 제거된 내용에 대한 문서화가 필요한 규정 준수 워크플로를 지원합니다. 마스킹 기능은 로그 파일과 보고서 자체가 데이터 노출의 원인이 되지 않도록 보장합니다.


PDF 파일에서 특정 영역이나 부분을 가리려면 어떻게 해야 하나요?

텍스트 수정 기능은 문자 기반 콘텐츠를 효과적으로 처리하지만, PDF에는 텍스트 일치 기능으로는 처리할 수 없는 형태의 민감한 정보가 포함되는 경우가 많습니다. 서명, 사진, 손으로 쓴 주석, 도장 및 그래픽 요소는 다른 접근 방식이 필요합니다. 영역 기반 수정 기능을 사용하면 좌표를 이용하여 직사각형 영역을 지정하고 해당 영역 내의 모든 내용을 영구적으로 가릴 수 있습니다.

IronPDF는 RectangleF 구조를 사용하여 수정 영역을 정의합니다. 먼저 왼쪽 상단 모서리의 X, Y 좌표를 지정한 다음 영역의 너비와 높이를 지정합니다. 좌표는 페이지의 왼쪽 하단을 기준으로 포인트 단위로 측정되며, 이는 PDF 규격의 좌표계와 일치합니다.

입력

좌표 기반 영역 타겟팅을 사용하여 삭제해야 하는, 자필 서명과 사진이 포함된 계약서.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-region-basic.cs
using IronPdf;
using IronSoftware.Drawing;

// Load a document with signature blocks and photos
PdfDocument pdf = PdfDocument.FromFile("signed-agreement.pdf");

// Define a region for a signature block
// Located 100 points from left, 650 points from bottom
// Width of 200 points, height of 50 points
RectangleF signatureRegion = new RectangleF(100, 650, 200, 50);

// Redact the signature region on all pages
pdf.RedactRegionsOnAllPages(signatureRegion);

// Define a region for a photo ID in the upper right
RectangleF photoRegion = new RectangleF(450, 700, 100, 120);
pdf.RedactRegionsOnAllPages(photoRegion);

// Save the document with regions redacted
pdf.SaveAs("signed-agreement-redacted.pdf");
$vbLabelText   $csharpLabel

이 코드는 RectangleF 구조체를 사용하여 수정할 직사각형 영역을 정의합니다. 서명 영역은 200x50 픽셀 영역으로 좌표 (100, 650)에 위치하고, 사진 영역은 100x120 픽셀 영역으로 좌표 (450, 700)에 위치합니다. RedactRegionsOnAllPages 메서드는 모든 페이지의 이러한 영역에 검은색 사각형을 적용합니다.

샘플 출력

정확한 좌표를 결정하려면 종종 실험이나 측정이 필요합니다. PDF 페이지는 일반적으로 1점이 1/72인치에 해당하는 좌표계를 사용합니다. 미국 표준 레터 용지는 가로 612포인트, 세로 792포인트입니다. A4 용지는 대략 595 x 842포인트 크기입니다. 커서를 움직일 때 좌표를 표시하는 PDF 보기 도구를 사용하거나, 프로그램으로 페이지 크기를 추출할 수 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-region-dimensions.cs
using IronPdf;
using IronSoftware.Drawing;

PdfDocument pdf = PdfDocument.FromFile("form-document.pdf");

// Get dimensions of the first page
var pageInfo = pdf.Pages[0];

// Calculate regions relative to page dimensions
// Redact the bottom quarter of the page where signatures appear
float signatureAreaHeight = (float)(pageInfo.Height / 4);
RectangleF bottomQuarter = new RectangleF(
    0,                              // Start at left edge
    0,                              // Start at bottom
    (float)pageInfo.Width,          // Full page width
    signatureAreaHeight             // Quarter of page height
);

pdf.RedactRegionsOnAllPages(bottomQuarter);

// Redact a header area at the top containing letterhead with address
float headerHeight = 100;
RectangleF headerArea = new RectangleF(
    0,
    (float)(pageInfo.Height - headerHeight), // Position from bottom
    (float)pageInfo.Width,
    headerHeight
);

pdf.RedactRegionsOnAllPages(headerArea);

pdf.SaveAs("form-document-redacted.pdf");
$vbLabelText   $csharpLabel

여러 페이지에 걸쳐 특정 영역을 한 번에 가릴 수 있는 방법은 무엇인가요?

복잡한 문서의 경우 페이지마다 다른 영역을 가려야 하는 경우가 많습니다. 여러 페이지로 구성된 양식은 서명란의 위치가 페이지마다 다를 수 있으며, 각 페이지에는 사진, 도장 또는 기타 그래픽 요소가 고유한 위치에 포함될 수 있습니다. IronPDF에는 특정 영역을 선택적으로 삭제하는 페이지별 방법이 포함되어 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-multiple-regions.cs
using IronPdf;
using IronSoftware.Drawing;

PdfDocument pdf = PdfDocument.FromFile("multi-page-application.pdf");

// Define page-specific redaction regions
// Page 1: Cover page with applicant photo
RectangleF page1Photo = new RectangleF(450, 600, 120, 150);
pdf.RedactRegionOnPage(0, page1Photo);

// Page 2: Personal information section
RectangleF page2InfoBlock = new RectangleF(50, 400, 250, 200);
pdf.RedactRegionOnPage(1, page2InfoBlock);

// Pages 3-5: Signature lines at the same position
RectangleF signatureLine = new RectangleF(100, 100, 200, 40);
int[] signaturePages = { 2, 3, 4 };
pdf.RedactRegionOnPages(signaturePages, signatureLine);

// Page 6: Multiple regions - notary stamp and witness signature
RectangleF notaryStamp = new RectangleF(400, 150, 150, 150);
RectangleF witnessSignature = new RectangleF(100, 150, 200, 40);
pdf.RedactRegionOnPage(5, notaryStamp);
pdf.RedactRegionOnPage(5, witnessSignature);

pdf.SaveAs("multi-page-application-redacted.pdf");
$vbLabelText   $csharpLabel

레이아웃이 일관된 문서는 재사용 가능한 영역 정의를 통해 이점을 얻습니다.

using IronPdf;
using IronSoftware.Drawing;

public class FormRegions
{
    // Standard form regions based on common templates
    public static RectangleF HeaderLogo => new RectangleF(20, 720, 150, 60);
    public static RectangleF SignatureBlock => new RectangleF(72, 72, 200, 50);
    public static RectangleF DateField => new RectangleF(400, 72, 120, 20);
    public static RectangleF PhotoId => new RectangleF(480, 650, 100, 130);
    public static RectangleF AddressBlock => new RectangleF(72, 600, 250, 80);
}

class Program
{
    static void Main()
    {
        PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf");

        // Apply standard redactions using predefined regions
        pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock);
        pdf.RedactRegionsOnAllPages(FormRegions.DateField);
        pdf.RedactRegionOnPage(0, FormRegions.PhotoId);

        pdf.SaveAs("standard-form-redacted.pdf");
    }
}
using IronPdf;
using IronSoftware.Drawing;

public class FormRegions
{
    // Standard form regions based on common templates
    public static RectangleF HeaderLogo => new RectangleF(20, 720, 150, 60);
    public static RectangleF SignatureBlock => new RectangleF(72, 72, 200, 50);
    public static RectangleF DateField => new RectangleF(400, 72, 120, 20);
    public static RectangleF PhotoId => new RectangleF(480, 650, 100, 130);
    public static RectangleF AddressBlock => new RectangleF(72, 600, 250, 80);
}

class Program
{
    static void Main()
    {
        PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf");

        // Apply standard redactions using predefined regions
        pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock);
        pdf.RedactRegionsOnAllPages(FormRegions.DateField);
        pdf.RedactRegionOnPage(0, FormRegions.PhotoId);

        pdf.SaveAs("standard-form-redacted.pdf");
    }
}
$vbLabelText   $csharpLabel

개인 정보를 노출할 수 있는 메타데이터를 어떻게 제거할 수 있나요?

PDF 메타데이터는 정보 유출의 주요 원인 중 하나이지만, 종종 간과되는 경우가 많습니다. 모든 PDF 파일에는 작성자 이름과 사용자 이름, 문서 생성에 사용된 소프트웨어, 생성 및 수정 타임스탬프, 원본 파일 이름, 수정 내역, 다양한 응용 프로그램에서 추가한 사용자 지정 속성 등과 같이 민감한 정보를 드러낼 수 있는 속성이 포함되어 있습니다. 문서를 외부와 공유하기 전에 이러한 메타데이터를 제거하거나 정제하는 것이 필수적입니다. 메타데이터 작업에 대한 포괄적인 개요는 메타데이터 사용 방법 가이드를 참조하세요.

IronPDF는 MetaData 속성을 통해 문서 메타데이터를 노출하므로 기존 값을 읽거나 수정하거나 완전히 제거할 수 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/view-metadata.cs
using IronPdf;
using System;

// Load a document containing sensitive metadata
PdfDocument pdf = PdfDocument.FromFile("internal-report.pdf");

// Access current metadata properties
string author = pdf.MetaData.Author;
string title = pdf.MetaData.Title;
string subject = pdf.MetaData.Subject;
string keywords = pdf.MetaData.Keywords;
string creator = pdf.MetaData.Creator;
string producer = pdf.MetaData.Producer;
DateTime? creationDate = pdf.MetaData.CreationDate;
DateTime? modifiedDate = pdf.MetaData.ModifiedDate;

// Get all metadata keys including custom properties
var allKeys = pdf.MetaData.Keys();
$vbLabelText   $csharpLabel

배포 전에 민감한 메타데이터를 제거하려면:

입력

작성자 이름, 생성 시간, 사용자 지정 속성 등과 같은 메타데이터가 포함된 내부 메모는 조직의 민감한 정보를 드러낼 수 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/remove-metadata.cs
using IronPdf;
using System;

PdfDocument pdf = PdfDocument.FromFile("confidential-memo.pdf");

// Replace identifying metadata with generic values
pdf.MetaData.Author = "Organization Name";
pdf.MetaData.Creator = "Document System";
pdf.MetaData.Producer = "";
pdf.MetaData.Title = "Public Document";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";

// Normalize dates to remove timing information
pdf.MetaData.CreationDate = DateTime.Now;
pdf.MetaData.ModifiedDate = DateTime.Now;

// Remove specific custom metadata keys
pdf.MetaData.RemoveMetaDataKey("OriginalFilename");
pdf.MetaData.RemoveMetaDataKey("LastSavedBy");
pdf.MetaData.RemoveMetaDataKey("Company");
pdf.MetaData.RemoveMetaDataKey("Manager");

// Remove custom properties added by applications
try
{
    pdf.MetaData.CustomProperties.Remove("SourcePath");
}
catch { }

pdf.SaveAs("confidential-memo-cleaned.pdf");
$vbLabelText   $csharpLabel

이 코드는 식별 메타데이터 필드를 일반 값으로 대체하고, 타임스탬프를 현재 날짜로 정규화하며, 애플리케이션에서 추가했을 수 있는 사용자 지정 메타데이터 키를 제거합니다. RemoveMetaDataKey 메서드는 "OriginalFilename" 및 "LastSavedBy"와 같이 내부 정보를 노출할 수 있는 특정 속성을 대상으로 합니다.

샘플 출력

일괄 처리 전반에 걸친 철저한 메타데이터 정리를 위해서는 체계적인 접근 방식이 필요합니다.

using IronPdf;
using System;
using System.Collections.Generic;

public class MetadataCleaner
{
    private readonly string _defaultAuthor;
    private readonly string _defaultCreator;

    public MetadataCleaner(string organizationName)
    {
        _defaultAuthor = organizationName;
        _defaultCreator = $"{organizationName} Document System";
    }

    public void CleanMetadata(PdfDocument pdf)
    {
        // Replace standard metadata fields
        pdf.MetaData.Author = _defaultAuthor;
        pdf.MetaData.Creator = _defaultCreator;
        pdf.MetaData.Producer = "";
        pdf.MetaData.Subject = "";
        pdf.MetaData.Keywords = "";

        // Normalize timestamps
        DateTime now = DateTime.Now;
        pdf.MetaData.CreationDate = now;
        pdf.MetaData.ModifiedDate = now;

        // Get all keys and remove potentially sensitive ones
        List<string> keysToRemove = new List<string>();
        foreach (string key in pdf.MetaData.Keys())
        {
            // Keep only essential keys
            if (!IsEssentialKey(key))
            {
                keysToRemove.Add(key);
            }
        }

        foreach (string key in keysToRemove)
        {
            pdf.MetaData.RemoveMetaDataKey(key);
        }
    }

    private bool IsEssentialKey(string key)
    {
        // Keep only the basic display properties
        string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" };
        foreach (string essential in essentialKeys)
        {
            if (key.Equals(essential, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }
        return false;
    }
}

// Usage
class Program
{
    static void Main()
    {
        MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation");

        PdfDocument pdf = PdfDocument.FromFile("report.pdf");
        cleaner.CleanMetadata(pdf);
        pdf.SaveAs("report-clean.pdf");
    }
}
using IronPdf;
using System;
using System.Collections.Generic;

public class MetadataCleaner
{
    private readonly string _defaultAuthor;
    private readonly string _defaultCreator;

    public MetadataCleaner(string organizationName)
    {
        _defaultAuthor = organizationName;
        _defaultCreator = $"{organizationName} Document System";
    }

    public void CleanMetadata(PdfDocument pdf)
    {
        // Replace standard metadata fields
        pdf.MetaData.Author = _defaultAuthor;
        pdf.MetaData.Creator = _defaultCreator;
        pdf.MetaData.Producer = "";
        pdf.MetaData.Subject = "";
        pdf.MetaData.Keywords = "";

        // Normalize timestamps
        DateTime now = DateTime.Now;
        pdf.MetaData.CreationDate = now;
        pdf.MetaData.ModifiedDate = now;

        // Get all keys and remove potentially sensitive ones
        List<string> keysToRemove = new List<string>();
        foreach (string key in pdf.MetaData.Keys())
        {
            // Keep only essential keys
            if (!IsEssentialKey(key))
            {
                keysToRemove.Add(key);
            }
        }

        foreach (string key in keysToRemove)
        {
            pdf.MetaData.RemoveMetaDataKey(key);
        }
    }

    private bool IsEssentialKey(string key)
    {
        // Keep only the basic display properties
        string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" };
        foreach (string essential in essentialKeys)
        {
            if (key.Equals(essential, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }
        return false;
    }
}

// Usage
class Program
{
    static void Main()
    {
        MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation");

        PdfDocument pdf = PdfDocument.FromFile("report.pdf");
        cleaner.CleanMetadata(pdf);
        pdf.SaveAs("report-clean.pdf");
    }
}
$vbLabelText   $csharpLabel

PDF 파일에서 내장된 스크립트와 숨겨진 위협 요소를 제거하려면 어떻게 해야 할까요?

PDF 검증은 보이는 콘텐츠와 메타데이터를 넘어선 보안 문제를 해결합니다. PDF 파일에는 자바스크립트 코드, 내장 실행 파일, 외부 연결을 트리거하는 폼 작업 및 기타 잠재적으로 악의적인 요소가 포함될 수 있습니다. 이러한 기능은 대화형 양식 및 멀티미디어 콘텐츠와 같은 합법적인 목적을 위해 존재하지만, 공격 경로를 만들기도 합니다. PDF를 정리하면 이러한 활성 요소가 제거되지만 시각적 콘텐츠는 유지됩니다. 소독 방법에 대한 자세한 내용은 당사의 소독 방법 PDF 가이드를 참조하십시오.

IronPDF의 Cleaner 클래스는 PDF를 이미지 형식으로 변환한 다음 다시 PDF로 변환하는 우아한 접근 방식을 통해 정제 작업을 처리합니다. 이 프로세스는 시각적 모양을 그대로 유지하면서 JavaScript, 내장 객체, 폼 액션 및 주석을 제거합니다. 이 라이브러리는 서로 다른 특성을 가진 두 가지 소독 방법을 제공합니다.

입력

외부 소스에서 수신한 PDF 문서에는 JavaScript, 내장 객체 또는 기타 잠재적으로 악성적인 활성 콘텐츠가 포함될 수 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/sanitize-pdf.cs
using IronPdf;

// Load a PDF that may contain active content
PdfDocument pdf = PdfDocument.FromFile("received-document.pdf");

// Sanitize using SVG conversion
// Faster processing, results in searchable text, slight layout variations possible
PdfDocument sanitizedSvg = Cleaner.SanitizeWithSvg(pdf);
sanitizedSvg.SaveAs("sanitized-svg.pdf");

// Sanitize using Bitmap conversion
// Slower processing, text becomes image (not searchable), exact visual reproduction
PdfDocument sanitizedBitmap = Cleaner.SanitizeWithBitmap(pdf);
sanitizedBitmap.SaveAs("sanitized-bitmap.pdf");
$vbLabelText   $csharpLabel

이 코드는 IronPDF의 Cleaner 클래스에서 제공하는 두 가지 검증 방법을 보여줍니다. SanitizeWithSvg는 PDF를 SVG 중간 형식으로 변환하여 검색 가능한 텍스트를 유지하면서 활성 콘텐츠를 제거합니다. SanitizeWithBitmap는 먼저 페이지를 이미지로 변환하여 정확한 시각적 복사본을 생성하지만 텍스트는 검색할 수 없는 그래픽으로 렌더링합니다.

샘플 출력

SVG 방식은 속도가 더 빠르고 텍스트를 검색 가능한 콘텐츠로 유지하므로 색인화 또는 접근성이 유지되어야 하는 문서에 적합합니다. 비트맵 방식은 정확한 시각적 복사본을 생성하지만 텍스트를 이미지로 변환하기 때문에 텍스트 선택 및 검색이 불가능합니다. 출력 문서의 요구 사항에 따라 선택하십시오.

정제 과정에서 렌더링 옵션을 적용하여 출력 결과를 조정할 수도 있습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/sanitize-with-options.cs
using IronPdf;

// Load the potentially unsafe document
PdfDocument pdf = PdfDocument.FromFile("untrusted-source.pdf");

// Configure rendering options for sanitization
var renderOptions = new ChromePdfRenderOptions
{
    MarginTop = 10,
    MarginBottom = 10,
    MarginLeft = 10,
    MarginRight = 10
};

// Sanitize with custom options
PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf, renderOptions);
sanitized.SaveAs("untrusted-source-safe.pdf");
$vbLabelText   $csharpLabel

높은 보안이 요구되는 환경에서는 소독을 비롯한 다른 보호 조치를 병행해야 하는 경우가 많습니다.

using IronPdf;
using System;

public class SecureDocumentProcessor
{
    public PdfDocument ProcessUntrustedDocument(string inputPath)
    {
        // Load the document
        PdfDocument original = PdfDocument.FromFile(inputPath);

        // Step 1: Sanitize to remove active content
        PdfDocument sanitized = Cleaner.SanitizeWithSvg(original);

        // Step 2: Clean metadata
        sanitized.MetaData.Author = "Processed Document";
        sanitized.MetaData.Creator = "Secure Processor";
        sanitized.MetaData.Producer = "";
        sanitized.MetaData.CreationDate = DateTime.Now;
        sanitized.MetaData.ModifiedDate = DateTime.Now;

        // Remove all custom metadata
        foreach (string key in sanitized.MetaData.Keys())
        {
            if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate")
            {
                sanitized.MetaData.RemoveMetaDataKey(key);
            }
        }

        return sanitized;
    }
}

// Usage
class Program
{
    static void Main()
    {
        SecureDocumentProcessor processor = new SecureDocumentProcessor();
        PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf");
        safe.SaveAs("email-attachment-safe.pdf");
    }
}
using IronPdf;
using System;

public class SecureDocumentProcessor
{
    public PdfDocument ProcessUntrustedDocument(string inputPath)
    {
        // Load the document
        PdfDocument original = PdfDocument.FromFile(inputPath);

        // Step 1: Sanitize to remove active content
        PdfDocument sanitized = Cleaner.SanitizeWithSvg(original);

        // Step 2: Clean metadata
        sanitized.MetaData.Author = "Processed Document";
        sanitized.MetaData.Creator = "Secure Processor";
        sanitized.MetaData.Producer = "";
        sanitized.MetaData.CreationDate = DateTime.Now;
        sanitized.MetaData.ModifiedDate = DateTime.Now;

        // Remove all custom metadata
        foreach (string key in sanitized.MetaData.Keys())
        {
            if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate")
            {
                sanitized.MetaData.RemoveMetaDataKey(key);
            }
        }

        return sanitized;
    }
}

// Usage
class Program
{
    static void Main()
    {
        SecureDocumentProcessor processor = new SecureDocumentProcessor();
        PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf");
        safe.SaveAs("email-attachment-safe.pdf");
    }
}
$vbLabelText   $csharpLabel

PDF 파일에서 보안 취약점을 스캔하는 방법은 무엇인가요?

문서를 처리하거나 삭제하기 전에 문서에 어떤 잠재적 위협이 포함되어 있는지 평가하는 것이 좋습니다. IronPDF의 Cleaner.ScanPdf 메서드는 YARA 규칙을 사용하여 문서를 검사합니다. YARA 규칙은 악성코드 분석 및 위협 탐지에 일반적으로 사용되는 패턴 정의입니다. 이 검사는 악성 PDF 파일과 관련된 특징을 식별합니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/scan-vulnerabilities.cs
using IronPdf;

// Load the document to scan
PdfDocument pdf = PdfDocument.FromFile("suspicious-document.pdf");

// Scan using default YARA rules
CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);

// Check the scan results
bool threatsDetected = scanResult.IsDetected;
int riskCount = scanResult.Risks.Count;

// Process identified risks
if (scanResult.IsDetected)
{
    foreach (var risk in scanResult.Risks)
    {
        // Handle each identified risk
    }

    // Sanitize the document before use
    PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf);
    sanitized.SaveAs("suspicious-document-safe.pdf");
}
$vbLabelText   $csharpLabel

특수한 탐지 요구 사항에 맞춰 사용자 지정 YARA 규칙 파일을 제공할 수 있습니다. 특정 위협 모델이나 규정 준수 요구 사항을 가진 조직은 특정 취약점 패턴을 대상으로 하는 자체 규칙 세트를 유지하는 경우가 많습니다.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/scan-custom-yara.cs
using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("incoming-document.pdf");

// Scan with custom YARA rules
string[] customYaraFiles = { "corporate-rules.yar", "industry-specific.yar" };
CleanerScanResult result = Cleaner.ScanPdf(pdf, customYaraFiles);

if (result.IsDetected)
{
    // Document triggered custom rules and requires review or sanitization
    PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf);
    sanitized.SaveAs("incoming-document-safe.pdf");
}
$vbLabelText   $csharpLabel

문서 입력 워크플로에 스캔 기능을 통합하면 보안 관련 의사 결정을 자동화하는 데 도움이 됩니다.

using IronPdf;
using System;
using System.IO;

public enum DocumentSafetyLevel
{
    Safe,
    Suspicious,
    Dangerous
}

public class DocumentSecurityGateway
{
    public DocumentSafetyLevel EvaluateDocument(string filePath)
    {
        PdfDocument pdf = PdfDocument.FromFile(filePath);
        CleanerScanResult scan = Cleaner.ScanPdf(pdf);

        if (!scan.IsDetected)
        {
            return DocumentSafetyLevel.Safe;
        }

        // Evaluate severity based on number of risks
        if (scan.Risks.Count > 5)
        {
            return DocumentSafetyLevel.Dangerous;
        }

        return DocumentSafetyLevel.Suspicious;
    }

    public PdfDocument ProcessIncomingDocument(string filePath, string outputDirectory)
    {
        DocumentSafetyLevel safety = EvaluateDocument(filePath);
        string fileName = Path.GetFileName(filePath);

        switch (safety)
        {
            case DocumentSafetyLevel.Safe:
                return PdfDocument.FromFile(filePath);

            case DocumentSafetyLevel.Suspicious:
                PdfDocument suspicious = PdfDocument.FromFile(filePath);
                return Cleaner.SanitizeWithSvg(suspicious);

            case DocumentSafetyLevel.Dangerous:
                throw new SecurityException($"Document {fileName} contains dangerous content");

            default:
                throw new InvalidOperationException("Unknown safety level");
        }
    }
}
using IronPdf;
using System;
using System.IO;

public enum DocumentSafetyLevel
{
    Safe,
    Suspicious,
    Dangerous
}

public class DocumentSecurityGateway
{
    public DocumentSafetyLevel EvaluateDocument(string filePath)
    {
        PdfDocument pdf = PdfDocument.FromFile(filePath);
        CleanerScanResult scan = Cleaner.ScanPdf(pdf);

        if (!scan.IsDetected)
        {
            return DocumentSafetyLevel.Safe;
        }

        // Evaluate severity based on number of risks
        if (scan.Risks.Count > 5)
        {
            return DocumentSafetyLevel.Dangerous;
        }

        return DocumentSafetyLevel.Suspicious;
    }

    public PdfDocument ProcessIncomingDocument(string filePath, string outputDirectory)
    {
        DocumentSafetyLevel safety = EvaluateDocument(filePath);
        string fileName = Path.GetFileName(filePath);

        switch (safety)
        {
            case DocumentSafetyLevel.Safe:
                return PdfDocument.FromFile(filePath);

            case DocumentSafetyLevel.Suspicious:
                PdfDocument suspicious = PdfDocument.FromFile(filePath);
                return Cleaner.SanitizeWithSvg(suspicious);

            case DocumentSafetyLevel.Dangerous:
                throw new SecurityException($"Document {fileName} contains dangerous content");

            default:
                throw new InvalidOperationException("Unknown safety level");
        }
    }
}
$vbLabelText   $csharpLabel

완벽한 데이터 삭제 및 정제 파이프라인을 구축하려면 어떻게 해야 할까요?

제작 문서 처리에는 일반적으로 여러 보호 기술을 통합된 워크플로로 결합하는 작업이 필요합니다. 완전한 파이프라인은 수신 문서를 스캔하여 위협 요소를 탐지하고, 초기 검사를 통과한 문서를 검증하고, 텍스트 및 영역 정보를 삭제하고, 메타데이터를 제거하고, 수행된 모든 작업을 기록하는 감사 로그를 생성할 수 있습니다. 이 예시는 그러한 통합적 접근 방식을 보여줍니다.

using IronPdf;
using IronSoftware.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

public class DocumentProcessingResult
{
    public string OriginalFile { get; set; }
    public string OutputFile { get; set; }
    public bool WasSanitized { get; set; }
    public int TextRedactionsApplied { get; set; }
    public int RegionRedactionsApplied { get; set; }
    public bool MetadataCleaned { get; set; }
    public List<string> SensitiveDataTypesFound { get; set; } = new List<string>();
    public DateTime ProcessedAt { get; set; }
    public bool Success { get; set; }
    public string ErrorMessage { get; set; }
}

public class ComprehensiveDocumentProcessor
{
    // Sensitive data patterns
    private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string>
    {
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
        { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }
    };

    // Standard regions to redact (signature areas, photo locations)
    private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF>
    {
        new RectangleF(72, 72, 200, 50),    // Bottom left signature
        new RectangleF(350, 72, 200, 50)    // Bottom right signature
    };

    private readonly string _organizationName;

    public ComprehensiveDocumentProcessor(string organizationName)
    {
        _organizationName = organizationName;
    }

    public DocumentProcessingResult ProcessDocument(
        string inputPath,
        string outputPath,
        bool sanitize = true,
        bool redactPatterns = true,
        bool redactRegions = true,
        bool cleanMetadata = true,
        List<string> additionalTermsToRedact = null)
    {
        var result = new DocumentProcessingResult
        {
            OriginalFile = inputPath,
            OutputFile = outputPath,
            ProcessedAt = DateTime.Now
        };

        try
        {
            // Load the document
            PdfDocument pdf = PdfDocument.FromFile(inputPath);

            // Step 1: Security scan
            CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);

            if (scanResult.IsDetected && scanResult.Risks.Count > 10)
            {
                throw new SecurityException("Document contains too many security risks to process");
            }

            // Step 2: Sanitization (if needed or requested)
            if (sanitize || scanResult.IsDetected)
            {
                pdf = Cleaner.SanitizeWithSvg(pdf);
                result.WasSanitized = true;
            }

            // Step 3: Pattern-based text redaction
            if (redactPatterns)
            {
                string fullText = pdf.ExtractAllText();
                HashSet<string> valuesToRedact = new HashSet<string>();

                foreach (var pattern in _sensitivePatterns)
                {
                    Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                    MatchCollection matches = regex.Matches(fullText);

                    if (matches.Count > 0)
                    {
                        result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})");
                        foreach (Match match in matches)
                        {
                            valuesToRedact.Add(match.Value);
                        }
                    }
                }

                // Apply redactions
                foreach (string value in valuesToRedact)
                {
                    pdf.RedactTextOnAllPages(value);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 4: Additional specific terms
            if (additionalTermsToRedact != null)
            {
                foreach (string term in additionalTermsToRedact)
                {
                    pdf.RedactTextOnAllPages(term);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 5: Region-based redaction
            if (redactRegions)
            {
                foreach (RectangleF region in _standardRedactionRegions)
                {
                    pdf.RedactRegionsOnAllPages(region);
                    result.RegionRedactionsApplied++;
                }
            }

            // Step 6: Metadata cleaning
            if (cleanMetadata)
            {
                pdf.MetaData.Author = _organizationName;
                pdf.MetaData.Creator = $"{_organizationName} Document Processor";
                pdf.MetaData.Producer = "";
                pdf.MetaData.Subject = "";
                pdf.MetaData.Keywords = "";
                pdf.MetaData.CreationDate = DateTime.Now;
                pdf.MetaData.ModifiedDate = DateTime.Now;
                result.MetadataCleaned = true;
            }

            // Step 7: Save the processed document
            pdf.SaveAs(outputPath);
            result.Success = true;
        }
        catch (Exception ex)
        {
            result.Success = false;
            result.ErrorMessage = ex.Message;
        }

        return result;
    }
}

// Usage example
class Program
{
    static void Main()
    {
        var processor = new ComprehensiveDocumentProcessor("Acme Corporation");

        // Process a single document with all protections
        var result = processor.ProcessDocument(
            inputPath: "customer-application.pdf",
            outputPath: "customer-application-redacted.pdf",
            sanitize: true,
            redactPatterns: true,
            redactRegions: true,
            cleanMetadata: true,
            additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" }
        );

        // Batch process multiple documents
        string[] inputFiles = Directory.GetFiles("incoming", "*.pdf");
        foreach (string file in inputFiles)
        {
            string outputFile = Path.Combine("processed", Path.GetFileName(file));
            processor.ProcessDocument(file, outputFile);
        }
    }
}
using IronPdf;
using IronSoftware.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

public class DocumentProcessingResult
{
    public string OriginalFile { get; set; }
    public string OutputFile { get; set; }
    public bool WasSanitized { get; set; }
    public int TextRedactionsApplied { get; set; }
    public int RegionRedactionsApplied { get; set; }
    public bool MetadataCleaned { get; set; }
    public List<string> SensitiveDataTypesFound { get; set; } = new List<string>();
    public DateTime ProcessedAt { get; set; }
    public bool Success { get; set; }
    public string ErrorMessage { get; set; }
}

public class ComprehensiveDocumentProcessor
{
    // Sensitive data patterns
    private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string>
    {
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
        { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }
    };

    // Standard regions to redact (signature areas, photo locations)
    private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF>
    {
        new RectangleF(72, 72, 200, 50),    // Bottom left signature
        new RectangleF(350, 72, 200, 50)    // Bottom right signature
    };

    private readonly string _organizationName;

    public ComprehensiveDocumentProcessor(string organizationName)
    {
        _organizationName = organizationName;
    }

    public DocumentProcessingResult ProcessDocument(
        string inputPath,
        string outputPath,
        bool sanitize = true,
        bool redactPatterns = true,
        bool redactRegions = true,
        bool cleanMetadata = true,
        List<string> additionalTermsToRedact = null)
    {
        var result = new DocumentProcessingResult
        {
            OriginalFile = inputPath,
            OutputFile = outputPath,
            ProcessedAt = DateTime.Now
        };

        try
        {
            // Load the document
            PdfDocument pdf = PdfDocument.FromFile(inputPath);

            // Step 1: Security scan
            CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);

            if (scanResult.IsDetected && scanResult.Risks.Count > 10)
            {
                throw new SecurityException("Document contains too many security risks to process");
            }

            // Step 2: Sanitization (if needed or requested)
            if (sanitize || scanResult.IsDetected)
            {
                pdf = Cleaner.SanitizeWithSvg(pdf);
                result.WasSanitized = true;
            }

            // Step 3: Pattern-based text redaction
            if (redactPatterns)
            {
                string fullText = pdf.ExtractAllText();
                HashSet<string> valuesToRedact = new HashSet<string>();

                foreach (var pattern in _sensitivePatterns)
                {
                    Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                    MatchCollection matches = regex.Matches(fullText);

                    if (matches.Count > 0)
                    {
                        result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})");
                        foreach (Match match in matches)
                        {
                            valuesToRedact.Add(match.Value);
                        }
                    }
                }

                // Apply redactions
                foreach (string value in valuesToRedact)
                {
                    pdf.RedactTextOnAllPages(value);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 4: Additional specific terms
            if (additionalTermsToRedact != null)
            {
                foreach (string term in additionalTermsToRedact)
                {
                    pdf.RedactTextOnAllPages(term);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 5: Region-based redaction
            if (redactRegions)
            {
                foreach (RectangleF region in _standardRedactionRegions)
                {
                    pdf.RedactRegionsOnAllPages(region);
                    result.RegionRedactionsApplied++;
                }
            }

            // Step 6: Metadata cleaning
            if (cleanMetadata)
            {
                pdf.MetaData.Author = _organizationName;
                pdf.MetaData.Creator = $"{_organizationName} Document Processor";
                pdf.MetaData.Producer = "";
                pdf.MetaData.Subject = "";
                pdf.MetaData.Keywords = "";
                pdf.MetaData.CreationDate = DateTime.Now;
                pdf.MetaData.ModifiedDate = DateTime.Now;
                result.MetadataCleaned = true;
            }

            // Step 7: Save the processed document
            pdf.SaveAs(outputPath);
            result.Success = true;
        }
        catch (Exception ex)
        {
            result.Success = false;
            result.ErrorMessage = ex.Message;
        }

        return result;
    }
}

// Usage example
class Program
{
    static void Main()
    {
        var processor = new ComprehensiveDocumentProcessor("Acme Corporation");

        // Process a single document with all protections
        var result = processor.ProcessDocument(
            inputPath: "customer-application.pdf",
            outputPath: "customer-application-redacted.pdf",
            sanitize: true,
            redactPatterns: true,
            redactRegions: true,
            cleanMetadata: true,
            additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" }
        );

        // Batch process multiple documents
        string[] inputFiles = Directory.GetFiles("incoming", "*.pdf");
        foreach (string file in inputFiles)
        {
            string outputFile = Path.Combine("processed", Path.GetFileName(file));
            processor.ProcessDocument(file, outputFile);
        }
    }
}
$vbLabelText   $csharpLabel

입력

고객 신청서에는 사회보장번호, 신용카드 번호, 이메일 주소, 서명란 등 여러 유형의 민감한 데이터가 포함되어 있어 철저한 보호가 필요합니다.

샘플 출력

이 종합 프로세서는 이 가이드에서 다룬 모든 기술을 하나의 구성 가능한 클래스로 결합합니다. 이 프로그램은 위협 요소를 탐지하고, 필요한 경우 정보를 삭제하고, 민감한 패턴을 찾아 수정하고, 지역별 수정 사항을 적용하고, 메타데이터를 정리하고, 상세 보고서를 생성합니다. 사용자의 특정 요구 사항에 맞게 민감도 패턴, 수정 영역 및 처리 옵션을 조정할 수 있습니다.


다음 단계

PDF 문서에서 중요한 정보를 보호하려면 표면적인 조치 이상의 것이 필요합니다. 진정한 내용 삭제는 문서 구조에서 콘텐츠를 영구적으로 제거합니다. 패턴 매칭은 사회 보장 번호, 신용 카드 정보, 이메일 주소와 같은 데이터를 자동으로 찾아내고 제거합니다. 영역 기반 수정 기능은 텍스트 일치로 처리할 수 없는 서명, 사진 및 기타 그래픽 요소를 처리합니다. 메타데이터 정리는 작성자, 타임스탬프 또는 내부 파일 경로와 같은 숨겨진 정보를 제거합니다. 보안 위험을 초래하는 내장 스크립트와 활성 콘텐츠를 제거하는 작업이 수행됩니다.

IronPDF는 C# 및 .NET 개발 방식과 자연스럽게 통합되는 일관되고 잘 설계된 API를 통해 이러한 모든 기능을 제공합니다. 이 가이드에서 설명하는 방법은 단일 문서를 처리하거나 수천 개의 파일을 일괄 처리하는 데까지 확장할 수 있습니다. 의료 데이터에 대한 규정 준수 워크플로를 구축하든, 소송을 위한 법률 문서를 준비하든, 또는 단순히 내부 보고서를 외부와 안전하게 공유할 수 있도록 보장하든, 이러한 기술은 책임감 있는 문서 관리의 기초를 형성합니다. 포괄적인 보안을 위해서는 정보 삭제 기능을 비밀번호 보호, 권한 설정디지털 서명 과 함께 사용하십시오.

건축을 시작할 준비가 되셨나요? IronPDF를 다운로드 하고 무료 체험판을 사용해 보세요. 이 라이브러리에는 무료 개발 라이선스가 포함되어 있으므로 프로덕션 라이선스를 구매하기 전에 수정, 텍스트 추출 및 정제 기능을 충분히 평가할 수 있습니다. 구현 또는 규정 준수 워크플로에 대해 궁금한 점이 있으면 엔지니어링 지원팀에 문의하십시오 .

자주 묻는 질문

PDF 수정이란 무엇인가요?

PDF 문서 수정은 PDF 문서에서 민감한 정보를 영구적으로 제거하는 과정입니다. 여기에는 개인 정보 보호 또는 규정 준수상의 이유로 숨겨야 하는 텍스트, 이미지 및 메타데이터가 포함될 수 있습니다.

C#을 사용하여 PDF에서 정보를 삭제하려면 어떻게 해야 하나요?

IronPDF를 사용하면 C#으로 PDF 문서의 정보를 수정할 수 있습니다. 이를 통해 PDF 문서에서 텍스트, 이미지 및 메타데이터를 영구적으로 제거하거나 숨길 수 있으므로 개인 정보 보호 및 규정 준수 기준을 충족할 수 있습니다.

PDF 문서 수정이 규정 준수에 중요한 이유는 무엇입니까?

PDF 문서 수정은 HIPAA, GDPR, PCI DSS와 같은 표준을 준수하는 데 매우 중요합니다. 민감한 데이터를 보호하고 기밀 정보에 대한 무단 접근을 방지하는 데 도움이 되기 때문입니다.

IronPDF는 PDF의 특정 영역 전체를 삭제할 수 있나요?

네, IronPDF는 PDF 문서의 특정 영역을 숨길 수 있습니다. 이를 통해 보안상의 이유로 문서 내 특정 영역을 숨기거나 삭제할 수 있습니다.

IronPDF를 사용하여 어떤 유형의 데이터를 삭제할 수 있습니까?

IronPDF는 PDF 문서에서 텍스트, 이미지, 메타데이터를 포함한 다양한 유형의 데이터를 삭제하여 완벽한 데이터 개인 정보 보호 및 보안을 보장합니다.

IronPDF는 문서 검증 기능을 지원합니까?

네, IronPDF는 문서 정리 기능을 지원합니다. 이 기능은 PDF에서 눈에 보이지 않지만 개인정보 침해의 소지가 될 수 있는 숨겨진 데이터나 메타데이터를 제거하는 것을 포함합니다.

IronPDF를 사용하여 PDF 문서 수정 작업을 자동화할 수 있습니까?

네, IronPDF는 C#을 사용하여 PDF 문서 수정 프로세스를 자동화할 수 있도록 지원하므로 민감한 데이터를 제거해야 하는 대량의 문서를 더 쉽게 처리할 수 있습니다.

IronPDF는 어떻게 수정 내용의 영구성을 보장합니까?

IronPDF는 선택한 텍스트와 이미지를 단순히 가리는 것이 아니라 문서에서 영구적으로 제거하여 수정 내용의 영구성을 보장합니다. 따라서 수정된 텍스트와 이미지는 복구하거나 볼 수 없습니다.

IronPDF는 PDF의 메타데이터를 삭제할 수 있나요?

예, IronPDF는 PDF 문서의 메타데이터를 수정하여 숨겨진 데이터나 배경 데이터를 포함한 모든 형태의 민감한 데이터를 완전히 제거할 수 있습니다.

PDF 수정 작업에 IronPDF를 사용하면 어떤 이점이 있나요?

IronPDF를 사용하여 PDF 내용을 수정하면 데이터 보호 규정 준수, 문서 보안 강화, 민감한 정보를 관리하는 효율적이고 자동화된 프로세스 제공과 같은 이점을 얻을 수 있습니다.

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.

시작할 준비 되셨나요?
Nuget 다운로드 17,527,568 | 버전: 2026.2 방금 출시되었습니다