Files
cloud-server/API.md
kappa abe052b538 feat: 코드 품질 개선 및 추천 API 구현
## 주요 변경사항

### 신규 기능
- POST /recommend: 기술 스택 기반 인스턴스 추천 API
- 아시아 리전 필터링 (Seoul, Tokyo, Osaka, Singapore)
- 매칭 점수 알고리즘 (메모리 40%, vCPU 30%, 가격 20%, 스토리지 10%)

### 보안 강화 (Security 9.0/10)
- API Key 인증 + constant-time 비교 (타이밍 공격 방어)
- Rate Limiting: KV 기반 분산 처리, fail-closed 정책
- IP Spoofing 방지 (CF-Connecting-IP만 신뢰)
- 요청 본문 10KB 제한
- CORS + 보안 헤더 (CSP, HSTS, X-Frame-Options)

### 성능 최적화 (Performance 9.0/10)
- Generator 패턴: AWS pricing 메모리 95% 감소
- D1 batch 쿼리: N+1 문제 해결
- 복합 인덱스 추가 (migrations/002)

### 코드 품질 (QA 9.0/10)
- 127개 테스트 (vitest)
- 구조화된 로깅 (민감정보 마스킹)
- 상수 중앙화 (constants.ts)
- 입력 검증 유틸리티 (utils/validation.ts)

### Vultr 연동 수정
- relay 서버 헤더: Authorization: Bearer → X-API-Key

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 11:57:35 +09:00

16 KiB
Raw Permalink Blame History

Cloud Instances API Documentation

개요

클라우드 인스턴스 가격 비교 및 기술 스택 기반 추천 API

  • Base URL: https://cloud-instances-api.kappa-d8e.workers.dev
  • 인증: X-API-Key 헤더 필수
  • Providers: Linode, Vultr, AWS
  • 지원 리전: 아시아 (서울, 도쿄, 오사카, 싱가포르, 홍콩)

인증

모든 API 요청에 X-API-Key 헤더 필요:

X-API-Key: your-api-key

인증 실패 시:

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "API key is missing or invalid"
  }
}

엔드포인트

1. Health Check

시스템 상태 및 provider 동기화 상태 확인

Request

GET /health

Response

{
  "status": "healthy",
  "timestamp": "2025-01-22T10:00:00.000Z",
  "components": {
    "database": {
      "status": "healthy",
      "latency_ms": 12
    },
    "providers": [
      {
        "name": "linode",
        "status": "healthy",
        "last_sync": "2025-01-22 09:30:00",
        "sync_status": "success",
        "regions_count": 11,
        "instances_count": 45
      },
      {
        "name": "vultr",
        "status": "healthy",
        "last_sync": "2025-01-22 09:28:00",
        "sync_status": "success",
        "regions_count": 8,
        "instances_count": 32
      },
      {
        "name": "aws",
        "status": "degraded",
        "last_sync": "2025-01-21 15:00:00",
        "sync_status": "success",
        "regions_count": 15,
        "instances_count": 120,
        "error": "Sync delayed"
      }
    ]
  },
  "summary": {
    "total_providers": 3,
    "healthy_providers": 2,
    "total_regions": 34,
    "total_instances": 197
  }
}

상태 코드

  • 200: 시스템 정상 (all components healthy)
  • 503: 시스템 문제 (degraded or unhealthy)

Health Status

  • healthy: 정상 작동 (최근 24시간 이내 동기화)
  • degraded: 부분 문제 (24-48시간 이내 동기화 또는 일부 에러)
  • unhealthy: 심각한 문제 (48시간 이상 미동기화 또는 데이터베이스 연결 실패)

2. 인스턴스 목록 조회

조건에 맞는 인스턴스 조회 (필터링, 정렬, 페이지네이션 지원)

Request

GET /instances?provider=linode&min_vcpu=2&max_price=50&sort_by=price&order=asc&limit=20

Query Parameters

파라미터 타입 필수 설명 기본값
provider string Provider 필터 (linode, vultr, aws) -
region string 리전 코드 필터 (예: ap-northeast-1) -
min_vcpu integer 최소 vCPU 수 -
max_vcpu integer 최대 vCPU 수 -
min_memory_gb number 최소 메모리 (GB) -
max_memory_gb number 최대 메모리 (GB) -
max_price number 최대 월 가격 (USD) -
instance_family string 인스턴스 패밀리 (general, compute, memory, storage, gpu) -
has_gpu boolean GPU 인스턴스 필터 (true, false) -
sort_by string 정렬 필드 (아래 참조) -
order string 정렬 순서 (asc, desc) asc
limit integer 결과 개수 (1-100) 50
offset integer 결과 오프셋 (페이지네이션) 0

