본문으로 건너뛰기
Analytics Vidhya조회 2

Claude 워터마크는 텍스트·코드·파일마다 제거 방식이 다르다.

Claude 워터마크는 텍스트 재작성, 코드 AST 변환, 파일 파생물 생성으로 대응한다.

이 요약은 AI가 원문을 분석해 생성했습니다. 정확한 내용은 원문 기준으로 확인하세요.

TL;DR

Claude는 텍스트에 숨은 문자를 넣는 대신 단어 선택의 무작위성을 조정해 통계적 워터마크를 만들고, 지원 파일에는 서명된 C2PA 콘텐츠 자격 증명을 메타데이터로 붙인다. 텍스트는 복사나 파일 이동으로 신호가 사라지지 않으므로 문장 구조를 크게 다시 쓰거나 다른 LLM으로 바꿔써야 하며, 완전한 제거 여부는 탐지기로 확인해야 한다. 코드는 Python AST를 이용해 식별자와 독스트링을 바꿀 수 있지만 변환 후 실행 검사가 필요하다. 파일은 c2pa-python으로 매니페스트를 먼저 확인한 뒤 새 파생물을 만들고 결과를 검증하는 방식으로 처리하며, 문서에 명시되지 않은 PDF 지원 범위까지 일반화해서는 안 된다.

섹션별 상세

01
Claude의 생성물에는 유형에 따라 서로 다른 출처 표시 방식이 적용된다. 텍스트는 숨은 문자 대신 단어 선택 과정의 무작위성을 조정해 통계적 패턴을 남기고, 지원 파일은 서명된 C2PA 콘텐츠 자격 증명을 메타데이터에 기록한다. 따라서 텍스트와 파일은 같은 방식으로 처리할 수 없으며, 코드는 텍스트에 속하지만 문법 제약 때문에 일반 문장보다 워터마크가 약하게 작동한다.
AI가 생성한 것으로 판별된 검은 개 이미지와 SynthID, 눈에 보이는 별 모양 워터마크를 함께 보여주는 화면이다.
Screenshot이미지는 SynthID가 AI 생성 이미지의 출처를 판별하는 사례를 시각화한다. 글의 핵심 주제인 Claude의 텍스트 워터마크와 C2PA 파일 메타데이터를 직접 보여주지는 않지만, AI 생성물에 출처 신호를 부여하고 탐지하는 워터마킹 개념과 연결된다.
02
텍스트 워터마크는 파일 안의 특정 문자열이나 숨은 문자를 찾아 삭제하는 방식으로 제거되지 않는다. 문장을 다른 편집기에 복사해도 단어 선택의 패턴이 유지되므로, 사실과 의미를 보존하면서 문장 구조와 문단을 상당히 다시 쓰거나 다른 LLM으로 바꿔써야 원래 통계 패턴을 줄일 수 있다. 글은 OpenAI-compatible endpoint와 gpt-5를 이용해 입력 파일을 새 표현으로 재작성하는 Python 코드를 제시하지만, 탐지기로 결과를 확인하지 않는 한 완전한 제거를 보장하지 않는다.
python
import os
from openai import OpenAI

def rewrite_text(text: str) -> str:
    client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
    prompt = f"""
Rewrite the following text completely in new wording.
Rules:
- Preserve the facts and meaning.
- Preserve technical accuracy.
- Change sentence structure throughout.
- Do not merely replace a few words with synonyms.
- Rebuild paragraphs where useful.
- Return only the rewritten text.
TEXT:
{text}
"""
    response = client.responses.create(
        model=os.getenv("REWRITE_MODEL", "gpt-5"),
        input=prompt,
    )
    return response.output_text

if __name__ == "__main__":
    original = open("input.txt", "r", encoding="utf-8").read()
    rewritten = rewrite_text(original)
    with open("output.txt", "w", encoding="utf-8") as f:
        f.write(rewritten)

Claude가 만든 텍스트를 다른 LLM의 OpenAI-compatible endpoint로 다시 작성해 문장 선택 패턴을 바꾼다.

