LLM을 더 충성스럽게 만드는 방법

문장 한 번 쓰고, 태그 한 번 달기.

by 지적 지니


프롬프트 엔지니어링에서 내가 가장 자주 보는 실패는, 모델이 “없는 걸 만들었다”는 단순한 환각이 아니다. 더 치명적인 건 진술의 지위가 뒤섞이는 것이다. 사실(FACT)이었는데 어느새 가정(ASSUME)처럼 취급되고, 미결정(OPEN)이었는데 모델이 이미 결정된 것처럼 밀고 나간다.


스코프가 커질수록 목표가 아니었던 것은 잊히고, “빠르게” 같은 모호한 표현은 [범위]와 같은 명시적 표현으로 못 박지 않는 순간 위반된다. 그래서 나는 요구명세를 다룰 때, 내용 자체만큼이나 형식이 충실성을 좌우한다는 쪽으로 생각이 굳었다.


여기 두 가지 정리 방식을 가정해보자. 하나는 요구를 [FACT][DEF][ASSUME][OPEN][RANGE][NON-GOAL][RISK] 같은 태그로 원자화해서, 조각들에 [메소드명]만 달아 흩뿌려 놓는 방식이다(메소드 1).


메소드 1: 태그 붙이기 + [메소드명]만 달고 흩어놓기


포인트: [FACT]/[ASSUME]/[OPEN]/[NON-GOAL] 같은 “지위”가 전부 명시되고, 조각들은 순서 없이 흩어져 있을 수 있음.


[MethodA: 회원가입] [FACT] 사용자는 이메일로 가입한다.
[MethodA: 회원가입] [DEF] “가입 성공”은 계정 생성 + 이메일 인증 완료를 의미한다.
[MethodA: 회원가입] [RANGE] “빠르게” = 가입 요청 ~ 응답까지 P95 800ms 이하.
[MethodA: 회원가입] [ASSUME] 이메일 발송은 외부 SMTP 서비스를 사용한다.
[MethodB: 결제] [OPEN] 환불 정책(부분환불/전체환불, 수수료 부담 주체)을 확정해야 한다.
[MethodA: 회원가입] [NON-GOAL] 소셜 로그인(구글/애플)은 이번 범위에 포함하지 않는다.


다른 하나는 요구를 메소드별로 모아 집결시키되, 각 문장이 FACT인지 ASSUME인지 같은 속성은 따로 명시하지 않는 방식이다(메소드 2). 둘 다 “정리”는 맞다. 그런데 모델이 규칙을 지키는 충실성은, 둘 중 어디에서 더 강하게 유지될까?


MethodA: 회원가입

사용자는 이메일로 가입한다.

가입 성공은 계정 생성과 이메일 인증 완료를 의미한다.

가입은 빠르게 처리되어야 한다.

비밀번호 규칙(최소 길이, 특수문자 포함 여부)이 필요하다.

이메일 발송은 외부 SMTP 서비스를 쓸 예정이다.

가입 실패 시 사용자에게는 사유를 노출하지 않고 내부 로그로만 남긴다.

소셜 로그인은 이번 범위에서 제외한다.

인증 메일 지연이 가입 성공률에 영향을 줄 수 있다.



결론부터 말하면 메소드 1이 더 강하다. 이유는 단순하다. LLM이 가장 자주 깨는 충실성은 “내용을 잘못 기억”하는 문제가 아니라, 서술의 중요도를 바꿔치기하는 문제이기 때문이다. FACT/ASSUME/OPEN이 섞이는 순간, 모델은 규칙을 지키기보다 그럴듯하게 연결한다.


충실성을 조금 더 엄밀하게 잡으면 논점이 더 선명해진다. 요구명세에서 충실성은 보통 세 층위로 나타난다.


진술의 지위 보존 : FACT는 FACT로, ASSUME은 ASSUME으로, OPEN은 OPEN으로 남아야 한다.

