ACN (자동 충돌 알림) API 코드랩
개요
이 코드랩은 자동 충돌 알림(ACN) API를 구현하는 방법을 안내합니다. 이 API는 차량 사고를 자동으로 감지하고 긴급 대응을 조정합니다. 긴급 상황 처리, 사고 데이터 관리, 구조 서비스 통합 방법을 배우게 됩니다.
사전 요구 사항
- REST API에 대한 기본 이해
- JavaScript/TypeScript 친숙도
- Node.js와 npm 설치
- 긴급 대응 워크플로 이해
- 텍스트 에디터 또는 IDE
학습 목표
- ACN 사고 감지 및 관리 구현
- SSE를 통한 실시간 긴급 알림 처리
- 에이전트 워크플로 및 사고 할당 관리
- 사고 데이터 처리 및 구조 서비스 조정
- 긴급 대응 모범 사례 구현
설정
1. 프로젝트 초기화
mkdir acn-api-demo
cd acn-api-demo
npm init -y
npm install axios node-fetch moment2. 구성
config.js 파일을 생성하세요:
export const API_CONFIG = {
baseURL: 'https://api.ecarus.run/api/v1/safety',
authToken: 'sk_4f9c7b8e2d1a6c0f3e7a9b5d8c1e4f2a7c6d9e0b3f5a8c1d4e7f9b2c6a1e3d',
sampleVIN: 'KMHSH81C7LU123456',
sampleAgentId: 'AGENT_001',
timeout: 10000 // 긴급 서비스용 10초
};단계 1: ACN 시스템 상태 및 모니터링
시스템 건강 모니터링 구현
acnSystem.js를 생성하세요:
import axios from 'axios';
import { API_CONFIG } from './config.js';
class ACNSystem {
constructor() {
this.client = axios.create({
baseURL: API_CONFIG.baseURL,
headers: {
'Authorization': `Bearer ${API_CONFIG.authToken}`,
'Content-Type': 'application/json'
},
timeout: API_CONFIG.timeout
});
}
async getSystemHealth() {
try {
const response = await this.client.get('/acn/system/health');
console.log('ACN 시스템 건강:', response.data);
return response.data;
} catch (error) {
console.error('시스템 건강 가져오기 실패:', error.response?.data || error.message);
throw error;
}
}
async getStatistics() {
try {
const response = await this.client.get('/acn/stats');
console.log('ACN 통계:', response.data);
return response.data;
} catch (error) {
console.error('ACN 통계 가져오기 실패:', error.response?.data || error.message);
throw error;
}
}
isSystemHealthy(healthData) {
return healthData.status === 'HEALTHY' &&
Object.values(healthData.services).every(service => service === 'ACTIVE');
}
getServiceStatus(healthData) {
return {
overall: healthData.status,
services: healthData.services,
metrics: healthData.metrics,
isHealthy: this.isSystemHealthy(healthData)
};
}
}
export default ACNSystem;시스템 모니터링 테스트
test-system.js를 생성하세요:
import ACNSystem from './acnSystem.js';
const acnSystem = new ACNSystem();
async function testSystemMonitoring() {
try {
console.log('🏥 ACN 시스템 모니터링 테스트 중...');
// 시스템 건강 확인
const health = await acnSystem.getSystemHealth();
const status = acnSystem.getServiceStatus(health);
console.log('📊 시스템 상태:', status);
if (status.isHealthy) {
console.log('✅ ACN 시스템이 완전히 운영 중입니다');
} else {
console.log('⚠️ ACN 시스템에 주의가 필요한 문제가 있습니다');
}
// 통계 가져오기
const stats = await acnSystem.getStatistics();
console.log('📈 ACN 통계:', stats);
} catch (error) {
console.error('❌ 시스템 모니터링 테스트 실패:', error.message);
}
}
testSystemMonitoring();단계 2: 사고 관리
사고 제어 구현
incidentManager.js를 생성하세요:
import axios from 'axios';
import { API_CONFIG } from './config.js';
class IncidentManager {
constructor() {
this.client = axios.create({
baseURL: API_CONFIG.baseURL,
headers: {
'Authorization': `Bearer ${API_CONFIG.authToken}`,
'Content-Type': 'application/json'
},
timeout: API_CONFIG.timeout
});
}
async getIncidentStatus(vin, cid) {
try {
const response = await this.client.get(
`/vehicles/${vin}/acn/status`,
{ params: { cid } }
);
console.log('사고 상태:', response.data);
return response.data;
} catch (error) {
console.error('사고 상태 가져오기 실패:', error.response?.data || error.message);
throw error;
}
}
async getIncidentHistory(vin, options = {}) {
try {
const params = {
limit: options.limit || 50,
offset: options.offset || 0,
startDate: options.startDate,
endDate: options.endDate
};
const response = await this.client.get(
`/vehicles/${vin}/acn/history`,
{ params }
);
console.log('사고 기록:', response.data);
return response.data;
} catch (error) {
console.error('사고 기록 가져오기 실패:', error.response?.data || error.message);
throw error;
}
}
async closeIncident(vin, incidentData) {
try {
const payload = {
cid: incidentData.cid,
closureReason: incidentData.closureReason || 'EMERGENCY_SERVICES_DISPATCHED',
result: incidentData.result || 'SUCCESS',
agentId: incidentData.agentId || API_CONFIG.sampleAgentId,
notes: incidentData.notes || ''
};
const response = await this.client.post(
`/vehicles/${vin}/acn/close`,
payload
);
console.log('사고 종료:', response.data);
return response.data;
} catch (error) {
console.error('사고 종료 실패:', error.response?.data || error.message);
throw error;
}
}
formatIncidentLocation(location) {
return {
latitude: location.latitude,
longitude: location.longitude,
accuracy: location.accuracy || 'Unknown',
formatted: `${location.latitude.toFixed(4)}, ${location.longitude.toFixed(4)}`
};
}
assessIncidentSeverity(severity, trigger) {
const severityLevels = {
'LOW': { priority: 3, responseTime: '15 min', color: '🟡' },
'MEDIUM': { priority: 2, responseTime: '10 min', color: '🟠' },
'HIGH': { priority: 1, responseTime: '5 min', color: '🔴' },
'CRITICAL': { priority: 0, responseTime: 'Immediate', color: '🚨' }
};
const triggerSeverity = {
'AIRBAG_DEPLOYMENT': 'HIGH',
'ROLLOVER_DETECTED': 'CRITICAL',
'IMPACT_DETECTED': 'MEDIUM',
'MANUAL_SOS': 'HIGH',
'SOS_BUTTON': 'HIGH'
};
const assessedSeverity = severity || triggerSeverity[trigger] || 'MEDIUM';
return severityLevels[assessedSeverity] || severityLevels['MEDIUM'];
}
}
export default IncidentManager;사고 관리 테스트
test-incident.js를 생성하세요:
import IncidentManager from './incidentManager.js';
import { API_CONFIG } from './config.js';
const incidentManager = new IncidentManager();
async function testIncidentManagement() {
const vin = API_CONFIG.sampleVIN;
const testCid = 'ACN_20260307_001';
try {
console.log('🚨 사고 관리 테스트 중...');
// 사고 상태 가져오기
const status = await incidentManager.getIncidentStatus(vin, testCid);
const severity = incidentManager.assessIncidentSeverity(status.severity, status.trigger);
console.log('📊 사고 평가:', {
cid: status.cid,
severity: severity,
location: incidentManager.formatIncidentLocation(status.location),
rescueStatus: status.rescueStatus
});
// 사고 기록 가져오기
const history = await incidentManager.getIncidentHistory(vin, { limit: 10 });
console.log('📜 사고 기록:', history.incidents.length, '건의 사고 발견');
// 활성 상태인 경우 사고 종료
if (status.status === 'ACTIVE') {
console.log('🔒 사고 종료 중...');
await incidentManager.closeIncident(vin, {
cid: testCid,
closureReason: 'EMERGENCY_SERVICES_DISPATCHED',
result: 'SUCCESS',
notes: '테스트 사고 종료'
});
}
} catch (error) {
console.error('❌ 사고 관리 테스트 실패:', error.message);
}
}
testIncidentManagement();단계 3: 에이전트 워크플로 관리
에이전트 관리 구현
agentManager.js를 생성하세요:
import axios from 'axios';
import { API_CONFIG } from './config.js';
class AgentManager {
constructor() {
this.client = axios.create({
baseURL: API_CONFIG.baseURL,
headers: {
'Authorization': `Bearer ${API_CONFIG.authToken}`,
'Content-Type': 'application/json'
},
timeout: API_CONFIG.timeout
});
}
async getAgentStatus(agentId) {
try {
const response = await this.client.get(`/acn/agents/${agentId}/status`);
console.log('에이전트 상태:', response.data);
return response.data;
} catch (error) {
console.error('에이전트 상태 가져오기 실패:', error.response?.data || error.message);
throw error;
}
}
async getAgentIncidents(agentId, options = {}) {
try {
const params = {
status: options.status,
limit: options.limit || 50,
offset: options.offset || 0
};
const response = await this.client.get(
`/acn/agents/${agentId}/incidents`,
{ params }
);
console.log('에이전트 사고:', response.data);
return response.data;
} catch (error) {
console.error('에이전트 사고 가져오기 실패:', error.response?.data || error.message);
throw error;
}
}
calculateAgentWorkload(agentStatus, agentIncidents) {
const workload = {
currentIncidents: agentStatus.currentIncidents,
totalHandled: agentStatus.totalHandled,
averageHandlingTime: agentStatus.averageHandlingTime,
isActive: agentStatus.status === 'ACTIVE',
capacity: this.calculateCapacity(agentStatus),
efficiency: this.calculateEfficiency(agentStatus, agentIncidents)
};
return workload;
}
calculateCapacity(agentStatus) {
// 현재 사고와 평균 처리 시간을 기반으로 한 간단한 용량 계산
const maxConcurrentIncidents = 3;
const currentLoad = agentStatus.currentIncidents / maxConcurrentIncidents;
if (currentLoad >= 1) return 'FULL';
if (currentLoad >= 0.7) return 'HIGH';
if (currentLoad >= 0.4) return 'MEDIUM';
return 'LOW';
}
calculateEfficiency(agentStatus, agentIncidents) {
// 처리 시간과 성공률을 기반으로 효율성 계산
const avgTime = parseFloat(agentStatus.averageHandlingTime);
const targetTime = 10; // 10분 목표
const timeEfficiency = Math.max(0, Math.min(100, (targetTime / avgTime) * 100));
return {
timeEfficiency: timeEfficiency.toFixed(1),
grade: timeEfficiency >= 90 ? 'A' : timeEfficiency >= 75 ? 'B' : timeEfficiency >= 60 ? 'C' : 'D'
};
}
async assignIncidentToAgent(agentId, incidentId) {
try {
// 일반적으로 내부 API 호출
// 데모 목적으로 할당 시뮬레이션
console.log(`사고 ${incidentId}을(를) 에이전트 ${agentId}에게 할당`);
const assignment = {
agentId,
incidentId,
assignedTime: new Date().toISOString(),
status: 'ASSIGNED'
};
console.log('사고 할당됨:', assignment);
return assignment;
} catch (error) {
console.error('에이전트에게 사고 할당 실패:', error.message);
throw error;
}
}
}
export default AgentManager;에이전트 관리 테스트
test-agent.js를 생성하세요:
import AgentManager from './agentManager.js';
import { API_CONFIG } from './config.js';
const agentManager = new AgentManager();
async function testAgentManagement() {
const agentId = API_CONFIG.sampleAgentId;
try {
console.log('👮 에이전트 관리 테스트 중...');
// 에이전트 상태 가져오기
const status = await agentManager.getAgentStatus(agentId);
// 에이전트 사고 가져오기
const incidents = await agentManager.getAgentIncidents(agentId);
// 워크로드 계산
const workload = agentManager.calculateAgentWorkload(status, incidents);
console.log('📊 에이전트 워크로드 분석:', {
agentId: status.agentId,
status: status.status,
currentIncidents: workload.currentIncidents,
capacity: workload.capacity,
efficiency: workload.efficiency,
totalHandled: workload.totalHandled
});
// 워크로드가 FULL이 아니고 활성 사고가 3개 미만인 경우 사고 할당 시뮬레이션
if (workload.capacity !== 'FULL' && incidents.activeCount < 3) {
await agentManager.assignIncidentToAgent(agentId, 'ACN_TEST_001');
}
} catch (error) {
console.error('❌ 에이전트 관리 테스트 실패:', error.message);
}
}
testAgentManagement();단계 4: 실시간 긴급 알림
ACN용 SSE 클라이언트 구현
acnSSEClient.js를 생성하세요:
export class ACNSSEClient {
constructor(url, authToken) {
this.url = url;
this.authToken = authToken;
this.eventSource = null;
this.listeners = new Map();
this.incidentHandlers = new Map();
}
connect() {
return new Promise((resolve, reject) => {
try {
this.eventSource = new EventSource(this.url, {
headers: {
'Authorization': `Bearer ${this.authToken}`
}
});
this.eventSource.onopen = () => {
console.log('🚨 ACN SSE 연결 열림');
resolve();
};
this.eventSource.onerror = (error) => {
console.error('ACN SSE 연결 오류:', error);
if (this.eventSource.readyState === EventSource.CLOSED) {
reject(new Error('ACN SSE 연결 닫힘'));
}
};
this.eventSource.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
this.handleEvent(data);
} catch (error) {
console.error('ACN SSE 데이터 파싱 실패:', error);
}
};
} catch (error) {
reject(error);
}
});
}
on(eventType, callback) {
if (!this.listeners.has(eventType)) {
this.listeners.set(eventType, []);
}
this.listeners.get(eventType).push(callback);
}
handleEvent(data) {
const eventType = data.type || 'default';
const callbacks = this.listeners.get(eventType) || [];
callbacks.forEach(callback => {
try {
callback(data);
} catch (error) {
console.error('ACN 이벤트 콜백에서 오류:', error);
}
});
// 특정 사고 이벤트 처리
if (eventType === 'INCIDENT_CREATED') {
this.handleIncidentCreated(data);
} else if (eventType === 'INCIDENT_UPDATED') {
this.handleIncidentUpdated(data);
}
}
handleIncidentCreated(data) {
console.log('🚨 새로운 사고 생성됨:', data.data.cid);
const incident = data.data;
const severity = this.assessIncidentSeverity(incident.severity, incident.trigger);
console.log(`📍 위치: ${incident.location.latitude}, ${incident.location.longitude}`);
console.log(`🔥 심각도: ${severity.color} ${incident.severity}`);
console.log(`⚡ 트리거: ${incident.trigger}`);
// 긴급 대응 워크플로 트리거
this.triggerEmergencyWorkflow(incident);
}
handleIncidentUpdated(data) {
console.log('📝 사고 업데이트됨:', data.data.cid);
console.log('상태:', data.data.status);
}
assessIncidentSeverity(severity, trigger) {
const severityLevels = {
'LOW': { priority: 3, responseTime: '15 min', color: '🟡' },
'MEDIUM': { priority: 2, responseTime: '10 min', color: '🟠' },
'HIGH': { priority: 1, responseTime: '5 min', color: '🔴' },
'CRITICAL': { priority: 0, responseTime: 'Immediate', color: '🚨' }
};
const triggerSeverity = {
'AIRBAG_DEPLOYMENT': 'HIGH',
'ROLLOVER_DETECTED': 'CRITICAL',
'IMPACT_DETECTED': 'MEDIUM',
'MANUAL_SOS': 'HIGH',
'SOS_BUTTON': 'HIGH'
};
const assessedSeverity = severity || triggerSeverity[trigger] || 'MEDIUM';
return severityLevels[assessedSeverity] || severityLevels['MEDIUM'];
}
triggerEmergencyWorkflow(incident) {
console.log('🚑 긴급 대응 워크플로 트리거 중...');
// 긴급 대응 단계 시뮬레이션
const workflow = [
{ step: 1, action: '사고 세부 정보 확인', delay: 1000 },
{ step: 2, action: '긴급 서비스에 연락', delay: 2000 },
{ step: 3, action: '구조 팀 파견', delay: 1500 },
{ step: 4, action: '사고 상태 업데이트', delay: 1000 }
];
workflow.forEach(({ step, action, delay }) => {
setTimeout(() => {
console.log(` 단계 ${step}: ${action}`);
}, delay);
});
}
disconnect() {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = null;
console.log('ACN SSE 연결 닫힘');
}
}
}실시간 알림 테스트
test-sse.js를 생성하세요:
import { ACNSSEClient } from './acnSSEClient.js';
import { API_CONFIG } from './config.js';
async function testRealTimeNotifications() {
const sseUrl = `${API_CONFIG.baseURL}/acn/events`;
const sseClient = new ACNSSEClient(sseUrl, API_CONFIG.authToken);
try {
await sseClient.connect();
// 사고 이벤트 수신
sseClient.on('INCIDENT_CREATED', (data) => {
console.log('🚨 새로운 사고 감지:', data.data);
});
sseClient.on('INCIDENT_UPDATED', (data) => {
console.log('📝 사고 업데이트:', data.data);
});
sseClient.on('RESCUE_DISPATCHED', (data) => {
console.log('🚑 구조 파견됨:', data.data);
});
console.log('👂 ACN 이벤트 수신 중... 중지하려면 Ctrl+C를 누르세요');
// 연결 유지
process.on('SIGINT', () => {
console.log('\n연결 해제 중...');
sseClient.disconnect();
process.exit(0);
});
} catch (error) {
console.error('ACN SSE 연결 실패:', error.message);
}
}
testRealTimeNotifications();단계 5: 긴급 대응 조정
긴급 대응 시스템 구현
emergencyResponse.js를 생성하세요:
import IncidentManager from './incidentManager.js';
import AgentManager from './agentManager.js';
class EmergencyResponseSystem {
constructor() {
this.incidentManager = new IncidentManager();
this.agentManager = new AgentManager();
this.activeIncidents = new Map();
this.agentAssignments = new Map();
}
async handleNewIncident(incidentData) {
try {
console.log('🚨 새로운 사고 처리 중:', incidentData.cid);
// 사고 심각도 평가
const severity = this.incidentManager.assessIncidentSeverity(
incidentData.severity,
incidentData.trigger
);
// 사용 가능한 에이전트 찾기
const agentId = await this.findAvailableAgent(severity.priority);
if (agentId) {
// 사고를 에이전트에게 할당
await this.assignIncidentToAgent(incidentData.cid, agentId);
// 긴급 서비스 조정
await this.coordinateEmergencyServices(incidentData, severity);
// 사고 추적
this.activeIncidents.set(incidentData.cid, {
...incidentData,
assignedAgent: agentId,
severity,
status: 'ASSIGNED',
timestamp: new Date().toISOString()
});
console.log(`✅ 사고 ${incidentData.cid}이(가) 에이전트 ${agentId}에게 할당됨`);
} else {
console.log(`⚠️ 사고 ${incidentData.cid}에 사용 가능한 에이전트가 없습니다`);
await this.queueIncident(incidentData);
}
} catch (error) {
console.error('새로운 사고 처리 실패:', error.message);
}
}
async findAvailableAgent(priority) {
try {
// 데모용으로 단순화된 사용 가능한 에이전트 목록
const agents = [API_CONFIG.sampleAgentId];
for (const agentId of agents) {
const status = await this.agentManager.getAgentStatus(agentId);
const incidents = await this.agentManager.getAgentIncidents(agentId);
const workload = this.agentManager.calculateAgentWorkload(status, incidents);
if (workload.isActive && workload.capacity !== 'FULL') {
return agentId;
}
}
return null;
} catch (error) {
console.error('사용 가능한 에이전트 찾기 실패:', error.message);
return null;
}
}
async assignIncidentToAgent(incidentId, agentId) {
try {
await this.agentManager.assignIncidentToAgent(agentId, incidentId);
this.agentAssignments.set(agentId, (this.agentAssignments.get(agentId) || 0) + 1);
} catch (error) {
console.error('에이전트에게 사고 할당 실패:', error.message);
}
}
async coordinateEmergencyServices(incidentData, severity) {
console.log('🚑 긴급 서비스 조정 중...');
const emergencySteps = [
{ service: '경찰', priority: severity.priority <= 1 },
{ service: '소방서', priority: severity.priority <= 2 },
{ service: '의료 서비스', priority: true },
{ service: '견인 서비스', priority: severity.priority <= 2 }
];
for (const { service, priority } of emergencySteps) {
if (priority) {
console.log(`📞 사고 ${incidentData.cid}에 ${service}에 연락 중`);
// 서비스 파견 시뮬레이션
setTimeout(() => {
console.log(`✅ ${service}이(가) 위치: ${incidentData.location.latitude}, ${incidentData.location.longitude}로 파견됨`);
}, Math.random() * 2000 + 1000);
}
}
}
async queueIncident(incidentData) {
console.log(`📋 사고 ${incidentData.cid}을(를) 나중 할당을 위해 대기열에 추가`);
// 구현 시 우선순위 큐에 추가
}
async updateIncidentStatus(incidentId, newStatus, details = {}) {
try {
const incident = this.activeIncidents.get(incidentId);
if (incident) {
incident.status = newStatus;
incident.lastUpdate = new Date().toISOString();
incident.updateDetails = details;
console.log(`📝 사고 ${incidentId} 상태를 ${newStatus}로 업데이트함`);
if (newStatus === 'RESOLVED') {
await this.closeIncident(incidentId);
}
}
} catch (error) {
console.error('사고 상태 업데이트 실패:', error.message);
}
}
async closeIncident(incidentId) {
try {
const incident = this.activeIncidents.get(incidentId);
if (incident) {
await this.incidentManager.closeIncident(incident.vin, {
cid: incidentId,
closureReason: 'EMERGENCY_SERVICES_COMPLETED',
result: 'SUCCESS',
agentId: incident.assignedAgent,
notes: '긴급 대응이 성공적으로 완료되었습니다'
});
// 추적 정리
this.activeIncidents.delete(incidentId);
if (incident.assignedAgent) {
const currentCount = this.agentAssignments.get(incident.assignedAgent) || 0;
this.agentAssignments.set(incident.assignedAgent, Math.max(0, currentCount - 1));
}
console.log(`✅ 사고 ${incidentId}이(가) 성공적으로 종료됨`);
}
} catch (error) {
console.error('사고 종료 실패:', error.message);
}
}
getActiveIncidents() {
return Array.from(this.activeIncidents.values());
}
getAgentWorkload() {
const workload = {};
for (const [agentId, count] of this.agentAssignments) {
workload[agentId] = count;
}
return workload;
}
}
export default EmergencyResponseSystem;단계 6: 완전한 ACN 애플리케이션
완전한 ACN 시스템 생성
acnApp.js를 생성하세요:
import ACNSystem from './acnSystem.js';
import IncidentManager from './incidentManager.js';
import AgentManager from './agentManager.js';
import { ACNSSEClient } from './acnSSEClient.js';
import EmergencyResponseSystem from './emergencyResponse.js';
import { API_CONFIG } from './config.js';
class ACNApplication {
constructor() {
this.acnSystem = new ACNSystem();
this.incidentManager = new IncidentManager();
this.agentManager = new AgentManager();
this.emergencySystem = new EmergencyResponseSystem();
this.sseClient = null;
}
async initialize() {
try {
console.log('🚨 ACN 애플리케이션 초기화 중...');
// 시스템 건강 확인
await this.checkSystemHealth();
// 실시간 이벤트 연결
await this.connectRealTimeEvents();
// 에이전트 모니터링 초기화
await this.initializeAgentMonitoring();
console.log('✅ ACN 애플리케이션이 성공적으로 초기화됨');
} catch (error) {
console.error('❌ ACN 애플리케이션 초기화 실패:', error.message);
}
}
async checkSystemHealth() {
console.log('🏥 ACN 시스템 건강 확인 중...');
const health = await this.acnSystem.getSystemHealth();
const status = this.acnSystem.getServiceStatus(health);
if (status.isHealthy) {
console.log('✅ ACN 시스템이 운영 중입니다');
} else {
console.log('⚠️ ACN 시스템에 문제가 있습니다:');
Object.entries(status.services).forEach(([service, serviceStatus]) => {
if (serviceStatus !== 'ACTIVE') {
console.log(` - ${service}: ${serviceStatus}`);
}
});
}
const stats = await this.acnSystem.getStatistics();
console.log('📊 현재 통계:', stats);
}
async connectRealTimeEvents() {
console.log('👂 실시간 이벤트 연결 중...');
const sseUrl = `${API_CONFIG.baseURL}/acn/events`;
this.sseClient = new ACNSSEClient(sseUrl, API_CONFIG.authToken);
await this.sseClient.connect();
this.sseClient.on('INCIDENT_CREATED', (data) => {
this.handleNewIncident(data.data);
});
this.sseClient.on('INCIDENT_UPDATED', (data) => {
this.handleIncidentUpdate(data.data);
});
}
async initializeAgentMonitoring() {
console.log('👮 에이전트 모니터링 초기화 중...');
const agentId = API_CONFIG.sampleAgentId;
const status = await this.agentManager.getAgentStatus(agentId);
const incidents = await this.agentManager.getAgentIncidents(agentId);
const workload = this.agentManager.calculateAgentWorkload(status, incidents);
console.log('📊 에이전트 상태:', {
agentId: status.agentId,
status: status.status,
currentIncidents: workload.currentIncidents,
capacity: workload.capacity,
efficiency: workload.efficiency
});
}
async handleNewIncident(incidentData) {
console.log('🚨 새로운 사고 처리 중:', incidentData.cid);
try {
// 자세한 사고 정보 가져오기
const vin = incidentData.vin || API_CONFIG.sampleVIN;
const incidentStatus = await this.incidentManager.getIncidentStatus(vin, incidentData.cid);
// 긴급 대응 시스템을 통해 처리
await this.emergencySystem.handleNewIncident(incidentStatus);
// 사고 요약 표시
this.displayIncidentSummary(incidentStatus);
} catch (error) {
console.error('새로운 사고 처리 실패:', error.message);
}
}
async handleIncidentUpdate(incidentData) {
console.log('📝 사고 업데이트 처리 중:', incidentData.cid);
await this.emergencySystem.updateIncidentStatus(
incidentData.cid,
incidentData.status,
incidentData
);
}
displayIncidentSummary(incident) {
const severity = this.incidentManager.assessIncidentSeverity(incident.severity, incident.trigger);
const location = this.incidentManager.formatIncidentLocation(incident.location);
console.log('\n🚨 사고 요약');
console.log('==================');
console.log(`🆔 ID: ${incident.cid}`);
console.log(`🚗 차량: ${incident.vin}`);
console.log(`🔥 심각도: ${severity.color} ${incident.severity}`);
console.log(`⚡ 트리거: ${incident.trigger}`);
console.log(`📍 위치: ${location.formatted}`);
console.log(`🚑 구조 상태: ${incident.rescueStatus}`);
console.log(`⏰ 시간: ${incident.timestamp}`);
if (incident.estimatedArrival) {
console.log(`🕐 ETA: ${incident.estimatedArrival}`);
}
console.log('==================\n');
}
async getSystemStatus() {
console.log('\n📊 ACN 시스템 상태');
console.log('==================');
const activeIncidents = this.emergencySystem.getActiveIncidents();
const agentWorkload = this.emergencySystem.getAgentWorkload();
console.log(`🚨 활성 사고: ${activeIncidents.length}`);
console.log(`👮 에이전트 워크로드:`, agentWorkload);
activeIncidents.forEach(incident => {
console.log(` - ${incident.cid}: ${incident.status} (에이전트: ${incident.assignedAgent})`);
});
console.log('==================\n');
}
async shutdown() {
console.log('🔄 ACN 애플리케이션 종료 중...');
if (this.sseClient) {
this.sseClient.disconnect();
}
console.log('✅ ACN 애플리케이션 종료 완료');
}
}
// 사용 예제
async function main() {
const app = new ACNApplication();
try {
await app.initialize();
// 시스템 상태를 주기적으로 표시
setInterval(async () => {
await app.getSystemStatus();
}, 30000); // 30초마다
// 정상 종료 처리
process.on('SIGINT', async () => {
console.log('\n🔄 SIGINT 수신, 정상 종료 중...');
await app.shutdown();
process.exit(0);
});
console.log('🚨 ACN 애플리케이션이 실행 중입니다... 중지하려면 Ctrl+C를 누르세요');
} catch (error) {
console.error('애플리케이션 오류:', error.message);
process.exit(1);
}
}
main();구현 테스트
완전한 ACN 애플리케이션을 실행하세요:
node acnApp.js예상 출력:
🚨 ACN 애플리케이션 초기화 중...
🏥 ACN 시스템 건강 확인 중...
✅ ACN 시스템이 운영 중입니다
📊 현재 통계: { totalIncidents: 1250, activeIncidents: 3, resolvedToday: 8, averageResponseTime: "4.5 min", successRate: 98.2 }
👂 실시간 이벤트 연결 중...
🚨 ACN SSE 연결 열림
👮 에이전트 모니터링 초기화 중...
📊 에이전트 상태: { agentId: "AGENT_001", status: "ACTIVE", currentIncidents: 2, capacity: "MEDIUM", efficiency: { timeEfficiency: "85.0", grade: "B" } }
✅ ACN 애플리케이션이 성공적으로 초기화됨
🚨 ACN 애플리케이션이 실행 중입니다... 중지하려면 Ctrl+C를 누르세요
🚨 새로운 사고 생성됨: ACN_20260307_002
📍 위치: 37.4021, 127.1023
🔥 심각도: 🔴 HIGH
⚡ 트리거: AIRBAG_DEPLOYMENT
🚑 긴급 대응 워크플로 트리거 중...
단계 1: 사고 세부 정보 확인
단계 2: 긴급 서비스에 연락
단계 3: 구조 팀 파견
단계 4: 사고 상태 업데이트
✅ 사고 ACN_20260307_002이(가) 에이전트 AGENT_001에게 할당됨
🚨 사고 요약
==================
🆔 ID: ACN_20260307_002
🚗 차량: KMHSH81C7LU123456
🔥 심각도: 🔴 HIGH
⚡ 트리거: AIRBAG_DEPLOYMENT
📍 위치: 37.4021, 127.1023
🚑 구조 상태: DISPATCHED
⏰ 시간: 2026-03-07T14:30:00Z
🕐 ETA: 2026-03-07T14:45:00Z
==================챌린지 연습
다중 기관 조정: 서로 다른 응답 프로토콜을 가진 여러 긴급 기관 간 조정을 구현하세요.
예측 분석: 차량 텔레메트리 데이터를 기반으로 사고 심각도를 예측하는 예측 분석을 추가하세요.
모바일 통합: 사용자가 수동으로 SOS를 트리거하고 업데이트를 받을 수 있는 모바일 앱 인터페이스를 생성하세요.
사고 보고: 보험 및 법적 목적을 위한 상세한 사고 보고서를 생성하세요.
지리공간 분석: 사고 핫스팟을 식별하고 구조 자원 배치를 최적화하는 지리공간 분석을 구현하세요.
요약
이 코드랩에서 다음을 배웠습니다:
- ✅ ACN 사고 감지 및 관리 구현
- ✅ SSE를 통한 실시간 긴급 알림 처리
- ✅ 에이전트 워크플로 및 사고 할당 관리
- ✅ 긴급 대응 서비스 조정
- ✅ 완전한 긴급 대응 시스템 구축
ACN API는 차량 사고를 처리하고 긴급 대응을 조정하는 중요한 인프라를 제공합니다. 여기서 배운 구현 패턴은 신뢰성, 실시간 처리, 생명을 구하는 조정을 강조합니다.