Skip to content

Commit fe8d36b

Browse files
committed
refactor: 스케줄러 서비스에서 알림 발송 로직 분리 및 클래스명 개선
1 parent 61f07b8 commit fe8d36b

3 files changed

Lines changed: 78 additions & 62 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.wisoft.prepair.prepair_api.interview.question.service;
2+
3+
import io.wisoft.prepair.prepair_api.external.member.dto.MemberSchedulerInfo;
4+
import io.wisoft.prepair.prepair_api.external.member.enums.Notification;
5+
import io.wisoft.prepair.prepair_api.external.notification.email.EmailService;
6+
import io.wisoft.prepair.prepair_api.external.notification.kakao.KakaoService;
7+
import io.wisoft.prepair.prepair_api.interview.question.entity.InterviewQuestion;
8+
import lombok.RequiredArgsConstructor;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.stereotype.Service;
11+
import org.springframework.web.client.HttpClientErrorException;
12+
13+
@Slf4j
14+
@Service
15+
@RequiredArgsConstructor
16+
public class QuestionNotificationService {
17+
18+
private final EmailService emailService;
19+
private final KakaoService kakaoService;
20+
21+
public void notifyMember(MemberSchedulerInfo member, InterviewQuestion question) {
22+
Notification notification = member.notification();
23+
24+
if (notification == Notification.EMAIL || notification == Notification.BOTH) {
25+
sendEmail(member, question);
26+
}
27+
28+
if (notification == Notification.KAKAO || notification == Notification.BOTH) {
29+
sendKakao(member, question);
30+
}
31+
}
32+
33+
private void sendEmail(MemberSchedulerInfo member, InterviewQuestion question) {
34+
try {
35+
emailService.sendInterviewQuestion(
36+
member.email(),
37+
member.nickname(),
38+
question.getQuestionTag(),
39+
question.getQuestion()
40+
);
41+
log.info("이메일 발송 완료 | memberId={}", member.id());
42+
} catch (Exception e) {
43+
log.error("이메일 발송 실패 | memberId={}", member.id(), e);
44+
}
45+
}
46+
47+
private void sendKakao(MemberSchedulerInfo member, InterviewQuestion question) {
48+
if (!isValidKakaoToken(member)) return;
49+
try {
50+
kakaoService.sendInterviewQuestion(
51+
member.kakaoAccessToken(),
52+
question.getQuestion(),
53+
question.getQuestionTag()
54+
);
55+
log.info("카카오 발송 완료 | memberId={}", member.id());
56+
} catch (HttpClientErrorException.Unauthorized e) {
57+
log.warn("카카오 발송 실패 | memberId={} | reason=token_expired", member.id());
58+
} catch (Exception e) {
59+
log.error("카카오 발송 실패 | memberId={}", member.id(), e);
60+
}
61+
}
62+
63+
private boolean isValidKakaoToken(MemberSchedulerInfo member) {
64+
if (member.kakaoAccessToken() == null || member.kakaoAccessToken().isBlank()) {
65+
log.warn("멤버 스킵 | memberId={} | reason=no_kakao_token", member.id());
66+
return false;
67+
}
68+
return true;
69+
}
70+
71+
}

src/main/java/io/wisoft/prepair/prepair_api/interview/question/service/DailyQuestionGenerationService.java renamed to src/main/java/io/wisoft/prepair/prepair_api/interview/question/service/TodayQuestionService.java

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
package io.wisoft.prepair.prepair_api.interview.question.service;
22

3-
import io.wisoft.prepair.prepair_api.external.member.enums.Notification;
43
import io.wisoft.prepair.prepair_api.external.member.MemberServiceClient;
54
import io.wisoft.prepair.prepair_api.external.member.dto.MemberSchedulerInfo;
65
import io.wisoft.prepair.prepair_api.external.openai.OpenAiClient;
76
import io.wisoft.prepair.prepair_api.external.openai.dto.QuestionWithTags;
8-
import io.wisoft.prepair.prepair_api.external.notification.email.EmailService;
9-
import io.wisoft.prepair.prepair_api.external.notification.kakao.KakaoService;
107
import io.wisoft.prepair.prepair_api.interview.prompt.PromptBuilder;
118
import io.wisoft.prepair.prepair_api.interview.question.entity.InterviewQuestion;
129
import io.wisoft.prepair.prepair_api.interview.question.repository.QuestionRepository;
1310
import lombok.RequiredArgsConstructor;
1411
import lombok.extern.slf4j.Slf4j;
1512
import org.springframework.stereotype.Service;
16-
import org.springframework.web.client.HttpClientErrorException;
1713

