일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 코딩테스트
- responsepart
- 커밋 컨벤션
- VB
- 멋쟁이사자처럼
- Java
- 제작기
- 값 타입
- 반복문 탈출
- PDFBOX
- spring
- 스프링부트 쇼핑몰 프로젝트
- DOCS
- GitFlow
- PDF병합
- Git
- 알고리즘
- 연관관계
- orm
- querydsl
- Visual Basic
- springboot
- spring jpa
- break-label
- JPA
- Hibernate
- 부트캠프
- 프로그래머스
- 테킷
- 체인호출
- Today
- Total
섭섭한 개발일지
[SpringBoot RestAPI] Controller에서 json(dto)과 multipart 동시 요청 본문
jdk : 17
springboot : 3.2.1
사이드 프로젝트 개발 중 문의사항 등록 부분에서 데이터를 title, content, 이미지를 받아와야 하는 상황이 생겼다.
rest로 개발을 하는 중에 있어 postman을 통해 테스트를 해보던 중 미디어 타입의 문제가 발생했다.
초기 코드
// Controller
@PostMapping("/save")
@Operation(summary = "문의사항 등록")
public ResponseEntity<QuestionSaveResponse> saveQuestion(@RequestBody QuestionRequest questionRequest,
@AuthenticationPrincipal UserPrincipal user) {
QuestionSaveResponse response = questionService.saveQuestion(questionRequest, user.getMember());
return ResponseEntity.ok(response);
}
// DTO
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Schema(description = "문의사항 등록 요청 항목")
public class QuestionRequest {
@Schema(description = "문의사항 제목")
private String title;
@Schema(description = "문의사항 내용")
private String content;
private List<MultipartFile> files;
public static Question toEntity(QuestionRequest request, Member member) {
return Question.builder()
.title(request.getTitle())
.content(request.getContent())
.member(member)
.build();
}
public static Question toEntity(QuestionRequest request) {
return Question.builder()
.title(request.getTitle())
.content(request.getContent())
.build();
}
}
위와 같은 코드로 아래와 같은 에러가 발생했다.
무슨 문제일까?
콘솔에서 에러메세지를 확인할 수 있었다.
MediaType과 관련된 오류...
키워드를 통해 참고할 만한 글들을 봤다. (참고 글 : https://middleearth.tistory.com/35)
Multipart를 사용하면 @RequestBody가 아닌 @RequestPart를 통해서 받아야 한다는 것을 확인했다.
코드를 아래와 같이 수정했다.
1차 수정 코드
@PostMapping("/save/test")
@Operation(summary = "문의사항 등록")
public ResponseEntity<QuestionSaveResponse> saveQuestionTest(@RequestPart QuestionRequest questionRequest) {
QuestionSaveResponse response = questionService.saveQuestion(questionRequest, questionRequest.getFiles());
return ResponseEntity.ok(response);
}
이번에 서버문제..
콘솔을 확인해보니
questionRequest가 없단다
생각해 보니 당연히 없는 게 맞다.
RequestBody는 json type의 데이터를 java object로 파싱을 해주는데
지금 데이터는 json이 아닌 게 아닌가..
그럼 어떻게 수정을 해야 할까 하다가 서버사이드로 진행한 프로젝트와 같은 방식으로 dto 내부에 files를 두는 게 아닌 파라미터로 받는 선택을 했다.
2차 수정 코드
@PostMapping("/save/test")
@Operation(summary = "문의사항 등록")
public ResponseEntity<QuestionSaveResponse> saveQuestionTest(@RequestBody QuestionRequest questionRequest,
@RequestPart List<MultipartFile> files) {
QuestionSaveResponse response = questionService.saveQuestion(questionRequest, files);
return ResponseEntity.ok(response);
}
그렇다면 데이터가 파싱되는 형태를 json으로 처리를 할 수 있으니 dto는 @RequestBody로 어노테이션을 변경했다.
테스트 해보자
흠..... 왜그러는걸까.. 콘솔을 보니
또 타입 오류다.. 이게 왜 안될까 고민을 하다 조금의 시간이 지난 뒤 깨달았다.
@RequestBody와 @RequestPart는 같이 사용할 수 없다는 것을.. (참고 게시글 : https://okky.kr/questions/1212782)
결론
@RequestPart를 사용하기 위해서는 dto 또한 @RequestBody가 아닌 @RequestPart를 통해서 받아와야 한다.
최종적으로 작성된 코드와 포스트맨은 아래와 같다.
최종 수정 코드
@PostMapping("/save/test")
@Operation(summary = "문의사항 등록")
public ResponseEntity<QuestionSaveResponse> saveQuestionTest(@RequestPart QuestionRequest questionRequest,
@RequestPart List<MultipartFile> files) {
QuestionSaveResponse response = questionService.saveQuestion(questionRequest, files);
return ResponseEntity.ok(response);
}
후기
코드가 나만 불편한 건지 모르겠다..
팀원분과 이야기를 나눴을 때는 이 방식으로 결국 가야겠다고 결론을 내리기는 했지만
뭔가 마음에 들지 않는다..
dto 안에서 files까지 파싱을 해서 처리를 한다고 하면 컨트롤러의 파라미가 깔끔해지고 @Schema 를 통해 명확하게 역할을 알 수 있는데
이건 처음 보는 사람이 한눈에 파악을 하기에는 어렵지 않을까? 라는 고민이 있다.
프로젝트를 진행하면서 다른 방법이 있는지 알아보는 걸로 하고 우선 마무리를 하자
'프로그래밍 > Spring' 카테고리의 다른 글
[Swagger] Java DTO를 Record로 사용 시 Swagger 오류 (0) | 2024.07.19 |
---|---|
[SpringBoot RestAPI] 반환 객체 proxy 에러 hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor (0) | 2024.03.01 |