Listen Labs $69M 펀딩: 빌보드 채용 광고가 바이럴 → 시리즈 B 직행

목차

인터뷰 50건이 쌓인 Notion 페이지에서 새로 합류한 PM이 인사이트를 못 뽑길래 RAG를 직접 깔아봤다. 그 와중에 Listen Labs가 SF 빌보드 채용 광고로 바이럴 된 직후 $69M 시리즈 B를 받았다는 소식이 떴고, 이 회사가 푸는 문제가 정확히 내가 어제 막힌 지점이라 정리해둔다.

::: tip 이 글은 "Listen Labs를 써본 후기"가 아니다. 비슷한 문제를 직접 구축하다 막힌 구간을 정리한 TIL이고, Listen Labs의 펀딩 규모·세부 조건은 공개 보도 기준 추정치라 단정하지 않는다. 정확한 수치는 회사 공식 발표나 PitchBook을 확인하면 된다. :::

오늘 한 것 — 인터뷰 RAG 만들다가 막힌 세 지점

또한, 원래 계획은 단순했다. Whisper로 전사하고, 500토큰 단위로 청크 나눠 임베딩하고, pgvector에 박은 다음 Claude로 질의응답. 반나절이면 끝날 줄 알았다.

결과적으로 사흘이 걸렸고, 셋째 날 저녁에 "이거 그냥 Listen Labs 같은 도구 쓰는 게 맞나" 싶어서 검색하다가 펀딩 뉴스를 봤다. 막힌 지점이 셋이다.

청크가 인터뷰 맥락을 박살낸다

평범한 문서 RAG는 500토큰 슬라이딩 윈도우로 잘 굴러간다. 인터뷰는 다르다. "응 그건 작년엔 그랬는데 요즘은 좀 달라요, 왜냐하면…" 같은 발언이 청크 경계에서 갈라진다. 결과적으로 LLM이 "사용자는 X를 한다"고 잘못 단정한다.

그런데, 해결책은 화자 턴 단위로 끊는 것. 사용자가 한 발언 = 청크 1개로 고정하고, 직전 인터뷰어 질문을 메타데이터로 묶어둔다. 청크 크기가 들쭉날쭉해지지만 의미는 산다.

화자 분리를 안 넣으면 답이 흐려진다

그런데, 처음엔 트랜스크립트 통째로 임베딩했다. 그랬더니 인터뷰어가 유도하려고 던진 "혹시 가격이 부담스럽진 않으세요?" 문장까지 RAG가 "사용자가 가격이 부담스럽다고 말했다"로 인용한다.

예를 들어, Whisper diarization 결과를 청크에 speaker 필드로 박고, 검색 시 speaker = 'user' 필터를 거는 걸로 해결. 사소해 보이지만 안 하면 출력이 통째로 망가진다.

인사이트 추출은 검색이 아니라 집계다

진짜 막힌 건 여기. PM이 던진 첫 질문이 "사용자들이 가장 자주 말하는 불만 3개"였다. top-k=10으로 잘라봐야 50건 중 10건 안의 불만만 나온다. 검색이 아니라 전체 집계가 필요한 질문이었다.

map-reduce 패턴으로 다시 짰다. 배치마다 부분 테마를 뽑고, 마지막에 reduce로 통합. 응답 시간이 2초에서 40초로 늘었는데, 이건 사용자 경험상 받아들일 만한 수준이라 그대로 갔다.

새로 알게 된 것 — Listen Labs가 푸는 진짜 문제

Listen Labs를 처음 봤을 때는 "AI가 인터뷰 자동 진행"이 핵심인 줄 알았다. 펀딩 뉴스와 공식 사이트(2026-06 기준)를 다시 보니 그게 아니다.

빌보드 광고가 바이럴 된 맥락

즉, SF 101 도로변에 도발적인 카피로 채용 광고를 걸었고, Twitter/X에서 며칠간 화제가 됐다. 채용 마케팅인데 결과적으로 제품 인지도까지 같이 끌어올렸다는 게 흥미로운 지점이다. 시리즈 B 라운드 발표가 그 직후 시점이라 "바이럴이 펀딩을 견인했다"는 해석이 돌았는데, 인과를 단정하긴 어렵다. 라운드는 보통 몇 달 전부터 협상하니까.

그래서, 다만 그로스 해킹이 투자자 신호 역할을 한 건 분명해 보인다. "이 팀은 분배 채널을 안다"는 시그널.

진짜 차별점은 인터뷰 모집부터 분석까지의 파이프라인

물론, AI가 1:1 인터뷰를 진행한다는 건 이미 여러 회사가 시도했다. Listen Labs의 포지션은 그 위 단계다. 모집 → 진행 → 전사 → 테마 추출 → 세그먼트별 요약을 하나의 흐름으로 묶었다.

실제로, 사람 인터뷰어 1명이 하루 5건이라면 AI는 같은 시간에 1000건도 비동기로 받는다. 이게 단순한 비용 절감이 아니라, 통계적으로 의미 있는 표본 크기를 처음으로 사용자 리서치에 가져온다는 점에서 종이 한 장 차이로 다르다.