유효한 정렬 필드

  • price / monthly_price / hourly_price
  • vcpu
  • memory_mb / memory_gb
  • storage_gb
  • instance_name
  • provider
  • region

Response

{
  "success": true,
  "data": {
    "instances": [
      {
        "id": 123,
        "instance_id": "g6-standard-2",
        "instance_name": "Linode 4GB",
        "vcpu": 2,
        "memory_mb": 4096,
        "storage_gb": 80,
        "transfer_tb": 4,
        "network_speed_gbps": 4,
        "gpu_count": 0,
        "gpu_type": null,
        "instance_family": "general",
        "provider": {
          "id": 1,
          "name": "linode",
          "display_name": "Linode"
        },
        "region": {
          "id": 5,
          "region_code": "ap-northeast",
          "region_name": "Tokyo (jp-tyo-3)",
          "country_code": "JP"
        },
        "pricing": {
          "hourly_price": 0.036,
          "monthly_price": 24.0,
          "currency": "USD",
          "available": 1
        }
      }
    ],
    "pagination": {
      "total": 45,
      "limit": 20,
      "offset": 0,
      "has_more": true
    },
    "metadata": {
      "cached": false,
      "last_sync": "2025-01-22T10:00:00.000Z",
      "query_time_ms": 45,
      "filters_applied": {
        "provider": "linode",
        "min_vcpu": 2,
        "max_price": 50
      }
    }
  }
}

상태 코드

  • 200: 성공
  • 400: 잘못된 파라미터
  • 500: 서버 에러

캐시 동작

  • TTL: 5분 (300초)
  • 캐시 히트 시 metadata.cached: true
  • 캐시 헤더: Cache-Control: public, max-age=300

3. 데이터 동기화

Provider API에서 최신 데이터 가져오기

Request

POST /sync
Content-Type: application/json

{
  "providers": ["linode", "vultr", "aws"],
  "force": false
}

Request Body

필드 타입 필수 설명 기본값
providers string[] 동기화할 provider 목록 ["linode"]
force boolean 강제 동기화 여부 (사용되지 않음) false

Response

{
  "success": true,
  "data": {
    "sync_id": "sync_1737545678901_abc123def",
    "success": true,
    "started_at": "2025-01-22T10:00:00.000Z",
    "completed_at": "2025-01-22T10:02:15.000Z",
    "total_duration_ms": 135000,
    "providers": [
      {
        "provider": "linode",
        "success": true,
        "regions_synced": 11,
        "instances_synced": 45,
        "pricing_synced": 495,
        "duration_ms": 45000
      },
      {
        "provider": "vultr",
        "success": true,
        "regions_synced": 8,
        "instances_synced": 32,
        "pricing_synced": 256,
        "duration_ms": 38000
      },
      {
        "provider": "aws",
        "success": false,
        "regions_synced": 0,
        "instances_synced": 0,
        "pricing_synced": 0,
        "duration_ms": 52000,
        "error": "API authentication failed",
        "error_details": {
          "code": "CREDENTIALS_ERROR",
          "message": "Invalid AWS credentials"
        }
      }
    ],
    "summary": {
      "total_providers": 3,
      "successful_providers": 2,
      "failed_providers": 1,
      "total_regions": 19,
      "total_instances": 77,
      "total_pricing": 751
    }
  }
}

상태 코드

  • 200: 동기화 완료 (일부 실패 포함)
  • 400: 잘못된 요청 (잘못된 provider 이름 등)
  • 500: 서버 에러

에러 케이스

{
  "success": false,
  "error": {
    "code": "UNSUPPORTED_PROVIDERS",
    "message": "Unsupported providers: digitalocean",
    "details": {
      "unsupported": ["digitalocean"],
      "supported": ["linode", "vultr", "aws"]
    }
  }
}

4. 기술 스택 기반 인스턴스 추천

기술 스택과 규모에 맞는 최적 인스턴스 추천

Request

POST /recommend
Content-Type: application/json

{
  "stack": ["nginx", "php-fpm", "mysql"],
  "scale": "medium",
  "budget_max": 50
}

Request Body

필드 타입 필수 설명
stack string[] 기술 스택 목록 (아래 참조)
scale string 배포 규모 (small, medium, large)
budget_max number 월 최대 예산 (USD)