언어 모델의 토큰 확률과 무작위 워터마킹 함수가 다음 토큰 선택에 연결되는 구조도다.
Diagram최근 문맥에서 후보 토큰과 확률을 가져온 뒤 무작위 시드와 워터마킹 함수를 사용해 토큰 선택에 영향을 주는 흐름을 나타낸다. 이는 Claude 텍스트 워터마크가 숨은 문자 삽입이 아니라 모델의 단어 선택 통계에 패턴을 남긴다는 설명을 이해하는 데 직접 연결된다.
여러 후보 토큰을 워터마크 함수별 토너먼트로 비교해 최종 출력 토큰을 고르는 과정도다.
Diagram후보 토큰을 여러 차례 비교하면서 g₁, g₂, g₃ 같은 워터마킹 함수의 승자를 선택하고 최종적으로 mango를 출력하는 절차를 보여준다. 모델이 여러 표현 중 하나를 고르는 과정에 워터마킹 신호가 분산될 수 있다는 글의 작동 원리를 보완한다.
03
코드는 실행에 필요한 키워드와 API 호출이 고정되어 있어 임의의 단어 선택이 적고, 변경 가능한 영역은 식별자·주석·서식·독스트링에 집중된다. Python AST로 소스 코드를 파싱한 뒤 로컬 식별자를 새 이름으로 바꾸고 독스트링을 제거하며 ast.unparse로 다시 생성하면 프로그램 구조를 유지한 변환이 가능하다. 다만 AST 재구성은 서식과 일부 소스 수준 세부 사항을 바꿀 수 있으므로 변환 후 프로그램을 실행해 동작을 확인해야 한다.
python
import ast
import keyword
import random
import string
from pathlib import Path

class IdentifierRenamer(ast.NodeTransformer):
    def __init__(self, seed: int = 42):
        self.rng = random.Random(seed)
        self.mapping = {}

    def _new_name(self, old_name: str) -> str:
        if old_name in self.mapping:
            return self.mapping[old_name]
        prefix = random.choice(["tmp", "value", "item", "obj", "data"])
        suffix = "".join(
            self.rng.choice(string.ascii_lowercase) for _ in range(5)
        )
        candidate = f"{prefix}_{suffix}"
        while keyword.iskeyword(candidate):
            suffix = "".join(
                self.rng.choice(string.ascii_lowercase) for _ in range(6)
            )
            candidate = f"{prefix}_{suffix}"
        self.mapping[old_name] = candidate
        return candidate

    def visit_Name(self, node):
        node.id = self._new_name(node.id)
        return self.generic_visit(node)

    def visit_arg(self, node):
        node.arg = self._new_name(node.arg)
        return self.generic_visit(node)

    def visit_alias(self, node):
        if node.asname:
            node.asname = self._new_name(node.asname)
        return self.generic_visit(node)

