DBT 스킬 훈련

弘益人間 (Hongik Ingan) - "널리 인간을 이롭게 하라"
변증법적 행동치료 스킬은 감정 조절, 고통 내성 및 대인관계 효과성을 위한 실용적인 도구를 제공하며, 디지털 전달을 통해 이러한 생명을 변화시키는 스킬에 대한 접근을 확장합니다.

4.1 Mobile-First Architecture

Mobile devices have become the primary computing platform for billions of people worldwide. For many, particularly in developing nations and underserved communities, smartphones are the only internet-connected device they own. A mobile-first approach to digital therapeutics is not just convenient - it's essential for equitable access.

Mobile Platform Statistics

Metric Global Data Implication Design Response
Mobile-Only Internet Users 2.5 billion (31% of global population) No desktop/laptop access Full feature parity on mobile
Avg Daily Phone Usage 3-4 hours High engagement opportunity Microlearning, brief interventions
Push Notification Open Rate 7-10% (mental health apps: 15-20%) Effective for reminders Thoughtful notification strategy
Mobile App Retention (Day 30) 5-10% average, 25-35% for health apps Engagement critical Gamification, progress visualization
Offline Usage Scenarios 40% of time in areas with poor connectivity Offline capability essential Local storage, background sync

React Native Technical Stack

The WIA-MENTAL-001 standard recommends React Native for cross-platform mobile development, enabling a single codebase to serve both iOS and Android while maintaining native performance and UX quality.

// Mobile App Architecture

// Core Dependencies
{
  "dependencies": {
    "react": "18.2.0",
    "react-native": "0.72.0",
    "@react-navigation/native": "^6.1.0",
    "@react-navigation/stack": "^6.3.0",
    
    // State Management
    "@reduxjs/toolkit": "^1.9.5",
    "react-redux": "^8.1.0",
    "redux-persist": "^6.0.0",
    
    // Offline & Sync
    "@react-native-async-storage/async-storage": "^1.19.0",
    "@react-native-community/netinfo": "^9.4.0",
    
    // Security
    "react-native-keychain": "^8.1.0",
    "react-native-encrypted-storage": "^4.0.3",
    
    // Health Integration
    "react-native-health": "^1.19.0",
    "@react-native-community/google-fit": "^0.2.0",
    
    // Notifications
    "@react-native-firebase/messaging": "^18.0.0",
    "@react-native-firebase/analytics": "^18.0.0",
    
    // Media
    "react-native-track-player": "^4.0.0",
    "react-native-video": "^5.2.1",
    
    // Biometrics
    "react-native-biometrics": "^3.0.1"
  }
}

// App Structure
interface MobileApp {
  navigation: NavigationContainer;
  store: ReduxStore;
  
  modules: {
    auth: AuthModule;
    therapy: TherapyModule;
    assessment: AssessmentModule;
    progress: ProgressModule;
    messaging: MessagingModule;
    resources: ResourceModule;
  };
  
  services: {
    api: APIService;
    sync: SyncService;
    notifications: NotificationService;
    health: HealthKitService;
    analytics: AnalyticsService;
  };
}

// Offline-First Data Strategy
class OfflineDataManager {
  private localDB: SQLite.Database;
  private syncQueue: SyncOperation[];
  
  async saveTherapySession(session: TherapySession): Promise {
    // Save locally first
    await this.localDB.execute(
      `INSERT INTO therapy_sessions 
       (id, data, synced) 
       VALUES (?, ?, ?)`,
      [session.id, JSON.stringify(session), false]
    );
    
    // Add to sync queue
    this.syncQueue.push({
      type: 'CREATE',
      entity: 'session',
      data: session,
      timestamp: Date.now()
    });
    
    // Attempt immediate sync if online
    if (await this.isOnline()) {
      await this.syncData();
    }
  }
  
