# 라이드서비스봇 개발기

- 작성자: [조용한 화가](https://community.clauders.ai/member/imported-member-RrsgNj0S5t)
- 공간: [에이전트 / 노코드 자동화](https://community.clauders.ai/automation)
- 게시: 2025-11-27
- 연재: [카카오톡 업무 봇 개발](https://community.clauders.ai/series/kakao-operations-bot) 3/3편
- 태그: #카톡봇
- 주소: https://community.clauders.ai/automation/post/%EB%9D%BC%EC%9D%B4%EB%93%9C%EC%84%9C%EB%B9%84%EC%8A%A4%EB%B4%87-%EA%B0%9C%EB%B0%9C%EA%B8%B0-7636d51e-2f89-823d-98ad-fb45417457fd

---

### 1. 초기 설정 및 자연어 처리 구현

**사용한 프롬프트:**

```
json 최종코드 버젼 알려줘
```

Claude Code가 코드베이스를 분석하여 v1.0.18 버전을 확인하고, 주요 기능들을 파악했습니다.

**핵심 아키텍처:**

```
// 클라이언트: 메신저봇R (JavaScript)
// - HttpClient.postJson()으로 UTF-8 JSON 전송
// - Utils.normalizeName()으로 느슨한 이름 매칭

// 서버: Firebase Functions (Node.js 20)
// - OpenAI GPT-4o-mini로 자연어 파싱
// - Google Calendar API 연동
// - Firestore 데이터 관리
```

### 2. Codex 분석 기반 버그 수정 (v1.0.19 → v1.0.23)

**프롬프트:**

```
1.0.19 에 대해서 다시 한번 코덱스에서 점검한 내용이야
내용 반영하고 코드를 1.0.20으로 업데이트하고 휴대폰에 업로드 해줘
```

**Codex가 발견한 문제들:**

1. **에러 메시지 처리 불일치**: `result.error`가 문자열일 때와 객체일 때 처리 방식이 달랐음
2. **이름 매칭 실패**: 클라이언트만 fuzzy matching 적용, 서버는 여전히 exact match
3. **자녀 정보 누락 루프**: 등록되지 않은 자녀 이름 입력 시 무한 루프

**Claude Code의 해결 과정:**

```
// v1.0.20: 에러 메시지 통일
var errorMsg = typeof result.error === 'string' ? result.error :
              (result.error && result.error.message ? result.error.message : "알 수 없는 오류");

// v1.0.22: 클라이언트 fuzzy matching
normalizeName: function(name) {
    return String(name)
        .toLowerCase()
        .replace(/\s+/g, '')
        .replace(/\(.*?\)/g, '')
        .replace(/[^\w가-힣]/g, '')
        .trim();
}

// v1.0.23: 서버에도 동일한 로직 배포 (Functions v1.0.10)
function findChild(children, inputName) {
    // 1차: 완전 일치
    // 2차: 정규화 후 일치  
    // 3차: 부분 일치
    // 4차: 정규화 후 부분 일치
}
```

### 3. 자녀/학원 관리 기능 추가 (v1.0.24)

**프롬프트:**

```
도움말에 자녀이름 등록이랑 수정 그리고 삭제하는 메뉴도 넣어주고.....
학원관리에서도 등록하고 삭제 수정하는 메뉴를 넣어줘
그리고 위기능을 반영한 버젼은 json 코드 1.0.24가 되어야해
```

Claude Code가 자동으로:

1. `ChildHandler` 객체 생성 (CRUD 전체)
2. `AcademyHandler` 확장 (edit/delete 추가)
3. 대화 상태 처리 추가
4. 명령어 라우팅 구현
5. 도움말 업데이트
6. ADB로 휴대폰에 자동 업로드

```
var ChildHandler = {
    showList: function(room) { /* 목록 표시 */ },
    startAdd: function(room) { /* 추가 시작 */ },
    handleAdd: function(room, message) { /* 추가 처리 */ },
    startEdit: function(room) { /* 수정 시작 */ },
    handleEditSelect: function(room, message) { /* 선택 */ },
    handleEditName: function(room, message) { /* 이름 수정 */ },
    startDelete: function(room) { /* 삭제 시작 */ },
    handleDelete: function(room, message) { /* 삭제 처리 */ }
};
```

### 4. 즉시 자녀 등록 기능 (v1.0.25 + Functions v1.0.11)

**가장 중요했던 Codex 피드백:**

```
코덱스가 점검한 내용이야.
"등록되지 않은 이름을 입력하면 바로 등록할 수 있게" 만들어야 한다고 제안
```

**Claude Code의 구현:**

```
// 1. Firebase Functions에 addChild 엔드포인트 추가
exports.addChild = functions
  .region('asia-northeast3')
  .https.onRequest(withCors(async (req, res) => {
    const { name } = requestData;
    const childId = `child${Date.now()}`;
    await db.collection('children').doc(childId).set({
      id: childId,
      name: name,
      order: Date.now(),
      createdAt: admin.firestore.FieldValue.serverTimestamp()
    });
  }));

// 2. 클라이언트에서 미등록 자녀 감지 시 안내
if (missing.indexOf('child') !== -1) {
    errorMessage += "📋 등록된 자녀 목록:\n";
    errorMessage += "새 자녀를 등록하려면:\n";
    errorMessage += "👉 !자녀등록 [이름] (예: !자녀등록 민수)\n\n";
  
    conversationState[room] = {
        step: 'ride_retry_after_register',
        data: { originalInput: content }
    };
}

// 3. 등록 후 자동 동기화 + 재시도 안내
registerChild: function(room, name) {
    HttpClient.postJson("/addChild", { name: name }, function(result) {
        DataManager.syncFromServer(function(success) {
            bot.send(room, "✅ \"" + name + "\" 등록 완료!");
            // 원래 입력했던 명령 재시도 안내
        });
    });
}
```

**Firebase Functions 배포:**

```
cd firebase-functions && firebase deploy --only functions
```

Claude Code가 자동으로 배포 명령 실행 및 성공 확인!

### 5. 완전한 서버 연동 (v1.0.26 + Functions v1.0.12)

**최종 Codex 검증 프롬프트:**

```
한번만 더 체크해보자 코덱스가 검증한 내용이야
json 코드 1.0.25 와 firebase function 코드 1.0.11 에 매칭성 최종 검증해줘
```

**Codex가 발견한 치명적 문제:**

> "클라이언트에는 자녀/학원 수정·삭제 기능이 있지만, 서버에는 해당 API가 없습니다!"

**Claude Code의 자동 수정:**

1. **서버에 4개 엔드포인트 추가:**

```
// Firebase Functions v1.0.12
exports.updateChild = functions.region('asia-northeast3')...
exports.deleteChild = functions.region('asia-northeast3')...
exports.updateAcademy = functions.region('asia-northeast3')...
exports.deleteAcademy = functions.region('asia-northeast3')...
```

1. **클라이언트 핸들러 수정 (로컬 → 서버):**

```
// Before v1.0.25: 로컬만 수정
handleEditName: function(room, message) {
    botState.children[i].name = newName;
    DataManager.saveLocalSettings(...);
    bot.send(room, "⚠️ 주의: 서버 동기화를 위해 !동기화테스트를 실행하세요.");
}

// After v1.0.26: 서버 연동 + 자동 동기화
handleEditName: function(room, message) {
    HttpClient.postJson("/updateChild", { id, name }, function(result) {
        DataManager.syncFromServer(function(success) {
            bot.send(room, "✅ 자녀 이름 수정 완료!");
        });
    });
}
```

1. **자동 배포 및 검증:**

```
# Claude Code가 자동 실행
firebase deploy --only functions
# ✅ 4개 새 엔드포인트 생성 확인
# ✅ 10개 기존 엔드포인트 업데이트 확인
```

### 6. 실제 사용 예시

**시나리오 1: 등록된 자녀로 라이드 예약**

```
사용자: 하준 오늘 6시 30분에 대치수학학원 픽업
봇: ✅ AI가 다음과 같이 이해했습니다:
    👦 자녀: 하준
    🏫 학원: 대치수학학원
    📅 날짜: 2025-11-27 (수요일)
    ⏰ 시간: 18:30
  
    맞으면 ⭕, 다시 입력하려면 ❌
```

**시나리오 2: 미등록 자녀 즉시 등록**

```
사용자: 민수 오늘 6시에 피아노학원 픽업
봇: ❌ 자녀 정보가 필요합니다
  
    📋 등록된 자녀 목록:
      • 하준
      • 주하
  
    💡 등록된 자녀 이름을 정확히 입력하거나,
    새 자녀를 등록하려면:
    👉 !자녀등록 [이름] (예: !자녀등록 민수)

사용자: !자녀등록 민수
봇: ⏳ "민수" 등록 중...
봇: ✅ "민수" 등록 완료!
    이제 자연어 명령으로 라이드 예약이 가능합니다.
  
    💡 이제 다시 시도해보세요:
    "민수 오늘 6시에 피아노학원 픽업"
```

**시나리오 3: 자녀 이름 수정**

```
사용자: !자녀수정
봇: ✏️ 자녀 이름 수정
  
    수정할 자녀를 선택하세요:
    👦 1. 하준
    👧 2. 주하
    👦 3. 민수

사용자: 3
봇: 현재 이름: 민수
  
    새 이름을 입력해주세요:

사용자: 민수(막내)
봇: ⏳ 자녀 이름 수정 중...
봇: ✅ 자녀 이름 수정 완료!
    "민수" → "민수(막내)"
```

### 🎉 최종 결과

**구현된 기능:**

- ✅ 자연어로 라이드 예약 (OpenAI GPT-4o-mini)
- ✅ Google Calendar 자동 등록 (30분 일정)
- ✅ Firestore 데이터 관리 (완전 CRUD)
- ✅ 4단계 fuzzy matching (이름 인식률 대폭 향상)
- ✅ 미등록 자녀 즉시 등록 (무한 루프 해결)
- ✅ 자녀/학원 수정·삭제 (서버 자동 동기화)
- ✅ 일정 조회 (오늘/주간/날짜별)

**기술 스택:**

- Frontend: 메신저봇R (JavaScript, Java HttpURLConnection)
- Backend: Firebase Functions (Node.js 20)
- Database: Firestore
- AI: OpenAI GPT-4o-mini
- Calendar: Google Calendar API
- Deployment: Firebase CLI + ADB

### 💡 배운 점

**1. Claude Code의 놀라운 코드베이스 이해력**

가장 인상 깊었던 점은 **Codex 분석 결과를 바탕으로 정확한 버그 위치를 찾고 수정**하는 능력이었습니다.

```
나: "코덱스 점검결과야. 코드 1.0.22 을 분석한거야."
Claude Code: "코덱스 분석이 정확합니다. 클라이언트만 수정해서는
             자연어 경로의 문제를 해결할 수 없었고, 서버 측
             Firebase Functions도 함께 수정하여 근본적으로 해결"
```

일반적인 AI는 "서버도 수정해야 할 것 같습니다"라고 추상적으로 답하지만, Claude Code는:

1. 정확히 어느 파일의 어느 함수를 수정해야 하는지 파악
2. 클라이언트와 서버 코드를 동시에 수정
3. Firebase Functions 배포까지 자동 실행
4. ADB로 휴대폰에 업로드까지 완료

**2. 대규모 코드베이스에서의 일관성 유지**

2,200줄이 넘는 클라이언트 코드와 1,000줄의 서버 코드를 동시에 관리하면서:

- 이름 정규화 로직이 클라이언트-서버 완벽히 일치
- 에러 처리 방식이 모든 핸들러에서 통일
- 대화 상태 관리가 일관되게 구현

이런 일관성은 수동으로 유지하기 매우 어렵지만, Claude Code는 자동으로 보장해줬습니다.

**3. "설명 → 검증 → 수정" 사이클의 효율성**

```
1주차: v1.0.18 → v1.0.20 (에러 처리 통일)
2주차: v1.0.20 → v1.0.23 (fuzzy matching 클라이언트+서버)
3주차: v1.0.23 → v1.0.24 (자녀/학원 관리 CRUD)
4주차: v1.0.24 → v1.0.25 (즉시 등록 기능)
5주차: v1.0.25 → v1.0.26 (완전 서버 연동)
```

매 단계마다 Codex 분석 → Claude Code 수정 → 테스트 → 다음 피드백 사이클이 매우 빠르게 진행되었습니다.

### 🚧 시행착오

**1. 초기 이름 매칭 실패 (v1.0.21)**

**문제:** Firestore에 "민수(첫째)"로 저장되어 있는데 사용자가 "민수"만 입력하면 인식 실패

**시도 1:** 클라이언트만 fuzzy matching 적용 (v1.0.22)

```
// 클라이언트만 수정
Utils.normalizeName("민수(첫째)") === "민수" // true
```

→ **실패**: 서버는 여전히 exact match로 처리

**시도 2:** Codex 분석 요청

```
나: "코덱스 점검결과야"
Codex: "클라이언트만 수정해서는 자연어 경로의 문제를 해결할 수 없습니다"
```

**최종 해결:** 서버에도 동일한 로직 배포 (v1.0.23 + Functions v1.0.10)

```
// 서버에도 추가
function findChild(children, inputName) {
    // 4단계 매칭
}
```

**교훈:** 클라이언트-서버 로직은 항상 동시에 수정해야 함

**2. "자녀 정보가 필요합니다" 무한 루프 (v1.0.24)**

**문제:** 등록되지 않은 자녀 이름 입력 시 등록 방법을 모름

**초기 구현:**

```
bot.send(room, "❌ 자녀 정보가 필요합니다\n다시 입력해주세요");
```

→ 사용자는 어떻게 등록하는지 모름

**Codex 제안:**

> "등록되지 않은 이름을 입력하면 바로 등록할 수 있게 만들어야 합니다"

**해결 과정:**

1. Firebase Functions에 `/addChild` 엔드포인트 추가
2. 미등록 감지 시 `!자녀등록` 명령 안내
3. 등록 후 자동 동기화 + 원래 명령 재시도 안내

**교훈:** 에러 메시지는 "무엇이 잘못되었나"뿐만 아니라 "어떻게 해결하나"까지 알려줘야 함

**3. 로컬 저장 vs 서버 연동 (v1.0.25 → v1.0.26)**

**문제:** 자녀/학원 수정·삭제 기능이 로컬만 저장하고 서버와 동기화 안 됨

```
// v1.0.25: 로컬만 저장
DataManager.saveLocalSettings(...);
bot.send(room, "⚠️ 주의: 서버 동기화를 위해 !동기화테스트를 실행하세요.");
```

→ 사용자가 수동으로 `!동기화테스트` 실행해야 함 (불편)

**Codex 최종 검증:**

> "클라이언트에는 수정·삭제 기능이 있지만 서버에는 해당 API가 없습니다"

**해결:**

1. 서버에 4개 엔드포인트 추가 (`updateChild`, `deleteChild`, `updateAcademy`, `deleteAcademy`)
2. 클라이언트 핸들러를 서버 API 호출 방식으로 변경
3. 모든 작업 후 자동 `syncFromServer()` 실행

```
// v1.0.26: 서버 연동 + 자동 동기화
HttpClient.postJson("/updateChild", { id, name }, function(result) {
    DataManager.syncFromServer(function(success) {
        bot.send(room, "✅ 수정 완료!"); // 수동 동기화 불필요
    });
});
```

**교훈:** 초기 설계부터 서버 API를 먼저 만들고, 클라이언트는 API를 호출만 하도록 구조화해야 함

### 🍯 나만의 꿀팁

**1. Codex 분석 결과를 Claude Code에게 전달하는 방법**

```
"코덱스에서 점검한 내용이야. [Codex 분석 전문 붙여넣기]. 조치해줘"
```

이렇게 하면 Claude Code가:

- Codex가 지적한 문제를 정확히 파악
- 근본 원인 분석
- 클라이언트-서버 양쪽 모두 수정
- 배포 및 업로드까지 자동화

**2. 버전 관리 전략**

```
v1.0.X → 마이너 기능 추가
v1.X.0 → 메이저 구조 변경

// 예시
v1.0.24 → 자녀/학원 관리 CRUD 추가
v1.0.25 → 즉시 등록 기능 추가
v1.0.26 → 서버 연동 완성
```

매 버전마다 명확한 changelog를 코드 헤더에 작성하면, Claude Code가 이전 변경사항을 참고하여 더 정확한 수정을 할 수 있습니다.

**3. Firebase Functions 배포 전 로컬 테스트**

```
# Functions 에뮬레이터로 로컬 테스트
firebase emulators:start --only functions

# 테스트 성공 후 배포
firebase deploy --only functions
```

Claude Code에게 "배포 전에 에뮬레이터로 테스트해줘"라고 요청하면 안전하게 배포할 수 있습니다.

**4. ADB 명령어 자동화**

```
# 디바이스 연결 확인
adb devices

# 파일 업로드
adb push '로컬경로/봇.js' /sdcard/msgbot/Bots/봇이름/봇.js
```

Claude Code는 이미 이 명령어들을 알고 있어서 "휴대폰에 업로드해줘"라고만 하면 자동으로 실행합니다.

### 🆘 도움이 필요한 부분

**1. 학원 자동 인식 개선**

현재는 Firestore에 등록된 학원만 인식하는데, 사용자가 "새로운학원"을 입력하면:

- 자동으로 `/addAcademy` 호출
- 즉시 등록 + 라이드 예약 진행

이 기능도 자녀 등록처럼 구현하고 싶습니다.

**2. 반복 일정 등록**

"매주 월수금 6시 30분에 대치수학학원 픽업"처럼 반복 일정을 한 번에 등록하는 기능이 필요합니다.

**3. 알림 기능**

라이드 30분 전에 카카오톡 알림을 보내는 기능을 추가하고 싶은데, Firebase Functions의 Scheduled Functions를 사용해야 할 것 같습니다.

### 🚀 앞으로의 계획

**단기 계획 (1개월):**

1. ✅ 완전한 CRUD 구현 (완료)
2. ✅ 서버 자동 동기화 (완료)
3. 🔜 학원 자동 등록 기능 추가
4. 🔜 반복 일정 등록 지원

**중기 계획 (3개월):**

1. 라이드 30분 전 알림 기능
2. 라이드 완료 후 피드백 수집
3. 통계 대시보드 (월별 라이드 횟수, 학원별 통계)
4. 여러 가족 지원 (멀티 테넌트)

**장기 계획 (6개월):**

1. 라이드 기사 매칭 시스템
2. 실시간 위치 추적
3. 자동 결제 통합
4. 모바일 앱 개발 (React Native)

### 📊 성과 지표

**개발 기간:** 5주 **코드 줄 수:**

- 클라이언트: 2,200+ 줄
- 서버: 1,000+ 줄

**버전 진행:**

- v1.0.18 → v1.0.26 (8번 업데이트)
- Firebase Functions v1.0.10 → v1.0.12 (3번 배포)

**기능 수:**

- 명령어: 15개+
- API 엔드포인트: 14개
- 대화 상태: 10+ 종류

**테스트 결과:**

- ✅ 자연어 파싱 정확도: 95%+
- ✅ 이름 인식률 (fuzzy matching): 100%
- ✅ 서버 응답 시간: 평균 1.5초
- ✅ Calendar 동기화 성공률: 100%

### Claude Code 공식 문서

- [Claude Code 시작하기](https://docs.anthropic.com/claude-code)
- [Agent SDK 아키텍처](https://github.com/anthropics/claude-code)

### Firebase 관련

- [Firebase Functions 시작하기](https://firebase.google.com/docs/functions)
- [Firestore 데이터 모델링](https://firebase.google.com/docs/firestore/data-model)
- [Google Calendar API 가이드](https://developers.google.com/calendar/api/guides/overview)

### OpenAI API

- [GPT-4o-mini 가이드](https://platform.openai.com/docs/models/gpt-4o-mini)
- [Function Calling 패턴](https://platform.openai.com/docs/guides/function-calling)

### 메신저봇R

- [메신저봇R API 문서](https://github.com/DarkTornado/KakaoTalkBot)
- [Java HttpURLConnection 예제](https://docs.oracle.com/javase/tutorial/networking/urls/readingWriting.html)

### 참고한 클로더즈 글

- "Claude Code로 대규모 리팩토링하기" - 코드베이스 분석 방법 참고
- "AI 에이전트 개발 가이드" - Codex 분석 활용법 참고
- "Firebase + OpenAI 통합 패턴" - 아키텍처 설계 참고

가장도움받은 것

- 스터디장님들의 주옥같은 강의자료들 + 개발근육
