Skip to content

Commit 34868d1

Browse files
authored
OpenAi API의 답변을 출력할 때 SSE 적용 (#61)
* refactor: 서술형 문제 채점 메소드에서 @transactional 어노테이션을 제거하여 DB 커넥션을 빠르게 반납하도록 수정 * feat: 서술형 문제 채점시 SSE로 답변을 수신하도록 수정 - SSE 요청이 가능한 WebClient를 통해 chatgpt api에 http요청을 전송하도록 수정 * refactor: ChatCacheService가 메시지를 저장할 때 List<ChatGptMessageDto>로 저장하도록 수정 * feat: OpenAi API의 답변을 SSE로 받아오는 API 추가 1. PathVariable로 전달된 key로 저장되어있는 ChatMessage를 조회하여, 이를 OpenAi API에 전송 * refactor: WebClientService가 Sse로 값을 반환할 때, raw data를 요구된 형식에 맞게 파싱해서 반환하도록 수정 기존 Json 데이터 반환 -> ContentExtractor 메소드로 추출 후에 반환 * refactor: View - 답변 출력시 줄 바꿈 적용 * refactor: 서술형 문제 채점시 프롬프트 수정 * style: 코딩 컨벤션 적용 * refactor: 서술형 문제 채점 기준 수정 기능의 코드 수정
1 parent 23de226 commit 34868d1

32 files changed

+114487
-258
lines changed

application/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ dependencies {
2424
implementation 'org.springframework.boot:spring-boot-starter-actuator'
2525
implementation 'io.springfox:springfox-boot-starter:3.0.0'
2626

27+
2728
}
2829

2930
test {

application/src/main/java/com/comssa/api/question/service/rest/common/QuestionClassifyByCategoryService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010

1111
@Service
1212
public interface QuestionClassifyByCategoryService {
13-
Map<QuestionCategory, List<Question>> classifyQuestionByCategoryOrdered(List<? extends Question> questions);
13+
Map<QuestionCategory, List<Question>> classifyQuestionByCategoryOrdered(List<? extends Question> questions);
1414
}
1515

application/src/main/java/com/comssa/api/question/service/rest/common/implement/AmazonS3FileUploadService.java

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ private Optional<File> convert(MultipartFile file) throws IOException {
6161
}
6262
return Optional.of(convertFile);
6363
}
64+
6465
return Optional.empty();
6566
}
6667
}

application/src/main/java/com/comssa/api/question/service/rest/license/LicenseQuestionGetService.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010

1111
@Service
1212
public interface LicenseQuestionGetService {
13-
Map<QuestionCategory, List<Question>> getClassifiedLicenseMultipleChoiceQuestion(
14-
Long sessionId);
13+
Map<QuestionCategory, List<Question>> getClassifiedLicenseMultipleChoiceQuestion(
14+
Long sessionId);
1515
}

application/src/main/java/com/comssa/api/question/service/rest/license/implement/AdminLicenseQuestionGetService.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@
1919
@RequiredArgsConstructor
2020
public class AdminLicenseQuestionGetService implements LicenseQuestionGetService {
2121

22-
private final LicenseMultipleChoiceQuestionDslRepository licenseMultipleChoiceQuestionDslRepository;
23-
private final QuestionClassifyByCategoryService questionClassifyByCategoryService;
22+
private final LicenseMultipleChoiceQuestionDslRepository licenseMultipleChoiceQuestionDslRepository;
23+
private final QuestionClassifyByCategoryService questionClassifyByCategoryService;
2424

25-
/**
26-
* 관리자 조회시 허용 여부와 관련 없이 모든 문제를 가져온다.
27-
* 문제지도 섞지 않는다.
28-
* 허용 여부 순대로 섞는다
29-
*/
30-
@Override
31-
public Map<QuestionCategory, List<Question>> getClassifiedLicenseMultipleChoiceQuestion(
32-
Long sessionId) {
33-
List<LicenseMultipleChoiceQuestion> licenseMultipleChoiceQuestions = licenseMultipleChoiceQuestionDslRepository
34-
.findAllWhereLicenseSessionId(sessionId);
35-
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(licenseMultipleChoiceQuestions);
36-
}
25+
/**
26+
* 관리자 조회시 허용 여부와 관련 없이 모든 문제를 가져온다.
27+
* 문제지도 섞지 않는다.
28+
* 허용 여부 순대로 섞는다
29+
*/
30+
@Override
31+
public Map<QuestionCategory, List<Question>> getClassifiedLicenseMultipleChoiceQuestion(
32+
Long sessionId) {
33+
List<LicenseMultipleChoiceQuestion> licenseMultipleChoiceQuestions = licenseMultipleChoiceQuestionDslRepository
34+
.findAllWhereLicenseSessionId(sessionId);
35+
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(licenseMultipleChoiceQuestions);
36+
}
3737
}

