기존에는 User not found
와 같이 예외 메세지를 문자열로 직접 사용하여, 동일한 예외 문구라도 여러 곳에서 동일한 내용을 작성해야하는 문제가 존재함.
enum
을 이용하여 예외 메세지를 한 곳에서 수정, 관리하도록 변경CommonErrorCode
로 메세지를 설정public class InvalidRequestException extends RuntimeException {
public InvalidRequestException(String message) {
super(message);
}
}
@Getter
public enum CommonErrorCode {
// InvalidRequestException
UNREGISTERED_USER("가입되지 않은 유저입니다."),
TODO_NOT_FOUND("Todo not found"),
MANAGER_NOT_ALLOWED("담당자를 등록하려고 하는 유저가 일정을 만든 유저가 유효하지 않습니다."),
MANAGER_NOT_FOUND("등록하려고 하는 담당자 유저가 존재하지 않습니다."),
TODO_CREATOR_CANNOT_BE_MANAGER("일정 작성자는 본인을 담당자로 등록할 수 없습니다.")
;
private final String message;
CommonErrorCode(String message) {
this.message = message;
}
}
// 기존코드
User user = userRepository.findById(userId)
.orElseThrow(() -> new InvalidRequestException("User not found"));
// 수정된 코드
User user = userRepository.findById(userId)
.orElseThrow(() -> new InvalidRequestException(USER_NOT_FOUND));
response
변환 로직을 반복적으로 사용됨service의 책임
이 커짐response
내부에 toDto
정적 메서드를 생성하여 변환 로직을 캡슐화public TodoResponse getTodo(long todoId) {
Todo todo = todoRepository.findByIdWithUser(todoId)
.orElseThrow(() -> new InvalidRequestException(TODO_NOT_FOUND));
User user = todo.getUser();
return new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.getContents(),
todo.getWeather(),
new UserResponse(user.getId(), user.getEmail()),
todo.getCreatedAt(),
todo.getModifiedAt()
);
}
public static TodoResponse toDto(Todo todo){
return new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.getContents(),
todo.getWeather(),
new UserResponse(todo.getUser().getId(), todo.getUser().getEmail()),
todo.getCreatedAt(),
todo.getModifiedAt()
);
}
public TodoResponse getTodo(long todoId) {
Todo todo = todoRepository.findByIdWithUser(todoId)
.orElseThrow(() -> new InvalidRequestException(TODO_NOT_FOUND));
return TodoResponse.toDto(todo);
}
toDto
메서드를 재사용하여 코드의 중복을 줄임TodoResponse
에서 todo가 TodoResponse로 변환하는 과정을 처리하여 service
의 역할이 명확해짐할일 생성
이라는 기능을 위해서 요청 데이터를 그대로 service로 넘김Command
를 생성하여 할일 생성
에 필요한 매개변수를 정확히 정의command
를 이용하도록 변경 @PostMapping("/todos")
public ResponseEntity<TodoSaveResponse> saveTodo(
@Auth AuthUser authUser,
@Valid @RequestBody TodoSaveRequest todoSaveRequest
) {
return ResponseEntity.ok(todoService.saveTodo(authUser, todoSaveRequest));
@Getter
@AllArgsConstructor
public class CreateTodoCommand {
private AuthUser authUser;
private String title;
private String contents;
public Todo toDomain(String weather, User user){
return new Todo(this.title, this.contents, weather, user);
}
}
@PostMapping("/todos")
public ResponseEntity<TodoSaveResponse> saveTodo(
@Auth AuthUser authUser,
@Valid @RequestBody TodoSaveRequest todoSaveRequest
) {
CreateTodoCommand command =
new CreateTodoCommand(authUser, todoSaveRequest.getTitle(), todoSaveRequest.getContents());
return ResponseEntity.ok(todoService.saveTodo(command));
}
@Transactional
public TodoSaveResponse saveTodo(CreateTodoCommand command) {
User user = User.fromAuthUser(command.getAuthUser());
String weather = weatherClient.getTodayWeather();
Todo newTodo = command.toDomain(weather, user);
Todo savedTodo = todoRepository.save(newTodo);
return TodoSaveResponse.toDto(savedTodo);
}
command
를 생성하여 클라이언트의 요청
과 작업
을 명확히 분리 가능객체 생성
을 command
로 분리하여 service의 역할을 명확히 함