본문 바로가기
PlayGround/마실가실 리팩토링

[1년 후 마실가실] Custom Exception

by HJ0216 2024. 8. 10.

1년 전 진행했던 마실가실 프로젝트를 🛠️리팩토링하며 정리한 내용입니다.

 

회원 가입을 진행할 때, Email 중복 검사하는 로직을 추가했습니다.

 

처음에는 Email로 조회해서 리스트의 갯수가 0일 경우 통과하는 로직으로 작성했습니다.

그 다음으로는 JPA 강의를 들으면서 정리한 코드를 살펴보았는데,

Exceopion이 왜 거기서 나와...?

 

public void validateDuplicateMember(Member member) {
    List<Member> findMembers = memberRepository.findByName(member.getName());
    if(!findMembers.isEmpty()){
        throw new IllegalStateException("이미 존재하는 회원입니다.");
    }
}

 

그대로 코드를 사용할 수는 있지만, IllegalStateException 대신 CustomException을 사용해보고 싶었습니다.

왜냐면 HttpStatus도 함께 사용하는 멋진 코드를 발견했기 때문이죠.

 

그렇기에 이 글을

  1. Error Code를 Enum 형태로 만들고
  2. CustomException을 만들어
  3. Test Code를 작성해 본다

를 정리한 글입니다.

 

 

1. Error code Enum 생성

package com.msgs.msgs.error;

import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public enum ErrorCode {

    // 회원
    CHECK_LOGIN_ID_OR_PASSWORD(HttpStatus.NOT_FOUND, "아이디 또는 비밀번호를 확인해주세요."),
    DUPLICATED_EMAIL(HttpStatus.BAD_REQUEST, "이미 존재하는 이메일 입니다.");

    private final HttpStatus httpStatus;
    private final String message;

    ErrorCode(HttpStatus httpStatus, String message) {
        this.httpStatus = httpStatus;
        this.message = message;
    }
}

 

제가 알던 Enum과는 모양이 달라서 많이 놀랐습니다.

 

Enum은 아래와 같이 간단한 열거형만 써봤기 때문이죠.

public enum ErrorCode {
    CHECK_LOGIN_ID_OR_PASSWORD,
    DUPLICATED_EMAIL,
}

 

Enum 요소에 특정 값을 연결하려면 필드값을 추가해주면 됩니다.

 

Enum과 필드값을 매핑해주면, if문의 사용을 줄여 가독성을 높일 수 있습니다.

 

이 때, 유의해야 할 점은 반드시 Enum 값 선언 이후에 이후에 필드/생성자가 위치해야 한다는 것입니다.

그리고 Enum class에서 자체적으로 name()를 제공하기 때문에, 필드값을 name을 사용하지 않는 것이 좋습니다.

 

+ Enum은 Enum 값으로 데이터를 찾을 수 있지만 필드의 경우에는 따로 메서드를 만들어 줘야 합니다.

// HttpStatus -> ErrorCode 조회
private static final Map<HttpStatus, ErrorCode> BY_HTTPSTATUS =
        Stream.of(values()).collect(Collectors.toMap(ErrorCode::getHttpStatus, e -> e));

public static Optional<ErrorCode> valueOfHttpStatus(HttpStatus httpStatus){
    return Optional.ofNullable(BY_HTTPSTATUS.get(httpStatus));
}

// Message -> ErrorCode 조회
private static final Map<String, ErrorCode> BY_MESSAGE =
        Stream.of(values()).collect(Collectors.toMap(ErrorCode::getMessage, e -> e));

public static Optional<ErrorCode> valueOfMessage(String message){
    return Optional.ofNullable(BY_MESSAGE.get(message));
}

 

 

2. CustomException 생성

ErrorCode를 받아주는 CustomException을 만들어줍니다.

@Getter
public class BusinessException extends RuntimeException{
    private ErrorCode errorCode;

    public BusinessException(ErrorCode errorCode) {
        this.errorCode = errorCode;
    }
}

 

RuntimeException도 상속을 받습니다.

 

3. Test Code 작성

1 기능, 1 테스트 코스..

특히 테스트 코드는 익숙하지 않기 때문에 기능에 맞춰 계속 추가해 볼 예정입니다.

 

@SpringBootTest
@Transactional
public class UserServiceTest {

	// ...

    @Test
    @DisplayName("이메일이 동일한 회원이 존재할 경우, 예외가 발생한다.")
    public void emailDuplicateCheck() throws Exception {
        // given
        User userA = new User();
        userA.setStatus("M");
        userA.setEmail("test@email.com");
        userA.setPhone("01023456789");
        userService.create(userA);

        String existingEmail = "test@email.com";

        // when

        // then
        BusinessException exception = assertThrows(BusinessException.class,
                () -> userService.emailDuplicateCheck(existingEmail));
        assertEquals(DUPLICATED_EMAIL, exception.getErrorCode());
    }
}

 

 

 

🙋‍♀️

본 포스트는 공부 목적으로 작성하였습니다.
보시는 도중 잘못된 부분이나 개선할 부분이 있다면 댓글로 알려주시면 수정하도록 하겠습니다.

 

📑

참고 자료

 

Java Enum 1편 : Enum 기본적인 사용

1. Overview Java Enum 타입은 일정 개수의 상수 값을 정의하고, 그 외의 값은 허용하지 않습니다. 과거에는 특정 상수값을 사용하기 위해선 모두 상수로 선언해서 사용했습니다. public static final String M

bcp0109.tistory.com

 

GitHub - dbswhd4932/shoppingmall_project: Java Springboot Jpa 를 이용한 쇼핑몰 API 프로젝트

Java Springboot Jpa 를 이용한 쇼핑몰 API 프로젝트. Contribute to dbswhd4932/shoppingmall_project development by creating an account on GitHub.

github.com