기존에는 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의 역할을 명확히 함