
프롬프트로 금지해도 3번이나 재발했다 — 지시와 기계 검사의 활용 구분
요약
AI 에이전트에게 프롬프트로 특정 동작을 금지하더라도 오류가 재발하는 문제를 다룹니다. 프롬프트 지시의 확률적 한계를 인정하고, 기계적으로 판정 가능한 오류는 검사 로직을 통해 해결해야 함을 강조합니다.
핵심 포인트
- 프롬프트 금지 지시는 생성 모델의 근본적인 변환 습관을 바꾸기 어려움
- 지시와 함께 결과를 검증할 기계적 검사(Mechanical Check)가 반드시 병행되어야 함
- 기계적 판정이 가능한 영역은 지시가 아닌 검사 로직으로 해결해야 함
- 지시의 효과를 확인하기 위한 사후 검증 절차의 중요성
TL;DR
기사 작성을 서브 에이전트 (Sub-agent)에게 맡기고 있는데, 생성된 Markdown의 부등호가 HTML 엔티티 (HTML Entity) 상태로 출력되는 문제가 3개 기사 연속으로 발생했다. 2번째 기사에서 위임 프롬프트 (Delegation Prompt)에 명시적인 금지 사항을 적었지만, 3번째 기사에서도 재발했다. 지시를 강화하는 것을 그만두고, 저장 전의 기계 검사 (Mechanical Check)로 전환한 이야기다.
3번째 재발
기술 기사의 코드 블록 (Code Block)이나 Mermaid 도표에는 부등호가 빈번하게 등장한다. 화살표 기호, 비교 연산자, 태그 예시 등 피할 수 없는 문자들이다.
그런데 서브 에이전트가 생성한 Markdown에서는 그것이 HTML 엔티티로 변환되어 있는 경우가 있었다. Mermaid의 화살표가 실체 참조 (Entity Reference) 상태로 출력되어, 복사해서 붙여넣어도 파싱 (Parsing)이 깨진다. 코드 블록의 비교 연산자에서도 같은 일이 일어난다. Python으로 실행하면 구문 오류 (Syntax Error)가 발생한다.
첫 번째 기사는 저장하기 직전에 육안으로 발견했다. 우연히 직접 코드 블록을 읽다가 위화감을 느낀 형태였으며, 시스템으로서 방지할 수 있었던 것은 아니다.
두 번째 기사에서 동일한 증상이 나타났다. 여기서 위임 프롬프트에 한 문장을 추가했다.
코드 블록·Mermaid 도표의 부등호는 생(raw) 기호로 작성할 것.
HTML 엔티티로 만들지 말 것.
금지를 명문화하면 고쳐질 것이라고 생각했다.
세 번째 기사에서도 재발했다. 게다가 이번에는 금지를 작성한 이후의 재발이었다. 이 점이 결정적인 계기가 되어, "아직 강도가 부족하니까 더 강하게 쓰면 고쳐질 것이다"라는 발상을 버렸다.
왜 프롬프트의 금지는 효과가 없었는가
원인은 프롬프트의 작성 방식이 아니라 구조에 있다.
엔티티화 (Entity-fication)는 생성 모델이 Markdown 내의 코드 블록을 일반 문장의 일부로 취급하여, HTML적인 이스케이프 (Escape) 처리를 통과시켜 버리는 동작에 가깝다. 특정 지시를 지키느냐의 문제가 아니라, 생성 과정의 어딘가에서 일률적으로 적용되는 변환 습관이다. 금지 문구를 한 줄 추가한다고 해서 그 변환 단계 자체가 바뀌지는 않는다.
또 다른, 더 근본적인 문제가 있다.
"금지한 것"과 "금지가 지켜졌는지 확인하는 수단"은 세트로 준비하지 않으면, 지켜지지 않았더라도 알아차릴 수 없다.
두 번째 기사에서 금지를 적었을 때 한 일은 "프롬프트에 한 줄 추가하기"뿐이었다. 생성 결과를 기계적으로 스캔하는 절차는 준비하지 않았다. 그래서 세 번째 기사에서 재발했을 때도 저장 직전까지 알아차리지 못했다. 금지를 적었다는 사실에 안심하여 확인의 수고를 생략하고 있었던 것이다.
지시는 "전송한" 시점에서 업무가 끝난 것처럼 보인다. 하지만 지시가 실제로 효과가 있었는지는 출력을 보지 않으면 알 수 없다. 당연한 이야기 같지만, 기계 검사를 준비해두지 않으면 확인 자체를 스킵하게 된다.
지시에 적합한 것 · 기계 검사에 적합한 것의 경계선
이번 일을 통해 정리할 수 있었던 것은, AI에 대한 지시는 적합한 것과 부적합한 것이 명확히 나뉜다는 점이다.
| 종류 | 예 | 판정 방법 | 적합한 수단 |
|---|---|---|---|
| 문체·톤 | 문어체로 작성, 선동하지 않음 | 인간의 비교 읽기로만 판정 가능 | 지시 |
| ... |
구분 기준은 하나다. "지켜졌는지 여부를 인간이 읽지 않고도 기계적으로 판정할 수 있는가".
판정할 수 있는 것은 지시에 의존해서는 안 된다. 지시는 "대개는 지켜진다"라는 확률적인 효과밖에 내지 못한다. 기계 검사는 "지켜졌다면 0건, 지켜지지 않았다면 1건 이상 히트한다"라는 결정적인 판정이 된다.
반대로 문체나 논리 전개처럼 기계로 판정하기 어려운 것을 기계 검사로 넘기려 하면, 오탐 (False Positive)투성이인 취약한 스크립트가 된다. 이 부분은 지시와 리뷰에 맡기는 편이 빠르다.
3회 연속으로 엔티티화가 일어난 것은, 기계 판정이 가능한 종류의 문제를 지시라는 확률적인 수단으로 막으려 했던 것이 근본적인 원인이었다.
처음에 작성한 검사 스크립트는 3곳이 고장 나 있었다
판정할 수 있는 것을 전부 스크립트로 몰아넣었다. 처음에 작성한 것은 소박한 bash였으며, 4개 항목을 확인하고 있었다.
- HTML 엔티티가 남아있는지 grep 수행
- 코드 펜스 (Code Fence)의 개수가 짝수인지 계산 (닫기 누락 검출)
- 개인의 실제 경로 (Path)가 남아있는지 grep 수행
- 제목의 글자 수가 상한 이내인지 계산
작성 당시에는 작동할 것이라 생각했다. 4개의 기사에 돌려본 결과, 이 기사만 NG가 되었다. 조사해 보니 기사 측이 아니라 검사 측에 3가지 결함이 있었다.
결함 1: 자기 자신을 오검출함
엔티티 검사는 일반 문장뿐만 아니라 코드 블록의 내용도 보고 있었다. 이 기사에는 엔티티를 검출하는 grep 패턴이 코드 예시로 실려 있다. 그 검사 패턴 자체가 검사에 걸려버렸다.
결함 2: 개인 경로 검출이 항상 에러로 인해 통과됨
경로 검출용 정규 표현식이 끝부분의 백슬래시()로 끝나 있어서, grep이 구문 에러를 반환하고 있었다.
$ grep -n 'C:\Users\' article.md
grep: Trailing backslash
$ echo $?
...
문제는 종료 코드(exit code)가 2가 된다는 점이다. if grep ...; then이라고 작성했기 때문에, 비제로(non-zero) = 「해당 사항 없음」으로 해석되어 그대로 통과된다. 개인 경로 유출을 검출해야 할 항목이, 입력 내용과 상관없이 항상 아무것도 검사하지 않고 있었다.
이는 기사 전반부에서 쓴 「말없이 무효화되는 버그」 그 자체다. 에러 메시지는 나오고 있지만, 스크립트 전체로 보면 정상적으로 보인다.
결함 3: 일본어 제목의 글자 수를 셀 수 없음
bash의 ${#TITLE}은 이 환경에서 바이트(byte) 수를 반환했다.
bash의 ${#TITLE} → 90
실제 글자 수 → 32
70자 제한에 대해 90으로 판정되므로, 일본어 제목의 기사는 거의 전수 위양성(False Positive)으로 FAIL된다.
다시 만들다
단순한 grep으로는 「펜스(fence) 기호나 엔티티(entity) 자체를 주제로 다룬 기사」를 처리할 수 없다. 펜스 구조를 해석하는 구현으로 교체했다.
- 3연 백틱보다 긴 백틱으로 감싼 블록도 하나의 펜스로 올바르게 계산
- 엔티티 검사는 코드 블록 외부만을 대상으로 함 (코드 내의 grep 패턴은 정당한 기술이므로 제외)
- 글자 수는 바이트 수가 아닌 글자 수로 계산
- 검사 항목이 비정상 종료되면 「해당 사항 없음」이 아니라 「검사 실패」로 취급
다시 만든 버전을 모든 기사에 적용한 결과, 엔티티와는 별개의 불일치가 1건 발견되었다. 어떤 기사의 본문에 코드 펜스용 기호가 그대로 적혀 있어서, 파서(parser)에 따라서는 펜스의 시작으로 해석될 수도 있는 상태였다. 육안 리뷰는 통과했지만, 아무도 눈치채지 못했다.
「기계 검사에 맡기면 확실하다」는 아니다. 검사 자체가 고장 나 있다면, 지시에 의존하는 것보다 질이 나쁘다. 지시는 지켜지지 않을 수도 있다는 것을 알고 있지만, 고장 난 검사는 「OK」라고 표시하면서 아무것도 하지 않기 때문이다.
재발 3회로 규칙화하는 운영
같은 종류의 실패가 3번 발생하면 「주의한다」에서 「기계 검사로 넘긴다」로 전환한다는 기준선을 긋고 있다. 1회나 2회째는 아직 우연일 가능성이 있다. 하지만 3회째, 게다가 금지를 명시한 후의 재발은 지시라는 수단 자체가 효과가 없다는 증거로 취급한다.
이 기준선을 그음으로써 「다시 한번 프롬프트를 강하게 다시 쓰기」라는 무의미한 반복을 피할 수 있게 되었다. 프롬프트를 수정하는 것은 대처 비용이 낮아 보이기 때문에, 자기도 모르게 가장 먼저 손을 대게 된다. 하지만 판정 가능한 문제에 대해서는 아무리 다시 써도 효과가 한계에 부딪힌다. 3번째 재발은 그 한계에 부딪혔음을 깨닫기 위한 표식으로 기능했다.
자신에게 되돌아온 이야기
이 대응을 기사의 변경 이력에 정리하려고 했을 때, 아이러니한 일이 일어났다.
「본문에 코드 펜스 기호가 적혀 있었다」라는 수정 내용을 설명하는 문장 자체가, 펜스 기호를 그대로 적어버리고 말았다. 수정한 문제의 설명문이 동일한 구조의 결함을 가진 꼴이다.
이 기사 자체도 같은 함정에 빠졌다. 전절의 결함 1이 바로 그것으로, 엔티티를 검출하는 grep 패턴을 기사에 실은 결과, 그 패턴이 자신의 검사에 걸려버렸다. 검사를 설명하는 문장은 그 검사에게 있어 가장 혼란스러운 입력이 된다.
기계 검사를 작성하는 기사를 쓰는 것 자체가, 기계 검사로 잡아내야 할 실패를 유발한다. 규칙을 작성한 직후에 규칙을 어길 뻔했다는 것은 웃지 못할 이야기 같지만, 실제로 일어난 일이다. 검사 메커니즘을 만든 후에도, 그 검사를 설명하는 자신의 문장은 검사 대상에서 제외되지 않는다.
일반화된 교훈
- AI에 대한 지시로 막지 못하는 실패의 대부분은 지시의 강도 문제가 아니라 「지켜졌는지 확인할 수단이 없다」는 것이 원인이 된다
- 판정 기준이 「문자열의 유무」, 「수의 일치」, 「포맷의 정합성」처럼 자동화할 수 있는 것은 처음부터 지시가 아닌 검사로 설계한다
- 문체·구성처럼 인간의 판단이 필요한 것은 지시와 리뷰에 맡기는 것이 실질적이다
- 같은 종류의 실패가 3번, 특히 금지를 명시한 후에도 재발한다면 대처 수단 자체를 전환하는 신호로 취급한다
- 단, 검사로 옮긴다고 해서 안심할 수 있는 것은 아니다. 검사 자체가 고장 나 있지 않은지, 기지의 NG 사례와 OK 사례 모두로 한 번 확인한 뒤에 운영에 투입한다
이 검사를 거치면 동일한 종류의 결함은 잡아낼 수 있다. 하지만 검사를 수행하는 운영 프로세스 자체를 잊어버린다면, 다시 똑같은 일이 발생한다. 이번에 발견된 펜스 기호(fence symbol)의 혼입도 모든 기사에 적용하는 한 단계의 수고를 거쳤기에 발견된 사례이며, 그 수고를 생략한다면 앞으로도 똑같은 실수를 반복하게 될 것이다.
좋아요와 댓글로 반응해 주시면 큰 힘이 됩니다!
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기