외부 시스템을 이용하는 경우 불안하거나 경우에 따라서 장애가 발생해서 일시적으로 예외를 던지는 경우
피크타임에 터질 수 있으니깐 재시도를 한 두번 더 해봄으로 정상적인 흐름으로 복구할 수 있음
대안
환율 정보 서비스를 예로 들면 터질 수도 있으니까 두개 정도의 환율 정보 서비스를 준비하는 것
장애가 일어났을때 대체를 하거나 부하가 걸릴 것을 대비해 부하를 분산해놓는 방법
두가지 서버가 다 안될 경우 캐시해놓은 환율 정보를 대안으로 쓸 수 있음
버그인가?
버그인 경우 정상 흐름으로 돌릴 수 없음
예외가 발생한 코드의 버그인가
null이면 null 체크하면 되니까
클라이언트의 버그인가
클라이언트의 버그일 경우 친절한 예외 메세지를 예외에 담아서 던지도록 해야함
제어할 수 없는 예외 상황인가
예외를 잘못 다루는 코드
예외를 무시하는 코드
try {
...
}
catch(SQLException e) {
/// 예외를 catch하면 복구하거나 예외를 밖으로 던져서 로그로 확인할 수 있게 해야함
}
try {
...
}
catch(SQLException e) {
// 화면에 출력하기만 하고 끝나는 코드는 아무것도 안하는 것과 마찬가지
// why? 콘솔에 출력하는게 전부라면 아래쪽에서 또다른 예외가 발생할 확률 높음, 논리적인 버그 발생
e.printStackTrace();
}
무의미하고 무책임한 throws
진입점까지 throws가 되고 어떤 예외가 발생하는지 정보가 없어짐
public void method1() throws Exception {
method2();
}
public void method2() throws Exception {
method3();
}
public void method3() throws Exception {
.....
}
예외의 종류
Error
시스템에 비정상적인 상황이 발생
OutOfMemoryError
JVM이 메모리를 모두 사용했을 때 발생
ThreadDeath
스레드가 갑작스럽게 종료될 때 발생
이제 거의 사용되지 않음
Exception(checked)
catch나 throws를 강요
초기 라이브러리의 잘못된 예외 설계/사용
점점 사용하지 않는 쪽으로 흘러감
복구할 수 없다면 RuntimeException이나 적절한 추상화 레벨의 예외로 전환해서 던질 것
RuntimeException(unchecked)
예외의 추상화와 전환
사용 기술에 따라 같은 문제에 대해 다른 종류의 예외 발생
예시 ) 데이터베이스 접근 시 JDBC를 사용하면 SQLException이 발생하지만, JPA를 사용하면 PersistenceException이 발생할 수 있음
적절한 예외 추상화와 예외 번역이 필요
기술이 바뀌면 예외도 바뀌어야 함
상위 수준의 추상화된 예외로 변환
상황이 같다면 같은 번역의 예외가 필요하기 때문
동일한 상황에서는 일관된 예외가 발생하도록 해야 함
JPA Repository - 애플리케이션 인프라스트럭처 빈
데이터소스는 한개만 있으면 됨
데이터소스(DataSource)는 데이터베이스 연결 풀을 관리하는 객체로, 애플리케이션에서 데이터베이스에 접근하기 위해 필요
싱글톤, 빈
엔티티매니저는 매 트랜잭션마다 새로운게 만들어져야함
스프링 빈으로 등록되는건 아님
엔티티 매니저는 상태를 가지며, 트랜잭션이 끝나면 해당 상태를 유지할 필요가 없기 때문에 새로운 트랜잭션마다 새로 생성하는 것이 바람직
디비와 관련된 전용 오브젝트를 하나 만들어서 사용
repository를 빈으로 등록
엔티티 매니저를 만들기 위해 엔티티 매니저 팩토리가 필요
빈으로 만들수 있음
엔티티 매니저 팩토리는 엔티티 매니저를 생성하는 역할을 하며, 애플리케이션 전체에서 공유
트랜잭션 범위 내에서 새로운 엔티티 매니저를 쉽게 생성
스프링부트에 자동 구성방식으로 데이터소스와 엔티티매니저팩토리 만들어줌
스프링빈의 팩토리빈은 컨피규레이션이 붙어있는 클래스
이제 잘 사용하지 않음
@Bean이 붙어있는 메서드가 팩토리빈 역할을 하니까
JPA에서 엔티티를 정의할 때는 파라미터가 있는 생성자 외에 기본 생성자도 반드시 정의
리플렉션(Reflection)을 사용하여 엔티티 객체를 생성하기 때문에, 기본 생성자가 필요
엔티티가 데이터베이스에 삽입될 때, ID가 자동으로 생성되고 할당
더블 브래킷 기법, 익명 클래스, 인스턴스 초기화 기법
더블 브래킷 기법은 Java에서 컬렉션을 간편하게 초기화하는 방법 중 하나
두 쌍의 중괄호를 사용하여 컬렉션을 초기화하는 이 기법은 사실 익명 클래스와 인스턴스 초기화 블록을 결합
익명 클래스는 이름이 없는 클래스로, 한 번만 인스턴스화해서 사용할 때 유용
일반적으로 인터페이스나 추상 클래스를 구현할 때 사용
인스턴스 초기화 블록은 객체가 생성될 때마다 실행되는 코드 블록
생성자와 함께 객체 초기화를 위해 사용
Java 9부터 컬렉션 팩토리 메서드(List.of, Set.of, Map.of)를 제공하여 이러한 초기화를 더욱 간편하게 처리
스프링 데이터 엑세스 예외처리
주문번호 중복은 복구가 가능한 예외
ConstraintViolationException예외를 캐치하면 JPA를 지원하는 다른 라이브러리를 사용할떄 예외 클래스의 타입이 달라질 수 있음
동일한 상황에서 다른 exception이 던져질 수 있음
어떤 라이브러리, 엔진을 사용하더라도 똑같은 종류의 문제를 처리하는 코드가 예외를 다루게 해야 함
JDBC SQLException
JDBC를 기반으로 하는 모든 기술에서 발생하는 예외
JDBC, MyBatis, JPA
DB의 에러코드에 의존하거나, 데이터 기술에 의존적인 예외처리 코드
문제점
Unique 예외, SQL문법이 틀리거나 하는 DB가 만들수 있는 예외 상황을 세분화하지 않음
예외
예외가 발생하면
예외를 잘못 다루는 코드
예외의 종류
예외의 추상화와 전환
SQLException
이 발생하지만, JPA를 사용하면PersistenceException
이 발생할 수 있음JPA Repository - 애플리케이션 인프라스트럭처 빈
더블 브래킷 기법, 익명 클래스, 인스턴스 초기화 기법
List.of
,Set.of
,Map.of
)를 제공하여 이러한 초기화를 더욱 간편하게 처리스프링 데이터 엑세스 예외처리
JDBC SQLException
DataAccessException
스프링이 제공하는 DB 에러코드의 매핑 정보