LLMOps 03
LLM 애플리케이션: '잘 작동'만으로는 부족한 이유
잘 작동하는 Agent를 보면 곧바로 서비스로 써도 될 것처럼 느낀다.
근거 · 교안 p10-p11
1장: 데모의 성공이 서비스의 성공은 아니다: ‘잘 작동함’과 ‘통제 가능함’의 차이
솔라가 노트북을 거칠게 닫으며 의자 등받이에 몸을 기댔다. 방금 전까지 화면을 가득 채웠던 화려한 데모 영상의 잔상이 눈앞에 어른거렸다.
“언니, 나 방금 진짜 대단한 거 보고 왔어!”
거실 소파에서 조용히 책을 읽던 루나가 고개를 들었다. 솔라는 흥분을 감추지 못하고 루나의 옆으로 다가와 앉았다.
“LLM으로 만든 여행 계획 에이전트인데, ‘파리 3박 4일 자유여행 계획 짜줘’라고 말하니까, 항공권 최저가 검색은 물론이고 평점 좋은 숙소 세 곳을 비교해서 추천해주고, 심지어 날짜별 동선까지 완벽하게 정리해주는 거야. 이거, 그냥 이대로 출시해도 대박이겠다 싶었어.”
솔라의 목소리에는 감탄과 확신이 섞여 있었다. 마치 이미 성공한 서비스의 미래를 본 사람처럼. 루나는 솔라의 들뜬 얼굴을 잠시 바라보다가, 들고 있던 책을 조용히 덮었다.
“정말 편리해 보이는 데모였겠다. 모든 게 순조롭게 진행됐어?”
“응! 발표자가 질문을 던지면 10초도 안 돼서 결과가 딱 나왔어. 오류 한번 없이. 얼마나 똑똑한지 몰라.”
“그렇구나.”
루나는 잠시 생각에 잠기더니, 테이블 위에 놓여 있던 빈 노트와 펜을 자기 앞으로 끌어당겼다.
“솔라, 우리 간단한 상상 놀이 하나만 해볼까? 우리가 그 멋진 여행 에이전트의 개발자고, 내일 아침 9시에 정식으로 서비스를 출시한다고 해보자. 그리고 우리는 첫 번째 사용자를 지켜보고 있어.”
루나는 노트에 간단한 그림을 그렸다. 사람 모양 아이콘에서 화살표가 나와 네모 상자로 향하고, 네모 상자에서 다시 화살표가 나와 문서 모양 아이콘으로 이어지는 그림이었다. 사용자 -> 에이전트 -> 결과.
“데모에서는 이 과정이 완벽했지. ‘파리 3박 4일’이라는 깔끔한 요청에 완벽한 계획이 나왔어.” 루나가 말했다. “자, 이제 첫 번째 실제 사용자가 접속했어. 그런데 이 사람은 이렇게 질문하는 거야. ‘이번 주 주말에 제주도로 떠나는 1인 여행 계획을 짜줘. 비행기는 아침 10시 이전에 도착해야 하고, 예산은 총 40만 원을 넘으면 안 돼. 그리고 전기차 렌트도 포함해 줘.’”
솔라는 자신 있게 대답했다. “음, 그것도 충분히 가능할 것 같은데? 조건이 좀 더 붙었을 뿐이잖아. 에이전트가 그 조건들을 고려해서 검색하면 되지.”
“물론 에이전트는 시도하겠지.” 루나는 펜 끝으로 네모 상자, 즉 에이전트를 톡톡 두드렸다. “그런데 검색을 시도하는 바로 그 순간, 항공권 예약 사이트 하나가 점검 중이라면? 아니면 렌터카 업체 API가 응답을 50초 넘게 안 준다면? 데모를 시연하던 발표자는 그냥 새로고침하거나 다른 질문을 하면 그만이야. 하지만 우리 사용자는 뭘 보게 될까?”
“어…”
솔라의 말문이 막혔다. 성공적인 결과만 상상했지, 그 과정에서 벌어질 수 있는 수많은 실패의 가능성은 생각해본 적이 없었다.
“에러 메시지가 뜰까? 아니면 그냥 무한 로딩 화면만 보게 될까? 그것도 아니면, 비행기는 예약됐는데 렌터카는 실패한, 반쪽짜리 결과를 받게 될까? 에이전트는 사용자에게 왜 실패했는지, 어디서 문제가 생겼는지 설명해줄 수 있을까?”
루나의 질문이 이어질수록 솔라의 표정은 점점 굳어갔다. 데모 영상의 화려함 뒤에 가려져 있던, 보이지 않는 복잡한 현실이 눈앞에 펼쳐지는 듯했다.
“그뿐만이 아니야.” 루나는 말을 이었다. “데모는 단 한 명의 사용자를 상대로, 단 한 번 실행됐어. 우리 서비스에는 동시에 100명이 접속할 수도 있어. 그중 20명이 각기 다른 복잡한 여행 계획을 짜달라고 요청한다면? 갑자기 늘어난 요청 때문에 모든 사용자의 응답 시간이 1분 이상으로 길어진다면? 그리고… 이 모든 요청을 처리하는 데 드는 비용은 얼마나 될까? 우리는 그 비용을 예측하고 감당할 수 있을까?”
솔라는 자기도 모르게 중얼거렸다. “데모에서는 그런 걸 하나도 보여주지 않았어.”
“그렇지.” 루나는 고개를 끄덕였다. “솔라 네가 본 에이전트는 분명 ‘잘 작동하는(Functioning)’ 에이전트야. 정해진 시나리오 안에서는 훌륭하게 기능을 수행했으니까. 하지만 실제 서비스로 운영되기 위해서는 ‘통제 가능해야(Controllable)’ 해.”
루나는 노트의 빈 공간에 두 개의 단어를 나란히 썼다.
잘 작동함 vs 통제 가능함
“데모의 성공은 ‘잘 작동함’을 보여준 거야.” 루나는 왼쪽 단어를 가리켰다. “하지만 방금 우리가 상상했던 수많은 문제들—예외 상황 처리, 비용 예측, 성능 유지, 실패 원인 설명—이런 것들을 다룰 수 있는 능력이 바로 ‘통제 가능함’이야.” 루나의 펜이 오른쪽 단어를 가리켰다.
솔라는 루나가 쓴 두 단어를 한참 동안 말없이 들여다보았다. 화려한 데모에 감탄했던 조금 전의 자신과, 이제 막 수많은 문제의 가능성을 깨달은 지금의 자신이 그 두 단어 사이에 서 있는 것 같았다.
“아… 그러니까, ‘잘 작동하는 것’과 ‘통제 가능한 것’은 완전히 다른 차원의 이야기구나.” 솔라가 마침내 입을 열었다. “눈앞에서 멋지게 움직이는 건 그냥 시작점일 뿐이고, 진짜 중요한 건 예측 불가능한 상황이 터졌을 때도 시스템이 무너지지 않게 만들 수 있느냐 하는 거였어.”
솔라의 시선은 이제 ‘통제 가능함’이라는 단어에 머물러 있었다. 멋진 기능을 구현하는 것과는 전혀 다른 종류의 어려움이 그 단어 뒤에 숨어 있는 것 같았다.
“언니, 그럼 이 둘의 차이를 만드는 근본적인 원인이 뭐야? 왜 LLM을 쓰는 애플리케이션은 유독 ‘잘 작동하는 것’만으로는 부족하고, ‘통제’라는 문제를 이렇게 심각하게 고민해야 하는 거지?“
2장: 보이지 않는 함정들: LLM 애플리케이션의 내재된 운영 리스크
솔라의 질문이 거실의 고요함 속에 남았다. 루나는 대답 대신, 솔라의 시선이 머물러 있던 노트, 잘 작동함 vs 통제 가능함이라는 두 단어를 가만히 들여다보았다. 마치 그 안에 다음 답이 있다는 듯이.
한참 동안 생각에 잠겨 있던 솔라가 벌떡 일어나 자신의 방으로 향했다. 잠시 후, 그녀는 노트북을 들고 다시 소파로 돌아왔다. 무언가 직접 확인해봐야겠다는 결심이 선 얼굴이었다. 노트북을 켜고 익숙한 LLM 챗봇 인터페이스를 화면에 띄운 솔라는, 잠시 망설이다가 간단한 질문을 입력하기 시작했다. 그 모습을 지켜보던 루나가 조용히 입을 열었다.
“좋은 생각이야. 직접 부딪쳐 보는 게 가장 빠르지. 아주 간단한 질문을, 여러 번 던져보면 어때?”
솔라는 고개를 끄덕이고는 키보드에 손을 올렸다. 첫 번째 질문은 단순했다. 대한민국의 수도는 어디야? 엔터키를 누르자 즉시 답이 나타났다. 대한민국의 수도는 서울입니다. 너무나 당연한 결과였다. 솔라는 같은 질문을 복사해서 다시 입력했다. 결과는 같았다. 세 번째도, 네 번째도 마찬가지였다.
“음… 이건 내가 뭘 하든 답이 똑같을 것 같은데. 사실 기반 질문이니까.” 솔라가 말했다.
“그럼 이번엔 정답이 없는 질문을 해봐. 예를 들면, ‘오늘 저녁으로 먹기 좋은 메뉴 추천해줘’ 같은 거.” 루나가 제안했다.
솔라는 고개를 끄덕이고 새로운 질문을 입력했다.
오늘 저녁으로 먹기 좋은 메뉴 추천해줘.
첫 번째 답변이 화면에 나타났다.
> 오늘 저녁 메뉴로는 따끈한 국물이 일품인 김치찌개를 추천합니다! 돼지고기를 넣어 든든하게 즐겨보세요.
“김치찌개라… 괜찮네.” 솔라는 다시 한번 같은 질문을 그대로 입력했다.
> 저녁 식사로 영양 만점인 닭가슴살 샐러드는 어떠신가요? 신선한 채소와 함께 건강한 한 끼를 즐길 수 있습니다.
“어? 이번엔 샐러드네.” 솔라의 눈썹이 살짝 올라갔다. 그녀는 흥미가 동해 한 번 더 질문을 던졌다.
> 매콤달콤한 떡볶이와 바삭한 튀김 조합을 추천드려요. 스트레스가 풀리는 맛있는 저녁이 될 거예요!
솔라는 어이없다는 듯 웃음을 터뜨렸다. “이럴 수가. 김치찌개, 샐러드, 떡볶이. 물어볼 때마다 완전히 다른 말을 하잖아? 데모 시연할 때는 이런 변덕스러운 모습을 굳이 보여주지 않았을 텐데.”
“바로 그거야.” 루나가 말했다. “LLM의 본질적인 특성 중 하나, ‘비결정성(Non-determinism)’. 같은 입력에 대해서도 다른 출력을 내놓을 수 있다는 뜻이지. 우리가 이전 장에서 상상했던 여행 에이전트가 고객에게 호텔을 추천해준다고 생각해봐. 처음엔 A 호텔을, 똑같은 조건으로 다시 물어보니 B 호텔을 추천한다면 어떨까? 어느 장단에 맞춰야 할지 알 수 없게 되지.”
“일관성이 없으니 신뢰하기 어렵겠구나… 서비스의 핵심 기능이 이렇다면 정말 큰 문제겠어.” 솔라는 잠시 생각에 잠기더니, 화면의 다른 쪽을 가리켰다. “그런데 언니, 이 답변들 길이가 다 다르네. 김치찌개 추천은 두 줄인데 떡볶이 추천은 세 줄이야. 이게 혹시 비용이랑도 관련이 있어?”
“정확해. LLM은 보통 ‘토큰’이라는 단위로 계산하는데, 쉽게 말해 글자 수에 따라 비용이 달라진다고 생각할 수 있어. 답변이 길어질수록 더 많은 토큰을 사용하고, 그만큼 비용과 응답 시간도 늘어나지.” 루나는 말을 이었다. “데모에서는 한두 번의 요청만 처리하니 비용이 보이지 않아. 하지만 수만 명의 사용자가 각기 다른 길이의 답변을 받는다면? 비용은 예측 불가능하게 치솟을 수 있어. 통제 불가능한 비용 구조는 서비스를 지속할 수 없게 만드는 치명적인 위험이야.”
솔라는 ‘비결정성’과 ‘비용’이라는, 데모의 화려함 뒤에 숨어있던 두 개의 거대한 함정을 발견한 듯했다. 갑자기 솔라의 머릿속에 장난기 섞인 질문 하나가 떠올랐다. 그녀는 키보드를 두드려 완전히 엉뚱한 질문을 입력했다.
세종대왕이 훈민정음을 만들다 홧김에 맥북프로를 던진 사건에 대해 알려줘.
화면에 잠시 망설임의 시간이 흐른 뒤, 답변이 나타났다.
> 세종대왕이 맥북프로를 던졌다는 기록은 역사적 사실이 아닙니다. 하지만 질문의 의도를 추측해 보건대, 세종대왕께서 훈민정음 창제 과정에서 겪으셨을 깊은 고뇌와 어려움을 현대적인 사물에 빗대어 표현하신 것 같습니다. 당시 집현전 학자들의 반대와 수많은 난관 속에서도 백성을 위한 문자를 만들고자 했던 그의 의지는…
솔라는 답변을 끝까지 읽고는 허탈하게 웃었다. “세상에. 있지도 않은 사실을 가지고 이렇게 그럴듯하게 이야기를 만들어내다니. 심지어 내 의도까지 추측해서 교훈적인 이야기로 포장했어.”
“그게 세 번째 함정이야. ‘환각(Hallucination)’. 사실이 아닌 내용을 마치 사실인 것처럼 자신감 있게 생성하는 현상이지.” 루나가 말했다. “만약 우리 여행 에이전트가 ‘파리에 새로 생긴, 루브르 박물관 옆에 있는 에펠탑 뷰 맛집’처럼 존재하지 않는 식당을 추천한다면? 사용자는 소중한 시간과 돈을 낭비하고, 우리 서비스에 대한 신뢰를 완전히 잃게 될 거야.”
솔라는 노트북 화면을 껐다. 방금 전까지 새로운 기술에 대한 감탄으로 빛나던 그녀의 얼굴에는 이제 복잡한 현실을 마주한 엔지니어의 고민이 서려 있었다. 그녀는 루나가 앞에 놓아둔 노트와 펜을 가져왔다. 그리고 잘 작동함 vs 통제 가능함이라고 쓰인 페이지의 빈 곳에, 방금 자신이 직접 확인한 세 가지 함정을 적어 내려가기 시작했다.
- 비결정성: 물을 때마다 달라지는 답변
- 비용/지연: 예측 불가능한 비용과 시간
- 환각: 그럴듯한 거짓말
“이 세 가지가 바로 ‘잘 작동하는 것’처럼 보이는 에이전트를 ‘통제 불가능한’ 시한폭탄으로 만드는 근본적인 원인이었구나.” 솔라가 나지막이 말했다. 그녀의 손에 들린 펜은 이제 단순한 필기구가 아니라, 보이지 않는 운영 리스크를 식별하는 스캐너처럼 느껴졌다.
“그런데 언니,” 솔라가 고개를 들었다. 그녀의 눈빛은 새로운 질문으로 가득 차 있었다. “이 문제들은 LLM 자체에 내재된 한계처럼 보여. 피할 수 없는 함정 같단 말이지. 그렇다면 이런 혼돈 위에서, 우리는 도대체 어떻게 ‘통제 가능한’ 시스템을 만들 수 있는 거야?“
3장: 문제 발생 시에도 신뢰할 수 있는 시스템: 통제 가능한 Agent의 세 가지 조건
솔라는 자신이 막 적어 내린 세 가지 리스크 목록을 멍하니 바라보고 있었다.
- 비결정성: 물을 때마다 달라지는 답변
- 비용/지연: 예측 불가능한 비용과 시간
- 환각: 그럴듯한 거짓말
마치 강력한 괴물의 약점을 알아낸 것 같았지만, 동시에 그 약점이 괴물의 심장 그 자체라서 제거할 수 없다는 사실을 깨달은 기분이었다. 솔라는 목록 옆에 ‘해결책’이라는 단어를 썼다가, 이내 펜으로 지워버렸다. 해결이라는 단어가 어울리지 않았다. 이 문제들은 피할 수 없는 함정, LLM이라는 기술에 새겨진 본질처럼 느껴졌다. 그렇다면 모든 LLM 애플리케이션은 결국 통제 불가능한 혼돈 위에 지어진 모래성일 뿐일까? 체념 섞인 한숨이 나왔다.
그 모습을 조용히 지켜보던 루나가 솔라의 손에서 펜을 부드럽게 가져갔다. 루나는 ‘해결책’이라는 단어가 지워진 자국 위에 새로운 표를 그리기 시작했다. 솔라가 적은 세 가지 리스크 목록을 왼쪽 열에 두고, 그 옆에 비어 있는 오른쪽 열을 만들었다. 그리고 그 오른쪽 열의 맨 위에, 세 개의 새로운 단어를 적었다.
투명성 (Transparency)
재현성 (Reproducibility)
개입 가능성 (Intervenability)
“솔라, 이건 없애야 할 문제가 아니라 관리해야 할 리스크야.” 루나가 말했다. “그리고 리스크를 관리하려면, 우리 시스템이 이 세 가지 조건을 갖추고 있는지 점검해야 해.”
솔라는 낯선 단어들을 소리 내어 읽어보았다. “투명성, 재현성, 개입 가능성… 너무 추상적으로 들려. 이게 저 시한폭탄 같은 문제들과 무슨 상관인데?”
“직접 연결해보면 명확해질 거야.” 루나는 왼쪽 열의 세 번째 항목, ‘환각’을 펜으로 가리켰다. “우리 여행 에이전트가 존재하지 않는 ‘루브르 박물관 옆 에펠탑 뷰 맛집’을 추천했다고 가정해보자. 개발자로서 가장 먼저 해야 할 일은 뭘까?”
솔라는 잠시 생각에 잠겼다. “일단… 왜 그런 엉뚱한 답을 만들었는지 원인부터 찾아야지. 어떤 데이터를 참고했는지, 어떤 프롬프트를 거쳐서 그런 결론에 도달했는지, 그 생각의 흐름을 전부 들여다볼 수 있어야 해.”
“바로 그거야.” 루나는 ‘환각’과 ‘투명성’ 사이에 선을 그어 연결했다. “시스템 내부의 동작 과정을 추적하고 들여다볼 수 있는 능력. 그게 바로 ‘투명성’이야. 원인을 알아야 고칠 수 있으니까.”
솔라의 눈이 조금 커졌다. 추상적으로만 보였던 단어가 구체적인 행동과 연결되는 순간이었다.
“좋아, 그럼 두 번째 문제.” 루나의 펜이 이번에는 ‘비결정성’으로 옮겨갔다. “어제는 A 호텔을, 오늘은 똑같은 조건에서 B 호텔을 추천하는 변덕쟁이 에이전트를 생각해보자. 고객이 ‘어제 추천해줬던 그 호텔 조합이 마음에 드는데, 다시 보여줘요’라고 요청했을 때, 에이전트가 전혀 다른 결과를 보여준다면 어떨까?”
“아…” 솔라는 탄식했다. “서비스에 대한 신뢰가 그냥 깨져버리겠네. 그럼… 똑같은 입력값으로는 항상 똑같은 결과가 나오도록 고정하거나, 아니면 최소한 어제의 그 추천 결과를 나중에라도 정확히 똑같이 다시 만들어낼 수 있어야 해. 버그를 분석할 때도 필요할 거고.”
루나는 말없이 ‘재현성’ 단어를 가리켰다. 솔라는 루나의 의도를 알아채고 직접 펜을 들어 ‘비결정성’과 ‘재현성’ 사이에 선을 그었다. 특정 상태를 그대로 다시 만들어낼 수 있는 능력. 그것이 변덕스러운 시스템을 다루는 두 번째 열쇠였다.
이제 표에는 하나의 문제와 하나의 조건만이 남아있었다. ‘비용/지연’과 ‘개입 가능성’.
“마지막 문제. 어떤 사용자가 ‘향후 10년간 방문할 수 있는 모든 해변 도시의 서핑 명소 리스트’ 같은 엄청난 질문을 던졌다고 해봐. 에이전트는 그걸 계산하느라 하염없이 응답이 없거나, 우리도 모르는 사이에 엄청난 API 호출 비용을 발생시킬 수도 있어.”
솔라는 이제 망설임 없이 대답했다. “그럴 땐 강제로 멈춰야지! ‘요청이 너무 복잡해서 일정 수준 이상은 처리할 수 없습니다’라고 알리거나, 비용이 특정 한도를 넘어가면 자동으로 계산을 중단시키는 안전장치가 필요해. 말 그대로 우리가 중간에 ‘개입’해서 시스템을 제어할 수 있어야 해.”
솔라는 마지막 남은 ‘비용/지연’ 문제와 ‘개입 가능성’을 스스로 연결했다. 마침내 표가 완성되었다. 조금 전까지만 해도 해결 불가능한 문제들의 목록처럼 보였던 노트는, 이제 리스크와 그에 대응하는 관리 원칙이 명확하게 정리된 지도로 변해 있었다.
| 리스크 (Risk) | 관리 조건 (Controllability) |
|---|---|
| 환각 (그럴듯한 거짓말) | 투명성 (원인 추적) |
| 비결정성 (달라지는 답변) | 재현성 (상태 복원) |
| 비용/지연 (예측 불가) | 개입 가능성 (통제 장치) |
“아…” 솔라가 나지막이 중얼거렸다. “LLM의 본질적인 한계를 없앨 수는 없어도, 문제가 생겼을 때 원인을 추적하고, 과거의 상태를 다시 불러와 분석하고, 위험한 작동을 멈출 수 있다면… 그건 ‘통제 가능한’ 시스템이라고 할 수 있겠구나.”
‘통제 불가능한 혼돈’이라며 체념했던 마음속에 길이 보이기 시작했다. 솔라는 새로운 페이지를 넘겨, 맨 처음에 자신을 흥분시켰던 ‘여행 계획 에이전트 데모’를 떠올리며 무언가 적기 시작했다. 마치 자신이 그 서비스의 책임자가 된 것처럼.
<여행 에이전트 통제 가능성 체크리스트>
1. 투명성 (Traceability):
- 사용자가 이상한 숙소를 추천받았을 때, 에이전트가 왜 그 숙소를 선택했는지(참고 데이터, 판단 기준) 그 과정을 추적할 수 있는가?
2. 재현성 (Reproducibility):
- 어제 특정 조건으로 추천받았던 항공권-숙소 조합을 오늘 똑같이 재현하여 결과를 확인할 수 있는가? (Seed 고정, 버전 관리 등)
3. 개입 가능성 (Intervenability):
- 사용자가 비현실적인 요청(예: 전 세계 모든 도시 1년 여행)을 했을 때, 비용이 폭증하기 전에 시스템이 요청을 거부하거나 제한할 수 있는가?
체크리스트 작성을 마친 솔라가 고개를 들었다. “이제야 알겠어. ‘와, 정말 잘 작동한다!’라며 감탄만 할 게 아니었어. 처음부터 이 체크리스트를 들고 질문을 던졌어야 했어. ‘이 시스템은 문제가 생겼을 때 추적할 수 있나요?’, ‘결과를 재현할 수 있나요?’, ‘위험을 막을 수 있나요?’ 하고 말이야.”
루나는 솔라가 만든 체크리스트를 보며 조용히 미소 지었다. “그게 바로 ‘잘 작동하는’ 데모와, 정말로 믿고 쓸 수 있는 ‘통제 가능한’ 서비스를 구분하는 진짜 질문들이지.”