  async syncData(): Promise {
    const online = await this.isOnline();
    if (!online) {
      return { success: false, reason: 'offline' };
    }
    
    const operations = [...this.syncQueue];
    const results = [];
    
    for (const op of operations) {
      try {
        await this.executeSync(op);
        await this.markSynced(op);
        this.syncQueue = this.syncQueue.filter(q => q !== op);
        results.push({ op, success: true });
      } catch (error) {
        results.push({ op, success: false, error });
      }
    }
    
    return {
      success: results.every(r => r.success),
      results
    };
  }
  
  private async isOnline(): Promise {
    const netInfo = await NetInfo.fetch();
    return netInfo.isConnected && netInfo.isInternetReachable;
  }
}

4.2 Unique Mobile Features

Mobile platforms offer unique capabilities that can enhance therapeutic interventions beyond what's possible on desktop web applications.

Mobile-Specific Capabilities

Capability Therapeutic Application Technical Implementation Privacy Considerations
Camera & Photos Mood tracking via facial expressions, photo journaling react-native-camera, ML Kit face detection All processing on-device, no photo uploads
Microphone Voice journaling, speech pattern analysis react-native-audio-recorder-player Encrypted local storage, opt-in only
GPS Location Context-aware prompts, activity tracking react-native-geolocation-service Minimal accuracy, general areas only
Accelerometer Physical activity detection, sleep monitoring react-native-sensors Aggregated data only, no raw sensor logs
Health App Integration Sleep, exercise, heart rate data Apple HealthKit, Google Fit User-controlled permissions
Biometric Auth Face ID/Touch ID for secure access react-native-biometrics Device-level, no biometric data stored

Context-Aware Interventions

// Example: Location-based mindfulness prompts
class ContextAwarePrompts {
  private geofences: Geofence[] = [];
  
  async setupGeofences(userId: string): Promise {
    // User defines helpful reminder locations
    this.geofences = [
      {
        id: 'home',
        latitude: 37.7749,
        longitude: -122.4194,
        radius: 100, // meters
        prompt: 'Taking a moment to practice mindfulness?',
        action: 'breathing-exercise'
      },
      {
        id: 'work',
        latitude: 37.7849,
        longitude: -122.4094,
        radius: 200,
        prompt: 'Stressful day? Try a 3-minute breathing space.',
        action: '3-minute-breathing-space'
      }
    ];
    
    await GeofencingService.register(this.geofences);
  }
  
  async onGeofenceEnter(geofenceId: string): Promise {
    const geofence = this.geofences.find(g => g.id === geofenceId);
    if (!geofence) return;
    
    // Check if user wants notifications right now
    const userPrefs = await this.getUserPreferences();
    const now = new Date();
    const hour = now.getHours();
    
    if (userPrefs.quietHoursEnabled && 
        hour >= userPrefs.quietHoursStart || 
        hour < userPrefs.quietHoursEnd) {
      return; // Skip during quiet hours
    }
    
    // Send contextual notification
    await NotificationService.send({
      title: 'Mindfulness Moment',
      body: geofence.prompt,
      action: geofence.action,
      priority: 'default'
    });
  }
}

// Wearable Integration
interface WearableDataService {
  // Fetch health metrics from connected devices
  async getHeartRateData(
    startDate: Date,
    endDate: Date
  ): Promise;
  
  async getSleepData(
    startDate: Date,
    endDate: Date
  ): Promise;
  
  async getStepsData(
    startDate: Date,
    endDate: Date
  ): Promise;
  
  // Analyze patterns
  analyzeHeartRateVariability(): Promise;
  detectSleepDisturbances(): Promise;
  assessActivityLevel(): Promise;
  
  // Correlate with mental health
  correlateWithMood(
    healthData: HealthMetrics,
    moodData: MoodRating[]
  ): Correlation[];
}

4.3 Real-Time Messaging Architecture

Secure, HIPAA-compliant messaging enables asynchronous communication between patients and therapists, providing a safety net for patients while reducing therapist burden compared to synchronous appointments.

Messaging System Requirements

