66import com .project .InsightPrep .domain .question .dto .response .QuestionResponse .QuestionDto ;
77import com .project .InsightPrep .domain .question .dto .response .QuestionResponse .QuestionsDto ;
88import com .project .InsightPrep .domain .question .entity .AnswerStatus ;
9+ import com .project .InsightPrep .domain .question .entity .ItemType ;
910import com .project .InsightPrep .domain .question .entity .Question ;
1011import com .project .InsightPrep .domain .question .mapper .AnswerMapper ;
1112import com .project .InsightPrep .domain .question .mapper .QuestionMapper ;
1213import com .project .InsightPrep .domain .question .service .QuestionService ;
14+ import com .project .InsightPrep .domain .question .service .RecentPromptFilterService ;
1315import com .project .InsightPrep .global .auth .util .SecurityUtil ;
16+ import com .project .InsightPrep .global .gpt .dto .response .GptMessage ;
1417import com .project .InsightPrep .global .gpt .prompt .PromptFactory ;
1518import com .project .InsightPrep .global .gpt .service .GptResponseType ;
1619import com .project .InsightPrep .global .gpt .service .GptService ;
@@ -28,13 +31,26 @@ public class QuestionServiceImpl implements QuestionService {
2831 private final GptService gptService ;
2932 private final QuestionMapper questionMapper ;
3033 private final AnswerMapper answerMapper ;
34+ private final RecentPromptFilterService recentPromptFilterService ;
3135 private final SecurityUtil securityUtil ;
3236
3337 @ Override
3438 @ Transactional
3539 public QuestionDto createQuestion (String category ) {
36- GptQuestion gptQuestion = gptService .callOpenAI (PromptFactory .forQuestionGeneration (category ), 1000 , 0.6 , GptResponseType .QUESTION );
40+ long memberId = securityUtil .getLoginMemberId ();
41+ // 1) 최근 금지 주제/키워드 조회 (없을 수 있음)
42+ List <String > bannedTopics = recentPromptFilterService .getRecent (memberId , category , ItemType .TOPIC , 10 );
43+ List <String > bannedKeywords = recentPromptFilterService .getRecent (memberId , category , ItemType .KEYWORD , 10 );
44+
45+ // 2) 프롬프트 선택 (있으면 주입, 없으면 기본)
46+ List <GptMessage > prompt = (hasAny (bannedTopics , bannedKeywords ))
47+ ? PromptFactory .forQuestionGeneration (category , bannedTopics , bannedKeywords )
48+ : PromptFactory .forQuestionGeneration (category );
3749
50+ // 3) 호출
51+ GptQuestion gptQuestion = gptService .callOpenAI (prompt , 1000 , 0.6 , GptResponseType .QUESTION );
52+
53+ // 4) DB에 저장
3854 Question question = Question .builder ()
3955 .category (category )
4056 .content (gptQuestion .getQuestion ())
@@ -43,6 +59,14 @@ public QuestionDto createQuestion(String category) {
4359
4460 questionMapper .insertQuestion (question );
4561
62+ // 5) 기록 (Redis + DB) - 응답에 topic/keyword가 비어있을 수도 있으므로 방어
63+ if (isNotBlank (gptQuestion .getTopic ())) {
64+ recentPromptFilterService .record (memberId , category , ItemType .TOPIC , gptQuestion .getTopic ());
65+ }
66+ if (isNotBlank (gptQuestion .getKeyword ())) {
67+ recentPromptFilterService .record (memberId , category , ItemType .KEYWORD , gptQuestion .getKeyword ());
68+ }
69+
4670 return QuestionResponse .QuestionDto .builder ()
4771 .id (question .getId ())
4872 .content (question .getContent ())
@@ -64,4 +88,10 @@ public PageResponse<QuestionsDto> getQuestions(int page, int size) {
6488 long total = answerMapper .countQuestionsWithFeedback (memberId );
6589 return PageResponse .of (content , safePage , safeSize , total );
6690 }
91+
92+ private boolean hasAny (List <String > a , List <String > b ) {
93+ return (a != null && !a .isEmpty ()) || (b != null && !b .isEmpty ());
94+ }
95+
96+ private boolean isNotBlank (String s ) { return s != null && !s .isBlank (); }
6797}
0 commit comments