## ChatGPT 컨트롤러 ### DTO #### Request DTO ```java @Getter @Setter @AllArgsConstructor @NoArgsConstructor @ToString @Builder public class PromptTemplateRequest { private String id; private String content; public PromptTemplate toEntity(){ return PromptTemplate.builder() .id(id) .content(content) .build(); } } ``` - `ModelMapper`를 이용하는 방법도 있다. 나는 선호하지 않는다. #### Response DTO ```java @Getter @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode @ToString public class PromptTemplateResponse{ private String id; private String content; private LocalDateTime modifiedTime; public PromptTemplateResponse(PromptTemplate promptTemplate){ id = promptTemplate.getId(); content = promptTemplate.getContent(); modifiedTime = promptTemplate.getModifiedTime(); } } ``` - `ModelMapper`를 이용하는 방법도 있다. 나는 선호하지 않는다. ### 컨트롤러 #### `ChatGPTController` ##### 클래스 생성 및 의존성 주입 ```java @RestController @Slf4j public class ChatGPTController { @Autowired private PromptTemplateService promptTemplateService; @Autowired private ChatGPTClient chatGPTClient; } ``` - 서비스와 클라이언트를 동시에 사용하니 둘 다 주입 받는다. ##### 기본 CRUD API ```java @PostMapping("/prompt-template") public ResponseEntity<PromptTemplateResponse> createPromptTemplate( @RequestBody PromptTemplateRequest promptTemplateRequest) { PromptTemplate promptTemplate = promptTemplateRequest.toEntity(); promptTemplate = promptTemplateService.create(promptTemplate); PromptTemplateResponse templateResponse = new PromptTemplateResponse(promptTemplate); return ResponseEntity .status(HttpStatus.CREATED) .body(templateResponse); } @GetMapping("/prompt-template/{id}") public ResponseEntity<PromptTemplateResponse> readPromptTemplateById( @PathVariable("id") String id) { PromptTemplate promptTemplate = promptTemplateService.readById(id); PromptTemplateResponse templateResponse = new PromptTemplateResponse(promptTemplate); return ResponseEntity .status(HttpStatus.OK) .body(templateResponse); } @PutMapping("/prompt-template/{id}") public ResponseEntity<PromptTemplateResponse> updatePromptTemplateById( @PathVariable("id") String id, @RequestBody PromptTemplateRequest promptTemplateRequest) { PromptTemplate promptTemplate = promptTemplateRequest.toEntity(); promptTemplate = promptTemplateService.updateById(id, promptTemplate); PromptTemplateResponse templateResponse = new PromptTemplateResponse(promptTemplate); return ResponseEntity .status(HttpStatus.CREATED) .body(templateResponse); } @DeleteMapping("/prompt-template/{id}") public ResponseEntity<?> deletePromptTemplateById( @PathVariable("id") String id) { promptTemplateService.deleteById(id); return ResponseEntity .status(HttpStatus.OK) .body(null); } ``` - 예외 처리는 ExceptionHandler를 통해 한 번에 할 생각이기 때문에 따로 처리하지 않는다. ##### ChatGPT API 프록시 ```java @PostMapping("/prompt") public ResponseEntity<String> sendPrompt( @RequestBody String prompt) throws JsonProcessingException { return ResponseEntity .status(HttpStatus.OK) .body(chatGPTClient.chat(prompt)); } @PostMapping("/prompt/generated-by/prompt-template/{id}") public ResponseEntity<String> sendPromptByTemplate( @PathVariable("id") String id, @RequestBody HashMap<String, String> hashMap) throws TemplateException, IOException { return ResponseEntity .status(HttpStatus.OK) .body(chatGPTClient.chatByTemplate(id, hashMap)); } ``` - 컨트롤러에서 예외 처리를 하지 않고 `JsonProcessingException`를 `throws`하는 이유는 `@ControllerAdvice`에서 예외를 일괄적으로 처리하기 때문이다. ## [[4-3 컨트롤러 테스트 코드(API)|테스트 코드]] ![[4-3 컨트롤러 테스트 코드(API)#`ChatGPTControllerTest` 작성]]