# 카카오 API 기반 음식점 수집 서비스 카카오 로컬 API를 활용하여 음식점 정보를 수집하고 관리하는 RESTful API 서비스입니다. ## 📋 프로젝트 개요 ### 주요 기능 - 🔍 **카카오 로컬 API 연동**: 키워드 및 지역 기반 음식점 검색 - 📊 **다중 페이지 수집**: 최대 45페이지까지 데이터 수집 지원 - 💾 **자동 JSON 저장**: 수집된 데이터를 JSON 파일로 자동 저장 - 🚀 **RESTful API 제공**: FastAPI 기반의 완전한 API 서비스 - 📚 **Swagger UI 지원**: 자동 생성되는 API 문서 - ☸️ **Kubernetes 배포**: 완전한 컨테이너 오케스트레이션 지원 - 🔧 **환경변수 설정**: ConfigMap과 Secret을 통한 유연한 설정 관리 ### 기술 스택 - **Backend**: Python 3.11, FastAPI, aiohttp - **API**: Kakao Local API - **Container**: Docker, Multi-stage build - **Orchestration**: Kubernetes (AKS) - **Registry**: Azure Container Registry (ACR) - **Documentation**: Swagger UI, ReDoc ## 🏗️ 프로젝트 구조 ``` review-api/restaurant/ ├── app/ # 애플리케이션 소스 │ ├── main.py # 메인 애플리케이션 │ └── requirements.txt # Python 의존성 ├── deployment/ # 배포 관련 파일 │ ├── container/ # 컨테이너 이미지 빌드 │ │ ├── Dockerfile # 서비스 이미지 빌드 │ │ └── Dockerfile-base # 베이스 이미지 빌드 │ └── manifests/ # Kubernetes 매니페스트 │ ├── configmap.yaml # 환경 설정 │ ├── secret.yaml # 민감 정보 (API 키) │ ├── deployment.yaml # 애플리케이션 배포 │ ├── service.yaml # 서비스 노출 │ └── ingress.yaml # 외부 접근 ├── build-base.sh # 베이스 이미지 빌드 스크립트 ├── build.sh # 서비스 이미지 빌드 스크립트 ├── create-imagepullsecret.sh # ACR 인증 설정 스크립트 ├── setup.sh # 로컬 환경 설정 스크립트 └── README.md # 프로젝트 문서 ``` ## 📋 사전 작업 ### 카카오 API 설정 카카오 developers 포탈에서 애플리케이션 등록이 필요합니다. 1. **포탈 접속**: https://developers.kakao.com/console/app 2. **애플리케이션 등록**: - 앱 이름: `RestaurantCollector` - 회사명: `{회사명}` - 카테고리: `식음료` 3. **카카오맵 활성화**: 등록한 애플리케이션에서 좌측 '카카오맵' 메뉴 클릭하여 활성화 ## 🚀 빠른 시작 ### 1. 로컬 개발 환경 설정 ```bash # 저장소 클론 (review-api/restaurant 디렉토리로 이동) cd review-api/restaurant # 환경 설정 스크립트 실행 chmod +x setup.sh ./setup.sh # 가상환경 활성화 source venv/bin/activate # 애플리케이션 실행 python app/main.py ``` ### 2. 로컬 웹 브라우저 접속 ```bash # 애플리케이션이 정상 실행된 후 아래 URL로 접속 ``` - **메인 페이지**: http://localhost:18000 - **Swagger UI**: http://localhost:18000/docs - **ReDoc**: http://localhost:18000/redoc - **헬스체크**: http://localhost:18000/health ### 3. API 테스트 ```bash # 기본 음식점 수집 curl -X POST "http://localhost:18000/collect" \ -H "Content-Type: application/json" \ -d '{ "query": "치킨", "region": "서울", "size": 15, "pages": 3, "save_to_file": true }' # 수집된 파일 목록 조회 curl "http://localhost:18000/list-files" # 파일 다운로드 (예시) curl "http://localhost:18000/download/restaurant.json" -o downloaded_restaurants.json ``` ## 🐳 Docker 컨테이너 실행 ### 베이스 이미지 빌드 ```bash # ACR에 베이스 이미지 빌드 및 푸시 ./build-base.sh latest acrdigitalgarage03 rg-digitalgarage-03 ``` ### 서비스 이미지 빌드 ```bash # ACR에 서비스 이미지 빌드 및 푸시 ./build.sh latest acrdigitalgarage03 rg-digitalgarage-03 ``` ### 로컬 Docker 실행 ```bash # 컨테이너 실행 docker run -p 18000:8000 \ -e KAKAO_API_KEY=5cdc24407edbf8544f3954cfaa4650c6 \ -e PORT=8000 \ restaurant-api:latest # 백그라운드 실행 docker run -d -p 18000:8000 \ --name restaurant-api \ -e KAKAO_API_KEY=5cdc24407edbf8544f3954cfaa4650c6 \ -e PORT=8000 \ restaurant-api:latest ``` ## ☸️ Kubernetes 배포 ### 1. ACR Image Pull Secret 생성 ```bash # Image Pull Secret 생성 ./create-imagepullsecret.sh acrdigitalgarage03 rg-digitalgarage-03 ``` ### 2. Kubernetes 리소스 배포 ```bash # ConfigMap 및 Secret 적용 kubectl apply -f deployment/manifests/configmap.yaml kubectl apply -f deployment/manifests/secret.yaml # 애플리케이션 배포 kubectl apply -f deployment/manifests/deployment.yaml kubectl apply -f deployment/manifests/service.yaml kubectl apply -f deployment/manifests/ingress.yaml ``` ### 3. 배포 상태 확인 ```bash # Pod 상태 확인 kubectl get pods -l app=restaurant-api # 서비스 상태 확인 kubectl get svc restaurant-api-service # Ingress 상태 확인 kubectl get ingress restaurant-api-ingress # 로그 확인 kubectl logs -l app=restaurant-api -f ``` ### 4. 🌐 외부 브라우저에서 접속하기 #### Ingress 주소 확인 방법 ```bash # 1. Ingress 설정된 호스트 확인 kubectl get ingress restaurant-api-ingress -o jsonpath='{.spec.rules[0].host}' # 2. Ingress External IP 확인 (LoadBalancer 타입인 경우) kubectl get ingress restaurant-api-ingress # 3. Ingress Controller의 External IP 확인 kubectl get svc -n ingress-nginx ingress-nginx-controller # 4. 현재 설정된 ingress 주소 확인 INGRESS_HOST=$(kubectl get ingress restaurant-api-ingress -o jsonpath='{.spec.rules[0].host}') echo "🌐 Restaurant API URL: http://${INGRESS_HOST}" ``` #### 브라우저 접속 주소 현재 설정된 주소로 접속하세요: ```bash # 현재 설정된 기본 주소 (환경에 따라 다를 수 있음) INGRESS_URL="http://restaurant-api.20.249.191.180.nip.io" echo "브라우저에서 접속: ${INGRESS_URL}" ``` **주요 접속 페이지:** - **🏠 메인 페이지**: http://restaurant-api.20.249.191.180.nip.io - **📖 Swagger UI**: http://restaurant-api.20.249.191.180.nip.io/docs - **📄 ReDoc**: http://restaurant-api.20.249.191.180.nip.io/redoc - **❤️ 헬스체크**: http://restaurant-api.20.249.191.180.nip.io/health #### 접속 테스트 ```bash # API 접속 테스트 curl "http://restaurant-api.20.249.191.180.nip.io/health" # 설정 정보 확인 curl "http://restaurant-api.20.249.191.180.nip.io/config" # Swagger UI 접속 확인 curl -I "http://restaurant-api.20.249.191.180.nip.io/docs" ``` ## ⚙️ 환경 설정 ### 환경 변수 | 변수명 | 기본값 | 설명 | |--------|--------|------| | `KAKAO_API_KEY` | `5cdc24407edbf8544f3954cfaa4650c6` | 카카오 API 키 | | `APP_TITLE` | `카카오 API 기반 음식점 수집 서비스` | 애플리케이션 제목 | | `HOST` | `0.0.0.0` | 서버 호스트 | | `PORT` | `8000` | 서버 포트 (컨테이너 내부) | | `DEFAULT_QUERY` | `음식점` | 기본 검색 키워드 | | `DEFAULT_REGION` | `서울` | 기본 검색 지역 | | `DEFAULT_SIZE` | `15` | 페이지당 결과 수 | | `MAX_PAGES` | `45` | 최대 페이지 수 | | `DATA_DIR` | `/app/data` | 데이터 저장 디렉토리 | | `REQUEST_DELAY` | `0.1` | API 요청 간 지연시간(초) | ## 📊 API 엔드포인트 ### 주요 엔드포인트 | Method | Endpoint | 설명 | |--------|----------|------| | `GET` | `/` | 메인 페이지 | | `GET` | `/docs` | Swagger UI 문서 | | `GET` | `/health` | 헬스체크 | | `POST` | `/collect` | 음식점 정보 수집 | | `POST` | `/collect-background` | 백그라운드 수집 | | `GET` | `/list-files` | 저장된 파일 목록 | | `GET` | `/download/{filename}` | 파일 다운로드 | | `GET` | `/config` | 환경 설정 확인 | ### 수집 API 예시 ```json POST /collect { "query": "피자", "region": "강남구", "size": 15, "pages": 5, "save_to_file": true } ``` **응답:** ```json { "success": true, "message": "음식점 정보 수집이 완료되었습니다. (총 67개)", "metadata": { "collection_date": "2024-06-12T10:30:00", "query": "피자", "region": "강남구", "total_count": 67, "pages_collected": 5, "execution_time": 12.5 }, "restaurants": [...], "file_saved": true, "file_path": "/app/data/restaurants_피자_강남구_20240612_103000.json" } ``` ## 🔧 개발 및 확장 ### 로컬 개발 ```bash # 개발 모드로 실행 (자동 재시작) uvicorn app.main:app --host 0.0.0.0 --port 18000 --reload # 의존성 추가 pip install 새패키지명 pip freeze > app/requirements.txt # 코드 포맷팅 black app/main.py flake8 app/main.py ``` ### Ingress 호스트 변경 현재 환경에 맞게 Ingress 호스트를 변경하려면: ```bash # 1. 현재 External IP 확인 kubectl get svc -n ingress-nginx ingress-nginx-controller # 2. deployment/manifests/ingress.yaml 파일에서 host 수정 # 예: restaurant-api.{YOUR_EXTERNAL_IP}.nip.io # 3. 변경사항 적용 kubectl apply -f deployment/manifests/ingress.yaml # 4. 새로운 주소 확인 kubectl get ingress restaurant-api-ingress ``` ## 🐛 문제 해결 ### 일반적인 문제 **1. API 키 인증 실패** ```bash # API 키 확인 curl -H "Authorization: KakaoAK YOUR_API_KEY" \ "https://dapi.kakao.com/v2/local/search/keyword.json?query=테스트&size=1" # 환경변수 확인 echo $KAKAO_API_KEY ``` **2. Kubernetes 배포 실패** ```bash # Pod 로그 확인 kubectl logs -l app=restaurant-api # ConfigMap 확인 kubectl get configmap restaurant-api-config -o yaml # Secret 확인 kubectl get secret restaurant-api-secret -o yaml ``` **3. Ingress 접속 실패** ```bash # Ingress Controller 상태 확인 kubectl get pods -n ingress-nginx # Ingress 규칙 확인 kubectl describe ingress restaurant-api-ingress # Service 연결 확인 kubectl get endpoints restaurant-api-service ``` **4. 포트 관련 문제** - 로컬 개발: 18000번 포트 사용 - Docker 컨테이너: 8000번 포트로 실행 (외부 18000번으로 매핑) - Kubernetes: 8000번 포트로 실행 (Service에서 80번으로 노출, Ingress를 통해 외부 접근) ## 🎯 성능 최적화 ### 권장 설정 ```yaml # deployment.yaml에서 리소스 최적화 resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "500m" ``` ### 모니터링 ```bash # 리소스 사용량 확인 kubectl top pods -l app=restaurant-api # 메트릭 수집 (Prometheus 설정 시) kubectl get --raw /metrics ``` ## 📈 향후 확장 계획 - [ ] **전국 확대**: 지역별 음식점 수집 기능 확장 - [ ] **데이터베이스 연동**: PostgreSQL, MongoDB 지원 - [ ] **비동기 작업 큐**: Celery, Redis 활용 - [ ] **데이터 분석**: 음식점 트렌드 분석 기능 - [ ] **알림 시스템**: 새로운 음식점 알림 기능 - [ ] **사용자 인증**: JWT 기반 인증 시스템 - [ ] **API 레이트 리미팅**: 요청 제한 기능 - [ ] **GraphQL 지원**: 유연한 쿼리 인터페이스 - [ ] **실시간 모니터링**: Grafana, Prometheus 연동 --- ## 📞 지원 및 문의 - **이슈 리포트**: GitHub Issues - **기술 문의**: 개발팀 Slack - **API 문서**: Swagger UI에서 상세 확인