application/src/main/java/com/comssa/api/question/service/rest/major/AdminMajorQuestionClassifiedGetService.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.Map;
99

1010
public interface AdminMajorQuestionClassifiedGetService {
11-
Map<QuestionCategory, List<Question>> getClassifiedAllMajorMultipleChoiceQuestions();
11+
Map<QuestionCategory, List<Question>> getClassifiedAllMajorMultipleChoiceQuestions();
1212

13-
Map<QuestionCategory, List<Question>> getClassifiedAllMajorDescriptiveQuestions();
13+
Map<QuestionCategory, List<Question>> getClassifiedAllMajorDescriptiveQuestions();
1414
}

application/src/main/java/com/comssa/api/question/service/rest/major/MajorQuestionClassifiedGetService.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111

1212
@Service
1313
public interface MajorQuestionClassifiedGetService<T extends Question> {
14-
/**
15-
* 분류별로 나누어 문제를 반환
16-
*/
17-
Map<QuestionCategory, List<T>> getApprovedClassifiedMajorMultipleChoiceQuestions(
18-
RequestGetQuestionByCategoryAndLevelDto requestGetQuestionByCategoryAndLevelDto);
14+
/**
15+
* 분류별로 나누어 문제를 반환
16+
*/
17+
Map<QuestionCategory, List<T>> getApprovedClassifiedMajorMultipleChoiceQuestions(
18+
RequestGetQuestionByCategoryAndLevelDto requestGetQuestionByCategoryAndLevelDto);
1919

2020

21-
Map<QuestionCategory, List<T>> getApprovedClassifiedDescriptiveQuestions(
22-
RequestGetQuestionByCategoryAndLevelDto requestGetQuestionByCategoryAndLevelDto
23-
);
21+
Map<QuestionCategory, List<T>> getApprovedClassifiedDescriptiveQuestions(
22+
RequestGetQuestionByCategoryAndLevelDto requestGetQuestionByCategoryAndLevelDto
23+
);
2424

2525
}
2626

application/src/main/java/com/comssa/api/question/service/rest/major/implement/BasicAdminMajorQuestionClassifiedGetService.java

+21-21
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,27 @@
2020
@RequiredArgsConstructor
2121
@Transactional
2222
public class BasicAdminMajorQuestionClassifiedGetService implements AdminMajorQuestionClassifiedGetService {
23-
private final QuestionClassifyByCategoryService questionClassifyByCategoryService;
24-
private final MajorDescriptiveDslRepository majorDescriptiveQuestionChooseRepository;
25-
private final MajorMultipleChoiceQuestionDslRepository majorMultipleChoiceQuestionDslRepository;
23+
private final QuestionClassifyByCategoryService questionClassifyByCategoryService;
24+
private final MajorDescriptiveDslRepository majorDescriptiveQuestionChooseRepository;
25+
private final MajorMultipleChoiceQuestionDslRepository majorMultipleChoiceQuestionDslRepository;
2626

27-
/**
28-
* 관리자가 조회시 Approve됐는지 기준으로 정렬되며(false인 것부터),
29-
* 이후엔 객관식 -> 주관식으로 정렬된다.
30-
*
31-
* @return
32-
*/
33-
@Override
34-
public Map<QuestionCategory, List<Question>> getClassifiedAllMajorMultipleChoiceQuestions() {
35-
List<MajorMultipleChoiceQuestion> majorMultipleChoiceQuestions = majorMultipleChoiceQuestionDslRepository
36-
.findAllOrderByIfApprovedAsc();
37-
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorMultipleChoiceQuestions);
38-
}
27+
/**
28+
* 관리자가 조회시 Approve됐는지 기준으로 정렬되며(false인 것부터),
29+
* 이후엔 객관식 -> 주관식으로 정렬된다.
30+
*
31+
* @return
32+
*/
33+
@Override
34+
public Map<QuestionCategory, List<Question>> getClassifiedAllMajorMultipleChoiceQuestions() {
35+
List<MajorMultipleChoiceQuestion> majorMultipleChoiceQuestions = majorMultipleChoiceQuestionDslRepository
36+
.findAllOrderByIfApprovedAsc();
37+
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorMultipleChoiceQuestions);
38+
}
3939

