
시작하며
안녕하세요, 저는 현재 AI 휴먼 제품을 만드는 스타트업에서 PM으로 일하고 있습니다.
PM으로 일을 시작했을 때만 해도 멀티모달이라는 단어를 "이미지도 같이 이해하는 모델" 정도로만 알고 있었어요. 그런데 입사 후 저희 제품의 PM이 되고 나서, 그 단순한 정의가 얼마나 부족한지 매일같이 체감하게 되었습니다.
저희 제품은 사용자의 말(텍스트 또는 음성)을 듣고, 의미를 이해하고, 표정·립싱크·제스처·발화를 동시에 만들어내는 시스템입니다. 입력도 출력도 모두 멀티모달이죠. 그리고 최근 시야공유 기능까지 더해지면서 사용자의 얼굴과 환경, 들고 있는 사물까지 함께 보고 반응하는 단계로 진화하고 있습니다.
이걸 PM 관점에서 평가하고 검증하는 일을 거의 1년 가까이 하면서, 처음엔 알고 있다고 생각했던 것들이 계속 깨졌습니다. 직접 페르소나 프롬프트를 만져보고, 100턴 스트레스 테스터 같은 검증 툴을 사이드로 만들면서 부딪쳤던 실제 사례들을 묶어 6가지 통념으로 정리해봤어요.
다른 PM 분들께 한 시간이라도 시행착오를 줄여드릴 수 있다면 좋겠습니다.
통념 1. 이미지 정확도 90%면 좋은 모델이다
저도 처음엔 그렇게 믿었어요. 그런데 멀티모달은 modality별로 정확도가 따로 노는 경우가 정말 많더라구요.
같은 모델이 일반 사진은 95% 잘 보면서, 한국어 손글씨 OCR은 40% 수준에 머무는 경우가 있습니다. 가로세로 혼합된 한국어, 세로쓰기, 한자 섞임처럼 영어권 모델이 약한 영역이 한국 사용자 환경에는 너무 많아요.
저희 제품을 평가하면서 깨달은 점은, 평균 점수만 보면 한국 사용자가 실제로 어떤 경험을 하는지 알 수 없다는 거였습니다.
그래서 지금도 eval dataset을 만들 때는 modality·언어·상황별로 일단 잘게 자르는 것부터 시작해요. 평균값 하나만 보고 결정 내렸다가 한국 사용자 피드백으로 돌아오는 경험을 한 번 해보고 나니, 습관이 되더라구요.
통념 2. 멀티모달 모델이면 modality를 진짜 통합해서 본다
이것도 의외로 깨지는 가정이었습니다.
모델에 시야공유 기능을 도입하면서 검증을 돌렸을 때, 정말 다양한 패턴의 실패를 봤어요. 사용자가 카메라로 텀블러를 보여주면 잘 인식하는데, 그 다음 턴에 "아까 내 텀블러는 어떻게 생겼어?"라고 물으면 "정확히 못 봤는데요"라고 답하는 거예요.
원인을 파보니, 모델은 매 턴 현재 frame만 받는 stateless 구조였습니다. 모델이 거짓말을 하거나 회피하는 게 아니라, 진짜로 이전 frame 정보가 prompt에 없었던 것이었어요. "이미지를 본다"는 능력과 "이미지를 기억한다"는 능력은 완전히 다른 문제라는 걸 그때 처음 알았습니다.
해결은 vision 호출 응답에 모델이 본 것을 "메모" 형태로 한 줄 첨부하게 만들어서 다음 턴에 시각 컨텍스트 히스토리로 누적시키는 방식이었어요. 진짜 cross-modal reasoning은 모델 능력과 컨텍스트 설계가 같이 가야 가능합니다.
이 일을 겪은 뒤로는, 모델을 비교할 때 "여러 modality를 봐야만 풀리는 질문"과 "이전 modality 정보를 기억해야 풀리는 질문"을 따로 준비해서 보는 습관이 생겼어요. 둘은 정말 다른 능력이거든요.
통념 3. Latency는 평균값으로 보면 된다
이건 제가 가장 위험하게 느꼈던 통념이고, 가장 큰 시행착오를 겪었던 영역이에요.
저희 제품 검증용으로 100턴 스트레스 테스터를 만들고 있었는데, 한 응답에 25초가 걸리더라구요. 100턴이면 한 사이클이 40분 넘게 걸려서 QA 작업이 사실상 마비됐습니다.
원인 — 세 가지
- Streaming 미사용 — 게이트웨이·Edge Function·클라이언트 모두 unary 호출로, 응답 완성까지 사용자는 빈 화면 대기
- Pro급 reasoning 모델의 thinking time — 본질적으로 출력 시작이 느림
- Prompt caching 미적용 — 매 턴 400줄짜리 시스템 프롬프트를 새로 처리
해결 — 세 가지 동시 적용
- 게이트웨이를 우회해서 모델 API를 직접 호출하는 Edge Function 분리
stream: true+ SSE passthrough → 클라이언트가 토큰 단위로 점진 렌더링cache_control: ephemeral블록으로 system prompt를 5분 TTL로 캐시
결과적으로 16초에서 3초로, 약 81% 단축됐고, 100턴 검증이 8분 내에 끝나게 됐습니다.
진짜로 배운 건 다른 거였어요
Streaming은 "절대 latency 단축"이 아니라 "체감 latency 단축"입니다.
응답 완성까지의 총 시간은 사실 비슷합니다. 다만 사용자가 빈 화면을 보고 있는 시간이 사라지는 게 본질적 가치예요.
실시간 인터랙션이 필요한 제품에서는 더 중요합니다. 사용자가 말을 끝낸 직후 1초 안에 어떤 반응이라도 나와야 "살아있는" 느낌이 살더라구요. 풀 응답까지 4초가 걸리더라도, 첫 0.5초 안에 시각적인 반응이라도 시작되어야 합니다.
함정 1 — 모델별 caching 방식이 다 다르다
Anthropic은 명시적 블록이 필요하고, OpenAI는 자동, Google은 별도 API 호출이에요. "OpenAI 호환 API"라고 적혀 있다고 모두 똑같이 동작할 거라 가정하면 안 됩니다. 저도 처음엔 그렇게 생각했다가 한 번 데였어요.
함정 2 — 정적/동적 블록 분리 설계가 같이 가야 함
caching을 켰다고 끝이 아니라, 프롬프트 안에서 정적 블록과 동적 블록을 명확히 분리하는 설계가 같이 가야 효과가 납니다.
- 정적 블록 (앞쪽) — 안전 정책, 응답 컨트랙트, 페르소나 base, 모션·오디오 태그 설정. 거의 변하지 않음
- 동적 블록 (뒤쪽) — 런타임 상태, 검색된 메모리, 최근 대화, 안티-반복 신호. 매 턴 변함
이 순서를 안 지키면 매 턴 캐시 미스가 나서 caching이 사실상 무력화되는 걸 한 번 겪었습니다.
또 다른 강력한 방법 — "응답 후로 미루기"
응답 latency를 줄이는 가장 강력한 방법 중 하나는 사실 응답 후로 미루기였어요.
메모리 통합, 롤링 요약, 콜백 후보 갱신, 페르소나 상태 업데이트 같은 작업은 응답에 반드시 필요하지 않다면 응답을 먼저 내보내고 백그라운드(waitUntil)에서 처리합니다. 사용자가 체감하는 latency에 0을 더하면서 같은 일을 다 할 수 있어요.
"이 작업이 응답 전에 꼭 끝나야 하나?"를 매번 다시 물어보는 습관이 PM에게 정말 중요하더라구요.
측정 도구 — Latency Probe
마지막으로 latency 디버깅에서 가장 큰 시행착오를 줄여준 도구가 하나 있는데, latency probe라고 부르는 진단 패턴이에요. 같은 런타임에서 세 가지 모양의 호출을 측정해 모델·프로바이더 latency와 앱 오케스트레이션 latency를 분리합니다.
minimal_text— 가장 단순한 텍스트 호출, 48 토큰structured_small— 작은 구조화 JSON 스키마 호출, 96 토큰app_like— 실제 페르소나 프롬프트 + 스키마 + 정상 토큰 캡
해석은 이렇게 했어요.
minimal_text가 이미 1~2초 이상 → floor가 모델/프로바이더 latency. 앱 코드 최적화 의미 없음minimal_text빠른데structured_small이 느림 → strict 구조화 출력 비용- 둘 다 빠른데
app_like만 느림 → 프롬프트 크기·출력 토큰 캡·응답 스키마 쪽 최적화로
측정이 안 되면 최적화는 도박입니다.
이걸 만들기 전엔 "왜 느린지 모르는데 일단 코드부터 만지작거리는" 실수를 자주 했어요.
그래서 저는 이제 latency를 볼 때 P50 평균값엔 거의 신경을 안 써요. P95와 첫 글자가 보이는 시간(TTFT), 이 두 가지가 진짜 사용자 경험을 결정한다는 걸 그때 배웠습니다.
통념 4. 정확도와 안전성은 같이 좋아진다 — 페르소나도 마찬가지
텍스트 LLM에서는 어느 정도 맞는 말이었습니다. 그런데 멀티모달에 강한 페르소나가 결합되면 의외의 부작용이 나오더라구요.
저희 AI 캐릭터는 "당당하고 직설적이며 자기 기준이 분명한" 페르소나를 가지고 있어요. 그런데 시야공유 검증에서 충격적인 패턴을 발견했습니다.
이미지에 텀블러가 명백히 있는데, AI가 이렇게 답하는 거예요.
- "정확하게 안 봤는데요?"
- "굳이 신경 쓰진 않았어요"
- "기억에 안 남는 텀블러였으니까요"
14턴 중 7건이 "안 봤다·관심 없다·신경 안 썼다" 류의 회피였습니다.
분석해보니 시스템 프롬프트의 페르소나 룰("당당·직설·자기 기준")이 너무 강해서, 모델이 시각 정보를 무시하는 톤으로 응답하고 있었어요. "본 것은 봤다고 말하는 정직함" 룰이 명시적으로 없었던 거죠. 모델 입장에선 "쿨하게 안 봤다고 답하는 게 페르소나에 더 맞다"고 판단한 셈입니다.
이건 단순한 safety 이슈가 아니에요. vision 결과를 페르소나가 덮어쓰는 새로운 종류의 실패 모드입니다. 텍스트만 다룰 때는 절대 발생하지 않던 패턴이었어요.
해결은 프롬프트에 명시적인 회피 어휘 차단 룰을 추가하는 것이었습니다. "이미지가 첨부된 상태에서는 다음 표현 절대 금지" 식으로 구체 어휘를 나열하고, "본 사실 + 페르소나 평가" 형태로 변환하라는 가이드를 줬어요. "굳이 신경 쓰진 않았어요" 대신 "그 텀블러는 좀 평범하네요"처럼요.
이 경험 이후로 저는 페르소나 룰과 modality 활용 룰을 프롬프트에서 항상 별도 섹션으로 분리하고, 우선순위를 명시적으로 적어둡니다. 텍스트 레드팀과 이미지 레드팀도 무조건 따로 돌려요. 한 쪽 결과로 다른 쪽을 가정하면 안 된다는 게, 솔직히 가장 충격적이었던 학습이에요.
통념 5. 멀티모달 eval은 시간만 들이면 만들 수 있다
만들어보면 압니다. 멀티모달 eval dataset은 텍스트 eval의 5~10배 비용이 든다는 걸요.
라벨링이 어렵습니다. 사진과 질문, 정답, 근거를 세트로 만들어야 하니까요. 게다가 edge case 조합이 폭발적으로 많아요. 사진 각도, 조명, 해상도, 객체 수, 한국어/영어 혼합, 손글씨/인쇄체, 그리고 이전 턴과의 연속성까지요.
저는 한동안 "더 완벽한 eval을 만들어야 한다"는 강박에 사로잡혀 있었는데, 결국 깨달은 건 golden set 20~50개와 사용자 피드백 루프를 1주일에 세팅하는 게 6개월 걸쳐 완벽한 eval 만드는 것보다 훨씬 가치 있다는 거였어요.
위에서 말씀드린 시야공유 케이스도 결국 14턴짜리 검증 세션 하나로 가장 큰 문제 3개를 발견했습니다. 100턴 완벽 eval을 기다렸으면 그때까지 일정 다 놓쳤을 거예요.
지금 와서 정리하면, PM의 시간은 "더 큰 eval"이 아니라 "더 빠른 피드백 루프"에 써야 하는 것 같아요. 완벽한 eval 만든다고 몇 달을 깎아먹는 건 정말 비싼 비용이라는 걸 늦게 깨달았습니다.
통념 6. 에이전트 능력과 vision 품질은 같이 간다
이 두 가지는 의외로 따로 놉니다.
"이 사진 설명해줘" (vision) ≠ "이 사진 보고 Notion 페이지를 만들어줘" (agent)
후자는 사진을 보고, 적절한 도구를 선택하고, 호출하고, 실패 시 재시도하고, 사용자에게 보고하는 여러 단계 모두가 견고해야 합니다.
상태 관리는 더 까다롭다
멀티모달 에이전트는 상태 관리가 텍스트 에이전트보다 훨씬 까다로워요. 저는 사이드 프로젝트로 만든 스무고개 AI 튜터에서 이걸 깊게 배웠습니다.
게임이 길어질수록 LLM이 앞에서 정한 규칙(몇 번째 질문인지, 어떤 카테고리인지, 종료 조건)을 점점 잊어버리더라구요. 그래서 INTERNAL_STATE라는 JSON 블록을 매 응답 첫 줄에 강제 출력하게 만들었어요.
{
"status": "playing",
"turn": 3,
"guessed_category": "동물",
"candidates": ["강아지", "고양이", "토끼"],
"final_guess": ""
}
이렇게 매 턴 상태를 구조화된 포맷으로 강제 출력하게 만들었더니 규칙 준수율이 크게 올랐습니다. 단순히 "규칙을 지켜라"가 아니라 "매 턴 상태를 구조화된 포맷으로 출력하라"고 형식을 강제하는 것이 핵심이었어요.
"하지 마라"는 확률적으로 무시되지만, "이 조건을 체크하고 통과해야만 하라"는 구조적 가드레일은 잘 지켜집니다.
금지어 리스트보다 판단 기준 체크리스트가 훨씬 효과적이에요.
에이전트 비용 최적화 — 두 가지 패턴
1. Fast Path Router
처음엔 "모든 턴에 도구 스키마를 다 보내두면 LLM이 알아서 필요할 때 호출하겠지" 하고 시작했는데, 이게 문제였어요.
- 매 턴 토큰 비용과 latency가 같이 올라감
- 별 의미 없는 대화에서도 LLM이 도구를 잘못 부르는 케이스 발생
그래서 LLM 호출 전에 deterministic 라우터가 "이 턴이 카메라/장소/웹 검색 같은 도구가 진짜 필요한 의도인가"를 판단하게 만들고, 일반 대화에서는 아예 도구 스키마를 안 보냅니다. 평균적인 대화 비용이 눈에 띄게 줄었어요.
2. Deferred Tool Request
그런데 라우터가 모든 도구 의도를 잡아내진 못하더라구요. 그래서 정상 빠른 경로에서도 LLM이 자기 판단으로 도구를 요청할 수 있도록, 구조화된 응답 안에 deferredToolRequest 필드를 둡니다.
OpenAI tool calling을 안 켜고도 LLM이 "이번 턴엔 카메라가 필요해요"라고 말할 수 있는 우회로예요. 평소엔 도구 비용 0, 정말 필요할 때만 2번째 호출이 들어가는 구조라 비용과 표현력 사이의 균형이 잘 맞았습니다.
정리
저는 모델을 평가할 때 vision 점수와 agent 점수를 분리해서 봐요. 그리고 에이전트의 신뢰도를 높이고 싶을 때, 모델을 더 비싼 걸로 바꾸는 것보다 상태를 어떻게 구조화할지 프롬프트를 다듬는 게 효과가 더 크다는 것도 같이 배웠습니다.
"모든 턴에 모든 능력을 다 노출"하는 단순한 설계보다, "필요할 때만 능력을 깨우는" 라우팅 설계가 PM 입장에서 훨씬 운영하기 좋은 시스템을 만들어 줍니다.
그래서 지금 Claude로 뭘 할 수 있을까요? (2026-01 기준)
이론만 풀어놓으면 재미없으니, 제가 직접 부딪쳐본 이야기를 짧게 드릴게요.
올해 사이드 프로젝트로 한국어 끝말잇기 미니게임을 Claude Code와 페어 프로그래밍으로 만들면서, 비개발자 PM 입장에서 Claude 멀티모달의 경계를 직접 만져봤어요.
✅ Claude가 잘하는 영역
- 이미지·차트·UI 스크린샷·PDF의 통합 이해 (한국어 OCR도 1년 전보다 확연히 좋아졌습니다)
- 디자인 스크린샷을 코드로 변환 (와이어프레임만 그려도 React 컴포넌트가 나옵니다)
- Computer Use, 화면을 보고 직접 마우스·키보드로 도구를 조작
- 1M context로 긴 영상 transcript와 수십 장 이미지를 한 번에 추론
- Prompt caching이 명시적이라 latency·비용 최적화 설계가 명확함
❌ Claude가 아직 못하는 영역 (PM이 꼭 알아야 합니다)
- 음성 native 입출력 미지원. Whisper 같은 STT로 변환 후 전달해야 합니다
- 동영상 직접 처리 불가. 프레임 추출 후 이미지 시퀀스로 전달
- 이미지 생성 불가. Imagen, DALL-E 같은 별도 모델 호출 필요
- 실시간 멀티모달 스트림 불가
실시간 AI 휴먼을 100% Claude로만 만들기는 아직 어렵습니다. 다만 워크플로우와 에이전트 일부, 그러니까 고객 인터뷰 분석이나 스펙 작성, eval 데이터셋 생성, 프로토타입 같은 영역은 PM 혼자서 Claude로 충분히 돌릴 수 있는 영역이 되어 가고 있어요. 그리고 이 영역이 매달 넓어지고 있다고 느낍니다.
마치며
1년 동안 PM으로 일하면서, 사이드 프로젝트로 직접 멀티모달 제품을 만져보면서, 결국 가장 크게 배운 한 가지가 있어요.
멀티모달 에이전트는 더 이상 ML 엔지니어만의 영역이 아닙니다.
PM이 직접 만져보지 않으면 "뭘 모르는지조차 모르는" 상태로 제품을 기획하게 되더라구요. 이론서를 5번 읽는 것보다 직접 1주일 만져보는 게 훨씬 빠르게 평가 축을 체득시켜주었습니다.
특히 위에 적은 6가지 통념은 전부 책에서가 아니라 실제로 깨져봐야 알게 되는 것들이었어요. "이미지를 본다"와 "이미지를 기억한다"의 차이, "페르소나 룰이 vision을 누른다"는 부작용, "streaming은 체감 latency 단축이지 절대 단축이 아니다"라는 깨달음. 모두 한 번 데여본 후에야 PM 결정 회의에서 정확한 질문을 던질 수 있게 되더라구요.
긴 글 읽어주신 모든 분께 감사드려요.
'AI' 카테고리의 다른 글
| 매주 30분 걸리던 주간 보고를 3분으로 줄인 이야기 — Claude Code Skill 자동화 후기 (0) | 2026.05.26 |
|---|
댓글