|
| 1 | +# Emotion 패키지 기술 문서 |
| 2 | + |
| 3 | +## 개요 |
| 4 | +Emotion 패키지는 캠퍼스 게시글의 감정을 AI로 분석하여 실시간 캠퍼스 온도를 계산하고, 게시글 활동도를 함께 반영하여 동적으로 관리하는 고도화된 시스템입니다. |
| 5 | + |
| 6 | +## 주요 기술적 특징 |
| 7 | + |
| 8 | +### 1. GPT-5 기반 배치 감정 분석 시스템 ⭐ |
| 9 | + |
| 10 | +**기술 스택**: OpenAI GPT-5, Batch Processing, Orchestration Pattern |
| 11 | + |
| 12 | +**핵심 구현**: |
| 13 | +```java |
| 14 | +// PostBatchProcessor.java:24-34 |
| 15 | +public Map<String, Integer> processBatchEmotions(List<PostData> posts, BatchEmotionAnalyzer analyzer) { |
| 16 | + if (posts.size() <= MAX_BATCH_SIZE) { |
| 17 | + return analyzer.analyzeSingleBatch(posts); |
| 18 | + } |
| 19 | + return processInChunks(posts, analyzer); // 30개씩 청크 분할 |
| 20 | +} |
| 21 | + |
| 22 | +// EmotionAnalysisService.java:28-35 |
| 23 | +public Map<String, Integer> analyzeBatchEmotions(List<PostData> posts) { |
| 24 | + Map<String, Integer> result = batchProcessor.processBatchEmotions(posts, this); |
| 25 | + return result; // 6가지 감정: 우울함, 밝음, 신남, 화남, 슬픔, 흥분된 |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +**기술적 특징**: |
| 30 | +- **배치 분할 처리**: 30개씩 청크로 나누어 API 호출 최적화 |
| 31 | +- **오케스트레이션 패턴**: 다양한 전문 서비스들을 조합하여 복잡한 감정 분석 프로세스 관리 |
| 32 | +- **Strategy Pattern**: BatchEmotionAnalyzer 인터페이스를 통한 분석 로직 추상화 |
| 33 | + |
| 34 | +### 2. 동적 캠퍼스 온도 관리 시스템 ⭐ |
| 35 | + |
| 36 | +**핵심 알고리즘**: |
| 37 | +```java |
| 38 | +// CampusTemperatureManager.java:71-95 |
| 39 | +private double calculateBidirectionalAdjustment(double currentTemp, int postCount, int hour) { |
| 40 | + // 1. 게시글 활동도 분석 |
| 41 | + PostActivityLevel activityLevel = postActivityAnalyzer.analyzeCurrentActivity(postCount); |
| 42 | + |
| 43 | + // 2. 온도 보호 계수 적용 (극한 온도 방지) |
| 44 | + double protectionFactor = getTemperatureProtectionFactor(currentTemp, activityLevel.isIncreasing()); |
| 45 | + |
| 46 | + // 3. 시간대별 활동 패턴 반영 |
| 47 | + double timeMultiplier = guideline.getIncreaseMultiplier() : guideline.getDecreaseMultiplier(); |
| 48 | + |
| 49 | + // 4. 최종 조정률 계산 |
| 50 | + double finalRate = baseAdjustmentRate * protectionFactor * timeMultiplier; |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +**고급 보호 메커니즘**: |
| 55 | +```java |
| 56 | +// CampusTemperatureManager.java:100-118 |
| 57 | +private double getTemperatureProtectionFactor(double currentTemp, boolean isIncreasing) { |
| 58 | + if (isIncreasing) { |
| 59 | + // 95도 이상: 95% 억제, 90도 이상: 80% 억제 |
| 60 | + if (currentTemp >= 95.0) return 0.05; |
| 61 | + if (currentTemp >= 90.0) return 0.2; |
| 62 | + } else { |
| 63 | + // 2도 이하: 95% 억제, 5도 이하: 80% 억제 |
| 64 | + if (currentTemp <= 2.0) return 0.05; |
| 65 | + if (currentTemp <= 5.0) return 0.2; |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +### 3. 고급 스케줄러 시스템 |
| 71 | + |
| 72 | +**통합 스케줄링 전략**: |
| 73 | +```java |
| 74 | +// EmotionAnalysisScheduler.java:27-38 |
| 75 | +@Scheduled(cron = "0 0 * * * *") // 매시간 정각 |
| 76 | +public void executeHourlyTasks() { |
| 77 | + // 1. 감정 분석 (감정 기반 온도 계산) |
| 78 | + campusEmotionService.analyzeHourlyEmotions(); |
| 79 | + |
| 80 | + // 2. 게시글 활동 기반 온도 조정 |
| 81 | + temperatureManager.adjustHourlyTemperature(); |
| 82 | +} |
| 83 | + |
| 84 | +@Scheduled(cron = "0 30 * * * *") // 매시간 30분 |
| 85 | +public void naturalTemperatureStabilization() { |
| 86 | + temperatureManager.naturalTemperatureRecovery(); // 자연적 온도 회복 |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +**예측 및 보정 시스템**: |
| 91 | +```java |
| 92 | +// EmotionAnalysisScheduler.java:57-64 |
| 93 | +@Scheduled(cron = "0 0 22 * * *") // 매일 밤 10시 |
| 94 | +public void preventiveTemperatureAdjustment() { |
| 95 | + temperatureManager.predictAndAdjustForMorning(); // 다음날 아침 온도 예측 |
| 96 | +} |
| 97 | + |
| 98 | +@Scheduled(cron = "0 0 6 * * *") // 매일 오전 6시 |
| 99 | +public void ensureMorningTemperature() { |
| 100 | + temperatureManager.ensureMinimumMorningTemperature(); // 최저 온도 보장 |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +### 4. 실시간 온도 예측 알고리즘 |
| 105 | + |
| 106 | +**예측 모델**: |
| 107 | +```java |
| 108 | +// CampusTemperatureManager.java:298-327 |
| 109 | +private double predictMorningTemperature() { |
| 110 | + // 현재 시간부터 다음날 6시까지의 예상 변화 계산 |
| 111 | + for (int h = currentHour + 1; h <= 24 + 6; h++) { |
| 112 | + int expectedPosts = postActivityAnalyzer.getExpectedPostsForHour(hour); |
| 113 | + |
| 114 | + if (expectedPosts <= expectedAverage * 0.5) { |
| 115 | + // 활동도 감소 시 온도 하락 예측 |
| 116 | + double reductionRate = level.getAdjustmentRate() * guideline.getDecreaseMultiplier(); |
| 117 | + predictedTemp *= (1 + reductionRate); |
| 118 | + } |
| 119 | + |
| 120 | + // 자연 회복 반영 (7-22시) |
| 121 | + if (hour >= 7 && hour <= 22) { |
| 122 | + predictedTemp += guidelineConfig.getNaturalRecoveryRate(hour) * 0.3; |
| 123 | + } |
| 124 | + } |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +### 5. Redis 기반 실시간 캐싱 전략 |
| 129 | + |
| 130 | +**다층 캐시 구조**: |
| 131 | +```java |
| 132 | +// CampusTemperatureManager.java:37-42 |
| 133 | +private static final String CURRENT_TEMP_KEY = "campus:temperature:current"; |
| 134 | +private static final String BASE_EMOTION_TEMP_KEY = "campus:temperature:base_emotion"; |
| 135 | +private static final String TODAY_MAX_TEMP_KEY = "campus:temperature:today_max"; |
| 136 | +private static final String TODAY_MIN_TEMP_KEY = "campus:temperature:today_min"; |
| 137 | + |
| 138 | +// 실시간 최고/최저 온도 업데이트 |
| 139 | +private void updateTodayMinMaxTemperature(double newTemp) { |
| 140 | + // 현재 최고/최저 온도와 비교하여 실시간 갱신 |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +### 6. 데이터 영속화 및 통계 |
| 145 | + |
| 146 | +**일일 통계 저장**: |
| 147 | +```java |
| 148 | +// CampusTemperatureManager.java:352-394 |
| 149 | +public void saveDailyCampusData() { |
| 150 | + // 어제 온도 통계 계산 |
| 151 | + Object[] minMaxTemp = temperatureRepository.findMaxMinTemperatureByDate(startTime); |
| 152 | + |
| 153 | + // 어제 게시글 통계 |
| 154 | + int totalPosts = contentRepository.countByCreatedAtBetween(startTime, endTime); |
| 155 | + |
| 156 | + // DailyCampus 저장 |
| 157 | + DailyCampus dailyCampus = DailyCampus.builder() |
| 158 | + .date(yesterday) |
| 159 | + .finalTemperature(finalTemp) |
| 160 | + .totalPostCount(totalPosts) |
| 161 | + .maxTemperature(maxTemp) |
| 162 | + .minTemperature(minTemp) |
| 163 | + .build(); |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +## 성능 최적화 포인트 |
| 168 | + |
| 169 | +1. **배치 처리 최적화**: 30개 단위 청크로 API 호출 효율화 |
| 170 | +2. **Redis 캐싱**: 실시간 온도 데이터 30분 TTL 캐싱 |
| 171 | +3. **스케줄링 분산**: 다양한 시간대별 작업 분산으로 서버 부하 최소화 |
| 172 | +4. **예측 알고리즘**: 사전 온도 조정으로 극단적 온도 변화 방지 |
| 173 | + |
| 174 | +## 확장성 고려사항 |
| 175 | + |
| 176 | +- **다중 캠퍼스 지원**: 캠퍼스별 독립적인 온도 관리 시스템 확장 가능 |
| 177 | +- **머신러닝 통합**: 과거 데이터를 활용한 예측 모델 고도화 |
| 178 | +- **실시간 알림**: WebSocket을 통한 온도 변화 실시간 알림 |
| 179 | +- **외부 API 연동**: 실제 날씨 데이터와의 융합 분석 |
| 180 | + |
| 181 | +이 시스템을 통해 단순한 감정 분석을 넘어 **실시간 캠퍼스 분위기의 온도화**와 **예측 기반 동적 관리**를 구현했습니다. |
0 commit comments