Messaging Architecture: ═════════════════════════════════ ┌─────────────┐ ┌──────────────┐ │ Patient │◄───────►│ Therapist │ │ Mobile App │ │ Portal │ └──────┬──────┘ └──────┬───────┘ │ │ │ WebSocket (TLS 1.3) │ │ │ ▼ ▼ ┌──────────────────────────────────────┐ │ Message Broker (Redis) │ │ - Real-time delivery │ │ - Presence detection │ │ - Read receipts │ └──────────────┬───────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Message Storage (PostgreSQL) │ │ - End-to-end encrypted │ │ - Audit logs │ │ - Retention policies │ └──────────────┬───────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Crisis Detection AI │ │ - Keyword analysis │ │ - Sentiment analysis │ │ - Suicide risk assessment │ │ - Automatic escalation │ └──────────────────────────────────────┘
interface MessagingService {
  // Send message
  sendMessage(message: MessageData): Promise;
  
  // Retrieve conversation
  getConversation(
    userId: string,
    otherUserId: string,
    pagination: PaginationParams
  ): Promise;
  
  // Real-time subscription
  subscribeToMessages(
    userId: string,
    callback: (message: Message) => void
  ): Subscription;
  
  // Read receipts
  markAsRead(messageId: string): Promise;
  
  // Crisis detection
  analyzeSafetyRisk(content: string): Promise;
  
  // File attachments
  uploadAttachment(file: File): Promise;
}

// End-to-End Encryption Implementation
class E2EEMessaging {
  private userKeyPair: CryptoKeyPair;
  
  async sendEncryptedMessage(
    recipientPublicKey: CryptoKey,
    content: string
  ): Promise {
    // Generate ephemeral symmetric key
    const symmetricKey = await crypto.subtle.generateKey(
      { name: 'AES-GCM', length: 256 },
      true,
      ['encrypt', 'decrypt']
    );
    
    // Encrypt message content
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encryptedContent = await crypto.subtle.encrypt(
      { name: 'AES-GCM', iv },
      symmetricKey,
      new TextEncoder().encode(content)
    );
    
    // Encrypt symmetric key with recipient's public key
    const exportedKey = await crypto.subtle.exportKey('raw', symmetricKey);
    const encryptedKey = await crypto.subtle.encrypt(
      { name: 'RSA-OAEP' },
      recipientPublicKey,
      exportedKey
    );
    
    return {
      encryptedContent: Array.from(new Uint8Array(encryptedContent)),
      encryptedKey: Array.from(new Uint8Array(encryptedKey)),
      iv: Array.from(iv),
      timestamp: Date.now()
    };
  }
  
  async decryptMessage(
    encrypted: EncryptedMessage
  ): Promise {
    // Decrypt symmetric key with private key
    const decryptedKey = await crypto.subtle.decrypt(
      { name: 'RSA-OAEP' },
      this.userKeyPair.privateKey,
      new Uint8Array(encrypted.encryptedKey)
    );
    
    // Import decrypted symmetric key
    const symmetricKey = await crypto.subtle.importKey(
      'raw',
      decryptedKey,
      { name: 'AES-GCM' },
      false,
      ['decrypt']
    );
    
    // Decrypt message content
    const decryptedContent = await crypto.subtle.decrypt(
      { 
        name: 'AES-GCM', 
        iv: new Uint8Array(encrypted.iv) 
      },
      symmetricKey,
      new Uint8Array(encrypted.encryptedContent)
    );
    
    return new TextDecoder().decode(decryptedContent);
  }
}

// Crisis Keyword Detection
class CrisisDetectionService {
  private crisisKeywords = [
    // Direct suicidal ideation
    'kill myself', 'end my life', 'want to die', 
    'suicide', 'suicidal', 'better off dead',
    
    // Self-harm
    'hurt myself', 'cut myself', 'harm myself',
    
    // Plans/methods
    'pills', 'overdose', 'jump off', 'hanging',
    
    // Hopelessness
    'no point', 'cant go on', 'no way out', 'give up'
  ];
  
