
Claude API를 사용하여 중고 바이크 22만 대의 AI 검색 기능을 만든 이야기
요약
Claude API를 활용하여 22만 대의 중고 바이크 데이터를 자연어로 검색하고 추천하는 AI 기능을 구현한 사례입니다. 자연어 입력을 JSON 검색 조건으로 변환하는 단계와 검색 결과를 문장으로 생성하는 단계를 분리하여 정확도와 안정성을 높였습니다.
핵심 포인트
- 자연어 입력을 구조화된 JSON으로 변환하여 DB 검색 연동
- 조건 추출과 문장 생성을 분리하여 LLM 파싱 안정성 확보
- Claude Sonnet을 사용하여 비용 효율적인 구조화 태스크 수행
- 사용자 편의를 위한 검색 프리셋 버튼 제공
MotoHub라는 중고 바이크 통합 검색 사이트를 개인적으로 운영하고 있습니다. GooBike, BDS, Webike 등 여러 사이트의 재고 데이터를 집약하여, 22만 대 이상의 바이크를 횡단 검색할 수 있는 서비스입니다. 이 외에도 39,000건의 주차장 맵, 차종 판정 AI, 바이크 진단 등 바이크 선택에 필요한 기능들을 끊임없이 만들어 가고 있습니다.
전직은 꽃집 직원이었습니다. 프로그래밍은 완전히 독학으로 했으며, 이 정도 규모의 서비스를 혼자서 개발 및 운영하고 있습니다.
이 기능을 만들게 된 계기는 친구로부터 온 LINE 메시지였습니다.
"우치(Uchi)의 사이트에서 원차리(원동기) 살 수 있어? 딸 아이 바이크가 고장 났어."
이에 대해 제가 한 행동은, MotoHub를 열고 "50cc 이하", "가나가와", "5만 엔 이하"라고 필터를 하나씩 설정한 뒤 스크린샷을 보내는 것이었습니다. 이 조작, AI에게 시키면 되지 않을까?
"예산 5만 엔, 원동기, 딸 아이용"이라고 입력하면, AI가 조건을 읽어 들여 재고를 검색하고 추천까지 생성해 준다. 그런 검색 경험을 만들기로 했습니다.
자연어 (Natural Language)로 입력하는 것만으로, AI가 검색 조건 추출 → DB 검색 → 추천 문장 생성까지 한 번에 수행합니다.
검색 예시 1: 재고 검색 모드
입력: 사가미하라 5만 엔 이하 딸 아이용 원동기
→ AI가 "가나가와현", "50cc 이하", "총액 5만 엔 이하"를 추출하여 검색. Let's 2나 Tact, DIO Fit 등을 제안. "딸 아이용"이라는 문맥에서 "가볍고 발이 잘 닿는 스쿠터가 중심입니다"라는 조언도 곁들임.
검색 예시 2: 상담 모드
입력: 드래그스타 250과 레블 250 중 어느 것이 좋아?
→ query_type: "consult"라고 판정되어, 조언이 메인인 화면으로 전환됨. 차량 스펙 비교, 유지비, 승차감의 차이를 정리하여 답변. 참고 차량도 옆에 표시.
첫 진입 장벽을 낮추기 위해 "예산 30만 엔, 125cc 원동기 2종", "CBR250RR과 Ninja250 중 어느 것이 좋아?" 등 6개의 프리셋 버튼을 마련했습니다. 무엇을 물어봐야 할지 모르는 문제에 대한 대책입니다.
처리 전체 구조는 다음과 같습니다.
사용자 입력
↓
[STEP1] Claude API: 자연어 → 검색 조건 JSON 추출
...
왜 2단계로 나누었는가? 처음에는 한 번의 API 호출로 "조건 추출 + 추천 생성"을 합치려 했습니다. 하지만 LLM에게 "JSON을 반환하고, 동시에 자연스러운 문장도 써줘"라고 요청하면, JSON 파싱 (Parsing)이 불안정해지거나 검색 조건의 정밀도가 떨어지게 됩니다.
역할을 분리함으로써, STEP1은 "정확한 JSON 생성"에 집중하고, STEP3는 "검색 결과에 기반한 문장 생성"에 집중할 수 있습니다.
STEP1의 system prompt가 이 기능의 핵심입니다.
$systemPrompt = <<<'PROMPT'
당신은 바이크 검색 어시스턴트입니다. 사용자의 자연어 입력으로부터 검색 조건을 추출해 주세요.
출력은 JSON 형식으로만 합니다. 설명문이나 마크다운은 불필요합니다.
...
입출력 예시:
| 입력 | 추출되는 JSON |
|---|---|
예산 30만 엔, 125cc | max_price: 300000, max_displacement: 125 |
도쿄에서 혼다 네이키드 | prefecture: "東京都", manufacturer: "ホンダ" |
레블 250과 드라스타 중 어느 것이 좋아? | query_type: "consult", model_name: null |
Claude Sonnet (claude-sonnet-4-20250514)를 사용하는 이유는 비용 효율성 때문입니다. 조건 추출과 같은 구조화된 태스크 (Structured Task)에서는 Sonnet으로도 충분한 정밀도가 나옵니다. Opus를 사용하면 정밀도는 약간 올라가지만 비용이 5배 이상 발생하여 개인 개발자에게는 부담스럽습니다.
max_tokens: 300으로 제한한 것도 포인트입니다. JSON 출력만 필요하므로 300 토큰이면 충분하며, 불필요한 출력을 억제할 수 있습니다.
DB 검색 결과를 컨텍스트 (Context)로서 Claude API에 전달합니다.
$userPrompt = <<<PROMPT
사용자의 질문: {$userQuery}
검색된 건수: {$totalCount}건
...
query_type에 따라 system prompt를 전환하고 있습니다.
search 모드: 150300자 내외로 검색 결과의 핵심 포인트를 간결하게 조언500자 내외로 Markdown(굵게, 글머리 기호)을 사용한 풍부한 답변
consult 모드: 300
"딸을 위한 원동기"라고 입력하면, LLM은 "따님용"이라는 컨텍스트 (Context)를 이해하여 "가볍고 발 착지성이 좋다", "시트고가 낮다"와 같은 관점을 자연스럽게 포함해 줍니다. 이는 조건 필터만으로는 절대 구현할 수 없는 경험입니다.
"무엇을 물어봐야 할지 모르겠다"는 자연어 UI (Natural Language UI)의 가장 큰 과제입니다. 이를 위해 6개의 프리셋을 준비하여, 원탭으로 검색을 체험할 수 있도록 했습니다. search와 consult 두 가지 패턴을 모두 포함하고 있습니다.
바이크 카드를 클릭 → 상세 페이지 → 브라우저 뒤로 가기를 했을 때 검색 결과가 사라지는 문제. sessionStorage에 검색 상태를 저장하고, 페이지 표시 시 복원함으로써 해결했습니다.
init() {
try {
var saved = sessionStorage.getItem(STORAGE_KEY);
...
검색 결과 아래에 후속 질문 입력란을 마련하여, "조금 더 저렴한 것은?", "유지비 비교는?"와 같이 이어서 질문할 수 있습니다. conversationHistory를 Claude API의 messages에 포함함으로써 문맥 (Context)을 유지하고 있습니다.
body: JSON.stringify({
query: currentQuery,
history: this.conversationHistory.slice(-10) // 최대 5회 왕복
...
백엔드 (Backend) 측에서는 history를 검증 (Validation)하여, STEP1과 STEP3 두 API 호출 모두에 과거 대화를 삽입하고 있습니다.
개인 개발에서 가장 신경 쓰이는 부분은 API 비용입니다.
| 항목 | 값 |
|---|---|
| 1회 검색당 호출 | 2회 (조건 추출 + 조언 생성) |
| ... | 1회 검색당 비용 |
| 약 $0.006 | |
| 속도 제한 (Rate Limit) | 10회/일/IP |
| 월간 예상 (100회 검색/일) | 약 $18/월 |
// AppServiceProvider.php
RateLimiter::for('ai-search', fn (Request $request) => Limit::perDay(10)->by($request->ip()));
월 $18 정도라면 개인 개발에서도 충분히 운영 가능합니다. 속도 제한을 IP당 하루 10회로 설정해 두었기 때문에, 갑자기 화제가 되어 트래픽이 몰리더라도 치명적인 비용이 발생하지는 않습니다.
| 레이어 | 기술 |
|---|---|
| 백엔드 (Backend) | Laravel 12 / PHP 8.3 |
| ... |
프론트엔드 (Frontend)는 Alpine.js만 사용하였으며, React는 사용하지 않았습니다. x-data, x-show, x-for만으로도 충분히 인터랙티브 (Interactive)한 UI를 만들 수 있습니다.
Claude API를 사용하면 개인 개발 서비스라도 대기업에 뒤처지지 않는 AI 경험을 만들 수 있습니다.
2단계 방식으로 정확도와 비용의 균형을 맞춤
query_type 판정으로 검색과 상담을 자동으로 전환
sessionStorage로 브라우저 뒤로 가기 시 상태 복원
대화 이력으로 후속 질문 대응 - 월 $18로 22만 대의 AI 검색이 작동
전직 꽃집 주인도 만들 수 있었습니다. LLM 덕분에 "자연어로 재고 검색"과 같이, 이전에는 큰 팀이 아니면 만들 수 없었던 기능을 혼자서도 구현할 수 있는 시대가 되었습니다.
꼭 한번 체험해 보세요 👉 https://www.motohub.jp/ai-search
질문이나 피드백이 있다면 댓글로 편하게 남겨주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기