[Trouble Shooting] Controller 와 Service의 강한 결합

FeelingXD·2023년 5월 26일
0

1트러블슈팅

목록 보기
2/2
post-thumbnail

❌ 문제

//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());
  }

참고자료

우아한 기술블로그 - 잊을만 하면 돌아오는 정산 신병들

profile
tistory로 이사갑니다. :) https://feelingxd.tistory.com/

0개의 댓글