개발일지
Decision·3 min read

LangGraph 얹었다가 출처가 사라졌습니다

단일턴 엔진에 LangGraph 다단계 추론을 토글로 얹자 출처 뱃지가 통째로 빠졌다. 버그가 아니라 구조가 부딪힌 것이었고, 전부 통일하는 대신 경로를 갈라 풀었다.

관리자 화면에서 추론 엔진 토글을 native에서 LangGraph로 넘겼다. 같은 질문을 다시 던졌다. 답은 멀쩡히 나왔다.

그런데 답변 아래 붙던 출처 뱃지가 통째로 사라져 있었다. 에러도 없고 로그도 조용했다. 기능 하나가 소리 없이 빠진 것이다.

원래 엔진은 한 번에 끝났다

새김AI의 기본 엔진은 단일 턴이다. LLM이 한 번 불리면서 필요한 툴을 고르고, 툴이 완성된 문장을 돌려주면 그걸 그대로 답으로 내보낸다. 툴 결과를 LLM에 다시 먹여 한 번 더 생각하게 만드는 과정이 없다. 날씨 툴이 "오늘 서울은..." 하고 이미 문장으로 답을 주니, 되먹일 이유가 없었다.

출처 뱃지는 이 구조 위에 얹혀 있었다. LLM이 응답을 만들 때 문장 끝에 [1][2] 같은 마커를 심으면, 프론트가 그 마커를 파싱해 근거 카드를 렌더한다. 웹검색 툴은 아예 LLM에게 "문장 끝에 마커만 붙이고 출처 목록은 따로 만들지 마라, 카드는 화면이 그린다"고 지시해 둔다.

뱃지는 그 마커가 최종 출력에 살아 있다는 전제로 돌아간다.

왜 굳이 다른 엔진을 얹었나

LangGraph를 공부하던 참이었다. 프레임워크가 감춰 둔 추론 루프를 직접 열어보고 싶었다. 손으로 짠 엔진과 프레임워크로 짠 엔진이 실제로 뭐가 다른지 몸으로 겪고 싶었다.

그래서 갈아끼우지 않고 토글로 뒀다. 관리자가 native와 LangGraph를 오가며 같은 질문에 두 엔진이 어떻게 답하는지 나란히 볼 수 있게. 나중엔 ReAct까지 세 번째 엔진으로 붙였다.

이 토글이 결국 문제를 빨리 잡아줬다. 같은 질문을 두 엔진에 던지고 답을 나란히 놓으니, 뱃지가 있고 없고가 그 자리에서 보였다.

스크린샷 준비중

같은 질문, 다른 엔진. 오른쪽 답에는 근거 카드가 없다.

뱃지는 버그로 사라진 게 아니었다

처음엔 파싱 코드를 의심했다. 마커를 놓치는 정규식이거나, 뱃지 렌더 조건이 어긋난 줄 알았다.

아니었다. 마커 자체가 최종 출력에 없었다.

단일 턴에서는 LLM이 내뱉은 문장이 곧 답이다. 마커도 그 문장에 실려 그대로 나간다. 그런데 다단계 추론은 중간에 생각을 한 겹 더 쌓는다. 최종 응답은 그 추론을 종합한 결과물이라, 원래 문장에 박혀 있던 마커가 종합을 거치며 살아남으리란 보장이 없다. LLM이 뜻을 정리하면서 [1][2]를 흘려버리는 것이다.

고칠 버그가 없었다. 출처 뱃지는 "LLM이 마커를 직접 만들고 그게 그대로 나온다"는 단일 턴의 전제 위에 서 있었다. 다단계 추론은 그 전제를 깬다.

뜻은 지켜지고, 각주만 사라진다.
뜻은 지켜지고, 각주만 사라진다.

여기서 딜레마가 생겼다. 모든 답을 다단계로 종합하게 하면 출처 추적이 깨진다. 그렇다고 추론 강화를 접으면 LangGraph를 얹은 의미가 없다.

전부 통일하지 않기로 했다

한 엔진으로 밀어붙여 통일하는 대신 경로를 갈랐다.

출처 뱃지가 중요한 답은 마커가 보존되는 단일 턴으로 흘리고, 다단계 추론이 이득인 답은 종합 경로로 흘린다.

ReAct 엔진을 붙이면서 이 분기를 하이브리드로 다듬었다. 기준은 툴을 몇 번 부르느냐, 라운드 수였다.

  • 툴을 안 부르면 LLM이 바로 답한다.
  • 툴을 한 번만 부르면 그 답을 원문 그대로 내보낸다. 마커도 출처도 산다.
  • 툴을 여러 번 체이닝할 때만 LLM이 종합한다. 이때는 마커 소실을 감수한다.

출처가 정말 필요한 순간은 대개 한 번의 검색으로 끝나는 질문이었다. 그 경로만 원문을 지켜주면 뱃지는 살아 있다. 여러 툴을 엮어야 답이 나오는 질문은 애초에 종합이 필요하고, 거기선 추적성보다 답의 완결성이 더 중요했다.

라운드 수로 경로를 가른다. 한 번까지는 원문 보존, 그 위는 종합.
라운드 수로 경로를 가른다. 한 번까지는 원문 보존, 그 위는 종합.

남은 것

이번 일로 확실해진 게 하나 있다. 추론을 한 겹 얹으면 답 자체는 멀쩡해도, 답에 딸려 나오던 것이 조용히 떨어질 수 있다. 이번엔 그게 출처 마커였다. 나는 답 텍스트만 보고 있었고 그 텍스트는 멀쩡했으니, 뱃지가 빠진 걸 한참 뒤에야 알아챘다.

하이브리드도 마커를 살려낸 건 아니다. 체이닝 경로에서는 여전히 마커가 사라진다. 그걸 고친 게 아니라, 출처가 필요한 질문을 그 경로로 안 보내는 쪽으로 피해 간 것이다. 종합 단계가 정확히 언제 마커를 흘리는지는 아직 다 파악하지 못했다.

두 엔진을 나란히 켜 둔 건 계속 그렇게 할 생각이다. 하나만 돌렸다면 뱃지가 없는 게 원래 그런 건지 빠진 건지 몰랐을 거다. 옆에 비교할 답이 있으니 빠진 게 바로 보였다.