Skip to content

Commit da02a57

Browse files
committed
Refact : ChatController, ChatServiceImpl 리팩토링
- controller에서 불필요한 주석을 제거하였습니다. - ChatServiceImpl에서 외부 API 호출 부분만 try/catch로 감싸주었습니다. - 컨버터에 DTO 생성로직을 모아 중복을 제거하고, 일관성을 확보해주었습니다. - 전반적으로 Controller와 service, converter의 역할을 분리하였습니다.
1 parent d7874b1 commit da02a57

File tree

3 files changed

+77
-91
lines changed

3 files changed

+77
-91
lines changed

src/main/java/com/perfact/be/domain/chat/controller/ChatController.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,50 +9,41 @@
99
import io.swagger.v3.oas.annotations.Parameter;
1010
import io.swagger.v3.oas.annotations.tags.Tag;
1111
import lombok.RequiredArgsConstructor;
12-
import lombok.extern.slf4j.Slf4j;
1312
import org.springframework.validation.annotation.Validated;
1413
import org.springframework.web.bind.annotation.*;
1514

16-
@Slf4j
15+
@Validated
1716
@RestController
1817
@RequestMapping("/api/report")
1918
@RequiredArgsConstructor
2019
@Tag(name = "Chat", description = "챗봇 API")
21-
@Validated
2220
public class ChatController {
2321

24-
private final ChatService chatService;
22+
private final ChatService chatServiceImpl;
2523

2624
@Operation(summary = "리포트 기반 채팅", description = "특정 리포트의 분석 결과를 바탕으로 AI와 채팅합니다.")
2725
@PostMapping("/{reportId}/chat")
2826
public ApiResponse<ChatResponse.ChatResponseDTO> sendMessage(
2927
@Parameter(description = "리포트 ID", required = true, example = "1") @PathVariable Long reportId,
3028
@Parameter(description = "채팅 요청", required = true) @RequestBody ChatRequestDTO request) {
31-
ChatResponse.ChatResponseDTO response = chatService.sendMessage(reportId, request);
29+
ChatResponse.ChatResponseDTO response = chatServiceImpl.sendMessage(reportId, request);
3230
return ApiResponse.onSuccess(response);
3331
}
3432

3533
@Operation(summary = "채팅 로그 조회", description = "특정 리포트의 채팅 로그를 시간 순으로 조회합니다.")
3634
@GetMapping("/{reportId}/chat")
3735
public ApiResponse<ChatResponse.ChatLogListResponseDTO> getChatLogs(
3836
@Parameter(description = "리포트 ID", required = true, example = "1") @PathVariable Long reportId) {
39-
40-
log.info("채팅 로그 조회 요청 - reportId: {}", reportId);
41-
42-
ChatResponse.ChatLogListResponseDTO response = chatService.getChatLogs(reportId);
43-
37+
ChatResponse.ChatLogListResponseDTO response = chatServiceImpl.getChatLogs(reportId);
4438
return ApiResponse.onSuccess(response);
4539
}
4640

4741
@Operation(summary = "추천 질문 조회", description = "특정 리포트의 분석 결과를 바탕으로 AI가 추천하는 질문을 조회합니다.")
4842
@GetMapping("/{reportId}/chat/recommend")
4943
public ApiResponse<ChatResponse.RecommendQuestionsResponseDTO> getRecommendQuestions(
5044
@Parameter(description = "리포트 ID", required = true, example = "1") @PathVariable Long reportId) {
51-
52-
log.info("추천 질문 조회 요청 - reportId: {}", reportId);
53-
54-
ChatResponse.RecommendQuestionsResponseDTO response = chatService.getRecommendQuestions(reportId);
55-
45+
ChatResponse.RecommendQuestionsResponseDTO response = chatServiceImpl.getRecommendQuestions(reportId);
5646
return ApiResponse.onSuccess(response);
5747
}
48+
5849
}