"themes → quotes → segments" 출력 구조

단순 트랜스크립트 요약이 아니라, PM이 슬라이드에 바로 붙일 수 있는 형태로 정리된다는 게 핵심이다. 테마 1개당 인용 3~5개, 그 인용을 말한 사용자 세그먼트(신규/기존, 결제/미결제)까지 같이. 이거 직접 만들려면 출력 스키마를 강제하는 프롬프트 설계가 별도로 필요한데, 생각보다 까다롭다.

코드 — 막힌 부분 직접 메워본 파이프라인

특히, Anthropic Claude API + pgvector로 비슷한 구조를 흉내낸 코드. 실제로 돌려본 버전을 단순화했다.

# requirements: anthropic>=0.40.0, pgvector, psycopg2-binary
import anthropic
from typing import Iterator

client = anthropic.Anthropic()

def chunk_with_context(transcript: list[dict]) -> Iterator[dict]:
    """
    transcript: [{"speaker": "user|interviewer", "text": "...", "ts": 12.3}, ...]
    사용자 발언 1개 = 청크 1개. 직전 인터뷰어 질문을 메타로 묶음.
    """
    prev_question = None
    for turn in transcript:
        if turn["speaker"] == "interviewer":
            prev_question = turn["text"]
            continue
        yield {
            "text": turn["text"],
            "context_question": prev_question,  # 검색 필터링/리랭킹에 사용
            "speaker": "user",
            "ts": turn["ts"],
        }

테마 추출은 검색이 아니라 map-reduce로 짰다. 100건 인터뷰가 대략 80만 토큰이라 한 번에 못 던지는 경우가 많다.

def extract_themes(chunks: list[dict], batch_size: int = 200) -> str:
    batches = [chunks[i:i+batch_size] for i in range(0, len(chunks), batch_size)]
    partial = []

    for batch in batches:
        msg = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=4096,
            system="너는 UX 리서처다. 사용자 인용을 원문 그대로 보존하면서 반복 테마를 뽑아라.",
            messages=[{
                "role": "user",
                "content": (
                    "아래 사용자 발언에서 반복되는 불만 테마 5개와 "
                    "각 테마별 원문 인용 3개씩 추출:\n\n"
                    f"{batch}"
                )
            }]
        )
        partial.append(msg.content[0].text)

    # reduce — 부분 테마를 다시 통합
    final = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=4096,
        messages=[{
            "role": "user",
            "content": f"아래 부분 테마들을 중복 제거하고 최종 7개로 통합:\n\n{partial}"
        }]
    )
    return final.content[0].text

두 방식의 트레이드오프는 다음과 같다.

항목 단순 RAG (top-k=10) map-reduce 요약
응답 시간 2~3초 30~60초
100건 비용 (체감) 약 $0.05 약 $1.0~1.5
빈도 반영 안 됨
"왜 그런지" 후속 질문 강함 약함
인용 출처 추적 쉬움 추가 작업 필요

용도가 다르다. "이 사용자가 그때 뭐라고 했지?"는 RAG가 맞고, "전체 사용자가 가장 자주 말하는 게 뭐지?"는 map-reduce가 맞다. 둘 다 깔아두고 질문 유형에 따라 라우팅하는 게 결과적으로 제일 깔끔했다.

메모 — 언제 직접 만들고 언제 Listen Labs류를 쓸까

물론, 판단 기준이 단순하다.

  • 인터뷰 건수가 월 20건 이하라면 Notion + Claude 수동 처리로 충분하다. 도구 도입 ROI 안 나온다. 그냥 트랜스크립트 통째로 Claude에 던지면 된다.
  • 월 100건 넘고 리서처/PM이 2명 이상이면 전용 도구가 맞다. 직접 만들면 유지보수에 0.5인분이 통째로 들어간다. 인덱스 재빌드, 화자 분리 정확도, 모델 버전 업데이트까지 다 직접 봐야 한다.
  • 모집부터 자동화하고 싶으면 Listen Labs류가 맞다. 패널 모집 인프라는 직접 만들면 사용자 신뢰 확보부터 막힌다. 분석만 자동화하고 싶다면 위 코드 수준으로 자체 구축이 더 저렴할 가능성이 높다.
  • 한국어 사용자 대상이면 음성 인식 정확도를 별도로 확인해야 한다. 영어권 도구의 한국어 성능은 작성 시점(2026-06) 기준 여전히 격차가 있다고 보인다. 데모 영상만 보고 결정하면 곤란하다.

펀딩 뉴스의 진짜 교훈은 "AI 도구도 분배 채널이 제품만큼 중요하다"는 쪽인 것 같다. 인터뷰 자동화 자체는 기술 난이도가 그렇게 높지 않다. 빌보드 한 장이 시리즈 B를 만들었다고는 못 해도, 적어도 투자자에게 "이 팀은 GTM을 안다"는 시그널은 확실히 보냈다.

그러나, 참고 — Anthropic Messages API 공식 문서(docs.anthropic.com), pgvector 0.7.0 릴리스 노트(github.com/pgvector/pgvector). 두 곳만 봐도 위 코드는 돌아간다.

관련 글