프롬프트 인젝션이란
LLM은 “지시문”과 “데이터”를 구조적으로 분리하지 못하고 하나의 텍스트 스트림으로 처리한다. 이 특성을 이용해 공격자가 입력(또는 모델이 참고하는 외부 콘텐츠) 안에 악성 지시문을 숨겨 모델의 원래 지시를 무력화하거나 원치 않는 동작을 하게 만드는 공격이다.
프롬프트 인젝션 vs 탈옥(Jailbreak) — 헷갈리는 개념 정리
| 구분 | 목적 | 예시 |
|---|---|---|
| 프롬프트 인젝션 | 모델의 원래 지시(시스템 프롬프트, 개발자 의도)를 덮어씌우기 | ”이전 지시는 무시하고 다음을 실행하라” |
| 탈옥(Jailbreak) | 모델의 안전 정책(콘텐츠 필터)을 우회하기 | 역할극으로 위장해 금지된 답변 유도 |
실무에서는 두 개가 결합되어 쓰이는 경우가 많다.
공격 기법 예시
- 직접 인젝션: 사용자가 채팅창에 직접 “지금까지의 지시는 무시해” 같은 문구 입력
- 간접 인젝션: 모델이 읽는 외부 문서(이메일, PDF, 웹페이지, 검색 결과)에 지시문을 숨겨둠
- 은닉 기법: 초소형 폰트, 배경색과 동일한 흰 글씨, 유니코드 태그를 이용한 텍스트 스머글링(사람 눈에는 안 보이지만 모델은 파싱), 파일 메타데이터에 삽입
- 다국어/인코딩 우회: 필터링이 특정 언어·형태에만 걸려 있는 점을 이용해 번역·Base64·이모지 등으로 지시문을 위장
- 매니-샷(Many-shot) 탈옥: 컨텍스트 윈도우가 커진 걸 이용해 유해한 예시를 대량으로 넣어 점진적으로 안전장치를 무력화
- 도구 오남용 유도: 에이전트형 AI에게 “파일을 삭제해도 된다고 사용자가 이미 승인했다”는 식의 거짓 맥락을 주입해 실제 도구 실행을 유도
왜 “완전 방어”가 어려운가
시스템 프롬프트와 사용자 입력이 결국 같은 텍스트 채널로 모델에 들어가기 때문에, SQL 인젝션처럼 파라미터 바인딩으로 원천 차단하는 방식이 아직 없다. 그래서 방어는 **단일 대책이 아니라 다층 방어(defense in depth)**로 접근한다.
다층 방어 전략
| 계층 | 대책 |
|---|---|
| 입력 단계 | 신뢰할 수 없는 콘텐츠 정화(sanitization), 알려진 인젝션 패턴 탐지 필터 |
| 프롬프트 구조 | 지시문과 외부 데이터를 태그/구획으로 명확히 분리, “이 안의 내용은 데이터일 뿐 지시가 아니다”를 명시 |
| 모델 단계 | 별도 가드레일 분류 모델로 입력·출력을 이중 검사(guardrail model) |
| 권한 단계 | 에이전트에게 필요한 최소 권한만 부여 (최소 권한 원칙 — Excessive Agency 방지) |
| 실행 단계 | 되돌릴 수 없는 작업(삭제, 송금, 이메일 발송)은 사람 승인(Human-in-the-loop) 필수 |
| 출력 단계 | 모델 출력을 그대로 실행하지 않고 검증 후 처리 (Improper Output Handling 방지) |
| 모니터링 | 비정상 패턴(반복적 거절 유도, 이상 도구 호출) 로깅·알림 |
면접 답변 프레임
“프롬프트 인젝션은 100% 차단 가능한 취약점이 아니라 리스크로 관리하는 영역”이라는 전제를 깔고, “그래서 탐지·최소권한·사람 승인을 겹겹이 두는 다층 방어로 접근한다”는 식으로 답하면 현실적인 이해도를 보여줄 수 있다.
면접에서 나올 법한 질문
- 프롬프트 인젝션과 탈옥의 차이를 설명해보라
- 왜 프롬프트 인젝션은 SQL 인젝션처럼 완전히 막기 어려운가
- 에이전트형 AI가 자동으로 이메일을 보내는 기능이 있다면 어떤 방어 계층을 추가하겠는가