src/main/java/com/perfact/be/domain/chat/converter/ChatLogConverter.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
@Slf4j
1212
@Component
1313
public class ChatLogConverter {
14-
// ChatLog 엔티티를 ChatLogListResponseDTO로 변환
14+
// reportId, List<ChatLong> -> ChatLogListResponseDTO
1515
public ChatResponse.ChatLogListResponseDTO toResponseDto(Long reportId, List<ChatLog> chatLogs) {
1616
List<ChatResponse.ChatLogDTO> chatLogDTOs = chatLogs.stream()
1717
.map(this::toChatLogDto)
@@ -25,7 +25,7 @@ public ChatResponse.ChatLogListResponseDTO toResponseDto(Long reportId, List<Cha
2525
return result;
2626
}
2727

28-
// ChatLog 엔티티를 ChatLogDTO로 변환
28+
// ChatLogEntity -> ChatLogDTO
2929
private ChatResponse.ChatLogDTO toChatLogDto(ChatLog chatLog) {
3030
return ChatResponse.ChatLogDTO.builder()
3131
.chatId(chatLog.getChatId())
@@ -34,4 +34,19 @@ private ChatResponse.ChatLogDTO toChatLogDto(ChatLog chatLog) {
3434
.createdAt(chatLog.getCreatedAt())
3535
.build();
3636
}
37+
38+
// String -> ChatResponseDTO
39+
public ChatResponse.ChatResponseDTO toCharResponseDto(String polishedResponse) {
40+
return ChatResponse.ChatResponseDTO.builder()
41+
.aiResponse(polishedResponse)
42+
.build();
43+
}
44+
45+
// List<String> -> RecommendQuestionsResponseDTO
46+
public ChatResponse.RecommendQuestionsResponseDTO toRecommendQuestionsResponseDto(List<String> questions) {
47+
return ChatResponse.RecommendQuestionsResponseDTO.builder()
48+
.questions(questions)
49+
.build();
50+
}
51+
3752
}

src/main/java/com/perfact/be/domain/chat/service/ChatServiceImpl.java

Lines changed: 54 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -35,103 +35,83 @@ public class ChatServiceImpl implements ChatService {
3535
@Override
3636
@Transactional
3737
public ChatResponse.ChatResponseDTO sendMessage(Long reportId, ChatRequestDTO request) {
38-
try {
39-
log.info("채팅 메시지 요청 - reportId: {}, userInput: {}", reportId, request.getUserInput());
40-
41-
// 1. 리포트 조회
42-
Report report = reportRepository.findById(reportId)
43-
.orElseThrow(() -> new ChatHandler(ChatErrorStatus.CHAT_REPORT_NOT_FOUND));
44-
45-
// 2. 사용자 메시지를 ChatLog에 저장
46-
ChatLog userChatLog = ChatLog.builder()
47-
.senderType(SenderType.USER)
48-
.message(request.getUserInput())
49-
.reportId(report.getReportId())
50-
.build();
51-
chatLogRepository.save(userChatLog);
52-
53-
// 3. Clova API 호출을 위한 요청 생성
54-
var clovaRequest = clovaApiConverter.createChatRequest(report.getChatbotContext(), report.getArticleContent(),
55-
request.getUserInput());
38+
log.info("채팅 메시지 요청 - reportId: {}, userInput: {}", reportId, request.getUserInput());
39+
// 1. 레포트 조회
40+
Report report = reportRepository.findById(reportId).orElseThrow(() -> new ChatHandler(ChatErrorStatus.CHAT_REPORT_NOT_FOUND));
41+
42+
// 2. 사용자 메시지를 ChatLog에 저장
43+
ChatLog userChatLog = ChatLog.builder()
44+
.senderType(SenderType.USER)
45+
.message(request.getUserInput())
46+
.reportId(report.getReportId())
47+
.build();
48+
chatLogRepository.save(userChatLog);
49+
50+
// 3. Clova API 호출을 위한 요청 생성
51+
var clovaRequest = clovaApiConverter.createChatRequest(report.getChatbotContext(), report.getArticleContent(), request.getUserInput());
52+
String polishedResponse;
5653

57-
// 4. Clova API 호출
54+
try {
55+
// 4. Clova API 호출 및 응답 메세지 다듬기
5856
var clovaResponse = clovaApiConverter.callChatAPI(clovaRequest);
57+
polishedResponse = chatMessageUtil.polishMessage(
58+
clovaResponse.getResult().getMessage().getContent());
59+
} catch(Exception e){
60+
log.error("Clova API 처리 실패 - reportId: {}, 에러: {}", reportId, e.getMessage(), e);
61+
throw new ChatHandler(ChatErrorStatus.CHAT_API_CALL_FAILED);
62+
}
5963

60-
// 5. AI 응답 메시지 다듬기
61-
String polishedResponse = chatMessageUtil.polishMessage(clovaResponse.getResult().getMessage().getContent());
62-
63-
// 6. AI 응답을 ChatLog에 저장
64-
ChatLog aiChatLog = ChatLog.builder()
65-
.senderType(SenderType.AI)
66-
.message(polishedResponse)
67-
.reportId(report.getReportId())
68-
.build();
69-
chatLogRepository.save(aiChatLog);
70-
71-
log.info("채팅 메시지 처리 완료 - reportId: {}, AI 응답 길이: {}",
72-
reportId, polishedResponse.length());
64+
// 6. AI 응답을 ChatLog에 저장
65+
ChatLog aiChatLog = ChatLog.builder()
66+
.senderType(SenderType.AI)
67+
.message(polishedResponse)
68+
.reportId(report.getReportId())
69+
.build();
70+
chatLogRepository.save(aiChatLog);
71+
log.info("채팅 메시지 처리 완료 - reportId: {}, AI 응답 길이: {}", reportId, polishedResponse.length());
7372

74-
return ChatResponse.ChatResponseDTO.builder()
75-
.aiResponse(polishedResponse)
76-
.build();
73+
return chatLogConverter.toCharResponseDto(polishedResponse);
7774

78-
} catch (Exception e) {
79-
log.error("채팅 메시지 처리 실패 - reportId: {}, 에러: {}", reportId, e.getMessage(), e);
80-
throw new ChatHandler(ChatErrorStatus.CHAT_API_CALL_FAILED);
81-
}
8275
}
8376

8477
@Override
8578
@Transactional(readOnly = true)
8679
public ChatResponse.ChatLogListResponseDTO getChatLogs(Long reportId) {
87-
try {
88-
log.info("채팅 로그 조회 요청 - reportId: {}", reportId);
89-
90-
// 1. 리포트 존재 여부 확인
91-
Report report = reportRepository.findById(reportId)
92-
.orElseThrow(() -> new ChatHandler(ChatErrorStatus.CHAT_REPORT_NOT_FOUND));
93-
94-
// 2. 채팅 로그 조회 (시간 순으로 오름차순)
95-
List<ChatLog> chatLogs = chatLogRepository.findByReportIdOrderByCreatedAtAsc(reportId);
96-
97-
log.info("채팅 로그 조회 완료 - reportId: {}, 로그 개수: {}", reportId, chatLogs.size());
80+
// 1. 리포트 존재 여부 확인
81+
if (!reportRepository.existsById(reportId)) {
82+
throw new ChatHandler(ChatErrorStatus.CHAT_REPORT_NOT_FOUND);
83+
}
84+
// 2. 채팅 로그 조회 (시간 순으로 오름차순)
85+
List<ChatLog> chatLogs = chatLogRepository.findByReportIdOrderByCreatedAtAsc(reportId);
86+
log.info("채팅 로그 조회 완료 - reportId: {}, 로그 개수: {}", reportId, chatLogs.size());
9887

99-
return chatLogConverter.toResponseDto(reportId, chatLogs);
88+
return chatLogConverter.toResponseDto(reportId, chatLogs);
10089

101-
} catch (Exception e) {
102-
log.error("채팅 로그 조회 실패 - reportId: {}, 에러: {}", reportId, e.getMessage(), e);
103-
throw new ChatHandler(ChatErrorStatus.CHAT_API_CALL_FAILED);
104-
}
10590
}
10691

10792
@Override
10893
@Transactional
10994
public ChatResponse.RecommendQuestionsResponseDTO getRecommendQuestions(Long reportId) {
110-
try {
111-
log.info("추천 질문 요청 - reportId: {}", reportId);
95+
// 1. 리포트 조회
96+
Report report = reportRepository.findById(reportId)
97+
.orElseThrow(() -> new ChatHandler(ChatErrorStatus.CHAT_REPORT_NOT_FOUND));
11298

113-
// 1. 리포트 조회
114-
Report report = reportRepository.findById(reportId)
115-
.orElseThrow(() -> new ChatHandler(ChatErrorStatus.CHAT_REPORT_NOT_FOUND));
99+
// 2. 추천 질문 요청 생성
100+
var recommendRequest = clovaApiConverter.createRecommendRequest(report.getChatbotContext());
101+
List<String> questions;
116102

117-
// 2. 추천 질문 요청 생성
118-
var recommendRequest = clovaApiConverter.createRecommendRequest(report.getChatbotContext());
119-
120-
// 3. Clova API 호출
103+
// 3. Clova API 호출 및 응답에서 질문 목록 추출
104+
try {
121105
var recommendResponse = clovaApiConverter.callRecommendAPI(recommendRequest);
122-
123-
// 4. 응답에서 질문 목록 추출
124-
List<String> questions = jsonConverter.parseJsonArray(recommendResponse.getResult().getMessage().getContent());
125-
126-
log.info("추천 질문 생성 완료 - reportId: {}, 질문 개수: {}", reportId, questions.size());
127-
128-
return ChatResponse.RecommendQuestionsResponseDTO.builder()
129-
.questions(questions)
130-
.build();
131-
106+
questions = jsonConverter.parseJsonArray(recommendResponse.getResult().getMessage().getContent());
132107
} catch (Exception e) {
133108
log.error("추천 질문 생성 실패 - reportId: {}, 에러: {}", reportId, e.getMessage(), e);
134109
throw new ChatHandler(ChatErrorStatus.CHAT_API_CALL_FAILED);
135110
}
111+
112+
log.info("추천 질문 생성 완료 - reportId: {}, 질문 개수: {}", reportId, questions.size());
113+
114+
return chatLogConverter.toRecommendQuestionsResponseDto(questions);
115+
136116
}
137117
}

0 commit comments

Comments
 (0)