- Phase 0: INDEX.md 전면 재작성, CLAUDE.md→INDEX.md 통합 삭제 - Phase 0: front/→guides/ 이관(5개 파일), changes/ D7 포맷 통일(3개) - Phase 0: guides/ai-config-설정.md→ai-config-settings.md D3 통일 - Phase 2: architecture/+specs/→system/ 이관(6개 이동, 4개 폐기) - Phase 2: 13개 파일 경로 참조 수정 (specs/→system/, architecture/→system/) - Phase 4: 7개 파일 11개 교차참조 깨진 링크 수정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.8 KiB
7.8 KiB
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
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):
{
"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):
{
"auth_type": "api_key"
}
GCS Provider:
{
"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 설정
# 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 설정 (참고)
# 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 설정 관리 페이지 |
라우트
// 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 모델
// 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
$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)
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)
use App\Services\GeminiService;
$gemini = new GeminiService();
$result = $gemini->extractBusinessCard($imagePath);
배포 가이드
서버 최초 설정
-
.env파일에 GCS 설정 추가:GCS_BUCKET_NAME=production-bucket GCS_SERVICE_ACCOUNT_PATH=/var/www/sales/apikey/google_service_account.json -
서비스 계정 JSON 파일 배치:
/var/www/sales/apikey/google_service_account.json -
설정 캐시 갱신:
docker exec sam-mng-1 php artisan config:cache
이후 배포
- 코드 push만으로 동작 (설정 변경 불필요)
- UI에서 오버라이드하고 싶을 때만 DB 설정 사용
트러블슈팅
GCS 업로드 실패
-
설정 확인:
$gcs = new GoogleCloudStorageService(); dd($gcs->isAvailable(), $gcs->getConfigSource(), $gcs->getBucketName()); -
로그 확인:
docker exec sam-mng-1 tail -f storage/logs/laravel.log | grep GCS -
일반적인 원인:
- 서비스 계정 파일 경로 오류
- 서비스 계정에 Storage 권한 없음
- 버킷 이름 오타
AI API 연결 실패
- API 키 확인: UI에서 "테스트" 버튼 클릭
- 모델명 확인: provider별 지원 모델 확인
- 할당량 확인: 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/