Claude 워터마크 직접 재현하기 — 로컬 모델에 SynthID-Text 걸고 탐지·공격 실험
Claude가 채택한 SynthID-Text를 Gemma 2 2B에 직접 적용해 실험했습니다. 키가 없으면 탐지가 왜 불가능한지, 몇 토큰부터 탐지되는지, 짧은 글에서 오탐이 왜 폭발하는지, 그리고 로컬 3B 모델 재작성 한 번에 워터마크가 어떻게 사라지는지를 숫자로 보여드립니다.

Claude 워터마크 직접 재현하기 -- 로컬 모델에 SynthID-Text 걸고 탐지·공격 실험
Part 1에서 Claude 텍스트 워터마크의 원리를 설명했습니다. 이번에는 말로만 하지 않고 직접 돌려봅니다. Claude 자체는 시크릿 키가 Anthropic에만 있어서 검증할 수 없지만, Claude가 채택했다고 밝힌 SynthID-Text 알고리즘은 Hugging Face `transformers`에 이미 구현되어 있습니다. 같은 알고리즘을 로컬 오픈 모델(Gemma 2 2B)에 걸고, 탐지가 얼마나 잘 되는지, 몇 토큰부터 되는지, 어떻게 하면 지워지는지를 숫자로 확인합니다.
이 글은 Claude 워터마크 시리즈 2부작 중 Part 2입니다.
- Part 1: 워터마크가 동작하는 원리 -- 샘플링, 시크릿 키, 토너먼트, 탐지, 그리고 한계
- Part 2 (이 글): 같은 알고리즘을 로컬 오픈 모델에 직접 적용해 생성·탐지·공격 실험하기
전체 코드는 노트북(claude-watermark-part2-tutorial.ipynb)으로 제공합니다. A100 한 장 기준 약 30분이면 전부 재현됩니다.
1. 실험 설계
| 항목 | 설정 |
|---|---|
| 생성 모델 | google/gemma-2-2b-it (bf16) |
| 워터마크 | SynthIDTextWatermarkingConfig(keys=[20개 정수], ngram_len=5) -- 깊이 20, 직전 4토큰이 씨앗 |
| 샘플링 | temperature 1.0, top-k 40, 최대 220 토큰 |
| 프롬프트 | "~에 대해 200단어 에세이를 써라" × 50개 주제 (하늘이 파란 이유, 백신, 인쇄술, 체스 규칙 등) |
| 조건 | 각 프롬프트를 워터마크 있음/없음으로 1회씩 생성 → 텍스트 100개, 평균 218 토큰 |
| 탐지기 | 논문의 가장 단순한 형태: 선택된 토큰의 g-value 평균 (반복 컨텍스트 마스킹 적용) |
| 임계값 | 워터마크 없는 텍스트 50개 점수의 99퍼센타일 = 0.514. 즉 "오탐 1%" 기준 |
탐지기를 단순 평균으로 둔 이유는 두 가지입니다. 첫째, Part 1에서 설명한 "0.5와의 싸움"이 그대로 눈에 보입니다. 둘째, 논문의 학습된 베이지안 탐지기보다 보수적이므로 여기서 나온 탐지율은 하한선으로 읽으면 됩니다. Anthropic의 실제 탐지 API는 이보다 잘 될 겁니다.
코드는 놀랄 만큼 짧습니다. 워터마크를 켜는 건 generate()에 인자 하나를 넘기는 것이 전부입니다.
from transformers import (AutoTokenizer, AutoModelForCausalLM,
SynthIDTextWatermarkingConfig, SynthIDTextWatermarkLogitsProcessor)
cfg = SynthIDTextWatermarkingConfig(keys=KEYS, ngram_len=5) # KEYS: 정수 20개
out = model.generate(ids, do_sample=True, temperature=1.0, top_k=40,
max_new_tokens=220, watermarking_config=cfg) # 이 한 줄탐지기는 같은 키로 LogitsProcessor를 만들어 g-value를 재계산하면 됩니다. 모델은 필요 없습니다.
lp = SynthIDTextWatermarkLogitsProcessor(**cfg.to_dict(), device="cuda")
def score(ids):
g = lp.compute_g_values(ids).float() # [1, T, depth]
mask = lp.compute_context_repetition_mask(ids).float()[..., None]
return ((g * mask).sum() / (mask.sum() * g.shape[-1])).item() # 0.5면 무표식2. 결과 1: 키가 있으면 완벽히 갈리고, 없으면 아무것도 안 보인다