지원 기술 스택

스택 최소 메모리 권장 메모리
nginx 128 MB 256 MB
php-fpm 512 MB 1 GB
mysql 1 GB 2 GB
mariadb 1 GB 2 GB
postgresql 1 GB 2 GB
redis 256 MB 512 MB
elasticsearch 2 GB 4 GB
nodejs 512 MB 1 GB
docker 1 GB 2 GB
mongodb 1 GB 2 GB

스케일별 리소스 계산

스케일 메모리 계산 vCPU 계산
small 최소 사양 메모리 기반 (2GB당 1 vCPU)
medium 권장 사양 메모리 기반 (2GB당 1 vCPU)
large 권장 × 1.5배 메모리 기반 (2GB당 1 vCPU)
  • OS 오버헤드: 768 MB (모든 스케일 공통)
  • 최소 vCPU: 1개

Response

{
  "success": true,
  "data": {
    "requirements": {
      "min_memory_mb": 4096,
      "min_vcpu": 2,
      "breakdown": {
        "nginx": "256MB",
        "php-fpm": "1GB",
        "mysql": "2GB",
        "os_overhead": "768MB"
      }
    },
    "recommendations": [
      {
        "rank": 1,
        "provider": "linode",
        "instance": "Linode 4GB",
        "region": "Tokyo (jp-tyo-3)",
        "specs": {
          "vcpu": 2,
          "memory_mb": 4096,
          "storage_gb": 80
        },
        "price": {
          "monthly": 24.0,
          "hourly": 0.036
        },
        "match_score": 95,
        "pros": [
          "메모리 최적 적합",
          "vCPU 적합",
          "스토리지 80GB 포함"
        ],
        "cons": []
      },
      {
        "rank": 2,
        "provider": "vultr",
        "instance": "4GB Memory",
        "region": "Seoul (icn)",
        "specs": {
          "vcpu": 2,
          "memory_mb": 4096,
          "storage_gb": 80
        },
        "price": {
          "monthly": 24.0,
          "hourly": 0.036
        },
        "match_score": 95,
        "pros": [
          "메모리 최적 적합",
          "vCPU 적합",
          "스토리지 80GB 포함"
        ],
        "cons": []
      },
      {
        "rank": 3,
        "provider": "linode",
        "instance": "Linode 8GB",
        "region": "Tokyo (jp-tyo-3)",
        "specs": {
          "vcpu": 4,
          "memory_mb": 8192,
          "storage_gb": 160
        },
        "price": {
          "monthly": 48.0,
          "hourly": 0.072
        },
        "match_score": 75,
        "pros": [
          "vCPU 여유 (4 cores)",
          "메모리 충분 (8GB)",
          "스토리지 160GB 포함"
        ],
        "cons": [
          "예산 초과 ($48 > $50)"
        ]
      }
    ]
  },
  "meta": {
    "query_time_ms": 85
  }
}

매칭 스코어 계산

조건 점수
메모리 정확히 일치 100점
메모리 20% 초과 90점
메모리 50% 초과 70점
메모리 부족 0점 (제외)
vCPU 일치 +0점
vCPU 부족 -10점
예산 초과 -20점

상태 코드

  • 200: 성공
  • 400: 잘못된 요청
  • 500: 서버 에러

에러 케이스

{
  "success": false,
  "error": {
    "code": "INVALID_STACK",
    "message": "Unsupported stacks: mongodb-atlas",
    "details": {
      "invalid": ["mongodb-atlas"],
      "supported": [
        "nginx", "php-fpm", "mysql", "mariadb",
        "postgresql", "redis", "elasticsearch",
        "nodejs", "docker", "mongodb"
      ]
    }
  }
}

아시아 리전 목록

Linode

  • ap-northeast - Tokyo (jp-tyo-3)
  • ap-south - Osaka (jp-osa-1)
  • ap-southeast - Singapore (sg-sin-1)

Vultr

  • icn - Seoul
  • nrt - Tokyo
  • itm - Osaka

AWS

  • ap-northeast-1 - Tokyo
  • ap-northeast-2 - Seoul
  • ap-northeast-3 - Osaka
  • ap-southeast-1 - Singapore
  • ap-east-1 - Hong Kong

에러 응답 형식

모든 에러는 아래 형식으로 응답:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human readable error message",
    "details": {
      "additional": "error details"
    }
  }
}

