관리 메뉴

ballqs 님의 블로그

[Spring] CustomException , ErrorCode 작성 및 적용 본문

코딩 공부/Spring

[Spring] CustomException , ErrorCode 작성 및 적용

ballqs 2024. 9. 5. 17:42

뉴스피드 프로젝트를 진행할 때 여러모로 작성해두었던 예외처리들이 많이 지저분해보여서 CustomException 작성 등 ErrorCode 를 Enum으로 관리해서 코드를 바꾸기로 했다.


수정 전 UserService.java 의 한 메서드

// 회원 탈퇴
public void deleteAccount(AuthUser authUser, UserUnregisterDto userUnregisterDto) {
    // 사용자 조회
    User user = userRepository.findById(authUser.getUserId())
            .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다."));

    if (!user.getEmail().equals(authUser.getEmail())) {
        throw new IllegalArgumentException("이메일이 일치하지 않습니다.");
    }

    // 비밀번호 확인
    if (!passwordEncoder.matches(userUnregisterDto.getPassword(), user.getPassword())) {
        throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
    }

    // 이미 탈퇴한 사용자 확인
    if (user.getStatus() == UserStatusEnum.REMOVE) {
        throw new IllegalArgumentException("이미 탈퇴한 사용자입니다.");
    }

    friendRepository.deleteByBaseIdOrFriendId(user, user);

    // 사용자 상태를 탈퇴 상태로 변경
    user.updateStatus(UserStatusEnum.REMOVE);
    userRepository.save(user);
}

 

해당 코드를 보면 Exception 처리 부분에 String으로 들어간것도 많고 많이 지저분해보인다.

이를 해결하기 위해 클린 코드 형태로 바꿔보고자 노력했다.


수정 후 UserService.java 의 한 메서드

 

ErrorCode 작성

@Getter
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ErrorCode {

    // 400 Bad Request: 클라이언트의 요청이 잘못되어 서버가 처리할 수 없을 때 발생하는 에러입니다. 주로 파라미터나 요청 형식의 오류에 사용됩니다.
    SELF_FRIEND_REQUEST_NOT_ALLOWED(400,"자신에게 친구 요청을 할 수 없습니다."),
    SELF_FRIEND_REQUEST_APPROVAL_NOT_ALLOWED(400,"자신에게 친구 요청을 승인할 수 없습니다."),
    CANNOT_LIKE_OWN_BOARD(400,"본인의 게시물은 좋아요를 누를 수 없습니다."),
    LIKE_LIMIT_EXCEEDED(400,"좋아요가 이미 눌려진 상태입니다."),
    LIKE_NOT_FOUND(400,"좋아요가 눌러지지 않은 게시물입니다."),
    INVALID_PASSWORD_FORMAT(400,"비밀번호는 대소문자 포함 영문, 숫자, 특수문자를 최소 1글자씩 포함하며, 최소 8글자 이상이어야 합니다."),
    INVALID_EMAIL_OR_PASSWORD(400,"이메일 혹은 비밀번호가 맞지 않습니다."),
    EMAIL_NOT_MATCHED(400,"이메일이 일치하지 않습니다."),
    PASSWORD_NOT_MATCHED(400,"비밀번호가 일치하지 않습니다."),
    CURRENT_PASSWORD_NOT_MATCHED(400,"현재 비밀번호가 일치하지 않습니다."),
    NEW_PASSWORD_SAME_AS_OLD(400,"새로운 비밀번호는 현재 비밀번호와 동일할 수 없습니다."),
    USER_ALREADY_WITHDRAWN(400,"이미 탈퇴한 사용자입니다."),
    ALREADY_LIKED_COMMENT(400,"이미 이 댓글에 좋아요를 눌렀습니다."),
    FRIEND_REQUEST_NOT_FOUND(400,"친구요청을 찾지 못했습니다."),
    LIKE_DOES_NOT_EXIST(400,"좋아요가 존재하지 않습니다."),
    ALREADY_FRIEND_NOT_DELETE(400 , "친구인 회원을 삭제 및 반려 처리할 수 없습니다."),

    // 403 Forbidden: 서버가 요청을 이해했지만, 클라이언트에게 그 요청을 실행할 권한이 없을 때 발생합니다.
    NOT_A_FRIEND(403,"친구가 아닙니다."),
    AUTHOR_ONLY_CAN_DELETE(403,"작성자만 삭제할 수 있습니다."),
    AUTHOR_ONLY_CAN_EDIT(403,"작성자만 수정할 수 있습니다."),
    COMMENT_AUTHOR_ONLY_CAN_EDIT(403,"작성자 본인만 댓글을 수정할 수 있습니다."),
    COMMENT_AUTHOR_ONLY_CAN_DELETE(403,"작성자 본인만 댓글을 삭제할 수 있습니다."),

    // 404 Not Found: 요청한 리소스를 찾을 수 없을 때 발생합니다.
    BOARD_NOT_FOUND(404, "게시물을 찾을 수 없습니다."),
    USER_NOT_FOUND(404, "유저를 찾을 수 없습니다."),
    COMMENT_NOT_FOUND(404, "댓글을 찾을 수 없습니다."),
    FRIEND_NOT_FOUND(404 , "친구가 없습니다."),

    // 409 Conflict: 현재 상태와 충돌하는 요청일 때 사용됩니다. 예를 들어, 중복된 자원이나 이미 존재하는 항목을 생성하려고 할 때 발생합니다.
    ALREADY_FRIEND(409,"이미 친구입니다."),
    ALREADY_FRIEND_REQUESTED(409,"이미 친구 요청을 하였습니다."),
    EMAIL_ALREADY_REGISTERED(409,"이미 등록된 이메일입니다."),

    // 500
    INTERNAL_SERVER_ERROR(500,"서버 에러");

    private final int status;
    private final String message;

    ErrorCode(final int status, final String message) {
        this.status = status;
        this.message = message;
    }
}

 