| 조건 | 평균 g-value | 범위 | 탐지율 (임계값 0.514) |
|---|---|---|---|
| 워터마크 없음 | 0.500 ± 0.006 | 0.488 ~ 0.517 | -- (정의상 ≤1%) |
| 워터마크 있음, 맞는 키 | 0.575 ± 0.014 | 0.549 ~ 0.607 | 100% (50/50) |
| 워터마크 있음, 틀린 키 | 0.501 | -- | 2% (1/50) |
| 사람이 쓴 문단 3개 | 0.502, 0.494, 0.512 | -- | 0% |
두 분포가 전혀 겹치지 않습니다. 워터마크 텍스트의 최저점(0.549)이 일반 텍스트의 최고점(0.517)보다 한참 위에 있습니다. 200토큰 정도면 단순 평균만으로도 완벽하게 구분됩니다.
더 중요한 건 주황색 막대입니다. 키의 정수값을 전부 1씩만 바꿔서 탐지를 시도하면 워터마크 텍스트는 평균 0.501, 즉 일반 텍스트와 구분이 안 됩니다. Part 1에서 "키 없이는 탐지가 불가능하다"고 한 것이 이론이 아니라 이렇게 생긴다는 뜻입니다. Anthropic 외에는 아무도 Claude 탐지기를 만들 수 없는 이유입니다.
3. 결과 2: 몇 토큰이면 탐지되는가 -- 그리고 함정
워터마크 텍스트의 앞부분만 잘라서 점수를 냈습니다.

| 검사 토큰 수 | 워터마크 텍스트 탐지 | 일반 텍스트 오탐 |
|---|---|---|
| 10 | 82% | 38% |
| 20 | 92% | 32% |
| 50 | 100% | 32% |
| 75 | 100% | 10% |
| 100 | 100% | 8% |
| 150 | 100% | 2% |
| 200 | 100% | 4% |
파란 선만 보면 "10토큰이면 82%"로 읽히지만 그건 절반의 이야기입니다. 임계값 0.514는 200토큰 기준으로 잡은 값입니다. 10토큰짜리 텍스트는 표본이 작아 분산이 크므로, 일반 텍스트도 38%가 임계값을 넘습니다. 같은 임계값을 짧은 텍스트에 쓰면 오탐이 폭발합니다.
실무적 결론은 이렇습니다. 탐지 임계값은 길이에 따라 달라져야 하고, 이 설정에서 "오탐 1%" 수준의 신뢰를 얻으려면 150토큰 안팎이 필요합니다. 한두 문장짜리 이메일이나 댓글에 워터마크 탐지를 들이대는 것은 원리적으로 무리입니다. 논문의 베이지안 탐지기는 이 한계를 상당히 줄이지만, 없애지는 못합니다.
4. 결과 3: 온도를 낮추면 워터마크가 옅어진다
Part 1의 핵심 주장 중 하나는 "워터마크는 모델이 선택의 여지를 가진 곳에만 들어간다"였습니다. 이를 가장 직접적으로 검증하는 방법은 sampling temperature를 낮추는 겁니다. 온도가 낮으면 후보 토큰이 하나로 수렴하고, 토너먼트는 같은 토큰끼리 겨루게 되어 의미가 없어집니다.

| Temperature | 평균 g-value | 탐지율 |
|---|---|---|
| 0.3 | 0.518 | 76% |
| 0.5 | 0.530 | 100% |
| 0.7 | 0.547 | 100% |
| 1.0 | 0.574 | 100% |
온도 1.0에서 0.3으로 내리면 신호 강도(0.5 위로 올라간 폭)가 0.074에서 0.018로, 4분의 1로 줄어듭니다. 온도 0.3에서는 200토큰인데도 4건 중 1건을 놓칩니다.
이 결과는 두 방향으로 읽을 수 있습니다.
- Anthropic이 "사실 위주 문단이나 코드에서는 워터마크가 성기다"고 한 것과 정확히 같은 현상입니다. 온도를 낮추는 것과 "정답이 하나인 텍스트를 쓰는 것"은 워터마크 입장에서 같은 일입니다.
- API 사용자가
temperature=0으로 호출하면 워터마크는 사실상 들어갈 자리가 없습니다. Anthropic이 이 경우를 어떻게 처리하는지(내부적으로 최소 온도를 강제하는지)는 발표문에 나와 있지 않습니다.
5. 결과 4: 품질은 떨어지는가
"비왜곡"이라는 이론적 보장이 있어도 실제로 확인해 봐야 합니다. 생성에 관여하지 않은 독립 모델(Qwen2.5-1.5B)로 각 텍스트의 perplexity를 쟀습니다. 낮을수록 자연스러운 텍스트입니다.