주요 에러 코드

코드 설명 상태 코드
UNAUTHORIZED 인증 실패 401
INVALID_PARAMETER 잘못된 파라미터 400
MISSING_PARAMETER 필수 파라미터 누락 400
INVALID_CONTENT_TYPE Content-Type이 application/json이 아님 400
INVALID_JSON JSON 파싱 실패 400
INVALID_STACK 지원하지 않는 기술 스택 400
EMPTY_STACK 스택 배열이 비어 있음 400
UNSUPPORTED_PROVIDERS 지원하지 않는 provider 400
QUERY_FAILED 쿼리 실행 실패 500
INTERNAL_ERROR 서버 내부 에러 500
SYNC_FAILED 동기화 작업 실패 500

Rate Limiting

엔드포인트 제한
/health 제한 없음
/instances 100 req/min
/sync 10 req/min
/recommend 60 req/min

Rate limit 초과 시:

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again later.",
    "details": {
      "limit": 60,
      "window": "1 minute",
      "retry_after": 45
    }
  }
}

사용 예시

1. 워드프레스 서버 추천

curl -X POST "https://cloud-instances-api.kappa-d8e.workers.dev/recommend" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "stack": ["nginx", "php-fpm", "mysql"],
    "scale": "medium"
  }'

예상 요구사항

  • 메모리: 4 GB (nginx 256MB + php-fpm 1GB + mysql 2GB + OS 768MB)
  • vCPU: 2 cores

2. Node.js 앱 (예산 제한 있음)

curl -X POST "https://cloud-instances-api.kappa-d8e.workers.dev/recommend" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "stack": ["nginx", "nodejs", "redis"],
    "scale": "small",
    "budget_max": 20
  }'

예상 요구사항

  • 메모리: 1.6 GB (nginx 128MB + nodejs 512MB + redis 256MB + OS 768MB)
  • vCPU: 1 core
  • 예산: $20 이하

3. 대규모 전자상거래 플랫폼

curl -X POST "https://cloud-instances-api.kappa-d8e.workers.dev/recommend" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "stack": ["nginx", "nodejs", "postgresql", "redis", "elasticsearch"],
    "scale": "large"
  }'

예상 요구사항

  • 메모리: 13.5 GB (nginx 384MB + nodejs 1.5GB + postgresql 3GB + redis 768MB + elasticsearch 6GB + OS 768MB)
  • vCPU: 7 cores

4. Provider별 가격 비교

# Linode만 조회
curl -X GET "https://cloud-instances-api.kappa-d8e.workers.dev/instances?provider=linode&min_vcpu=2&max_price=30&sort_by=price&order=asc&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

# Vultr만 조회
curl -X GET "https://cloud-instances-api.kappa-d8e.workers.dev/instances?provider=vultr&min_vcpu=2&max_price=30&sort_by=price&order=asc&limit=10" \
  -H "X-API-Key: YOUR_API_KEY"

# 모든 provider 조회 (가격 순 정렬)
curl -X GET "https://cloud-instances-api.kappa-d8e.workers.dev/instances?min_vcpu=2&max_price=30&sort_by=price&order=asc&limit=30" \
  -H "X-API-Key: YOUR_API_KEY"

5. 특정 리전에서 GPU 인스턴스 검색

curl -X GET "https://cloud-instances-api.kappa-d8e.workers.dev/instances?region=ap-northeast-1&has_gpu=true&sort_by=price&order=asc" \
  -H "X-API-Key: YOUR_API_KEY"

6. 메모리 최적화 인스턴스 검색

curl -X GET "https://cloud-instances-api.kappa-d8e.workers.dev/instances?instance_family=memory&min_memory_gb=16&sort_by=price&order=asc" \
  -H "X-API-Key: YOUR_API_KEY"

버전 정보

  • API Version: 1.0.0
  • Last Updated: 2025-01-22
  • Runtime: Cloudflare Workers
  • Database: Cloudflare D1 (SQLite)

지원 및 문의


변경 이력

v1.0.0 (2025-01-22)

  • 초기 릴리즈
  • /health 엔드포인트 구현
  • /instances 엔드포인트 구현 (필터링, 정렬, 페이지네이션)
  • /sync 엔드포인트 구현 (Linode, Vultr, AWS)
  • /recommend 엔드포인트 구현 (기술 스택 기반 추천)
  • 캐시 시스템 구현 (5분 TTL)
  • 아시아 리전 지원
  • Rate limiting 구현