# AI 및 스토리지 설정 기술문서 > 최종 업데이트: 2026-01-29 ## 개요 SAM MNG 시스템의 AI API 및 클라우드 스토리지(GCS) 설정을 관리하는 기능입니다. 관리자 UI에서 설정하거나, `.env` 환경변수로 설정할 수 있습니다. **접근 경로**: 시스템 관리 > AI 설정 (`/system/ai-config`) --- ## 지원 Provider ### AI Provider | Provider | 용도 | 기본 모델 | |----------|------|----------| | `gemini` | Google Gemini (명함 OCR, AI 어시스턴트) | gemini-2.0-flash | | `claude` | Anthropic Claude | claude-sonnet-4-20250514 | | `openai` | OpenAI GPT | gpt-4o | ### Storage Provider | Provider | 용도 | |----------|------| | `gcs` | Google Cloud Storage (음성 녹음 백업) | --- ## 데이터베이스 구조 ### 테이블: `ai_configs` ```sql CREATE TABLE ai_configs ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, -- 설정 이름 (예: "Production Gemini") provider VARCHAR(20) NOT NULL, -- gemini, claude, openai, gcs api_key VARCHAR(255) NOT NULL, -- API 키 (GCS는 'gcs_service_account') model VARCHAR(100) NOT NULL, -- 모델명 (GCS는 '-') base_url VARCHAR(255) NULL, -- 커스텀 Base URL description TEXT NULL, -- 설명 is_active BOOLEAN DEFAULT FALSE, -- 활성화 여부 (provider당 1개만) options JSON NULL, -- 추가 옵션 (아래 참조) created_at TIMESTAMP, updated_at TIMESTAMP, deleted_at TIMESTAMP NULL -- Soft Delete ); ``` ### options JSON 구조 **AI Provider (Gemini Vertex AI)**: ```json { "auth_type": "vertex_ai", "project_id": "my-gcp-project", "region": "us-central1", "service_account_path": "/var/www/sales/apikey/google_service_account.json" } ``` **AI Provider (API Key)**: ```json { "auth_type": "api_key" } ``` **GCS Provider**: ```json { "bucket_name": "my-bucket-name", "service_account_path": "/var/www/sales/apikey/google_service_account.json", "service_account_json": { ... } // 또는 JSON 직접 입력 } ``` --- ## 설정 우선순위 ### GCS 설정 우선순위 ``` 1. DB 설정 (ai_configs 테이블의 활성화된 gcs provider) ↓ 없으면 2. 환경변수 (.env의 GCS_BUCKET_NAME, GCS_SERVICE_ACCOUNT_PATH) ↓ 없으면 3. 레거시 파일 (/sales/apikey/gcs_config.txt, google_service_account.json) ``` ### AI 설정 우선순위 ``` 1. DB 설정 (ai_configs 테이블의 활성화된 provider) ↓ 없으면 2. 환경변수 (.env의 GEMINI_API_KEY 등) ↓ 없으면 3. 레거시 파일 ``` --- ## 환경변수 설정 (.env) ### GCS 설정 ```env # Google Cloud Storage (음성 녹음 백업) GCS_BUCKET_NAME=your-bucket-name GCS_SERVICE_ACCOUNT_PATH=/var/www/sales/apikey/google_service_account.json GCS_USE_DB_CONFIG=true # false면 DB 설정 무시, .env만 사용 ``` ### AI 설정 (참고) ```env # Google Gemini API GEMINI_API_KEY=your-api-key GEMINI_PROJECT_ID=your-project-id ``` --- ## 관련 파일 목록 ### 모델 | 파일 | 설명 | |------|------| | `app/Models/System/AiConfig.php` | AI 설정 Eloquent 모델 | ### 컨트롤러 | 파일 | 설명 | |------|------| | `app/Http/Controllers/System/AiConfigController.php` | CRUD + 연결 테스트 | ### 서비스 | 파일 | 설명 | |------|------| | `app/Services/GoogleCloudStorageService.php` | GCS 업로드/다운로드/삭제 | | `app/Services/GeminiService.php` | Gemini API 호출 (명함 OCR 등) | ### 설정 | 파일 | 설명 | |------|------| | `config/gcs.php` | GCS 환경변수 설정 | ### 뷰 | 파일 | 설명 | |------|------| | `resources/views/system/ai-config/index.blade.php` | AI 설정 관리 페이지 | ### 라우트 ```php // routes/web.php Route::prefix('system')->name('system.')->group(function () { Route::resource('ai-config', AiConfigController::class)->except(['show', 'create', 'edit']); Route::post('ai-config/{id}/toggle', [AiConfigController::class, 'toggle'])->name('ai-config.toggle'); Route::post('ai-config/test', [AiConfigController::class, 'test'])->name('ai-config.test'); Route::post('ai-config/test-gcs', [AiConfigController::class, 'testGcs'])->name('ai-config.test-gcs'); }); ``` --- ## 주요 메서드 ### AiConfig 모델 ```php // Provider별 활성 설정 조회 AiConfig::getActiveGemini(); // ?AiConfig AiConfig::getActiveClaude(); // ?AiConfig AiConfig::getActiveGcs(); // ?AiConfig AiConfig::getActive('openai'); // ?AiConfig // GCS 전용 메서드 $config->getBucketName(); // ?string $config->getServiceAccountJson(); // ?array $config->getServiceAccountPath(); // ?string $config->isGcs(); // bool // Vertex AI 전용 메서드 $config->isVertexAi(); // bool $config->getProjectId(); // ?string $config->getRegion(); // string (기본: us-central1) ``` ### GoogleCloudStorageService ```php $gcs = new GoogleCloudStorageService(); // 사용 가능 여부 $gcs->isAvailable(); // bool // 설정 소스 확인 $gcs->getConfigSource(); // 'db' | 'env' | 'legacy' | 'none' // 파일 업로드 $gcsUri = $gcs->upload($localPath, $objectName); // 'gs://bucket/object' | null // 서명된 다운로드 URL (60분 유효) $url = $gcs->getSignedUrl($objectName, 60); // string | null // 파일 삭제 $gcs->delete($objectName); // bool ``` --- ## UI 구조 ### 탭 구성 - **AI 설정 탭**: Gemini, Claude, OpenAI 설정 관리 - **스토리지 설정 탭**: GCS 설정 관리 ### 기능 - 설정 추가/수정/삭제 - 활성화/비활성화 토글 (provider당 1개만 활성화) - 연결 테스트 --- ## 사용 예시 ### GCS 업로드 (ConsultationController) ```php use App\Services\GoogleCloudStorageService; public function uploadAudio(Request $request) { // 파일 저장 $path = $file->store("tenant/consultations/{$tenantId}"); $fullPath = storage_path('app/' . $path); // 10MB 이상이면 GCS에도 업로드 if ($file->getSize() > 10 * 1024 * 1024) { $gcs = new GoogleCloudStorageService(); if ($gcs->isAvailable()) { $gcsUri = $gcs->upload($fullPath, "consultations/{$tenantId}/" . basename($path)); } } } ``` ### 명함 OCR (GeminiService) ```php use App\Services\GeminiService; $gemini = new GeminiService(); $result = $gemini->extractBusinessCard($imagePath); ``` --- ## 배포 가이드 ### 서버 최초 설정 1. `.env` 파일에 GCS 설정 추가: ```env GCS_BUCKET_NAME=production-bucket GCS_SERVICE_ACCOUNT_PATH=/var/www/sales/apikey/google_service_account.json ``` 2. 서비스 계정 JSON 파일 배치: ``` /var/www/sales/apikey/google_service_account.json ``` 3. 설정 캐시 갱신: ```bash docker exec sam-mng-1 php artisan config:cache ``` ### 이후 배포 - 코드 push만으로 동작 (설정 변경 불필요) - UI에서 오버라이드하고 싶을 때만 DB 설정 사용 --- ## 트러블슈팅 ### GCS 업로드 실패 1. **설정 확인**: ```php $gcs = new GoogleCloudStorageService(); dd($gcs->isAvailable(), $gcs->getConfigSource(), $gcs->getBucketName()); ``` 2. **로그 확인**: ```bash docker exec sam-mng-1 tail -f storage/logs/laravel.log | grep GCS ``` 3. **일반적인 원인**: - 서비스 계정 파일 경로 오류 - 서비스 계정에 Storage 권한 없음 - 버킷 이름 오타 ### AI API 연결 실패 1. **API 키 확인**: UI에서 "테스트" 버튼 클릭 2. **모델명 확인**: provider별 지원 모델 확인 3. **할당량 확인**: Google Cloud Console에서 API 할당량 확인 --- ## 레거시 파일 위치 (참고) Docker 컨테이너 내부 경로: ``` /var/www/sales/apikey/ ├── gcs_config.txt # bucket_name=xxx ├── google_service_account.json # GCP 서비스 계정 키 └── gemini_api_key.txt # Gemini API 키 (레거시) ``` 호스트 경로 (mng 기준): ``` ../sales/apikey/ ```