| 워터마크 없음 | 워터마크 있음 | |
|---|---|---|
| 중앙값 PPL (Qwen2.5-1.5B 기준) | 6.70 | 7.09 |
| 평균 PPL | 6.91 | 7.28 |
| 중앙값 PPL (Gemma 자체 기준) | 4.50 | 4.71 |
약 5~6% 높습니다. 두 분포가 크게 겹치고 눈으로 읽어서 구분되는 수준은 아니지만, 0은 아닙니다. 앞의 샘플을 직접 읽어보면 차이를 느끼기 어렵습니다.
워터마크 없음: The vibrant blue hue of our daytime sky is a result of a phenomenon called Rayleigh scattering. Sunlight, appearing white to us, is actually composed of all the colors of the rainbow...
워터마크 있음: The azure expanse that we call the sky is a captivating sight, but its vibrant blue hues aren't simply a reflection of a perfect mirror. It all stems from an interplay of sunlight and the atmosphere...
이 차이를 어떻게 해석해야 할까요. 이 실험은 깊이 20, 온도 1.0이라는 꽤 강한 설정입니다. 비왜곡 보장은 "단일 토큰의 기대 분포"에 대한 것이고, perplexity는 토큰 시퀀스 전체에 대한 것이므로 약간의 차이는 이론과 모순되지 않습니다. DeepMind의 2천만 건 실사용 평가에서 사용자가 차이를 느끼지 못했다는 보고도 "측정 가능한 차이가 0"이 아니라 "사람이 선호도로 구분하지 못한다"는 뜻입니다. Anthropic의 "영향 없음"도 같은 의미로 읽는 것이 정확합니다.
6. 결과 5: 단어를 몇 %나 바꿔야 지워지는가
워터마크 텍스트의 단어를 무작위로 치환(다른 단어로 교체)하거나 삭제하고 다시 점수를 냈습니다.

| 편집 비율 | 치환 후 탐지 | 삭제 후 탐지 |
|---|---|---|
| 0% | 100% | 100% |
| 5% | 100% | 100% |
| 10% | 100% | 100% |
| 20% | 84% | 92% |
| 30% | 48% | 70% |
| 50% | 4% | 16% |
Anthropic이 "가벼운 편집으로는 완전히 안 지워진다"고 한 것이 맞습니다. 단어 10개 중 1개를 바꿔도 100% 탐지됩니다. 단어 하나를 건드리면 그 이후 4개 위치의 씨앗이 깨지지만, 나머지 위치의 신호가 충분히 남아 있기 때문입니다.
무너지는 지점은 20~30%입니다. 200단어 글에서 50개 이상을 바꿔야 절반이 빠져나갑니다. 사람이 손으로 하기엔 귀찮은 양이고, 결과물도 엉망이 됩니다(무작위 치환이니까요). 즉, 손편집은 현실적인 공격이 아닙니다.
삭제가 치환보다 견디는 이유도 설명됩니다. 삭제는 위치를 당길 뿐 남은 토큰들의 상대 순서를 유지하므로, 직전 4토큰 윈도우가 삭제 지점 근처에서만 깨집니다.
7. 결과 6: 로컬 모델 패러프레이즈 -- 진짜 공격
현실적인 공격은 다른 모델에게 "다시 써 달라"고 하는 것입니다. Qwen2.5-3B-Instruct(노트북에서도 돌아가는 크기)에 두 가지 강도로 시켰습니다.
- 가벼운 수정: "몇 군데 표현만 고치고 대부분 문장은 그대로 둬라"
- 전면 재작성: "문장 단위로 네 말로 완전히 다시 써라, 의미와 길이는 유지"

