따라하기 — 세션이 섞이지 않는지 검증하기
한 줄 요약
말로 확인하지 말고 코드로 검증합니다. 두 손님이 번갈아 대화해도 섞이지 않는지, 짧은 검증 코드를 직접 짜서 확인합니다.
1. 왜 검증하나
[2] 에서 이미 확인했습니다.
손님: 제가 뭘 샀다고 했죠?
봇 : 아직 어떤 상품을 구매하셨는지 말씀해주시지 않았습니다.
그런데 이건 "박서준이 아무 말도 안 한 상태" 였습니다. 실제 서비스에서는 두 손님이 번갈아 말합니다.
오지우: 스마트워치를 샀어요 ← A
박서준: 로봇청소기를 샀어요 ← B
오지우: 제가 뭘 샀다고 했죠? ← A (스마트워치라고 해야 함)
박서준: 제가 뭘 샀다고 했죠? ← B (로봇청소기라고 해야 함)
이게 진짜 검증입니다.
2. 검증 코드
직접 고쳐 보기 —
agentic_ai/code/ch07_memory.py를 열어[3]블록 아래에 아래를 덧붙인 뒤 다시 실행하세요.
# ── 4. 두 손님이 번갈아 대화해도 섞이지 않는가 ─────────────
print("\n" + "=" * 62)
print("[4] 두 손님이 번갈아 — 섞이지 않는지 검증")
conversations = [
("A-오지우", "스마트워치를 샀어요."),
("B-박서준", "로봇청소기를 샀어요."),
("A-오지우", "제가 뭘 샀다고 했죠?"),
("B-박서준", "제가 뭘 샀다고 했죠?"),
]
answers = {}
for customer, message in conversations:
answer = say(message, thread_id=customer)
answers[(customer, message)] = answer
print(f" [{customer}] {message}")
print(f" → {answer}")
# 검증
print("\n 검증 결과")
answer_a = answers[("A-오지우", "제가 뭘 샀다고 했죠?")]
answer_b = answers[("B-박서준", "제가 뭘 샀다고 했죠?")]
print(f" A 가 '스마트워치'라고 답했나 : {'스마트워치' in answer_a}")
print(f" A 답에 '로봇청소기'가 없나 : {'로봇청소기' not in answer_a}")
print(f" B 가 '로봇청소기'라고 답했나 : {'로봇청소기' in answer_b}")
print(f" B 답에 '스마트워치'가 없나 : {'스마트워치' not in answer_b}")
3. 예상 출력
==============================================================
[4] 두 손님이 번갈아 — 섞이지 않는지 검증
[A-오지우] 스마트워치를 샀어요.
→ 스마트워치 구매 감사합니다. 문의사항이 있으시면 말씀해주세요.
[B-박서준] 로봇청소기를 샀어요.
→ 로봇청소기 구매 감사합니다. 어떤 점을 도와드릴까요?
[A-오지우] 제가 뭘 샀다고 했죠?
→ 스마트워치를 구매하셨다고 말씀해주셨습니다.
[B-박서준] 제가 뭘 샀다고 했죠?
→ 로봇청소기를 구매하셨다고 말씀해주셨습니다.
검증 결과
A 가 '스마트워치'라고 답했나 : True
A 답에 '로봇청소기'가 없나 : True
B 가 '로봇청소기'라고 답했나 : True
B 답에 '스마트워치'가 없나 : True
네 개 모두 True 면 섞이지 않은 것입니다.
표현은 달라도 검증 네 줄이 전부 True 면 성공입니다.
4. 검증을 짤 때의 요령
① 사람이 눈으로 보지 말고 조건으로 쓴다
아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.
print(f" A 가 '스마트워치'라고 답했나 : {'스마트워치' in answer_a}")
답변이 매번 다르므로 글자를 통째로 비교할 수는 없습니다. 꼭 들어가야 할 단어가 있는지로 봅니다.
② "있어야 할 것"과 "없어야 할 것"을 둘 다 본다
아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.
'스마트워치' in answer_a # 있어야 할 것
'로봇청소기' not in answer_a # 없어야 할 것
첫 번째만 보면 놓칩니다. 만약 A가 "스마트워치와 로봇청소기를 사셨습니다"라고 답하면 첫 조건은 통과하지만 섞인 것이죠.
테스트를 짤 때의 기본 원칙입니다 — 충족해야 할 조건과 해당되면 안 되는 조건을 함께 봅니다.
③ 순서를 섞는다
아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.
("A-오지우", ...), ("B-박서준", ...), ("A-오지우", ...), ("B-박서준", ...)
A를 다 하고 B를 하면 섞일 기회 자체가 없습니다. 번갈아 해야 진짜 검증입니다.
5. 일부러 고장 내 보기
검증이 제대로 동작하는지 확인하려면, 일부러 틀리게 만들어 봅니다.
아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.
conversations = [
("A-오지우", "스마트워치를 샀어요."),
("B-박서준", "로봇청소기를 샀어요."),
("A-오지우", "제가 뭘 샀다고 했죠?"),
("A-오지우", "제가 뭘 샀다고 했죠?"), # ← B 를 A 로 바꿈
]
이러면 마지막 답이 "스마트워치" 가 나오고, 검증이 이렇게 됩니다.
B 가 '로봇청소기'라고 답했나 : False ← 실패를 잡아냄
검증이 실패를 잡아내는지 확인하는 것까지가 검증을 짜는 일입니다. 항상 True 만 나오는 검증은 아무것도 검증하지 않습니다.
6. 서랍 안을 직접 비교
더 확실한 방법은 상태를 직접 꺼내 보는 것입니다.
직접 고쳐 보기 —
agentic_ai/code/ch07_memory.py를 열어 아래처럼 바꾸거나 덧붙인 뒤 다시 실행하세요.
print("\n 서랍 안 비교")
for customer in ["A-오지우", "B-박서준"]:
snapshot = chatbot.get_state({"configurable": {"thread_id": customer}})
messages = snapshot.values["messages"]
print(f" [{customer}] {len(messages)}개")
for m in messages:
print(f" {type(m).__name__:14s} {str(m.content)[:40]}")
서랍 안 비교
[A-오지우] 4개
HumanMessage 스마트워치를 샀어요.
AIMessage 스마트워치 구매 감사합니다...
HumanMessage 제가 뭘 샀다고 했죠?
AIMessage 스마트워치를 구매하셨다고 말씀해주셨습니다.
[B-박서준] 4개
HumanMessage 로봇청소기를 샀어요.
AIMessage 로봇청소기 구매 감사합니다...
HumanMessage 제가 뭘 샀다고 했죠?
AIMessage 로봇청소기를 구매하셨다고 말씀해주셨습니다.
서랍 두 개가 완전히 독립입니다. A의 서랍에 "로봇청소기"라는 글자가 아예 없습니다.
모델의 답을 검사하는 것보다 이쪽이 확실합니다. 답은 흔들릴 수 있지만 저장된 내용은 흔들리지 않습니다.
7. 왜 이런 검증이 중요한가
대화가 섞이는 사고는 조용히 일어납니다.
[정상] 손님 A에게 A의 정보를 답한다 → 아무 일 없음
[사고] 손님 A에게 B의 정보를 답한다 → 개인정보 유출
오류가 안 납니다. 프로그램은 잘 돌아가고, 답도 그럴듯합니다. 다른 사람의 정보가 섞여 나올 뿐이죠.
5장 8절에서 말한 그 이야기 — "에이전트가 틀리는 방식은 대개 오류가 아니라 오류 없이 나오는 오답" — 이 여기서는 개인정보 사고가 됩니다.
그래서 검증이 필요합니다. 특히
thread_id를 만드는 부분을 고칠 때마다 이 검증을 돌려 봐야 합니다.
스스로 해 보기
- 위 코드를 넣고 실행해 네 조건이 전부
True인지 확인하세요. - 5번의 일부러 고장 내기를 해 보고, 검증이
False를 잡아내는지 확인하세요. - 손님을 세 명으로 늘려 검증해 보세요.
thread_id를 전부 같은 값으로 바꾸고 실행해 보세요. 어떻게 되나요?- 6번의 서랍 비교 코드를 실행해 두 서랍이 독립인지 눈으로 확인하세요.
핵심 정리
- 말로 확인하지 말고 코드로 검증합니다.
- 진짜 검증은 두 손님이 번갈아 대화하게 하는 것입니다. 한쪽씩 몰아서 하면 섞일 기회가 없습니다.
- 답변은 매번 다르므로 꼭 들어가야 할 단어가 있는지로 봅니다.
- "있어야 할 것"과 "없어야 할 것"을 둘 다 봅니다. 한쪽만 보면 섞인 것을 놓칩니다.
- 일부러 고장 내서 검증이 실패를 잡아내는지 확인합니다. 항상 통과하는 검증은 쓸모없습니다.
- 더 확실한 방법은
get_state()로 서랍 안을 직접 비교하는 것입니다. 답은 흔들려도 저장된 내용은 안 흔들립니다. - 대화가 섞이는 사고는 오류 없이 조용히 일어납니다. 그리고 그것은 개인정보 사고입니다.