1814
import java.time.DayOfWeek;
1915
import java.time.LocalDate;
@@ -23,15 +19,14 @@
2319
@Slf4j
2420
@Service
2521
@RequiredArgsConstructor
26-
public class DailyQuestionGenerationService {
22+
public class TodayQuestionService {
2723

28-
private final QuestionRepository questionRepository;
2924
private final QuestionPersistenceService interviewQuestionService;
25+
private final QuestionNotificationService questionNotificationService;
26+
private final QuestionRepository questionRepository;
3027
private final MemberServiceClient memberServiceClient;
3128
private final OpenAiClient openAiClient;
3229
private final PromptBuilder promptBuilder;
33-
private final EmailService emailService;
34-
private final KakaoService kakaoService;
3530

3631
public void generateTodayQuestions() {
3732
List<MemberSchedulerInfo> members = memberServiceClient.getMembers();
@@ -58,68 +53,19 @@ private void processTodayQuestion(MemberSchedulerInfo member) {
5853
InterviewQuestion question = interviewQuestionService.saveTodayQuestion(member.id(), result);
5954
log.info("질문 저장 완료 | memberId={}", member.id());
6055

61-
notifyMember(member, question);
56+
questionNotificationService.notifyMember(member, question);
6257
} catch (Exception e) {
6358
log.error("질문 처리 실패 | memberId={}", member.id(), e);
6459
}
6560
}
6661

67-
private void notifyMember(MemberSchedulerInfo member, InterviewQuestion question) {
68-
Notification notification = member.notification();
69-
70-
if (notification == Notification.EMAIL || notification == Notification.BOTH) {
71-
sendEmail(member, question);
72-
}
73-
74-
if (notification == Notification.KAKAO || notification == Notification.BOTH) {
75-
sendKakao(member, question);
76-
}
77-
}
78-
79-
private void sendEmail(MemberSchedulerInfo member, InterviewQuestion question) {
80-
try {
81-
emailService.sendInterviewQuestion(
82-
member.email(),
83-
member.nickname(),
84-
question.getQuestionTag(),
85-
question.getQuestion()
86-
);
87-
log.info("이메일 발송 완료 | memberId={}", member.id());
88-
} catch (Exception e) {
89-
log.error("이메일 발송 실패 | memberId={}", member.id(), e);
90-
}
91-
}
92-
93-
private void sendKakao(MemberSchedulerInfo member, InterviewQuestion question) {
94-
if (!isValidKakaoToken(member)) return;
95-
try {
96-
kakaoService.sendInterviewQuestion(
97-
member.kakaoAccessToken(),
98-
question.getQuestion(),
99-
question.getQuestionTag()
100-
);
101-
log.info("카카오 발송 완료 | memberId={}", member.id());
102-
} catch (HttpClientErrorException.Unauthorized e) {
103-
log.warn("카카오 발송 실패 | memberId={} | reason=token_expired", member.id());
104-
} catch (Exception e) {
105-
log.error("카카오 발송 실패 | memberId={}", member.id(), e);
106-
}
107-
}
108-
10962
private boolean shouldSendToday(MemberSchedulerInfo member, DayOfWeek today) {
11063
return switch (member.frequency()) {
11164
case EVERY -> true;
11265
case WEEKLY -> today == DayOfWeek.MONDAY;
11366
};
11467
}
11568

116-
private boolean isValidKakaoToken(MemberSchedulerInfo member) {
117-
if (member.kakaoAccessToken() == null || member.kakaoAccessToken().isBlank()) {
118-
log.warn("멤버 스킵 | memberId={} | reason=no_kakao_token", member.id());
119-
return false;
120-
}
121-
return true;
122-
}
12369

12470
private boolean isValidNotification(MemberSchedulerInfo member) {
12571
if (member.notification() == null) {
@@ -144,5 +90,4 @@ private boolean isValidJob(MemberSchedulerInfo member) {
14490
}
14591
return true;
14692
}
147-
14893
}

src/main/java/io/wisoft/prepair/prepair_api/scheduler/TodayQuestionScheduler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.wisoft.prepair.prepair_api.scheduler;
22

3-
import io.wisoft.prepair.prepair_api.interview.question.service.DailyQuestionGenerationService;
3+
import io.wisoft.prepair.prepair_api.interview.question.service.TodayQuestionService;
44
import lombok.RequiredArgsConstructor;
55
import lombok.extern.slf4j.Slf4j;
66
import org.slf4j.MDC;
@@ -15,15 +15,15 @@
1515
@RequiredArgsConstructor
1616
public class TodayQuestionScheduler {
1717

18-
private final DailyQuestionGenerationService dailyQuestionGenerationService;
18+
private final TodayQuestionService todayQuestionService;
1919

2020
@Scheduled(cron = "0 0 9 * * *")
2121
public void generateTodayQuestions() {
2222
String correlationId = "SCHEDULER-" + UUID.randomUUID().toString();
2323
MDC.put("correlationId", correlationId);
2424
try {
2525
log.info("오늘의 질문 생성 스케줄러 시작 - {}", LocalDateTime.now());
26-
dailyQuestionGenerationService.generateTodayQuestions();
26+
todayQuestionService.generateTodayQuestions();
2727
log.info("오늘의 질문 생성 스케줄러 종료");
2828
} finally {
2929
MDC.remove("correlationId");

0 commit comments

Comments
 (0)