| 평균 g-value | 탐지율 | |
|---|---|---|
| 원문 | 0.575 | 100% |
| 가벼운 수정 | 0.561 | 100% |
| 전면 재작성 | 0.503 | 8% |
가벼운 수정은 전혀 효과가 없습니다. 3B 모델이 "가볍게 고쳐라"를 들으면 실제로 거의 손을 안 대기 때문입니다. 아래 원문과 비교해 보면 like → such as, depending on → based on 정도만 바뀌었습니다.
반면 전면 재작성 한 번에 워터마크는 완전히 사라집니다. 평균 0.503은 일반 텍스트(0.500)와 구분 불가능하고, 탐지율 8%는 임계값 바로 위에 걸린 노이즈입니다. 재작성된 글은 여전히 같은 내용을 같은 순서로 말하고 있습니다.
원문 (워터마크): The azure expanse that we call the sky is a captivating sight, but its vibrant blue hues aren't simply a reflection of a perfect mirror. It all stems from an interplay of sunlight and the atmosphere. When sunlight enters our atmosphere, it encounters tiny particles like nitrogen and oxygen molecules...
전면 재작성 (Qwen 3B): The vast azure expanse we know as the sky is a mesmerizing view, yet its vivid blues aren't just due to a clear mirror. They result from the interaction between sunlight and our atmospheric environment. As sunlight penetrates our atmosphere, it meets tiny particles such as nitrogen and oxygen molecules...
3B짜리 로컬 모델, 텍스트 하나당 몇 초. 이것이 워터마크를 지우는 데 드는 비용의 전부입니다. Part 1에서 "지우는 방법은 전부 단어 선택을 다른 주체에게 넘기는 것"이라고 했는데, 그 비용이 얼마인지 이제 숫자로 압니다.
8. 이 실험이 말해 주지 않는 것
정직하게 범위를 적어 둡니다.
- Claude 본체가 아닙니다. Gemma 2 2B에 같은 알고리즘을 걸었습니다. Anthropic의 실제 깊이, 컨텍스트 길이, 탐지기는 공개되지 않았습니다. Anthropic은 "SynthID-Text의 변형(a version of)"이라고만 했습니다.
- 탐지기가 단순 평균입니다. 논문의 베이지안 탐지기는 짧은 텍스트에서 훨씬 잘 됩니다. 여기서 나온 "150토큰 필요"는 하한선이 아니라 상한선으로 읽어야 합니다(실제 API는 더 짧은 텍스트도 잡을 수 있습니다).
- 영어 에세이 50개입니다. 한국어, 코드, 표, 목록 위주 텍스트는 다르게 동작할 수 있습니다. 특히 코드와 한국어는 별도 실험 가치가 있습니다.
- 1회 생성 기준입니다. 같은 프롬프트를 반복 생성할 때의 다양성 감소(반복 컨텍스트 문제)는 측정하지 않았습니다.
9. 정리
실험 여섯 개를 한 문장씩으로 줄이면 다음과 같습니다.
- 키가 맞으면 200토큰에서 분포가 전혀 겹치지 않고 100% 탐지됩니다. 키가 틀리면 일반 텍스트와 똑같이 보입니다.
- 신뢰할 만한 탐지에는 150토큰 안팎이 필요하고, 임계값은 길이에 맞게 조정해야 합니다. 짧은 글에 고정 임계값을 쓰면 오탐이 30%를 넘습니다.
- 온도를 낮추면 워터마크가 옅어집니다. 0.3에서는 신호가 4분의 1로 줄어듭니다. 사실·코드 위주 텍스트에서 성기다는 Anthropic의 말과 같은 현상입니다.
- 품질은 독립 모델 perplexity 기준 5~6% 높습니다. 읽어서 구분되는 수준은 아니지만 정확히 0도 아닙니다.
- 손편집은 통하지 않습니다. 단어 10%를 바꿔도 100% 잡히고, 30%는 바꿔야 절반이 빠져나갑니다.
- 로컬 3B 모델 전면 재작성 한 번이면 완전히 지워집니다. 탐지율 100% → 8%.
숨기기로 마음먹은 사람을 막는 데 드는 비용이 얼마인지 이제 압니다. 노트북 한 대, 3B 모델, 텍스트당 몇 초입니다. 워터마크는 그 사람을 막지 못합니다.
반대로 워터마크가 잘 작동하는 곳도 분명해졌습니다. 편집 없이 원문을 그대로 뿌리는 대량 생성, 그리고 150토큰 이상의 글. 스팸과 콘텐츠 팜이 정확히 이 조건입니다. EU AI Act가 요구한 것도 이것입니다. 워터마크는 "AI가 썼는지 판별하는 도구"가 아니라 "가공 없이 뿌려진 AI 원문을 거르는 필터"로 이해하는 것이 맞습니다.
참고 자료
- Anthropic, How Claude's text watermarking works (2026)
- Dathathri et al., Scalable watermarking for identifying large language model outputs, *Nature* (2024)
- Hugging Face, SynthID Text --
transformers구현 - Sebastian Raschka, How Claude's Text Watermarking Works (2026)
이메일로 받아보기
관련 포스트

Claude 텍스트 워터마크, 원리부터 한계까지 — 토큰 하나 안 바꾸고 서명하는 법
Claude가 생성하는 모든 텍스트에 보이지 않는 워터마크가 들어갑니다. 글자를 추가하지 않고 어떻게 서명이 가능한지 — SynthID-Text의 시크릿 키, 토너먼트 샘플링, 탐지 원리와 한계까지 단계별로 풀어봅니다.

Reversal Curse를 깨는 Identity Bridge — ICML 2026, 이래도 되는데 되는 fix
언어 모델은 "Alice의 남편은 Bob"을 학습해도 "Bob의 아내는?"을 못 맞힙니다 — 유명한 reversal curse. ICML 2026 논문 하나가 학습 데이터에 이상한 자기참조 예제를 섞는 것만으로 이 문제를 해결합니다. 순진한 버전은 안 되고, 정교한 버전은 됩니다.

스스로 진화하는 AI 에이전트 — 2026년의 새로운 패러다임
GenericAgent, Evolver, Open Agents — 스스로 스킬을 만들고, 실행 경로를 기억하고, 실패에서 배우는 자가 진화 에이전트 3종 비교.