//Controller
public ResponseEntity<?> putDiary(@PathVariable Long id,@RequestBody DiaryForm form) { //기존 코드
URI location = ServletUriComponentsBuilder.fromCurrentRequest().build(id);
var result =diaryService.putDiary(id,form);
// . .logic
}
//Service
@Override
public Diary putDiary( Long id, DiaryForm form) {
// ..생략
if (!Objects.equals(diary.getUser().getId(), user.getId())) {
throw new CustomException(ErrorCode.NOT_AUTHORIZED);
}
diary.setContent(form.getContent());
diary.setTitle(form.getTitle());
return diaryRepository.save(diary);
}
기존 컨트롤러 레이어에서 사용자의 입력을 DiaryForm 으로 받아 form을 Service 레이어로 바로 넘겨주었었다.
이러한 경우 만약 서비스 정책등의 변경으로 form 구조가 변경되면 form 에의존하고있는 Service 메서드(getter,setter)등 을 모두 변경을 해야하고 서비스로직또한 수정 해야한다.
기존 service와 controller 에서 같이사용하는 form 을 service에서는 form으로 받되 controller 에서는 form 데이터를 적재해서 사용하는 dto클래스를 하나 추가하여 controller 레이어에서는 form 을 service레이어에서는 form 데이터를 적재한 dto클래스를 넘겨주어 사용하는 방법으로 변경하여 추후 사용자정책이 변경되어도 form 과 dto의 매핑 부분만 수정하면 문제없이 작동하도록 변경하였다.
//form
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@Getter
public class DiaryForm {
private String title;
private String content;
private String isPublic;
public static DiaryRequestDto toDiaryRequestDto(DiaryForm form) {
return DiaryRequestDto.builder()
.title(form.getTitle())
.content(form.getContent())
.isPublic(!form.getIsPublic().isBlank())
.build();
}
}
//추가된 dto
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@Getter
public class DiaryRequestDto {
private String title;
private String content;
private boolean isPublic;
public static Diary toEntity(DiaryRequestDto dto) {
return Diary.builder()
.title(dto.getTitle())
.content(dto.getContent())
.isPublic(dto.isPublic)
.build();
}
}
//controller
@PutMapping("/{id}")
public ResponseEntity<?> putDiary(@AuthenticationPrincipal User user, @PathVariable Long id,
@RequestBody DiaryForm form) {
URI location = ServletUriComponentsBuilder.fromCurrentRequest().build(id);
var result = diaryService.putDiary(user, id, DiaryForm.toDiaryRequestDto(form));
// 서비스 메서드로 기존의 form 대신 dto로 변경해서 넘겨줌
return ResponseEntity.ok().body(
ApiResponse.builder()
.code(ResponseCode.RESPONSE_CREATED)
.data(DiaryResultDto.of(result))
.build());
}
우아한 기술블로그 - 잊을만 하면 돌아오는 정산 신병들