AI API 보안을 강화하고 싶지만, 복잡한 네트워크 설정 때문에 망설이고 계신가요? IP 접근 제어를 제대로 설정하면 API 키 유출 시 무제한 호출 방지, 특정 지역 트래픽만 허용, 비용 이상 탐지 차단이 한 번에 가능합니다. 이 가이드에서는 HolySheep AI 게이트웨이에서 IP 화이트리스트와 블랙리스트를 구성하는 방법과 함께, 실제 마이그레이션 사례를 통해 30일 결과까지 상세히 다룹니다.

사례 연구: 서울의 AI 챗봇 스타트업

비즈니스 맥락

저는 최근 서울 성수동에 위치한 AI 챗봇 스타트업(가칭: 메타버스AI)의 마이그레이션을 도왔습니다. 이 팀은 한국 보험 회사의 고객 상담 챗봇을 운영하며, 일 50만 토큰 이상을 GPT-4.1로 처리하고 있었습니다. 월간 AI 비용이 $4,200에 달했고, 특히 야간에 의심스러운 API 호출 패턴이 발견되어 보안 강화가 시급한 상황이었죠.

기존 공급사의 페인포인트

HolySheep 선택 이유

저는 이 팀에 HolySheep AI 게이트웨이를 추천했습니다. 단일 API 키로 모든 주요 모델(GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2)을 통합 관리하면서, IP 화이트리스트/블랙리스트 기능을 통해 API 키 유출 시도를 원천 차단할 수 있었기 때문입니다. 게다가 로컬 결제 지원으로 해외 신용카드 없이 팀 내에서 직접 비용을 관리할 수 있게 되었죠.

마이그레이션 단계

1단계: 기존 코드에서 base_url 교체

기존 공급자의 API 엔드포인트를 HolySheep AI 게이트웨이로 교체합니다. 기존 코드는 다음과 같이 변경됩니다:

# 변경 전 (기존 공급사)
import openai

client = openai.OpenAI(
    api_key="sk-old-provider-xxx",
    base_url="https://api.openai.com/v1"  # ⚠️ 직접 호출
)

response = client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "보험 상담 시작"}]
)
# 변경 후 (HolySheep AI 게이트웨이)
import openai

client = openai.OpenAI(
    api_key="YOUR_HOLYSHEEP_API_KEY",  # HolySheep 단일 키
    base_url="https://api.holysheep.ai/v1"  # ✅ 게이트웨이 경유
)

response = client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "보험 상담 시작"}]
)

print(f"사용량: {response.usage.total_tokens} 토큰")
print(f"모델: {response.model}")  # 실제 호출 모델 확인

Python 외에 다른 언어에서도 동일한 패턴으로 변경 가능합니다:

# JavaScript / Node.js
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: 'YOUR_HOLYSHEEP_API_KEY',
  baseURL: 'https://api.holysheep.ai/v1',  // HolySheep 게이트웨이
});

// 모델 라우팅 자동화 - 비용 최적화
const response = await client.chat.completions.create({
  model: 'gpt-4.1',  // 요청은 gpt-4.1로, 실제 라우팅은 게이트웨이에서 관리
  messages: [{ role: 'user', content: '고객 상담 메시지' }],
  max_tokens: 500
});

console.log('실제 모델:', response.model);
console.log('토큰 사용량:', response.usage.total_tokens);

2단계: HolySheep 대시보드에서 IP 화이트리스트 설정

API 키 발급 후 대시보드에서 IP 접근 제어를 구성합니다. HolySheep AI의 설정은 대시보드의 API KeysIP Restrictions 메뉴에서 관리합니다:

# 허용 IP 설정 예시 (대시보드 또는 API로 설정 가능)

HolySheep AI 대시보드 → API Keys → IP Whitelist

허용 IP 목록 설정

