당근의 AX를 꽤 자세하게 들여다 볼 수 있는, 요즘 당근 AI 개발

주말에 뭐 하세요? 건넨 질문에 교보문고 가서 책을 3권씩 읽으신다는 우리 CPO님의 말씀에 감명받아 나도 어느 주말 교보문고를 찾았다. 교보문고에서 집어 들고, 읽고, 우리 회사 사람들이 읽으면 좋겠다고 구매 요청도 한 그 책, 요즘 당근 AI의 독후감.
들어가며
AI가 우리 삶에 어느 정도 익숙하게 녹아들었을 무렵, ‘이게 최선인가?’라는 질문이 들기 시작했다.
그 질문은 나만의 것은 아니었고, 자신들이 어떻게 일하는 가를 공유하는 문화가 있는 개발자들 사이에서도 당연히 ‘님들은 AI 어떻게 쓰시는지?’라는 궁금증이 생기고 있었다. 이러한 니즈를 파악한 몇몇 회사들에서 어디어디 개발자가 공유해주는 AI 이야기에 대한 세션, 밋업들을 열어주기 시작했다. 그 중 하나에 참석해 연사님들의 발표를 들었고, 발표 시간 이후 개발자들끼리 네트워킹 시간도 가져봤으나 딱히 새로운 건 없었다.
해당 경험에서 아쉬웠던 점은 아무래도 ‘구체적인 사례의 부족’이 아니었을까 싶다. 이 책에서는 그러한 아쉬움이 느껴지지 않도록, 세세하게 다양한 이야기들이 나와 있었다. 당근이 실제로 AI를 어떻게 서비스에 녹여냈는지, 어떤 문제에 부딪혔고 어떻게 해결했는지가 꽤 자세하게 나온다. 이 책뿐만 아니라 당근의 AX에 대해 소개해주시는 영상도 봤는데, 이토록 공개적이고 구체적으로 자신들의 AI 활용 사례를 밝히는 회사가 있었나 싶다.
책에는 비개발자가 쓴 챕터, 개발자가 쓴 챕터가 섞여 있어서 누구나 읽기에 적합하다고 느껴졌다. 우리 회사 사람들도 읽어보면 좋겠다 싶어서 회사에 구비해달라고 요청도 했을 정도로..!
1. 비개발자도 AI로 이걸 만들 수 있다
프롬프트는 생각보다 간단하다
책 초반부에 비개발자가 바이브 코딩하는 과정이 서술되어 있다. 쓰는 프롬프트가 생각보다 간단해서 인상 깊었다.
“비개발자가 이해하기 쉽게 설명해줘”
사실 나도 모르는 개념이 나오면 이렇게 요청한다. 이해하기 쉽게 설명해줘라고.

