OOP & JAVA

[JAVA] 예외처리 및 예시(결제 시스템)

쉽코기 2021. 12. 4. 22:07

기본적인 예외처리 방법과 함께 예외처리로 구현한 결제 시스템 예시를 정리해 보았습니다.

 

 

예외상속도

1. try / catch / finally  문

  • 에러가 발생할 경우 직접 에러를 해결하는 방법이다.
  • try 에서 에러가 발생했을 경우 catch에 명시된 에러의 종류일 경우 이를 받아 처리할 수 있다. 
  • 예외 상속도 에 따라 상위 에러일 경우 하위 에러를 받아서 처리합니다.
  • 해당 예외를 받는 catch 블럭이 없을 경우 스택 블럭을 타고 내려가면서 해당 에러를 처리할 수 있는 catch 블럭을 찾습니다.
  • 메인 함수까지 올라가서 에러를 캐치하지 않으면 에러가 터져 프로그램이 종료합니다.

 

try{

//예외가 발생할 수 있는 코드

} catch(에러클래스1 에러변수1){

// 처리 코드

} catch(애러클래스2 에러변수2){

// 처리코드

}

 

2. throws 를 통한 예외 발생

:  다음 과 같이 에러를 사용자가 발생 시킬 수 도 있습니다.

 

 if (super.getAmount() < 0) {
                throw new RuntimeException("overflow 발생");
            } else {
                return true;
            }

 

3. 사용자 정의 예외 만들기

  • 상황에 따라서 사용자가 자신만의 에러를 만들어 사용할 수 있습니다.
  • 쓰임에 따라 원하는 예외 클래스를 상속받아 커스텀 상속클래스를 생성합니다.

 

// OverflowException.java
public class OverflowException extends RuntimeException {
    private static final long serialVersionUID = 1222179582713735628L;

    public OverflowException(String message) {
        super(message);
    }
}
//main 함수
if (super.getAmount() < 0) {
                throw new OverflowException("overflow 발생");
            } else {
                return true;
            }

 

4. Checked / UnChecked 예외

 

  • UnChecked 예외는 예외 상속도중 Runtime 예외와 그를 상속받는 모든 클래스를 말합니다.
  • Checked 예외는 예외중 이를 제외한 에러들을 말합니다.
  • Checked 예외를 발생 시킬 때에는 try-catch 문으로으로 throw절을 감싸거나
  • throw 절이 포함된 메서드 시그내처 옆에 throws <예외클래스>를 명시해야만 합니다.

 

 

 

illegalArgumentException 은 예외 상속도중 runtime 을 상속받지 않으므로 checked 이고 이를 사용하기 위해 thrwos를 붙여 사용한 예시입니다.

 public Wallet(final User user) throws IllegalAccessException {
        if (user == null) {
            throw new IllegalArgumentException("user cannot be null");
        }
    }

 

5.  예외처리 예제 - 결제시스템 

 

결재 과정 중간에 결재에 실패 했을때 야기되는 문제를 예외처리를 통해 해결 해보았습니다.

 

  1. 상품의 금액 만큼 사용자의 계좌에서 금액을 차감한다.
  2. 재품의 재고 수량을 한개 줄인다.

 만약 이 결재 과정중 1번을 진행 했지만 2번을 진행하던 중 재고 수량이 없을 경우 사용자의 계좌에 돈을 다시 돌려주어야합니다.

 결재를 진행하기 앞서 수량을 확인한다 하더라도 다른 사용자가 먼저 결재를 해 수량이 없어지는 경우가 생길 수가 있습니다.

 

<제품이 있다면>

  1. 지갑에서 상품의 가격만큼 차감한다.
  2. 창고에서 해당 제품을 제거한다.

 

<제품없다면>

  1. 지갑에서 상품의 가격만큼 차감한다.
  2. 창고에서 해당 제품을 제거하는 과정중 removeProduct 내부에서 ProductNotFoundException(Rumtime 을 상속받음) 을 발생시킨다.
  3. removeProduct 내부에서 발생한 예외는 스택 블럭을 타고 메인함수의 그자리로 넘어와 터지고 catch에서 받아진다.
  4. 지갑에 상품의 가격만큼을 다시 더해줍니다.

 

// main.java
 
wallet.withdraw(product.getPrice());

try {
	warehouse.removeProduct(product.getId());
	} catch (ProductNotFoundException e) {
		wallet.deposit(product.getPrice());
    }

 

//warehouse.java

...

public void removeProduct(final UUID id) {
        for (int i = 0; i < this.products.size(); ++i) {
            if (this.products.get(i).getId().equals(id)) {
                this.products.remove(i);

                if (isProductOutOfStockMock(i)) {
                    throw new ProductNotFoundException("Product not found!");
                }
            }
        }
    }

 

 

 

참고 : https://finewoo.tistory.com/22