📚 Agentic AI - 기업용 자율 에이전트 개발 7장 · 기억하는 에이전트 Agentic AI란

따라하기 — 세션이 섞이지 않는지 검증하기

한 줄 요약

말로 확인하지 말고 코드로 검증합니다. 두 손님이 번갈아 대화해도 섞이지 않는지, 짧은 검증 코드를 직접 짜서 확인합니다.


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 를 만드는 부분을 고칠 때마다 이 검증을 돌려 봐야 합니다.


스스로 해 보기

  1. 위 코드를 넣고 실행해 네 조건이 전부 True 인지 확인하세요.
  2. 5번의 일부러 고장 내기를 해 보고, 검증이 False 를 잡아내는지 확인하세요.
  3. 손님을 세 명으로 늘려 검증해 보세요.
  4. thread_id전부 같은 값으로 바꾸고 실행해 보세요. 어떻게 되나요?
  5. 6번의 서랍 비교 코드를 실행해 두 서랍이 독립인지 눈으로 확인하세요.

핵심 정리

  • 말로 확인하지 말고 코드로 검증합니다.
  • 진짜 검증은 두 손님이 번갈아 대화하게 하는 것입니다. 한쪽씩 몰아서 하면 섞일 기회가 없습니다.
  • 답변은 매번 다르므로 꼭 들어가야 할 단어가 있는지로 봅니다.
  • "있어야 할 것"과 "없어야 할 것"을 둘 다 봅니다. 한쪽만 보면 섞인 것을 놓칩니다.
  • 일부러 고장 내서 검증이 실패를 잡아내는지 확인합니다. 항상 통과하는 검증은 쓸모없습니다.
  • 더 확실한 방법은 get_state() 로 서랍 안을 직접 비교하는 것입니다. 답은 흔들려도 저장된 내용은 안 흔들립니다.
  • 대화가 섞이는 사고는 오류 없이 조용히 일어납니다. 그리고 그것은 개인정보 사고입니다.
← 이전 절07. thread_id 사용자별로 대화를 갈라 두기다음 절 →09. 정리 체크리스트