왜 WhatsApp이 나의 스페인어 학습 웹 앱을 이겼는가 (그리고 이를 가능하게 한 메모리 해킹 기술)
요약
스페인어 학습 웹 앱보다 WhatsApp 에이전트의 리텐션이 압도적으로 높았던 사례를 분석합니다. 컨텍스트 스위칭을 줄이는 메시징 플랫폼의 중요성과 비용 효율적인 대화 메모리 구축 전략을 다룹니다.
핵심 포인트
- 사용자 경험 측면에서 컨텍스트 스위칭을 최소화하는 채널 선택이 리텐션에 결정적임
- WhatsApp과 같은 기존 메시징 플랫폼 활용 시 재방문율이 극적으로 상승함
- 모든 메모리 구현에 고비용 벡터 데이터베이스를 사용할 필요는 없음
- 비용 효율적인 2계층 메모리 구조를 통해 세션 간 대화 맥락 유지 가능
AIdeazz에 처음 게시되었습니다 — 정식 링크(canonical link)와 함께 이곳에 교차 게시되었습니다.
저는 스페인어 학습을 위한 웹 앱을 만드는 데 6주를 보냈습니다. 깔끔한 React 프론트엔드, 진행 상황 대시보드, 간격 반복 (Spaced-repetition) 로직 등 모든 것을 갖추고 있었습니다. 처음 2주 동안 100명의 무료 가입자를 확보했고, 3주 차에는 4%의 재방문율을 기록했습니다. 그러고 나서 저는 동일한 기능을 9일 만에 WhatsApp 에이전트로 다시 구축했고, 월 9달러를 청구했으며, 3명이 결제했습니다. 그 세 명은 웹 앱 코호트(cohort) 전체를 합친 것보다 리텐션 (Retention), 기억 (Memory), 그리고 "AI 언어 학습"이 실제로 무엇을 의미하는지에 대해 저에게 더 많은 것을 가르쳐 주었습니다.
이것은 WhatsApp과 Telegram에서 작동하는 이중 언어 스페인어/영어 튜터인 EspaLuz의 아키텍처 (Architecture)이며, 특히 관리형 벡터 스토어 (Managed vector store) 비용을 지불하지 않고도 세션 간에 유지되는 대화 메모리 (Conversation memory)를 어떻게 구축했는지에 대한 내용입니다. 만약 당신이 웹 앱과 메시징 에이전트 사이에서 고민 중인 창업자이거나, 누군가 "메모리"라고 말하자마자 Pinecone을 찾으려는 개발자라면, 확정하기 전에 비용 수치를 먼저 읽어보시기 바랍니다.
웹 앱은 조명이 좋은 공동묘지였다
문제는 기능이 아니라 대시보드였습니다. 언어를 배우기 위한 모든 웹 앱은 사용자에게 똑같은 행동을 요구합니다. 일상을 멈추고, 탭을 열고, 로그인한 뒤, "공부"하는 것입니다. 그것은 컨텍스트 스위칭 (Context switch)이며, 컨텍스트 스위칭은 리텐션 (Retention)이 죽는 지점입니다. 저의 100명 가입자들이 이탈한 이유는 레슨이 나빠서가 아니었습니다. 스페인어를 연습하기 위해 전용 탭을 여는 행위가 이메일, Slack, 그리고 그들이 파나마에 온 실제 이유 — 즉, 공부하러 온 것이 아니라 여기서 살기 위해 온 것 — 와 경쟁했기 때문입니다.
WhatsApp은 문맥 전환 (context switch)을 요구하지 않습니다. 이미 열려 있으니까요. 라틴 아메리카에서 WhatsApp은 단순한 앱이 아니라 하나의 기질 (substrate)입니다. 집주인이 그 앱으로 문자를 보내고, 아이의 학교에서 숙제를 보내며, 에어컨 수리 기사가 수리 일정을 확인합니다. EspaLuz가 그 동일한 대화 스레드 (thread) 안에 존재할 때, 스페인어를 연습하는 것은 별개의 활동이 아닙니다. 사용자가 이미 하루에 40번씩 확인하는 대화 목록 중 하나로 포함되는 또 다른 대화일 뿐입니다.
수치로 보면 이렇습니다. 웹 앱의 3주 차 재방문율 (return rate)은 4%였습니다. 반면, 아주 적은 유료 사용자 집단 (cohort)을 대상으로 한 WhatsApp 에이전트의 3주 차 재방문율은 100%였습니다. 즉, 3명 중 3명이었습니다. 표본이 작다는 것은 맞습니다. 하지만 4%와 100%의 차이는 표본 크기에 의한 인위적인 결과 (artifact)가 아닙니다. 그것은 전달 채널 (delivery-channel)에 의한 결과입니다.
유료 벡터 스토어(vector store) 없는 2계층 메모리
여기서 대부분의 개발자가 실수하는 부분이 있습니다. 누군가 "AI가 대화를 기억해야 한다"라고 말하는 순간, 모두가 임베딩 (embeddings)과 벡터 데이터베이스 (vector database)를 찾습니다. 언어 튜터에게 그것은 과하며, 비용을 발생시키고, 대부분 필요하지 않은 검색 (retrieval)을 위해 지연 시간 (latency)을 추가할 뿐입니다.
EspaLuz는 두 개의 메모리 계층을 사용하며, 둘 다 관리형 벡터 스토어 (managed vector store)를 필요로 하지 않습니다.
계층 1 — 롤링 대화 창 (Rolling conversation window). 실제 대화의 마지막 N개 메시지를 Oracle Cloud의 Postgres에 일반 행 (rows)으로 저장합니다. 사용자당 대략 최근 20번의 턴 (turns)을 유지합니다. 이것이 작업 메모리 (working memory)입니다. 방금 우리가 이야기한 내용, 사용자가 세 메시지 전에 어려워했던 동사 시제, 사용자가 했던 농담 같은 것들 말이죠. 임베딩은 사용하지 않습니다. 그저 SELECT ... WHERE user_id = $1 ORDER BY created_at DESC LIMIT 20 쿼리를 실행하고, 순서를 뒤집어 프롬프트 (prompt)에 집어넣을 뿐입니다.
Layer 2 — 구조화된 학습자 프로필 (Structured learner profile). 이 사람이 학습자로서 누구인지에 대한 요약되고 천천히 변화하는 기록입니다. 이들의 수준 (A2, B1을 향해 가는 중), 반복되는 실수 (_ser_와 _estar_를 혼동함, 목적격 전치사 _a_를 생략함), 관심 주제 (자녀의 학교, 식료품 어휘, 집주인과 대화하기), 그리고 목표가 포함됩니다. 이것은 가공되지 않은 대화(raw conversation)가 아닙니다. 저렴한 요약 프로세스(summarization pass)를 통해 몇 세션마다 한 번씩 업데이트되는, Postgres의 단일 행(single row)이자 정제된 JSON 블롭(JSON blob)입니다.
메시지가 들어오면, 프롬프트(prompt)는 프로필 블롭(profile blob), 롤링 윈도우(rolling window), 그리고 새로운 메시지를 결합하여 두 레이어(layer)를 모두 구성합니다. 이것이 전체 메모리 시스템의 전부입니다. 총 관리형 벡터 스토어(managed-vector-store) 비용: $0. 이미 실행 중인 Oracle 인스턴스 외의 총 인프라(infra) 비용: $0.
실제로 임베딩 (embeddings)이 필요한 때는 언제인가요?
애매하게 답변하는 대신 확실한 답을 드리겠다고 말씀드렸으니, 바로 말씀드리겠습니다. 벡터 스토어(vector store)가 필요한 경우는 사용자가 작성하지 않은, 대규모의 정적인 코퍼스(corpus) — 문서 세트, 법률 라이브러리, 400페이지 분량의 교과서 등 — 에서 정보를 검색해야 할 때입니다. 즉, 콘텐츠를 검색하는 경우입니다.
언어 튜터는 그 반대의 경우입니다. 코퍼스를 검색하는 것이 아닙니다. 제한된 횟수의 대화 턴(turns) 동안 한 개인에 대한 상태(state)를 유지하는 것입니다. 관련 컨텍스트(context)는 거의 항상 최근의 것이거나(롤링 윈도우), 구조적으로 안정적입니다(프로필). 누군가의 18개월 치 스페인어 연습 기록을 대상으로 시맨틱 검색 (Semantic search)을 수행하는 것은 강력해 보일 수 있지만, 실제로는 90초 전에 저지른 실수가 중요한 상황에서 3월의 무작위 메시지를 끌어올리는 방식일 뿐입니다.
만약 EspaLuz가 성장하여 학습자가 수천 번의 세션을 갖게 되고, 제가 "3개월 전에 생선 시장에서 주문하는 것에 대해 이야기했던 거 기억해?"라는 기능을 구현하고 싶다면, 임베딩 (embeddings)을 사용한 세 번째 레이어를 추가할 것입니다. 이는 장기적인 에피소드 기억 (episodic recall)에만 범위를 한정하며, 가공되지 않은 대화가 아닌 요약본만을 대상으로 할 것입니다. 그것은 12개월 차를 위한 기능이지, MVP (Minimum Viable Product)를 위한 것이 아닙니다. 첫날부터 이를 구축하는 것은, 유료 사용자 3명이 겪지도 않을 문제를 해결하기 위해 돈과 지연 시간 (latency)을 낭비하는 일이었을 것입니다.
세션 간의 대화 연속성 (Conversation continuity)이 곧 제품의 핵심입니다
유료 사용자를 계속 머물게 만든 단 하나의 요소는 바로 EspaLuz가 기억한다는 점이었습니다. 마케팅적인 의미가 아니라, 사용자가 이틀 뒤에 돌아왔을 때 에이전트가 이전에 무엇을 학습했는지 언급한다는 문자 그대로의 의미입니다. "지난번에 아파트에 대해 이야기할 때 _por_와 _para_를 헷갈려 하셨죠. 다시 한번 해볼까요?"
이것은 프로필 레이어 (profile layer)와 롤링 윈도우 (rolling window)가 제 역할을 수행한 결과입니다. 기술적으로 웹 앱에도 이 데이터가 있었습니다. 진행 상황 대시보드 (progress dashboard)에 들어 있었죠. 하지만 아무도 대시보드를 읽지 않습니다. 차이점은 대화 속에서는 연속성 (continuity)이 클릭 뒤에 숨겨져 있는 것이 아니라, 대화 내에서 사용자에게 직접 '전달'된다는 점입니다. WhatsApp에서의 AI 언어 학습 경험이 작동하는 이유는 대화 메모리 (conversation memory)가 차트가 아닌 대화로서 나타나기 때문입니다.
여기서 기술적인 함정은 세션 경계 (session boundaries)입니다. WhatsApp은 네이티브한 세션 개념을 제공하지 않으며, 모든 메시지는 단순한 웹훅 (webhook)일 뿐입니다. 따라서 "세션"은 개발자가 직접 정의해야 하는 것입니다. 저는 몇 시간 이상의 공백이 생기면 새로운 세션으로 간주하고, 프로필에서 정보를 가져와 가벼운 재인사 (re-greeting)를 트리거합니다. 이 재인사가 사용자로 하여금 기억되고 있다는 느낌을 받게 합니다. 이는 복귀 세션의 첫 번째 메시지에서 저렴한 LLM 호출을 한 번 더 수행하는 비용이 발생합니다.
모델 라우팅 (Model routing): 속도를 위한 Groq, 까다로운 상황을 위한 Claude
EspaLuz는 단일 모델이 아닌 라우팅 레이어 (routing layer) 위에서 작동합니다. 어휘 교정, 빠른 번역, "X를 어떻게 말하나요?"와 같은 대부분의 메시지는 1초 미만의 응답 속도를 위해 Groq에서 호스팅되는 Llama로 전달됩니다. 메시징 맥락에서 지연 시간 (latency)은 매우 잔혹하게 느껴집니다. 웹 앱 사용자는 페이지 로딩을 기다리지만, WhatsApp 사용자는 "입력 중..." 표시를 4초 동안 보고 있으면 서비스가 고장 났다고 생각합니다.
더 까다로운 상황(harder turns)은 Claude로 라우팅됩니다. 사용자가 문단을 작성하여 미묘한 피드백을 원할 때, 실제 요약 과정을 통해 프로필을 업데이트해야 할 때, 또는 대화가 감정적으로 격앙될 때(포기하기 직전의 좌절한 학습자 등)가 이에 해당합니다. Claude는 이러한 상황을 더 잘 처리하며, 이러한 메시지는 전체의 소수에 불과하기 때문에 비용 측면에서도 정당화됩니다.
라우팅 결정(routing decision)은 수신된 메시지에 몇 가지 휴리스틱(heuristics)을 더한 저렴한 분류기(classifier)입니다. 메시지 길이, 사용자가 채팅 중인지 아니면 교정을 요청하는지 여부, 최근 오류 밀도(error density) 등이 이에 해당합니다. 트래픽의 약 80%는 Groq로 향하고, 20%는 Claude로 향합니다. 이러한 분할 덕분에 사용자당 월간 모델 비용을 1달러 미만으로 유지할 수 있으며, 이는 Twilio의 WhatsApp 메시징 수수료를 제외하고도 월 9달러의 가격이 실제로 마진을 가질 수 있게 해줍니다. 여기서 당신이 주의 깊게 살펴봐야 할 실제 비용 항목은 LLM이 아니라 Twilio의 수수료입니다.
100명의 무료 가입자도 가르쳐주지 못한 세 명의 유료 사용자가 내게 가르쳐준 것
무료 가입자는 허영심(vanity)을 충족시켜 줍니다. 헤드라인이 효과가 있었다는 것만 알려줄 뿐입니다. 하지만 사용자가 아무런 이해관계(skin in the game)가 없고 다시 돌아올 이유도 없기 때문에, 제품이 누군가의 실제 삶과 접촉했을 때 생존할 수 있을지에 대해서는 아무것도 알려주지 않습니다.
세 명의 유료 사용자는 제가 기반하여 구축할 수 있는 구체적인 정보들을 제공했습니다:
- 한 명은 의사와 대화가 필요한 은퇴자였습니다. 그녀의 어휘 요구 사항은 전적으로 의료 및 행정적인 것이었습니다. 무료 사용자 집단은 스페인어를 실제로 '무엇을 위해' 필요로 하는지 아무도 말해주지 않았기에 이를 밝혀내지 못했습니다. 하지만 그녀는 비용을 지불했고 서비스가 작동하기를 기대했기 때문에 저에게 말해주었습니다.
- 한 명은 문장 중간에 계속 영어로 전환하며 에이전트가 부드럽게 제지해주기를 원했습니다. 이것은 '몰입 허용도: 낮음(tolerance for immersion: low)'이라는 프로필 플래그(flag)가 되었고, 이는 EspaLuz가 스페인어 대 이중 언어(bilingual) 모드에서 얼마나 공격적으로 반응할지를 결정합니다.
- 한 명은 전체 문장을 전혀 사용하지 않고 단어 하나만 던졌으며, 에이전트가 과하게 설명할 때 좌절감을 느꼈습니다. 이를 통해 응답 길이(response length)가 사용자의 메시지 길이에 맞춰 적응해야 한다는 것을 배웠고, 이제 이는 라우팅 입력값(routing input)으로 사용됩니다.
이 세 가지 통찰 중 그 어떤 것도 100명의 무료 가입자에게서는 얻을 수 없었습니다. 무료 사용자는 조용히 이탈(churn)합니다. 유료 사용자는 불만을 제기하며, 이러한 불만은 당신이 얻을 수 있는 가장 저렴하고 해상도가 높은(highest-resolution) 제품 피드백입니다. 일찍부터 비용을 청구하세요. 세 명에게서 돈을 벌기 위해서가 아니라, 가격표야말로 관광객을 학습자로 바꾸는 요소이기 때문입니다.
채널을 선택하려는 창업자에게 해주고 싶은 말
만약 사용자들이 당신의 제품이 해결하고자 하는 이유 때문에 이미 메시징 앱(messaging app)을 사용하고 있다면, 그곳에 에이전트(agent)를 구축하세요. 사용자가 당신에게 오게 만들지 마세요. 웹 앱(web app)이 적절한 선택인 경우는 경험상 진정으로 화면이 필요한 경우, 즉 코드 에디터(code editor), 디자인 캔버스(design canvas), 혹은 상호작용이 필요한 데이터 대시보드(data dashboard)와 같은 경우입니다. 언어 튜터, 코치, 리마인더 에이전트(reminder agent) 등 근본적으로 '대화(conversation)'인 모든 것은 사용자가 이미 머물고 있는 스레드(thread) 안에 있어야 합니다.
그리고 실제 검색 패턴(retrieval pattern)을 해결할 수 있는 가장 저렴한 메모리(memory)를 구축하세요. 제한된 이력(bounded history) 내에서 한 개인에 대한 대화 상태(conversational state)를 관리하는 데에는, 비용, 지연 시간(latency), 복잡성 측면에서 Postgres 행(row) 두 개가 벡터 스토어(vector store)보다 낫습니다. 슬라이딩 윈도우(rolling window)와 프로필(profile)로 해결할 수 없는 특정 쿼리(query)를 명확히 정의할 수 있을 때 임베딩(embeddings)을 추가하세요. 만약 그것을 명확히 정의할 수 없다면, 아직은 필요하지 않은 것입니다.
자주 묻는 질문 (Frequently Asked Questions)
Q: 별도의 Postgres 메모리 레이어 대신 LLM의 네이티브 컨텍스트 윈도우(context window)를 사용하면 안 되나요?
A: 컨텍스트 윈도우는 요청(request) 단위로 작동하며, WhatsApp이 보내는 웹훅(webhook) 호출 간에는 상태가 유지되지 않는 무상태(stateless) 방식이기 때문입니다. 각 메시지는 이전 메시지에 대한 기억이 없는 독립적인 HTTP 이벤트입니다. 따라서 매번 직접 상태를 재수화(rehydrate)해야 합니다. Postgres는 요청들 사이에서 해당 상태가 머무는 곳이며, 컨텍스트 윈도우는 단 한 번의 호출을 위해 상태를 조립하는 곳일 뿐입니다.
Q: 소규모 규모에서 Twilio/WhatsApp 메시징 비용은 실제로 어느 정도인가요?
A: 이 규모에서는 LLM 청구서보다 그 항목이 더 중요합니다. 비즈니스 시작 대화(Business-initiated conversation) 수수료와 메시지당 가격은 국가마다 다르지만, 소수의 활성 사용자만 있는 경우 Groq 추론(inference) 비용보다 더 많은 비용이 들었습니다. 구독 가격을 책정할 때 메시징 수수료를 최우선으로 고려하세요. 모델 비용은 사용자당 1달러 미만으로 유지하기가 비교적 쉬운 부분입니다.
Q: 학습자에 대한 프로필 요약이 드리프트(drift)되거나 사실을 환각(hallucination)하지 않도록 어떻게 유지하나요?
A: 모든 메시지마다 요약을 수행하지는 않습니다. 몇 세션마다 프로필 업데이트를 실행하며, 요약 프롬프트는 자유 형식으로 다시 쓰는 대신 특정 필드(레벨, 반복되는 오류, 주제, 몰입 허용치)를 업데이트하도록 제한합니다. 출력 스키마(output schema)를 제한하면 대부분의 드리프트 현상을 차단할 수 있습니다. 또한 원본 롤링 윈도우(rolling window)를 유지하여 에이전트가 최근 문맥을 파악할 때 요약본에만 의존하지 않도록 합니다.
Q: 유료 사용자 3명은 표본이라고 할 수 없습니다. 왜 리텐션(retention) 수치를 신뢰하나요?
A: 저는 100%라는 숫자 자체를 신뢰하는 것이 아니라, 그 이면에 있는 메커니즘을 신뢰합니다. 웹 앱의 이탈률(churn)이 높았던 이유는 컨텍스트 스위칭(context switch)을 요구했기 때문이며, WhatsApp 에이전트는 그렇지 않았습니다. 이는 통계적인 차이가 아니라 구조적인 차이입니다. 3명의 사용자는 퍼센트가 아닌 메커니즘을 검증한 것입니다. 코호트(cohort)가 커짐에 따라 리텐션이 떨어질 것으로 예상하지만, 채널의 이점은 그와 상관없이 실재합니다.
Q: 일관성을 위해 하나의 모델만 사용하는 대신 왜 Groq와 Claude 사이를 라우팅(routing)하나요?
A: 지연 시간(latency)과 비용은 품질과는 다른 양상을 보입니다. 대부분의 메시지는 짧은 교정 작업이며, 이들은 트래픽의 80%를 차지합니다. 이 경우 Claude의 미묘한 뉘앙스보다 Groq의 1초 미만 응답 속도가 더 중요합니다. 실제 추론이나 세심한 감정적 처리가 필요한 나머지 20%는 Claude의 비용을 정당화합니다. 하나의 모델만 사용하는 것은 쉬운 단계에서 과다 지불하거나, 어려운 단계에서 서비스를 제대로 제공하지 못함을 의미합니다. 라우팅을 통해 각 단계를 최적화할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기