스프링 예외 처리

바그다드·2023년 7월 27일
0

예외

목록 보기
8/9

지난 포스팅에서 자바 예외처리에 대해 알아보았다. 이번 포스팅에서는 인터페이스 활용에 있어서 체크 예외와 언체크 예외에 따라 어떻게 바뀌는지 알아보고자 한다.

1. 체크 예외

Repository 인터페이스 생성

public interface MemberRepositoryEx {
    Member save(Member member) throws SQLException;
    Member findById(String memberId) throws SQLException;
    void update(String memberId, int money) throws SQLException;
    void delete(String memberId) throws SQLException;
}
  • 인터페이스에 예외가 선언되어 있다.

Repository 구현체 생성

	/*생략*/
	public Member save(Member member) throws SQLException {
        String sql = "insert into member(member_id, money) values (?,?)";

        Connection con = null;
        PreparedStatement pstmt = null;

        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1, member.getMemberId());
            pstmt.setInt(2, member.getMoney());
            pstmt.execute();
            return member;
        } catch (SQLException e) {
            log.error("db error", e);
            throw e;
        }finally {
            close(con, pstmt, null);

        }
    }
    /*생략*/
  • 구현체에서도 SQLException을 던지고 있다.

Service 로직

그렇다면 Repository를 활용하는 Service는 어떨까?

@Slf4j
public class MemberServiceV3_3 {
	
    /*생략*/

    private void bizLogic(String fromId, String toId, int money) throws SQLException {
        Member fromMember = memberRepository.findById(fromId);
        Member toMember = memberRepository.findById(toId);

        memberRepository.update(fromId, fromMember.getMoney() - money);
        validation(toMember);
        memberRepository.update(toId, toMember.getMoney() + money);
    }
}
  • 순수 자바 코드로 이뤄져야할 서비스 로직이 SQLException이라는 특정 기술에 종속되어 있는 문제가 있다.

체크 예외의 경우 일종의 표준인 인터페이스가 특정 기술에 종속되어 있다. 만약 JDBC가 아닌 다른 기술을 사용하게 된다면 인터페이스 자체를 바꿔야 하는 문제가 생긴다.
특히 순수 자바 코드를 유지해야할 서비스가 특정 기술에 종속된다는 문제가 있다.

그렇다면 런타임 예외의 경우에는 어떨까?
먼저 서비스를 순수 자바 코드로 구축할 수 있다.
또 인터페이스에 예외를 선언하지 않아도 된다. 따라서 인터페이스가 특정 기술에 종속되지 않는다.
코드로 확인해보자.

2. 런타임 예외(언체크 예외)

Repository 인터페이스 생성

public interface MemberRepository {
    Member save(Member member);
    Member findById(String memberId);
    void update(String memberId, int money);
    void delete(String memberId);
}
  • 순수 인터페이스의 형태를 가지고 있다.
    즉, 특정 기술에 종속되어 있지 않다.

런타임 예외 클래스 생성

  • 순수 서비스 로직을 유지하기 위해 생성해주자.
public class MyDbException extends RuntimeException{
    public MyDbException() {
    }

    public MyDbException(String message) {
        super(message);
    }

    public MyDbException(String message, Throwable cause) {
        super(message, cause);
    }

    public MyDbException(Throwable cause) {
        super(cause);
    }
}

Repository 구현체 생성

	/*생략*/
    @Override
    public Member save(Member member) {
        String sql = "insert into member(member_id, money) values (?,?)";

        Connection con = null;
        PreparedStatement pstmt = null;

        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            pstmt.setString(1, member.getMemberId());
            pstmt.setInt(2, member.getMoney());
            pstmt.execute();
            return member;
        } catch (SQLException e) {
            throw new MyDbException(e);
        }finally {
            close(con, pstmt, null);

        }
    }
    /*생략*/
  • SQLException을 앞서 생성한 MyDbException으로 변환한 것을 주목하자.
    런타임 예외를 던지고 있으므로 예외 선언을 하지 않아도 된다.
  • 메서드를 상속받아 사용하는 경우 @Override를 선언해주자.
    그래야 혹시 에러가 있을 경우 컴파일러가 체크할 수 있다.

그럼 서비스 로직은 어떻게 되어 있을까?

Service 로직

@Slf4j
public class MemberServiceV4 {

	/*생략*/
    
    private void bizLogic(String fromId, String toId, int money) {
        Member fromMember = memberRepository.findById(fromId);
        Member toMember = memberRepository.findById(toId);

        memberRepository.update(fromId, fromMember.getMoney() - money);
        validation(toMember);
        memberRepository.update(toId, toMember.getMoney() + money);
    }
}
  • 순수 자바 코드로 이루어져 있다.
    체크 예외와 달리 서비스 로직이 특정 기술(JDBC)에 종속되어 있지 않기 때문이다.

런타임 예외를 활용하면서 인터페이스와 서비스의 순수성을 유지할 수 있게 되었다.
따라서 향후 구현체를 변경하더라도 서비스 로직을 변경하지 않아도 된다.

그런데 만약 특정 상황에서 예외를 잡아서 다른 처리를 하고 싶다면 예외를 어떻게 구분하고, 또 각 예외에 따라 처리를 할 수 있을까?

이번 포스팅에서는 스프링에서 예외의 종류에 따라 코드가 어떻게 변하게 되는지 알아보았다. 다음 포스팅에서는 각 예외를 구분하여 처리하는 방법과, 거기서 발생하는 문제에 대해서 알아보도록 하자.

profile
꾸준히 하자!

0개의 댓글