UserInvalidException 작성(Custom Exception Class) -> 다른 예외처리도 아래와 같이 비슷하게 작성

public class UserInvalidException extends BadRequestException {
    public UserInvalidException(ErrorCode errorCode) {
        super(errorCode);
    }
}

 

UserRepository에도 findById 마다 Exception 처리해두는 것이 지저분해서 아래와 같이 작성

public interface UserRepository extends JpaRepository<User, Long> {
    default User findByIdOrElseThrow(long userId) {
        return findById(userId).orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
    }
}

 

UserService 의 메서드가 수정

// 회원 탈퇴
public void deleteAccount(AuthUser authUser, UserUnregisterDto userUnregisterDto) {
    // 사용자 조회
    User user = userRepository.findByIdOrElseThrow(authUser.getUserId());

    if (!user.getEmail().equals(authUser.getEmail())) {
        throw new UserInvalidException(ErrorCode.EMAIL_NOT_MATCHED);
    }

    // 비밀번호 확인
    if (!passwordEncoder.matches(userUnregisterDto.getPassword(), user.getPassword())) {
        throw new UserInvalidException(ErrorCode.PASSWORD_NOT_MATCHED);
    }

    // 이미 탈퇴한 사용자 확인
    if (user.getStatus() == UserStatusEnum.REMOVE) {
        throw new UserInvalidException(ErrorCode.USER_ALREADY_WITHDRAWN);
    }

    friendRepository.deleteByBaseIdOrFriendId(user, user);

    // 사용자 상태를 탈퇴 상태로 변경
    user.updateStatus(UserStatusEnum.REMOVE);
    userRepository.save(user);
}

마무리

ErrorCode 에 enum으로 작성해두어서 Custom Exception 작성하여 해보니 뭔가 코드가 많이 깔끔해진것 같기도하다.

이것 자체가 클린 코드는 아닐수 있지만 좀더 깔끔해진것에 의미를 두기위해 이렇게 작성할수도 있다는 것을 남기려고 쓴다.

좀 더 많이 코드를 작성해봐야 이보다 더 깔끔한 코딩이 되지 않을까 한다.