  async analyzeMessage(content: string): Promise {
    const lowerContent = content.toLowerCase();
    
    // Check for crisis keywords
    const foundKeywords = this.crisisKeywords.filter(
      keyword => lowerContent.includes(keyword)
    );
    
    if (foundKeywords.length === 0) return null;
    
    // Calculate risk level
    let riskLevel: 'low' | 'medium' | 'high' | 'severe';
    if (foundKeywords.length >= 3) riskLevel = 'severe';
    else if (foundKeywords.length >= 2) riskLevel = 'high';
    else riskLevel = 'medium';
    
    // Enhanced analysis with NLP
    const sentiment = await this.analyzeSentiment(content);
    const context = await this.analyzeContext(content);
    
    if (sentiment.score < -0.8 && context.includesPlan) {
      riskLevel = 'severe';
    }
    
    return {
      riskLevel,
      foundKeywords,
      sentiment,
      context,
      timestamp: new Date(),
      requiresImmediateResponse: riskLevel === 'severe' || riskLevel === 'high',
      recommendedActions: this.getRecommendedActions(riskLevel)
    };
  }
  
  private getRecommendedActions(riskLevel: string): string[] {
    switch (riskLevel) {
      case 'severe':
        return [
          'Immediate therapist notification',
          'Emergency services contact information',
          '988 Suicide & Crisis Lifeline display',
          'Safety plan activation',
          'Emergency contact notification (if authorized)'
        ];
      case 'high':
        return [
          'Urgent therapist notification',
          'Crisis resources display',
          'Safety plan review',
          'Check-in scheduling'
        ];
      default:
        return [
          'Therapist notification',
          'Supportive resources',
          'Coping skills reminder'
        ];
    }
  }
}

4.4 Push Notifications Strategy

Thoughtful push notifications can significantly improve engagement and outcomes. However, poorly designed notifications lead to annoyance, app deletion, and reduced trust.

Notification Best Practices

Notification Type Timing Frequency User Control
Practice Reminders User-scheduled (e.g., daily 9am) Once daily max Full customization: time, days, snooze
Session Follow-ups 24 hours after incomplete session One reminder only Can disable per session type
Assessment Reminders Biweekly at user's preferred time Biweekly Can set preferred day/time
Therapist Messages Immediate Per message Cannot disable (clinical safety)
Progress Milestones Upon achievement As earned Can disable celebrations
Crisis Resources When crisis keywords detected Per crisis event Cannot disable (safety)

핵심 요점

복습 질문

  1. Why is React Native chosen for the mobile platform over native iOS/Android development or other cross-platform frameworks?
  2. How does the offline-first data strategy work? Describe the process from local storage through sync to the server.
  3. What are three mobile-specific capabilities that enhance therapeutic interventions, and how would you implement them while preserving privacy?
  4. Explain the end-to-end encryption process for secure messaging. Why is a hybrid approach (symmetric + asymmetric) used?
  5. How does the crisis detection system balance sensitivity and specificity? What are the risks of false positives vs. false negatives?
  6. What makes a push notification strategy effective vs. annoying? How should user control be balanced with clinical recommendations?

한국 의료 인프라 매핑 (제4장)

한국 의료·바이오 인프라 — 보건복지부(MOHW)·식품의약품안전처(MFDS, 식약처)·국민건강보험공단(NHIS)·건강보험심사평가원(HIRA)·통계청(KOSTAT)·국립암센터·국립중앙의료원·국립재활원·6대 병원 (서울대·삼성·아산·세브란스·분당서울대·고려대)·KRIBB(한국생명공학연구원)·KRICT(한국화학연구원)·KFRI(한국식품연구원)·KIST·KAIST·POSTECH 협력. 「의료법」·「약사법」·「생명윤리 및 안전에 관한 법률」·「의료기기법」·「개인정보 보호법」·「국민건강보험법」·「응급의료에 관한 법률」 적용. KS X HL7 FHIR R5·KS X ISO/IEC 25237 (의료 비식별)·KCD-8 (한국표준질병분류)·SNOMED CT·LOINC·ICD-11·OMOP CDM v5.4·CDISC SDTM/ADaM·DICOM·KS X (한국 의료정보 표준) 한국 프로파일이 적용된다.