40-
@Override
41-
public Map<QuestionCategory, List<Question>> getClassifiedAllMajorDescriptiveQuestions() {
42-
List<MajorDescriptiveQuestion> majorDescriptiveQuestions =
43-
majorDescriptiveQuestionChooseRepository.findAllOrderByIfApprovedAsc();
44-
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorDescriptiveQuestions);
45-
}
40+
@Override
41+
public Map<QuestionCategory, List<Question>> getClassifiedAllMajorDescriptiveQuestions() {
42+
List<MajorDescriptiveQuestion> majorDescriptiveQuestions =
43+
majorDescriptiveQuestionChooseRepository.findAllOrderByIfApprovedAsc();
44+
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorDescriptiveQuestions);
45+
}
4646
}

application/src/main/java/com/comssa/api/question/service/rest/major/implement/BasicAdminMajorQuestionMakeService.java

+62-62
Original file line numberDiff line numberDiff line change
@@ -22,74 +22,74 @@
2222
@Transactional
2323
public class BasicAdminMajorQuestionMakeService implements AdminMajorQuestionMakeService {
2424

25-
private final QuestionRepository questionRepository;
26-
private final MajorMultipleChoiceQuestionRepository majorMultipleChoiceQuestionRepository;
27-
private final QuestionChoiceService questionChoiceService;
28-
private final DuplicateQuestionDetector duplicateQuestionDetector;
25+
private final QuestionRepository questionRepository;
26+
private final MajorMultipleChoiceQuestionRepository majorMultipleChoiceQuestionRepository;
27+
private final QuestionChoiceService questionChoiceService;
28+
private final DuplicateQuestionDetector duplicateQuestionDetector;
2929

30-
/**
31-
* 리스트로 생성
32-
*/
33-
@Override
34-
public List<MajorMultipleChoiceQuestion> makeMultipleChoiceQuestions(
35-
List<RequestMakeMultipleChoiceQuestionDto> requestDtos) {
36-
// 중복되지 않은 질문을 필터링하여 저장
37-
return requestDtos.stream()
38-
.filter(this::isNotDuplicateQuestion)
39-
.map(this::saveMajorMultipleChoiceQuestion)
40-
.collect(Collectors.toList());
41-
}
30+
/**
31+
* 리스트로 생성
32+
*/
33+
@Override
34+
public List<MajorMultipleChoiceQuestion> makeMultipleChoiceQuestions(
35+
List<RequestMakeMultipleChoiceQuestionDto> requestDtos) {
36+
// 중복되지 않은 질문을 필터링하여 저장
37+
return requestDtos.stream()
38+
.filter(this::isNotDuplicateQuestion)
39+
.map(this::saveMajorMultipleChoiceQuestion)
40+
.collect(Collectors.toList());
41+
}
4242

43-
/**
44-
* 단일 생성
45-
*/
46-
@Override
47-
public MajorMultipleChoiceQuestion makeMultipleChoiceQuestion(
48-
RequestMakeMultipleChoiceQuestionDto requestDto) throws DuplicateQuestionContentException {
49-
if (!isNotDuplicateQuestion(requestDto)) {
50-
throw new DuplicateQuestionContentException();
51-
}
52-
return saveMajorMultipleChoiceQuestion(requestDto);
53-
}
43+
/**
44+
* 단일 생성
45+
*/
46+
@Override
47+
public MajorMultipleChoiceQuestion makeMultipleChoiceQuestion(
48+
RequestMakeMultipleChoiceQuestionDto requestDto) throws DuplicateQuestionContentException {
49+
if (!isNotDuplicateQuestion(requestDto)) {
50+
throw new DuplicateQuestionContentException();
51+
}
52+
return saveMajorMultipleChoiceQuestion(requestDto);
53+
}
5454

55-
@Override
56-
public List<MajorDescriptiveQuestion> makeDescriptiveQuestions(
57-
List<RequestMakeMajorDescriptiveQuestionDto> requestNormalQuestionDto) {
55+
@Override
56+
public List<MajorDescriptiveQuestion> makeDescriptiveQuestions(
57+
List<RequestMakeMajorDescriptiveQuestionDto> requestNormalQuestionDto) {
5858

59-
return requestNormalQuestionDto.stream()
60-
.map(this::saveMajorDescriptiveQuestion)
61-
.collect(Collectors.toList());
62-
}
59+
return requestNormalQuestionDto.stream()
60+
.map(this::saveMajorDescriptiveQuestion)
61+
.collect(Collectors.toList());
62+
}
6363

64-
/**
65-
* 중복되지 않은 질문인지 확인하는 메서드
66-
* 매번 DB에서 새롭게 조회 후 검증한다.(DTO 자체의 중복된 데이터)
67-
*/
68-
private boolean isNotDuplicateQuestion(RequestMakeMultipleChoiceQuestionDto requestDto) {
69-
return majorMultipleChoiceQuestionRepository.findAll().stream()
70-
.noneMatch(existingQuestion -> duplicateQuestionDetector.isQuestionDuplicate(
71-
existingQuestion.getContent(), requestDto.getContent()));
72-
}
64+
/**
65+
* 중복되지 않은 질문인지 확인하는 메서드
66+
* 매번 DB에서 새롭게 조회 후 검증한다.(DTO 자체의 중복된 데이터)
67+
*/
68+
private boolean isNotDuplicateQuestion(RequestMakeMultipleChoiceQuestionDto requestDto) {
69+
return majorMultipleChoiceQuestionRepository.findAll().stream()
70+
.noneMatch(existingQuestion -> duplicateQuestionDetector.isQuestionDuplicate(
71+
existingQuestion.getContent(), requestDto.getContent()));
72+
}
7373

74-
/**
75-
* 새로운 질문을 저장하고 선택지를 저장하는 메서드
76-
*/
77-
private MajorMultipleChoiceQuestion saveMajorMultipleChoiceQuestion(
78-
RequestMakeMultipleChoiceQuestionDto requestDto) {
79-
MajorMultipleChoiceQuestion question = MajorMultipleChoiceQuestion.makeWithDto(requestDto);
80-
questionRepository.save(question);
81-
questionChoiceService.saveWith(requestDto, question);
82-
return question;
83-
}
74+
/**
75+
* 새로운 질문을 저장하고 선택지를 저장하는 메서드
76+
*/
77+
private MajorMultipleChoiceQuestion saveMajorMultipleChoiceQuestion(
78+
RequestMakeMultipleChoiceQuestionDto requestDto) {
79+
MajorMultipleChoiceQuestion question = MajorMultipleChoiceQuestion.makeWithDto(requestDto);
80+
questionRepository.save(question);
81+
questionChoiceService.saveWith(requestDto, question);
82+
return question;
83+
}
8484

85-
private MajorDescriptiveQuestion saveMajorDescriptiveQuestion(
86-
RequestMakeMajorDescriptiveQuestionDto requestDto
87-
) {
88-
MajorDescriptiveQuestion question = MajorDescriptiveQuestion.makeWithDto(
89-
requestDto
90-
);
91-
questionRepository.save(question);
92-
return question;
93-
}
85+
private MajorDescriptiveQuestion saveMajorDescriptiveQuestion(
86+
RequestMakeMajorDescriptiveQuestionDto requestDto
87+
) {
88+
MajorDescriptiveQuestion question = MajorDescriptiveQuestion.makeWithDto(
89+
requestDto
90+
);
91+
questionRepository.save(question);
92+
return question;
93+
}
9494
}
9595

