Redis를 사용해 슬랙 사용자의 활동을 추적하는 서비스 생성
주요 필드
- KEY_PREFIX = "activity:" -> Redis 키 접두사
- ttlHours = 4 -> 데이터 자동 삭제 시간(4시간)
- redisTemplate -> Redis 작업용
- objectMapper -> Java, JSON 변환
recordActivity(userId, channelId)
/**
* 사용자 활동 기록 -> 메시지 받을 때 마다 실행
* @param userId 사용자 ID
* @param channelId 채널 ID
*/
public void recordActivity(String userId, String channelId) {
String key = createKey(channelId, userId);
try {
UserActivity activity = getUserActivity(userId, channelId)
.orElse(new UserActivity(userId, channelId));
activity.updateActivity(); // 활동 시간 업데이트
// Redis에 JSON으로 저장
String json = objectMapper.writeValueAsString(activity);
redisTemplate.opsForValue().set(key, json);
// TTL 설정 - ttlHours 시간 후 자동 삭제
redisTemplate.expire(key, ttlHours, TimeUnit.HOURS);
logger.debug("활동 기록 - User: {}, Channel: {}, TTL: {}h",
userId, channelId, ttlHours);
} catch(JsonProcessingException e) {
logger.error("활동 기록 실패 - JSON 직렬화 오류", e);
throw new RuntimeException("활동 기록 실패", e);
}
}
-> Redis에서 기존 데이터 조회
-> lastActivityTime을 현재 시간으로 업데이트
-> JSON 변환 후 Redis 저장
-> TTL은 4시간으로 설정
findAllAbsentUsers(absenceHours) : 우선 2분 설정
/**
* 모든 채널에서 지정 시간 이상 부재한 사용자 찾기
*/
public List<UserActivity> findAllAbsentUsers(int absenceHours) {
String pattern = KEY_PREFIX + "*";
Set<String> keys = redisTemplate.keys(pattern);
if (keys == null || keys.isEmpty()) {
return Collections.emptyList();
}
return getActivitiesByKeys(keys).stream()
.filter(activity -> activity.isAbsentForMinutes(2)) // TODO : 테스트용 2분 설정
// .filter(activity -> activity.isAbsentForHours(absenceHours))
.collect(Collectors.toList());
}
-> 스케줄러가 1분마다 실행하며 호출 중
updateActivity(activity)
public void updateActivity(UserActivity activity) {
String key = KEY_PREFIX + activity.getChannelId() + ":" + activity.getUserId();
try {
String json = objectMapper.writeValueAsString(activity);
redisTemplate.opsForValue().set(key, json);
logger.info("활동 업데이트 완료 - User: {}, Channel: {}",
activity.getUserId(), activity.getChannelId());
} catch (JsonProcessingException e) {
logger.error("활동 업데이트 실패", e);
}
}
-> UserActivity 객체 Redis에 업데이트
-> absent 상태 true로
전체 흐름 정리
1. 메시지 전송
-> recordActivity()
-> Redis에 저장
2. 스케줄러(1분마다)
-> findAllAbsentUsers(2)
3. DM 전송 후
-> activity.setAbsent(true)
-> Reids 업데이트(absent : true)
테스트 : 사용자 부재 감지 기준을 2분으로 설정해두고, 디엠 전송이 제대로 동작하는지 확인
12:37 메시지 전송

2분 부재 후 DM 전송된 것 확인

DM 전송 보다는 채널에 봇이 메시지를 전달하는 것이 더 자연스러울 것 같아 수정
* TODO : "2분 부재중이십니당 !" 메시지 대신, open AI의 요약본 전달

레디스 접속

레디스에 저장된 값 확인
absent : false -> DM 전송 후 -> absent : true로 업데이트

'Projects' 카테고리의 다른 글
| [Slack AI Bot] 사용자 부재 이벤트 감지 방법 -> Redis? (1) | 2025.11.30 |
|---|---|
| [Slack AI Bot] 슬랙 메시지 수집 & 디엠 전송 기능 점검 (0) | 2025.11.23 |
| [Slack AI Bot] ngrok으로 로컬 서버 외부 노출 (0) | 2025.11.23 |
| [Slack AI Bot] Slack 애플리케이션 설정 (0) | 2025.11.23 |
| [Slack AI Bot] 스프링 부트 CI/CD 파이프라인 구축 (0) | 2025.11.18 |