ALLOWED_IPS = [ "211.45.128.0/24", # 회사 본부 网段 "103.75.152.0/22", # GCP 서울 리전 "52.78.0.0/16", # AWS 서울 리전 "10.0.0.0/8", # 내부 사설망 (개발/스테이징) ]

블랙리스트 (특정 IP 차단)

BLOCKED_IPS = [ "185.220.101.0/24", # 알려진 Tor Exit 노드 "45.33.32.0/24", # 의심스러운 범위 ] print(f"✅ {len(ALLOWED_IPS)}개 IP 대역 허용, {len(BLOCKED_IPS)}개 IP 차단")

3단계: 키 로테이션 스크립트

보안을 위해 월 1회 키 로테이션을 자동화합니다:

#!/usr/bin/env python3
"""
HolySheep AI API Key 로테이션 스크립트
Cron: 0 3 1 * * (매월 1일 새벽 3시 실행)
"""
import os
import requests
from datetime import datetime

HOLYSHEEP_API_KEY = os.environ.get("HOLYSHEEP_API_KEY")
BASE_URL = "https://api.holysheep.ai/v1"

def rotate_api_key():
    """기존 키 비활성화 + 새 키 발급"""
    headers = {
        "Authorization": f"Bearer {HOLYSHEEP_API_KEY}",
        "Content-Type": "application/json"
    }

    # 새 API 키 생성
    create_response = requests.post(
        f"{BASE_URL}/keys",
        headers=headers,
        json={
            "name": f"auto-rotated-{datetime.now().strftime('%Y%m')}",
            "allowed_ips": ["211.45.128.0/24", "103.75.152.0/22"],
            "rate_limit": 1000  # 분당 1000 요청 제한
        }
    )

    if create_response.status_code == 201:
        new_key_data = create_response.json()
        new_key = new_key_data["key"]
        print(f"✅ 새 API 키 발급 완료: {new_key[:8]}...")

        # 환경 변수 또는 시크릿 매니저에 새 키 저장
        save_new_key(new_key)
        return new_key

    print(f"❌ 키 생성 실패: {create_response.status_code}")
    return None

def save_new_key(key):
    """새 키를 환경 변수/시크릿 매니저에 저장"""
    # 예: AWS Secrets Manager, GCP Secret Manager 등
    print(f"🔐 새 키를 시크릿 매니저에 저장: {key[:8]}****")

if __name__ == "__main__":
    rotate_api_key()

4단계: 카나리아 배포 (段階적 배포)

전체 트래픽을 한 번에迁移하지 않고 5% → 20% → 100% 카나리아 배포로 안정성을 확보합니다:

# 카나리아 배포 라우팅 로직
import random

class CanaryRouter:
    def __init__(self, canary_percentage=5):
        self.canary_percentage = canary_percentage
        self.holysheep_key = "YOUR_HOLYSHEEP_API_KEY"
        self.old_provider_key = "sk-old-provider-xxx"

    def get_api_key(self):
        roll = random.randint(1, 100)
        if roll <= self.canary_percentage:
            return self.holysheep_key, "holysheep"
        return self.old_provider_key, "old-provider"

    def call_ai(self, user_message):
        api_key, provider = self.get_api_key()

        if provider == "holysheep":
            # HolySheep AI 게이트웨이 경유
            import openai
            client = openai.OpenAI(
                api_key=api_key,
                base_url="https://api.holysheep.ai/v1"
            )
        else:
            # 기존 공급사 (마이그레이션 완료 후 제거)
            import openai
            client = openai.OpenAI(api_key=api_key)

        response = client.chat.completions.create(
            model="gpt-4.1",
            messages=[{"role": "user", "content": user_message}],
            max_tokens=300
        )

        return {
            "provider": provider,
            "response": response.choices[0].message.content,
            "tokens": response.usage.total_tokens
        }

배포 후 모니터링

router = CanaryRouter(canary_percentage=5) result = router.call_ai("보험 상품 문의") print(f"호출 제공자: {result['provider']}") print(f"응답: {result['response'][:50]}...") print(f"토큰: {result['tokens']}")

마이그레이션 후 30일 실측치

지표 마이그레이션 전 마이그레이션 후 (HolySheep AI) 개선율
평균 응답 지연 420ms 180ms ↓ 57%
월간 AI 비용 $4,200 $680 ↓ 84%
API 키 보안 IP 제한 없음 IP 화이트리스트 + CIDR 지원 ✅ 강화
사용 가능 모델 단일 모델 4개 모델 자동 라우팅 ↑ 300%
불법 API 호출 시도 월 12건 (탐지 불가) 0건 (IP 차단으로 원천 격리) ↓ 100%
결제 편의성 해외 신용카드 필수 로컬 결제 지원 ✅大幅 개선

저는 이 마이그레이션 과정에서 특히 IP 화이트리스트 설정이 효과적이었음을 확인했습니다. 설정 직후 기존 공급사 키로 유출된 것 같던 호출 패턴이 HolySheep 게이트웨이에서 전수 차단되었고, 이는 월 $320에 달하던 의심스러운 추가 비용을 완전히 절감한 결과로 이어졌습니다.

HolySheep AI 게이트웨이 IP 제어 아키텍처

HolySheep AI의 IP 기반 접근 제어는 게이트웨이 레벨에서 동작합니다. 모든 API 요청은 HolySheep 게이트웨이(https://api.holysheep.ai/v1)를 경유하며, 요청 발신자의 IP 주소가 화이트리스트/블랙리스트와 자동 비교됩니다:

# HolySheep AI 게이트웨이 요청 흐름

1. 클라이언트 → HolySheheep 게이트웨이 (IP 자동 검증)

Allowed IPs: ["211.45.128.0/24"]

🚫 미등록 IP → 403 Forbidden 즉시 반환

2. 게이트웨이 → 업스트림 AI 모델 (OpenAI, Anthropic, Google 등)

단일 API 키로 모든 모델 호출 가능

3. 응답 → 클라이언트 (지연 측정, 로깅)

holy.sheep.trace_id로 요청 추적 가능

import openai client = openai.OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1", default_headers={ "X-Trace-ID": "insurance-chatbot-prod-001" } )

모델 자동 라우팅 예시 (비용 최적화)

models_config = { "simple_query": "gpt-4.1", "fast_response": "gpt-4.1-mini", "complex_reasoning": "claude-sonnet-4-5", "batch_processing": "deepseek-v3.2" } def get_optimal_model(query_type: str) -> str: return models_config.get(query_type, "gpt-4.1-mini") response = client.chat.completions.create( model=get_optimal_model("simple_query"), messages=[{"role": "user", "content": "보험금 청구 방법"}] ) print(f"모델: {response.model}, 토큰: {response.usage.total_tokens}")

이런 팀에 적합 / 비적합

✅ 이런 팀에 적합

❌ 이런 팀에는 비적합

가격과 ROI

모델 입력 ($/MTok) 출력 ($/MTok) 비교 (OpenAI 직접) 절감율
GPT-4.1 $8.00 $8.00 $15.00 / $60.00 ↓ 47%~87%
Claude Sonnet 4.5 $15.00 $15.00 $18.00 / $90.00 ↓ 17%~83%
Gemini 2.5 Flash $2.50 $2.50 $10.00 / $40.00 ↓ 75%~94%
DeepSeek V3.2 $0.42 $0.42 -$0.90 / $0.90 대량 배치 처리 최적

ROI 계산 (메타버스AI 사례):

왜 HolySheep AI를 선택해야 하나

  1. 로컬 결제 지원: 해외 신용카드 없이 원활한 결제가 가능하여 팀 내에서 직접 비용 관리
  2. 단일 API 키로 4개 모델 통합: GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2를 하나의 키로 관리
  3. IP 화이트리스트/블랙리스트: CIDR 표기법 지원으로 대규모 IP 대역 단위 제어가 가능
  4. 비용 최적화: 직접 호출 대비 최대 94% 절감 (Gemini 2.5 Flash 출력 기준)
  5. 가입 시 무료 크레딧: 실제 비용 부담 없이 즉시 테스트 가능
  6. 간단한 마이그레이션: base_url 교체만으로 기존 코드의 95% 이상 동작

자주 발생하는 오류와 해결책

오류 1: 403 Forbidden - IP不在 화이트리스트

# ❌ 오류 메시지

{

"error": {

"message": "IP address 203.0.113.45 is not allowed.

Please add this IP to your whitelist.",

"type": "invalid_request_error",

"code": "ip_not_allowed"

}

}

✅ 해결: 대시보드에서 IP 추가 또는 임시 전체 허용 후 점진적 축소

HolySheep AI 대시보드 → API Keys → [키 선택] → IP Restrictions

개발 환경에서는 0.0.0.0/0 (모든 IP 허용)으로 시작

프로덕션 배포 시 실제 클라이언트 IP만 화이트리스트에 추가

ALLOWED_IPS_PROD = [ "211.45.128.0/24", # 프로덕션 서버 "103.75.152.0/22", # 클라우드 LB ]

CIDR 표기법으로 간단히 IP 범위 설정

예: 211.45.128.0/24 = 211.45.128.0 ~ 211.45.128.255 (256개 IP)

오류 2: 401 Unauthorized - 잘못된 API Key

# ❌ 오류 메시지

{

"error": {

"message": "Incorrect API key provided.

You passed: sk-***abc.

Did you mean: HolySheep API key?",

"type": "authentication_error"

}

}

✅ 해결: 기존 공급사 키를 HolySheep 키로 교체

1. HolySheep AI 대시보드에서 새 키 발급

2. 환경 변수 확인

import os

환경 변수 설정

export HOLYSHEEP_API_KEY="hsa-xxxxxxxxxxxx"

api_key = os.environ.get("HOLYSHEEP_API_KEY") if not api_key: raise ValueError( "HOLYSHEEP_API_KEY 환경 변수가 설정되지 않았습니다.\n" "https://www.holysheep.ai/register 에서 가입 후 발급하세요." ) client = openai.OpenAI( api_key=api_key, base_url="https://api.holysheep.ai/v1" )

키 유효성 검증

try: response = client.models.list() print(f"✅ HolySheep AI 연결 성공! 사용 가능한 모델 수: {len(response.data)}") except Exception as e: print(f"❌ 연결 실패: {e}")

오류 3: 429 Too Many Requests - Rate Limit 초과

# ❌ 오류 메시지

{

"error": {

"message": "Rate limit exceeded.

Current: 500/min, Limit: 1000/min",

"type": "rate_limit_error",

"retry_after": 30

}

}

✅ 해결: 지수 백오프와 재시도 로직 구현

import time import openai from openai import RateLimitError client = openai.OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" ) def call_with_retry(messages, max_retries=5, base_delay=1.0): """지수 백오프를 적용한 재시도 로직""" for attempt in range(max_retries): try: response = client.chat.completions.create( model="gpt-4.1", messages=messages, max_tokens=500 ) return response except RateLimitError as e: if attempt == max_retries - 1: raise e wait_time = base_delay * (2 ** attempt) print(f"⏳ Rate limit. {wait_time}s 후 재시도 ({attempt + 1}/{max_retries})") time.sleep(wait_time) except Exception as e: print(f"❌ 예상치 못한 오류: {e}") raise e return None

사용 예시

result = call_with_retry([ {"role": "user", "content": "보험 상담"} ]) print(f"응답: {result.choices[0].message.content}")

추가 오류 4: 400 Bad Request - 모델 미인식

# ❌ 오류 메시지

{

"error": {

"message": " model's value must be one of gpt-4.1,

gpt-4.1-mini, claude-sonnet-4-5,

gemini-2.5-flash, deepseek-v3.2",

"type": "invalid_request_error"

}

}

✅ 해결: HolySheep에서 지원하는 모델명으로 변경

import openai client = openai.OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" )

HolySheep AI에서 지원하는 모델 목록

AVAILABLE_MODELS = { "gpt-4.1": "gpt-4.1", "gpt-4.1-mini": "gpt-4.1-mini", "claude-sonnet": "claude-sonnet-4-5", "gemini-flash": "gemini-2.5-flash", "deepseek": "deepseek-v3.2", }

모델 매핑 유틸리티

def resolve_model(model_name: str) -> str: return AVAILABLE_MODELS.get(model_name, "gpt-4.1-mini")

모델 목록 확인

models = client.models.list() supported = [m.id for m in models.data] print(f"지원 모델: {supported}") response = client.chat.completions.create( model=resolve_model("claude-sonnet"), # 매핑 후 호출 messages=[{"role": "user", "content": "테스트"}] )

빠른 시작 체크리스트

  1. HolySheep AI 가입하고 무료 크레딧 받기
  2. 대시보드에서 API 키 발급 + IP 화이트리스트 설정
  3. 기존 코드의 base_urlhttps://api.holysheep.ai/v1로 교체
  4. api_key를 HolySheep 키로 변경
  5. 카나리아 배포(5% 트래픽)로 안정성 검증
  6. 100% 트래픽 전환 후 비용 및 지연 모니터링

IP 화이트리스트와 블랙리스트 설정은 AI API 보안의 기본 중의 기본입니다. HolySheep AI 게이트웨이를 통하면 별도의 네트워크 인프라 구축 없이도 엔터프라이즈급 접근 제어를 손쉽게 적용할 수 있습니다. 서울의 메타버스AI 사례에서 보듯이, 마이그레이션 시간은 단 4시간, 월 비용은 84% 절감, 그리고 API 키 유출 사고는 100% 차단되었습니다.

AI API 비용이 점점 부담이 되가고 계시다면, 지금이 HolySheep AI로 전환할 최적의 시기입니다. 첫 월derrerr derrderr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr derr