8.1 WIA-PET-009 표준 개요
WIA-PET-009는 반려동물 영양 데이터의 표준화된 교환을 위한 국제 표준입니다. 이 장에서는 표준의 구조, 데이터 모델, API 사양, 그리고 실제 구현 방법을 다룹니다.
8.1.1 표준의 목적
- 반려동물 영양 데이터의 상호운용성 확보
- 사료 제조업체, 수의사, 반려동물 보호자 간 정보 교환 표준화
- 급여 계산 및 영양 추적 시스템의 호환성
- 국제적으로 통일된 영양 데이터 형식 제공
8.1.2 표준 구성요소
- 데이터 모델: JSON Schema 기반 영양 데이터 구조
- API 사양: RESTful API 엔드포인트 정의
- 계산 알고리즘: 에너지 요구량 및 급여량 계산
- 검증 규칙: 데이터 유효성 검사 기준
8.2 데이터 모델
8.2.1 반려동물 프로파일
{
"$schema": "https://wia.org/schemas/pet-009/pet-profile.json",
"type": "object",
"required": ["id", "species", "name", "birthDate", "weight"],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "고유 식별자"
},
"species": {
"type": "string",
"enum": ["dog", "cat", "bird", "rabbit", "ferret", "reptile", "other"],
"description": "동물 종"
},
"breed": {
"type": "string",
"description": "품종"
},
"name": {
"type": "string",
"description": "반려동물 이름"
},
"birthDate": {
"type": "string",
"format": "date",
"description": "출생일 (YYYY-MM-DD)"
},
"weight": {
"type": "object",
"properties": {
"value": {"type": "number", "minimum": 0},
"unit": {"type": "string", "enum": ["kg", "lb"]},
"measuredAt": {"type": "string", "format": "date-time"}
}
},
"sex": {
"type": "string",
"enum": ["male", "female", "neutered_male", "spayed_female", "unknown"]
},
"activityLevel": {
"type": "string",
"enum": ["sedentary", "normal", "active", "working", "athletic"]
},
"bodyConditionScore": {
"type": "integer",
"minimum": 1,
"maximum": 9
},
"healthConditions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"condition": {"type": "string"},
"diagnosedDate": {"type": "string", "format": "date"},
"severity": {"type": "string", "enum": ["mild", "moderate", "severe"]}
}
}
},
"allergies": {
"type": "array",
"items": {"type": "string"}
}
}
}
8.2.2 사료 제품 스키마
{
"$schema": "https://wia.org/schemas/pet-009/food-product.json",
"type": "object",
"required": ["id", "name", "manufacturer", "targetSpecies", "guaranteedAnalysis"],
"properties": {
"id": {
"type": "string",
"description": "제품 고유 식별자 (UPC/EAN 또는 내부 ID)"
},
"name": {
"type": "string"
},
"manufacturer": {
"type": "object",
"properties": {
"name": {"type": "string"},
"country": {"type": "string", "format": "iso-3166-1-alpha-2"}
}
},
"productType": {
"type": "string",
"enum": ["dry", "wet", "semi-moist", "freeze-dried", "raw", "treat", "supplement"]
},
"targetSpecies": {
"type": "array",
"items": {"type": "string", "enum": ["dog", "cat", "bird", "rabbit", "other"]}
},
"lifeStage": {
"type": "array",
"items": {"type": "string", "enum": ["puppy", "kitten", "adult", "senior", "all"]}
},
"ingredients": {
"type": "array",
"description": "중량 내림차순",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"aafcoDefinition": {"type": "string"},
"percentage": {"type": "number", "description": "선택적"}
}
}
},
"guaranteedAnalysis": {
"type": "object",
"properties": {
"basis": {"type": "string", "enum": ["as_fed", "dry_matter"]},
"crudeProtein": {"$ref": "#/definitions/nutrientRange"},
"crudeFat": {"$ref": "#/definitions/nutrientRange"},
"crudeFiber": {"$ref": "#/definitions/nutrientRange"},
"moisture": {"$ref": "#/definitions/nutrientRange"},
"ash": {"$ref": "#/definitions/nutrientRange"},
"calcium": {"$ref": "#/definitions/nutrientRange"},
"phosphorus": {"$ref": "#/definitions/nutrientRange"},
"omega6": {"$ref": "#/definitions/nutrientRange"},
"omega3": {"$ref": "#/definitions/nutrientRange"},
"taurine": {"$ref": "#/definitions/nutrientRange"}
}
},
"metabolizableEnergy": {
"type": "object",
"properties": {
"value": {"type": "number"},
"unit": {"type": "string", "enum": ["kcal/kg", "kJ/kg", "kcal/cup"]}
}
},
"feedingGuidelines": {
"type": "array",
"items": {
"type": "object",
"properties": {
"weightRange": {
"type": "object",
"properties": {
"min": {"type": "number"},
"max": {"type": "number"},
"unit": {"type": "string"}
}
},
"dailyAmount": {
"type": "object",
"properties": {
"min": {"type": "number"},
"max": {"type": "number"},
"unit": {"type": "string", "enum": ["g", "cup", "oz"]}
}
}
}
}
}
},
"definitions": {
"nutrientRange": {
"type": "object",
"properties": {
"min": {"type": "number"},
"max": {"type": "number"},
"typical": {"type": "number"},
"unit": {"type": "string"}
}
}
}
}
8.3 API 사양
8.3.1 엔드포인트 정의
// WIA-PET-009 REST API 엔드포인트
// 반려동물 관리
GET /api/v1/pets # 반려동물 목록
POST /api/v1/pets # 반려동물 등록
GET /api/v1/pets/{id} # 반려동물 상세
PUT /api/v1/pets/{id} # 반려동물 수정
DELETE /api/v1/pets/{id} # 반려동물 삭제
// 체중 기록
POST /api/v1/pets/{id}/weights # 체중 기록 추가
GET /api/v1/pets/{id}/weights # 체중 이력 조회
// 급여 계산
POST /api/v1/calculate/energy # 에너지 요구량 계산
POST /api/v1/calculate/feeding # 급여량 계산
// 사료 제품
GET /api/v1/products # 사료 제품 검색
GET /api/v1/products/{id} # 사료 제품 상세
POST /api/v1/products/compare # 제품 비교
// 영양 분석
POST /api/v1/analyze/diet # 식단 영양 분석
GET /api/v1/nutrients/requirements # 영양 요구량 조회
8.3.2 에너지 계산 API
// POST /api/v1/calculate/energy
// Request
{
"species": "dog",
"weight_kg": 15,
"age_months": 36,
"sex": "neutered_male",
"activityLevel": "normal",
"bodyConditionScore": 5,
"healthConditions": []
}
// Response
{
"success": true,
"data": {
"RER_kcal": 534,
"activityFactor": 1.6,
"adjustmentFactors": [],
"DER_kcal": 854,
"confidence": "high",
"notes": [
"중성화된 성견 기준 계산",
"이상적인 체형 상태 유지 권장"
],
"calculationMethod": "NRC_2006",
"timestamp": "2024-08-15T10:30:00Z"
}
}
8.3.3 급여량 계산 API
// POST /api/v1/calculate/feeding
// Request
{
"petId": "pet-uuid-123",
"productId": "product-456",
"DER_kcal": 854
}
// Response
{
"success": true,
"data": {
"product": {
"name": "프리미엄 성견 사료",
"energyDensity_kcal_per_kg": 3600
},
"dailyAmount": {
"grams": 237,
"cups": 2.4,
"cupSize_g": 100
},
"mealsPerDay": 2,
"perMealAmount": {
"grams": 119,
"cups": 1.2
},
"adjustmentRecommendations": [
"2주 후 체중 확인 권장",
"BCS 변화에 따라 10% 범위 내 조정"
]
}
}
8.4 TypeScript SDK 구현
8.4.1 SDK 설치 및 초기화
// npm install @wia/pet-nutrition-sdk
import { WiaPetNutrition, Pet, FoodProduct } from '@wia/pet-nutrition-sdk';
// SDK 초기화
const wia = new WiaPetNutrition({
apiKey: 'your-api-key',
region: 'asia-northeast3', // 한국
language: 'ko'
});
// 반려동물 등록
const pet: Pet = await wia.pets.create({
species: 'dog',
name: '멍멍이',
breed: '골든 리트리버',
birthDate: '2021-03-15',
weight: { value: 28, unit: 'kg' },
sex: 'neutered_male',
activityLevel: 'normal',
bodyConditionScore: 5
});
console.log(`등록된 반려동물 ID: ${pet.id}`);
8.4.2 에너지 및 급여량 계산
// 에너지 요구량 계산
const energy = await wia.calculate.energy({
species: pet.species,
weight_kg: pet.weight.value,
age_months: wia.utils.calculateAgeMonths(pet.birthDate),
sex: pet.sex,
activityLevel: pet.activityLevel,
bodyConditionScore: pet.bodyConditionScore
});
console.log(`RER: ${energy.RER_kcal} kcal`);
console.log(`DER: ${energy.DER_kcal} kcal`);
// 사료 검색
const products = await wia.products.search({
species: 'dog',
lifeStage: 'adult',
productType: 'dry',
limit: 10
});
// 급여량 계산
const feeding = await wia.calculate.feeding({
petId: pet.id,
productId: products[0].id,
DER_kcal: energy.DER_kcal
});
console.log(`일일 급여량: ${feeding.dailyAmount.grams}g`);
console.log(`1회 급여량: ${feeding.perMealAmount.grams}g (${feeding.mealsPerDay}회/일)`);
8.4.3 체중 추적
// 체중 기록 추가
await wia.pets.addWeight(pet.id, {
value: 27.5,
unit: 'kg',
measuredAt: new Date().toISOString()
});
// 체중 이력 조회
const weightHistory = await wia.pets.getWeights(pet.id, {
startDate: '2024-01-01',
endDate: '2024-08-15'
});
// 체중 변화 분석
const analysis = wia.utils.analyzeWeightTrend(weightHistory);
console.log(`체중 변화: ${analysis.changePercent}%`);
console.log(`트렌드: ${analysis.trend}`); // 'stable' | 'gaining' | 'losing'
8.5 데이터 검증
8.5.1 유효성 검사 규칙
// WIA-PET-009 검증 규칙
const validationRules = {
pet: {
weight: {
dog: { min: 0.5, max: 120, unit: 'kg' },
cat: { min: 0.5, max: 15, unit: 'kg' }
},
bodyConditionScore: { min: 1, max: 9 },
age: { min: 0, max: 300, unit: 'months' }
},
product: {
guaranteedAnalysis: {
crudeProtein: { min: 0, max: 100, unit: '%' },
crudeFat: { min: 0, max: 50, unit: '%' },
crudeFiber: { min: 0, max: 30, unit: '%' },
moisture: { min: 0, max: 90, unit: '%' }
},
energyDensity: {
dry: { min: 2500, max: 5000, unit: 'kcal/kg' },
wet: { min: 500, max: 1500, unit: 'kcal/kg' }
}
},
calculation: {
RER: { min: 30, max: 10000, unit: 'kcal' },
activityFactor: { min: 0.5, max: 10 }
}
};
8.5.2 오류 처리
import { WiaError, ValidationError, NotFoundError } from '@wia/pet-nutrition-sdk';
try {
const result = await wia.calculate.feeding({
petId: 'invalid-id',
productId: 'product-123'
});
} catch (error) {
if (error instanceof ValidationError) {
console.error('유효성 검사 실패:', error.details);
} else if (error instanceof NotFoundError) {
console.error('리소스를 찾을 수 없음:', error.message);
} else if (error instanceof WiaError) {
console.error('WIA API 오류:', error.code, error.message);
}
}
8.6 구현 모범 사례
8.6.1 데이터 동기화
- 체중 데이터는 최소 2주마다 업데이트
- BCS 평가는 월 1회 권장
- 급여량 재계산은 체중 변화 5% 이상 시
8.6.2 보안 고려사항
- API 키는 환경 변수로 관리
- 개인 정보(보호자 정보) 최소 수집
- 데이터 전송 시 TLS 1.3 사용
- 민감 데이터 암호화 저장
8.6.3 성능 최적화
// 배치 처리로 API 호출 최소화
const petIds = ['pet-1', 'pet-2', 'pet-3'];
const results = await wia.calculate.energyBatch(
petIds.map(id => ({ petId: id }))
);
// 캐싱 활용
const cachedProduct = await wia.products.get('product-id', {
cache: true,
maxAge: 3600 // 1시간
});
8.7 인증 및 준수
8.7.1 WIA 인증 프로그램
- WIA-PET-009 Compliant: 기본 데이터 형식 준수
- WIA-PET-009 Certified: API 호환성 검증 완료
- WIA-PET-009 Premium: 고급 기능 및 분석 지원
8.7.2 준수 검증
// 준수 검증 도구 사용
import { WiaValidator } from '@wia/pet-nutrition-sdk/validator';
const validator = new WiaValidator();
// 데이터 스키마 검증
const petValidation = validator.validatePet(petData);
if (!petValidation.valid) {
console.error('검증 실패:', petValidation.errors);
}
// API 응답 검증
const apiValidation = validator.validateApiResponse(response, 'energy');
console.log('API 응답 준수:', apiValidation.compliant);