application/src/main/java/com/comssa/api/question/service/rest/major/implement/UserMajorQuestionClassifiedGetService.java

+34-34
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,41 @@
2020
@Service
2121
@RequiredArgsConstructor
2222
public class UserMajorQuestionClassifiedGetService implements MajorQuestionClassifiedGetService<Question> {
23-
private final MajorMultipleChoiceQuestionDslRepository majorMultipleChoiceQuestionDslRepository;
24-
private final QuestionClassifyByCategoryService questionClassifyByCategoryService;
25-
private final MajorDescriptiveDslRepository majorDescriptiveQuestionDslRepository;
23+
private final MajorMultipleChoiceQuestionDslRepository majorMultipleChoiceQuestionDslRepository;
24+
private final QuestionClassifyByCategoryService questionClassifyByCategoryService;
25+
private final MajorDescriptiveDslRepository majorDescriptiveQuestionDslRepository;
2626

27-
/**
28-
* 분야, 난이도 파라미터로 문제를 조회하는 경우 - 객관식.
29-
* 문제 선택지들을 섞어준다.
30-
*/
31-
@Override
32-
public Map<QuestionCategory, List<Question>> getApprovedClassifiedMajorMultipleChoiceQuestions(
33-
RequestGetQuestionByCategoryAndLevelDto requestGetQuestionByCategoryAndLevelDto) {
34-
List<MajorMultipleChoiceQuestion> majorMultipleChoiceQuestions = majorMultipleChoiceQuestionDslRepository
35-
.findAllCategoriesAndLevelsAndIfApproved(
36-
requestGetQuestionByCategoryAndLevelDto.getQuestionCategories(),
37-
requestGetQuestionByCategoryAndLevelDto.getQuestionLevels(),
38-
true);
39-
for (MajorMultipleChoiceQuestion question : majorMultipleChoiceQuestions) {
40-
Collections.shuffle(question.getQuestionChoices());
41-
}
42-
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorMultipleChoiceQuestions);
43-
}
27+
/**
28+
* 분야, 난이도 파라미터로 문제를 조회하는 경우 - 객관식.
29+
* 문제 선택지들을 섞어준다.
30+
*/
31+
@Override
32+
public Map<QuestionCategory, List<Question>> getApprovedClassifiedMajorMultipleChoiceQuestions(
33+
RequestGetQuestionByCategoryAndLevelDto requestGetQuestionByCategoryAndLevelDto) {
34+
List<MajorMultipleChoiceQuestion> majorMultipleChoiceQuestions = majorMultipleChoiceQuestionDslRepository
35+
.findAllCategoriesAndLevelsAndIfApproved(
36+
requestGetQuestionByCategoryAndLevelDto.getQuestionCategories(),
37+
requestGetQuestionByCategoryAndLevelDto.getQuestionLevels(),
38+
true);
39+
for (MajorMultipleChoiceQuestion question : majorMultipleChoiceQuestions) {
40+
Collections.shuffle(question.getQuestionChoices());
41+
}
42+
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorMultipleChoiceQuestions);
43+
}
4444