AI가 나와 대화할 때 AI가 유념해야할 몇 가지 중요 원칙 중 하나이기도 하다.
근데 이 프로세스를 한 번도 겪어본 적 없는 사람에게, ‘그냥 이렇게 하면 된다’는 걸 예시와 함께 보여준다는 게 꽤 좋은 간접 경험이라고 느꼈다. 뭘 어떻게 만들어나갔는지 구체적으로 서술되어 있어서, 읽다 보면 ‘이게 되네’를 느낄 수 있다.
운영팀이 BigQuery를 직접 쓴다고?
아마 제일 인상깊었던 챕터가 이게 아닐까 싶다.
당근의 Operation Manager분이 직접 검색어 이상치 탐지 프로그램을 만들었다는 이야기다.
ML 엔지니어가 쓸 법한 PyOD v2 라이브러리까지 쓰면서..!
당근의 운영팀은 도대체 뭐하시는 분들일까하는 생각도 들었으나, 이게 단순 개인의 능력이 아니라 사내 문화일 수도 있겠다는 생각도 들었다.
당근은 데이터 기반으로 의사결정을 내리는 문화가 강합니다.
그래서 보안상 문제없는 데이터는 BigQuery에 모아서 팀 간에 공유하고 있습니다.
모두가 보아도 될만한 데이터가 잘 걸러져서 모아져 있고, 이에 대한 접근 권한이 운영팀(아마도 모두)에게 열려 있고, AI 툴을 모두가 자유롭게 쓸 수 있다는 점이 인상 깊었다.
모두가 볼 수 있는 공개 DB가 있는게 참 좋다고 느낀 게, 그러면 여기다 MCP 서버 연결해서 누구나 자연어로 데이터 다루기가 쉽기 때문이다. 민감 정보가 있는 DB를 AI에 직접 연결하는 건 여러모로 불안하니까.
이러한 BigQuery 활용은 이것만이 아니었다. 신규 가입자 지표 요약봇도 있어서, 매일 오전 9시에 자동 실행되며 이런 인사이트를 슬랙에 뿌려준다. ‘인사이트’도 함께 공유해준다는 점이 좋았는데, 이게 사실인지 아닌지는 차치하더라도 데이터 속에서 의미를 찾는 일의 초안 정도를 공유해주는 것 같아 좋았다.
“캐나다 신규 가입자가 전주 대비 15% 증가했는데, 이는 최근 진행한 프로모션 효과로 보입니다”
그럼 이런 데이터들은 어떻게 BigQuery에 저장되는가 하면, 이또한 섬세하게 가공되는 것으로 보였다. 게시글이 생성될 때마다 유의미한 정보를 LLM으로 구조화해서 BigQuery에 넣는 파이프라인이 있어서 모델명, 흠집 유무, 배터리 상태 같은 정보를 게시글에서 자동 추출하고 스마트폰 시세 서비스에 사용한다는 것이었다.
문제는 현장에 있는 사람이 잘 안다
문제 정의 능력은 결국 현장에 있는 사람이 제일 잘 갖고 있습니다.
그래서 비개발자인 ‘운영자’가 누구보다 LLM을 잘 다룰 수 있습니다.
위 내용이 마음에 참 와 닿았는데, 고객의 소리를 가장 잘 듣는 곳, 어떤 문제가 있는지 가장 먼저 아는 곳은 운영팀이기 때문이었다. 또 그간 있었던 고객의 CS와 이런 저런 맥락들을 잘 파악하고 있는 것 역시 운영팀일 거라 생각한다. 그런 의미에서, 그 맥락을 LLM을 통해 쉽게 코드로 옮길 수 있다면 참 이상적이겠다라는 생각이 들었다.
2. 이미 고민한 사람들의 답
프롬프트 설계의 핵심은 맥락과 예시
이미 AI를 활용하며 겪었던 문제점들을 해결한 사례들도 많이 볼 수 있었는데, 이러한 예시로 리뷰 자동화 챕터가 인상적이었다. Zapier + Slack + GPT를 연결해서 앱스토어 리뷰가 오면 자동으로 분류하고 담당자 슬랙에 멘션까지 하는 시스템이다.
여기서 핵심은 프롬프트 설계였다.
서비스: [중고거래/동네생활/알바 등]
유형: [제재/오류/개선 제안 등]
고객 불만 사항:
• 간결한 음슴체 요약
확인 필요 사항:
• 대응 필요 시 메일 안내
“앱 꺼져요” 같은 짧은 메시지만 보면 AI가 맥락을 몰라 잘 분류하지 못하는 일이 생겼나보다. 그래서 포맷을 주고, 엣지 케이스에 대한 예시도 함께 넣었다고 한다.
| 리뷰 내용 | 분류 |
|---|---|
| 앱 튕기고 아무것도 안 돼요 | 시스템 오류 |
| 페이 충전했는데 안들어와요 | 페이 오류 |
| 사기 당했어요 | 제재 필요 |
문장이 짧고 모호할수록 예시를 늘리는 게 효과적입니다.
서비스 분류가 애매한 때에는 샘플이 5개 이상일 때 정확도가 눈에 띄게 올라갔습니다.
GPT가 반환한 ‘서비스’ 값을 기반으로 슬랙 ID를 매핑해서 페이 관련이면 @pay_owner를 자동 멘션하는 것까지 구현된 시스템이었다.
아무래도 개발자다 보니, 개발자가 작성한 글들이 좀 더 흥미롭게 느껴지긴 했다. 특히 AI만으로 해결되지 않는 문제들을 어떻게 해결했는지를 볼 수 있던 점이 좋았다.
AI에게 DB를 직접 열어주면 안 되는 이유
사내 누구나 데이터에 접근할 수 있다면, AI가 DB를 알면 참 편할텐데, 불안한 마음도 사실이다. 이 마음에 누구나 공감할 수 있을 것이다.
LLM이 우리 대신 온콜 업무를 처리하려면 실제 시스템의 데이터에 접근할 수 있어야 합니다.
하지만 무작정 모든 데이터베이스를 열어줄 수는 없죠.
이에 대한 당근의 해법은 MCP 서버를 직접 구축하는 거였다. 미리 정의된 인터페이스를 통해서만 데이터를 주고받아 LLM이 접근할 수 있는 범위를 명확하게 제한한다.
통신 방식으로는 gRPC를 선택했다. REST와 gRPC를 한 줄로 비교하면 다음과 같다:
| REST | gRPC | |
|---|---|---|
| 데이터 형식 | JSON (텍스트) | 바이너리 (직렬화) |
| 인터페이스 정의 | 느슨함 | .proto로 엄격하게 고정 |
| 속도 | 보통 | 빠름 |
| 브라우저 호환 | 바로 가능 | 어려움 |
| 주 사용처 | 클라이언트 ↔ 서버 | 서버 ↔ 서버 |
MCP도 결국 ‘서버’이므로 서버 간 통신에 더 유리하고 인터페이스가 엄격한 gRPC를 쓰는 게 어찌 보면 자연스러운 선택인 것 같다.
구조화된 통신은 보안만의 이야기가 아니다
흥미로운 건 이 ‘구조화된 통신’이 보안뿐만 아니라 할루시네이션 방지에도 효과적이라는 거다.
에이전트 간 협업에서 구조화된 통신을 통해 커뮤니케이션의 기본 구조를 정의하면
할루시네이션을 최소화하고 예측 가능성을 높여 전체 시스템의 신뢰성을 향상시킬 수 있습니다.
자유 형식 텍스트로 에이전트끼리 소통하게 하면 통제 불가능한 할루시네이션이 발생한다고 한다. 구조화된 스키마를 강제하면 그게 줄어든다.
할루시네이션을 줄이는 다른 팁도 있었다. Temperature(온도 파라미터)를 가급적 낮춰서 쓰라는 것. 낮을수록 출력이 덜 랜덤하고 일관된다. 보안 측면에서는 명확한 거부 기준을 프롬프트에 반영하고, 알려진 프롬프트 공격 기법에 대한 방어 로직을 구현하라는 조언도 있었다.
RAG로 최신화된 내부 문서를 참조하게 한다
LLM의 단점으로 최신 정보 반영의 한계가 있고, 이를 보완하기 위해 RAG 기술을 사용해 인터넷에서 검색한다는 사실은 알고 있었다. 그래서 RAG가 그냥 인터넷을 검색해주는 거라고 인지하고 있었는데, 정확히는 내가 지정한 외부 문서나 DB에서 관련 정보를 검색해서 참조하는 기술이었다.
당근은 최신성을 유지하며 당근 내부 정보를 검색하기 위해 AI 에이전트에 RAG를 적용했다. 당근 내부 문서나 정책을 벡터로 변환해서 저장해두고, 에이전트가 답변할 때 거기서 찾아 참조하는 방식이다.
3. 연 8억짜리 기능..?
제일 흥미롭게 봤던 부분은 이 챕터였던 것 같다.
당근 채팅창에서 대화 흐름에 맞춰 다음 문장을 추천해주는 기능이 있다. 엄청나게 새로운 기능은 아닐 것이다. 심지어 요즘 내 claude cli도 내 다음 대답으로 웅 ㄱㄱ와 같은 걸 Tab만 누르면 입력할 수 있게 해주니까.
새로웠던 부분은 이 기능 하나에 연간 8~9억 원의 LLM 호출 비용이 들어간다는 것이었다. 하루 메시지가 1,000만 건이 넘으니 그게 다 LLM 호출로 이어지면 그렇게 된다는 거긴 한데.. 기능 하나에 억 단위 비용이 들어가는 세상이 어떤 건지 삶에서 겪어본 적이 없어서 감이 잘 안 오더라..ㅎ
여기서 인턴이 시맨틱 캐싱으로 연 2.1억을 절감했다는 이야기가 나온다.
의미가 비슷한 문장은 LLM을 다시 부르지 않고 저장해둔 답변을 재활용하자는 아이디어다.
벡터 DB로는 chromem-go를 선택했다. Pinecone 같은 외부 서비스 대신 서버 내부에 임베딩 방식으로 통합. 캐싱 데이터가 260개 대표 문장 수준이라, OpenAI text-embedding-3-small의 1536차원 기준으로 260 × 4byte × 1536 정도니까 메모리도 얼마 안 한다. 실제로 1,000개 벡터가 6MB라고 한다. 벡터 DB를 직접 써본 적이 없어서 이에 대한 감이 별로 없었는데, 생각보다 벡터화할 게 많지 않고 가볍다는 걸 알 수 있었다.
벡터 검색 자체는 2ms인데, 병목은 다른 곳에 있었다고 한다. 입력 문장을 벡터로 변환하는 OpenAI 임베딩 API 호출이 400~800ms씩 걸리는 거다. 이건 Kubernetes 레플리카를 수평 확장하셔서 해결했다고.
캐싱 셋은 ML로 만들었다
캐싱 셋도 섬세하게 세팅되었던 점도 인상깊었다. 분석 대상 데이터가 방대해서일까. 어떤 문장을 미리 저장해야 캐시 HIT이 잘 될지, 이걸 단순히 골라내지 않고 ML로 풀어냈다.
- 실제 채팅 데이터 수집
- PCA로 1,500차원 → 50차원 압축 (핵심 의미만 보존)
- DBSCAN 군집화로 비슷한 문장들 자동 그룹핑
K-평균 대신 DBSCAN을 선택한 이유는 다음과 같다고 한다.
| K-평균 | DBSCAN | |
|---|---|---|
| 클러스터 수 | 사전에 지정해야 함 | 자동으로 찾아줌 |
| 노이즈 처리 | 모든 점을 클러스터에 배정 | 노이즈 자동 제거 |
| 채팅 데이터 적합성 | 낮음 | 높음 |
결과: 62%는 노이즈로 버려지고, 38%에서 13개 군집 → 260개 대표 문장 추출.
읽고 나서
세 가지가 머릿속에 남는다.
첫째, 문제 정의는 사람이 한다. 기술을 모르는 사람이 AI를 못 쓰는 게 아니라, 무엇을 만들어야 하는지 모르는 사람이 AI를 못 쓰는 거다. 현장에 있는 운영팀이 가장 강력한 AI 사용자가 될 수 있다.
둘째, AI에게 자유를 주는 것과 안전을 지키는 것의 균형. gRPC + MCP 조합으로 허용된 범위 안에서만 동작하도록 설계한 것, 그리고 구조화된 통신이 보안과 할루시네이션 방지를 동시에 챙긴다는 것.
셋째, AI만으로 해결되지 않는 문제는 여전히 존재하며, 이를 규칙으로 보완할 수 있다. 리랭커가 안 되면 규칙 기반 스코어링으로, 프롬프트만으로 안 되면 BigQuery 뷰에서 후처리로. AI를 믿되, AI만 믿지는 않는 태도.
이미 그 길을 걸어간 사람들의 이야기를 읽는 건 역시 좋다. 미리 고민하고, 실패하고, 해결책을 찾아놨으니까. 맨땅에 헤딩 안해도 되도록 이런 이야기를 공유해주신 당근 팀에 감사!
여기까지. 안녕!