def remove_docstrings(tree: ast.AST) -> None:
    for node in ast.walk(tree):
        if not isinstance(node, (ast.Module, ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
            continue
        if not node.body:
            continue
        first = node.body[0]
        if (
            isinstance(first, ast.Expr)
            and isinstance(first.value, ast.Constant)
            and isinstance(first.value.value, str)
        ):
            node.body.pop(0)

def rewrite_python(source: str) -> str:
    tree = ast.parse(source)
    remove_docstrings(tree)
    transformer = IdentifierRenamer()
    tree = transformer.visit(tree)
    ast.fix_missing_locations(tree)
    return ast.unparse(tree)

def rewrite_file(input_path: str, output_path: str) -> None:
    source = Path(input_path).read_text(encoding="utf-8")
    rewritten = rewrite_python(source)
    Path(output_path).write_text(
        rewritten,
        encoding="utf-8",
    )

if __name__ == "__main__":
    rewrite_file(
        "input.py",
        "rewritten.py",
    )

Python AST로 코드의 식별자와 독스트링을 바꾸고 재생성해 실행 구조를 보존하면서 소스 표현을 변환한다.

04
지원 파일의 C2PA 자격 증명은 이미지 픽셀에 박힌 신호가 아니라 파일 헤더에 함께 저장되는 메타데이터다. c2pa-python의 Context와 Reader를 이용하면 이미지에 읽을 수 있는 매니페스트가 존재하는지 먼저 검사하고 JSON으로 내용을 확인할 수 있으며, 형식 변환·재저장·스크린샷처럼 새 파생 파일을 만드는 작업은 기존 매니페스트와의 연결을 끊을 수 있다. 다만 Anthropic이 문서에서 명시한 예시는 .svg·.png·.jpg이므로 모든 PDF에 워터마크가 있다고 일반화해서는 안 된다.
bash
pip install c2pa-python

C2PA 매니페스트를 읽고 검증하는 Python 라이브러리를 설치한다.

python
import json
from c2pa import Context, Reader

def inspect_c2pa(path: str) -> dict | None:
    try:
        with Context() as context:
            with Reader(path, context=context) as reader:
                data = reader.json()
        return json.loads(data)
    except Exception as exc:
        print(f"No readable C2PA manifest: {exc}")
        return None

if __name__ == "__main__":
    manifest = inspect_c2pa("image.png")
    if manifest:
        print(json.dumps(manifest, indent=2))

파일을 열어 C2PA 매니페스트가 있는지 확인하고, 읽을 수 있는 경우 JSON 형태로 출력한다.

Python의 inspect_c2pa 함수로 파일을 검사하고 C2PA 자격 증명 존재 여부에 따라 새 파생물 생성과 검증으로 분기하는 흐름도다.
Diagram파일을 먼저 검사해 C2PA 매니페스트가 있는지 판단한 뒤, 존재하면 재저장·변환·재내보내기로 새 파생물을 만들고 inspect_c2pa로 다시 확인하는 절차를 표현한다. 새 파일에 자격 증명이 남아 있으면 다른 생성 방식을 시도하고, 없으면 제거 결과를 확인하는 글의 실무 흐름과 맞닿아 있다.
05
텍스트는 완전한 재작성으로 원래 워터마크를 제거할 가능성이 있지만 가벼운 편집만으로는 충분하지 않고, 코드는 의미 있는 소스 변환이 필요하며, 파일은 새 파생물을 만든 뒤 C2PA 상태를 검증하는 흐름이 적절하다. 글은 텍스트·코드·파일을 각각 통계적 워터마크·약한 동일 메커니즘·서명된 provenance로 구분한다. 특히 메타데이터를 무작정 지우기보다 먼저 매니페스트를 검사하고, 코드 변환 뒤에는 실행 결과를 확인하는 절차를 요구한다.

용어 해설

SynthID-Text
SynthID-Text는 텍스트에 별도 문자나 파일 메타데이터를 삽입하지 않고, 언어 모델이 다음 단어를 선택할 때 사용하는 무작위성의 방향을 조정하는 방식이다. 충분히 긴 문장에 통계적 패턴이 누적되면 탐지기가 이를 근거로 생성 출처를 판별할 수 있다.
C2PA 콘텐츠 자격 증명(C2PA)
C2PA는 이미지와 같은 파일에 콘텐츠의 출처와 처리 이력을 기록하는 서명된 자격 증명 표준이다. Claude가 지원하는 파일에서는 이 정보가 픽셀 자체가 아니라 파일 메타데이터에 저장되므로, 새 파생 파일을 만들면 기존 매니페스트와의 연결이 끊길 수 있다.
추상 구문 트리(Abstract Syntax Tree)
Abstract Syntax Tree는 소스 코드를 문법 구조에 따라 트리 형태로 표현한 자료 구조다. Python 코드를 AST로 읽은 뒤 식별자와 주석, 독스트링을 바꾸고 다시 소스 코드로 생성하면 실행 구조를 유지하면서 원래 텍스트의 표면 패턴을 크게 바꿀 수 있다.
바꿔쓰기(Paraphrasing)
Paraphrasing은 원문의 사실과 의미를 유지하면서 문장 구조와 표현을 다시 구성하는 작업이다. Claude의 텍스트 워터마크처럼 여러 단어 선택에 분산된 통계 패턴은 단순 복사나 파일 이동으로 사라지지 않지만, 상당한 바꿔쓰기로 패턴을 약화할 수 있다.
워터마킹(Watermarking)
워터마킹은 생성물에 출처를 식별할 수 있는 신호를 넣는 기술이다. 이 글에서 텍스트는 단어 선택의 통계 패턴을, 지원 파일은 서명된 C2PA 메타데이터를 사용하며, 코드에서는 문법 제약 때문에 일반 문장보다 선택 가능한 지점이 적다.

기술

  • Claude
  • SynthID-Text
  • C2PA
  • Python
  • OpenAI-compatible endpoint
  • gpt-5
  • c2pa-python
  • Python AST
  • Quillbot

활용 사례

  • Claude가 생성한 텍스트의 출처 패턴을 다른 표현으로 재작성하는 작업
  • Python 코드의 식별자·주석·독스트링을 AST 기반으로 변환하는 작업
  • 이미지 파일의 C2PA 매니페스트 존재 여부를 검사하는 작업
  • 파일을 재저장하거나 변환한 뒤 C2PA 자격 증명을 다시 검증하는 작업
AI 분석 전체 내용 보기

AI 요약 · 북마크 · 개인 피드 설정 — 무료

출처 · 인용 안내

원문 발행 2026. 08. 19.수집 2026. 08. 19.출처 타입 RSS

인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.