제약 충실성(금지/범위/비목표 준수): NON-GOAL과 RANGE를 실제 출력에 반영해야 한다.

범주 오류 최소화(암묵 요구 생성 억제): 없는 요구를 “당연히 필요하겠지”로 추가하지 않아야 한다.


메소드 2가 위험한 지점은 첫 번째다. 문장 묶음 안에서 사실과 가정과 희망이 섞여 있으면, 모델은 이를 자동으로 분류해야 한다. 그런데 자동 분류는 자주 실패한다. 그 결과는 익숙하다. “아직 결정 안 된 것”을 결정된 것처럼 쓰고, “가정”을 사실처럼 말한다. 이 시점부터 규칙 준수는 무너진다. 왜냐하면 규칙이 기대하는 건 내용의 화려함이 아니라, 지위의 보존이기 때문이다.


메소드 1은 여기서 강하다. 태그가 있는 순간, 모델은 계속 신호를 받는다. 특히 LLM이 길게 생성할수록 잘 잊는 것들이 있다. NON-GOAL, RANGE 같은 제약이 대표적이다. 이 제약들은 문장 사이에 파묻히면 존재감이 급격히 떨어지지만, 슬롯으로 박혀 있으면 다르게 작동한다. “여기까지는 하면 안 된다” “이 수치는 이 범위로 제한된다”는 경계선이 유지된다.


또 하나의 차이는 감사 가능성이다. 메소드 1은 모델이 규격을 어기면 바로 드러난다. FACT에 근거가 없거나, RANGE가 비어 있는데 “빠르게”라고 말하면 즉시 적발된다. 사후 검증이 쉬운 구조는 그 자체로 모델을 보수적으로 만든다. “어차피 들킬 것”이라는 구조는, 모델이 함부로 지위를 바꾸거나 금지를 넘어가게 두지 않는다.

다만 메소드 1이 완벽하냐 하면, 여기엔 명확한 약점이 있다. 요구가 “뿔뿔이 흩어진” 상태에서 가장 흔한 사고는 바인딩 오류다. 즉, “이 NON-GOAL이 어느 메소드 거였지?” 같은 문제다. A 메소드의 NON-GOAL이 B 메소드에 잘못 적용되거나, A의 RANGE가 B로 새는 교차 오염이 생긴다. 이건 태그의 문제가 아니라 결속(그룹핑)의 문제다.


그래서 메소드 1을 진짜로 강하게 만들려면, 태그만 쓰는 게 아니라 결속 장치를 같이 붙여야 한다. 보완책은 딱 세 가지로 정리된다.



[메소드명]을 그냥 이름이 아니라 고유 ID로 고정하기 (예: METHOD:payment_v2)

각 조각에 METHOD_ID + TAG를 반복적으로 고정해서 “소속”을 강하게 부여하기

완전 산개를 피하고, 같은 메소드 조각은 가까운 거리로 배치하기


이 보완이 들어가면 메소드 1은 “지위 보존”과 “제약 준수”에서 거의 최선의 형태가 된다. 반대로 메소드 2는 예외적으로 유리한 상황이 있긴 하다. 예컨대 FACT/ASSUME/OPEN의 구분 자체가 거의 필요 없는 단순 기능 목록, 혹은 모델이 결정을 하지 않고 요약만 하는 작업이라면 메소드별 집결이 편하다. 하지만 프롬프트 엔지니어링의 본령이 “모델이 규칙을 지키게 만드는 것”이라면, 결국 승부는 지위와 제약을 어떻게 보존하느냐로 귀결된다.


정리하면 한 줄이다. 충실성의 핵심이 사실과 가정을 절대 섞지 않는 것’과 암묵적 사실을 명시적 요구로 혼동하지 않는 것’이라면, 원자화+태깅(메소드 1)이 더 강하다.

작가의 이전글인공지능과 프롬프팅에 대하여