10 KiB
10 KiB
콜백 API 가이드
📋 개요
전략 실행 시 callback_url 파라미터를 지정하면, 전략 실행이 완료된 후 해당 URL로 결과를 POST 메서드로 자동 전송합니다.
🚀 사용 방법
1. 기본 사용 예제
curl -X POST http://localhost:8000/strategies/execute/ \
-H "Content-Type: application/json" \
-d '{
"strategy_name": "BoldAssetAllocation",
"parameters": {
"variant": "BAA-G4",
"initial_capital": 100000
},
"callback_url": "https://your-server.com/webhook/strategy-result"
}'
응답:
{
"execution_id": 123,
"status": "pending",
"message": "Strategy execution started",
"callback_url": "https://your-server.com/webhook/strategy-result"
}
2. 콜백 URL 없이 실행 (기존 방식)
curl -X POST http://localhost:8000/strategies/execute/ \
-H "Content-Type: application/json" \
-d '{
"strategy_name": "MovingAverageCrossover",
"parameters": {
"short_window": 20,
"long_window": 50
}
}'
📨 콜백 페이로드
전략 실행이 완료되면 다음과 같은 JSON 데이터가 callback_url로 POST 요청됩니다.
성공 시 (status: completed)
{
"execution_id": 123,
"strategy": "BoldAssetAllocation",
"version": "1.0.0",
"status": "completed",
"started_at": "2025-10-04T12:00:00.000Z",
"completed_at": "2025-10-04T12:00:15.000Z",
"execution_parameters": {
"variant": "BAA-G4",
"initial_capital": 100000,
"use_real_data": false
},
"result": {
"strategy": "BoldAssetAllocation",
"variant": "BAA-G4",
"portfolio": {
"offensive_assets": ["VTI", "VEA"],
"weights": {
"VTI": 0.5,
"VEA": 0.5
}
},
"final_value": 125000,
"return": 0.25
}
}
실패 시 (status: failed)
{
"execution_id": 124,
"strategy": "BoldAssetAllocation",
"version": "1.0.0",
"status": "failed",
"started_at": "2025-10-04T12:05:00.000Z",
"completed_at": "2025-10-04T12:05:02.000Z",
"execution_parameters": {
"variant": "INVALID"
},
"error_message": "Unknown variant: INVALID. Available variants: BAA-G12, BAA-G4, ..."
}
🔍 실행 상태 확인
콜백 전송 정보를 포함한 실행 상태 조회:
curl http://localhost:8000/executions/123/
응답:
{
"execution_id": 123,
"strategy": "BoldAssetAllocation",
"version": "1.0.0",
"status": "completed",
"started_at": "2025-10-04T12:00:00.000Z",
"completed_at": "2025-10-04T12:00:15.000Z",
"execution_parameters": {...},
"result": {...},
"callback": {
"url": "https://your-server.com/webhook/strategy-result",
"sent": true,
"sent_at": "2025-10-04T12:00:15.500Z",
"response": {
"status_code": 200,
"response_text": "{\"status\": \"received\"}",
"headers": {
"Content-Type": "application/json"
}
}
}
}
🛠️ 콜백 서버 구현 예제
Python (Flask)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook/strategy-result', methods=['POST'])
def strategy_callback():
data = request.json
execution_id = data['execution_id']
status = data['status']
if status == 'completed':
result = data['result']
print(f"전략 실행 완료 (ID: {execution_id})")
print(f"최종 수익률: {result.get('return', 0) * 100:.2f}%")
# 결과를 데이터베이스에 저장하거나 다른 처리
# save_to_database(data)
elif status == 'failed':
error_message = data['error_message']
print(f"전략 실행 실패 (ID: {execution_id}): {error_message}")
# 에러 알림 전송
# send_error_notification(data)
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(port=8888)
Node.js (Express)
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook/strategy-result', (req, res) => {
const { execution_id, status, result, error_message } = req.body;
if (status === 'completed') {
console.log(`전략 실행 완료 (ID: ${execution_id})`);
console.log(`최종 수익률: ${(result.return * 100).toFixed(2)}%`);
// 결과 처리
// saveToDatabase(req.body);
} else if (status === 'failed') {
console.error(`전략 실행 실패 (ID: ${execution_id}): ${error_message}`);
// 에러 처리
// sendErrorNotification(req.body);
}
res.json({ status: 'received' });
});
app.listen(8888, () => {
console.log('콜백 서버 시작: http://localhost:8888');
});
Django View
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
import json
@csrf_exempt
def strategy_callback(request):
if request.method == 'POST':
data = json.loads(request.body)
execution_id = data['execution_id']
status = data['status']
if status == 'completed':
# 결과 처리
result = data['result']
print(f"전략 실행 완료: {result}")
elif status == 'failed':
# 에러 처리
error = data['error_message']
print(f"전략 실행 실패: {error}")
return JsonResponse({'status': 'received'})
return JsonResponse({'error': 'Method not allowed'}, status=405)
🧪 테스트 방법
1. 자동 테스트 스크립트 사용
python test_callback.py
이 스크립트는:
- 로컬에 콜백 수신 서버를 자동으로 시작
- 전략 실행 요청 (콜백 URL 포함)
- 콜백 수신 및 결과 출력
2. 수동 테스트
터미널 1 - 콜백 서버:
python -m http.server 8888
터미널 2 - 전략 실행:
curl -X POST http://localhost:8000/strategies/execute/ \
-H "Content-Type: application/json" \
-d '{
"strategy_name": "MovingAverageCrossover",
"parameters": {
"short_window": 10,
"long_window": 30
},
"callback_url": "http://localhost:8888/callback"
}'
3. 외부 테스트 도구
webhook.site 사용:
- https://webhook.site 방문
- 생성된 고유 URL 복사
- 해당 URL을
callback_url로 사용
curl -X POST http://localhost:8000/strategies/execute/ \
-H "Content-Type: application/json" \
-d '{
"strategy_name": "BoldAssetAllocation",
"parameters": {"variant": "BAA-G4"},
"callback_url": "https://webhook.site/your-unique-id"
}'
- webhook.site에서 실시간으로 수신된 데이터 확인
⚙️ 설정 및 동작
콜백 타임아웃
콜백 POST 요청은 10초 타임아웃이 설정되어 있습니다.
재시도 정책
현재 콜백은 1회만 시도합니다. 실패 시 재시도하지 않습니다.
실패 시 callback_response에 에러 정보가 저장됩니다:
{
"callback": {
"url": "https://unavailable.com/webhook",
"sent": false,
"sent_at": null,
"response": {
"error": "Connection refused"
}
}
}
보안 고려사항
- HTTPS 사용 권장: 프로덕션 환경에서는 HTTPS 콜백 URL 사용
- 서명 검증: 콜백 요청의 진위 확인을 위해 서명 메커니즘 고려
- IP 화이트리스트: 알려진 IP에서만 콜백 수신
- Rate Limiting: 과도한 요청 방지
📊 활용 사례
1. Slack 알림
import requests
@app.route('/webhook/strategy-result', methods=['POST'])
def strategy_callback():
data = request.json
if data['status'] == 'completed':
result = data['result']
message = f"✅ 전략 실행 완료\n" \
f"전략: {data['strategy']}\n" \
f"수익률: {result.get('return', 0) * 100:.2f}%"
else:
message = f"❌ 전략 실행 실패\n" \
f"오류: {data['error_message']}"
# Slack Webhook
requests.post(
'https://hooks.slack.com/services/YOUR/WEBHOOK/URL',
json={'text': message}
)
return jsonify({'status': 'ok'})
2. 이메일 전송
from django.core.mail import send_mail
@csrf_exempt
def strategy_callback(request):
data = json.loads(request.body)
if data['status'] == 'completed':
subject = f"전략 실행 완료: {data['strategy']}"
message = f"수익률: {data['result']['return'] * 100:.2f}%"
send_mail(
subject,
message,
'noreply@yoursite.com',
['admin@yoursite.com'],
)
return JsonResponse({'status': 'sent'})
3. 데이터베이스 저장
@csrf_exempt
def strategy_callback(request):
data = json.loads(request.body)
StrategyResult.objects.create(
execution_id=data['execution_id'],
strategy_name=data['strategy'],
status=data['status'],
result=data.get('result'),
error=data.get('error_message'),
completed_at=data.get('completed_at')
)
return JsonResponse({'status': 'saved'})
🐛 문제 해결
콜백이 전송되지 않음
확인사항:
callback_url이 올바른 형식인지 확인- 콜백 서버가 실행 중인지 확인
- 방화벽/보안 그룹 설정 확인
- 실행 상태 API에서
callback.response확인
curl http://localhost:8000/executions/{ID}/ | python -m json.tool
타임아웃 발생
콜백 서버의 응답 시간이 10초를 초과하는 경우:
해결책:
- 콜백 핸들러에서 빠르게 200 응답 후 백그라운드 처리
- 타임아웃 값 조정 필요 시
views.py의timeout=10수정
localhost 콜백이 작동하지 않음
Docker 컨테이너 내부에서 실행 중인 경우:
해결책:
localhost대신 호스트 IP 사용- Docker:
host.docker.internal사용 (Mac/Windows) - ngrok 등으로 로컬 서버 외부 노출
📚 참고
- API 전체 가이드:
API_USAGE_GUIDE.md - BAA 전략 설명:
BAA_STRATEGY_README.md - 배포 가이드:
DEPLOYMENT_GUIDE.md
🔄 업데이트 로그
| 날짜 | 변경 내용 |
|---|---|
| 2025-10-04 | 콜백 기능 최초 구현 |