4545

46-
/**
47-
* 분야, 난이도 파라미터로 문제를 조회하는 경우 - 서술형
48-
*/
49-
@Override
50-
public Map<QuestionCategory, List<Question>> getApprovedClassifiedDescriptiveQuestions(
51-
RequestGetQuestionByCategoryAndLevelDto dto) {
52-
List<MajorDescriptiveQuestion> majorDescriptiveQuestions = majorDescriptiveQuestionDslRepository
53-
.findAllCategoriesAndLevelsAndIfApproved(
54-
dto.getQuestionCategories(),
55-
dto.getQuestionLevels(),
56-
true
57-
);
58-
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorDescriptiveQuestions);
59-
}
46+
/**
47+
* 분야, 난이도 파라미터로 문제를 조회하는 경우 - 서술형
48+
*/
49+
@Override
50+
public Map<QuestionCategory, List<Question>> getApprovedClassifiedDescriptiveQuestions(
51+
RequestGetQuestionByCategoryAndLevelDto dto) {
52+
List<MajorDescriptiveQuestion> majorDescriptiveQuestions = majorDescriptiveQuestionDslRepository
53+
.findAllCategoriesAndLevelsAndIfApproved(
54+
dto.getQuestionCategories(),
55+
dto.getQuestionLevels(),
56+
true
57+
);
58+
return questionClassifyByCategoryService.classifyQuestionByCategoryOrdered(majorDescriptiveQuestions);
59+
}
6060
}

application/src/main/java/com/comssa/api/question/service/view/HtmlTagService.java

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public void forLicenseQuestion(LicenseSession licenseSession, Model model) {
7676
public void forMajor(Set<QuestionCategory> questionCategories, boolean isMultipleChoice, Model model) {
7777
if (isMultipleChoice) {
7878
addTagToModel(forMajorMultiple(questionCategories), model);
79+
return;
7980
}
8081
addTagToModel(forMajorDescriptive(questionCategories), model);
8182
}

0 commit comments

Comments
 (0)