728x90
예외 처리
@2024.04.11
예외 처리(Exception Handling)
💡
프로그램 실행 중에 발생할 수 있는 예상치 못한 상황(예외)에 대비하여 프로그램의 정상적인 흐름을 유지하고 예외 상황을 안전하게 처리하는 프로그래밍 기법
@기본 구조
try{
//예외가 발생할 수 있는 코드
}catch(예외 예외 객체){
// 발생한 예외 처리
}finally{
// 생략할 수 있으며, 예외 발생 여부와 관계없이 실행되는 코드
}
@기본 구조
try{
//예외가 발생할 수 있는 코드
}catch(예외 예외 객체){
// 발생한 예외 처리
}finally{
// 생략할 수 있으며, 예외 발생 여부와 관계없이 실행되는 코드
}
- 필요성
- 프로그램의 안정성과 신뢰성 보장
- 예상치 못한 상황에 직면했을 때 안전하게 동작하도록 보장
- 프로그램이 중단되지 않고 계속 실행될 수 있음
- 오류의 조기 발견 및 대응
- 오류 메시지를 통해 문제가 발생되는 원인과 위치를 파악하고, 이를 바탕으로 빠른 시간 내에 오류를 수정
- 사용자 경험 개선
- 사용자에게 보다 명확하게 이해하기 쉬운 피드백을 제공
- 시스템 자원의 안전한 관리
- 프로그램이 예외인 상황에도 finally 블록 또는 자동 리소스 닫기 구문을 통해 필수적인 자원 해제 작업을 보장함으로써, 시스템 자원을 안전하게 관리할 수 있다.
- 메모리 누수와 같은 문제를 예방
- 프로그램의 안정성과 신뢰성 보장
- 예외 처리를 제대로 하지 않았을 때
- 프로그램의 비정상적 중단
- 사용자에게 혼란을 주고, 프로그램의 신뢰성을 저하시키며, 중요한 작업이 완료되지 못하는 상황을 초래
- 데이터 손실
- 파일 작업 중 예외가 발생하면 파일이 손상될 위험 존재
- 데이터 베이스 작업 중 예외가 발생하면 일관성 없는 상태가 된다.
- 보안 취약점
- 시스템의 취약한 부분이 노출 되어 보안 공격에 쉽게 노출될 수 있다.
- 사용자 경험 저하
- 사용자는 프로그램의 오류 상황을 이해하기 어려운 메시지로 접하게 된다.
- 사용자 경험을 저하시키고, 사용자가 프로그램에 대한 신뢰를 잃게 만든다.
- 유지 보수의 어려움
- 예외 발생 시 정확한 원인을 파악하기 어렵다.
- 문제 해결 과정을 복잡하고 시간이 오래 걸린다.
- 프로그램의 비정상적 중단
try {
int result = 10 / 0; // 예외 발생 -> catch문으로 이동
System.out.println("Result: " + result); // 해당 코드 실행 X
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없어!"); // 사용자에게 알려주는 오류 메시지
} finally {
System.out.println("이건 무조건 출력될거야");
}
예외 오류 메시지 출력
try {
// 예외가 발생할 수 있는 코드
// 예외가 발생한 시점부터 나머지 코드는 실행되지 않는다!
int result = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println(e); //객체를 출력하면 toString()을 자동으로 호출
}



예외 종류
예외는 크게 컴파일 시점에서 체크하지 않는 RunTimeException과 컴파일 시점에서 체크하는 CheckedException이 존재
RunTimeException
💡
자바 예외 처리 체계에서 중요한 부분을 차지하는 클래스로, java.lang 패키지에 속하며 Exception 클래스의 서브 클래스
- 특징
- 비검사형 예외(Unchecked Exception) ⇒ 실행 시에 체크
- 컴파일 시점에서 체크되지 않으며, 주로 프로그래머의 실수로 인해 발생
- 잘못된 형 변환, 배열의 잘못된 인덱싱
- 자동으로 전파
- 메서드 시그니처에 예외를 명시적으로 선언하지 않아도 자동으로 호출 스택을 통해 전파
- 비검사형 예외(Unchecked Exception) ⇒ 실행 시에 체크
- 주요 예외
- ArrayIndexOutOfBoundsIOException : 배열의 인덱스를 잘못 접근하는 경우
- NullPointerIOException : null 참조에 대한 연산 시도
- ClassCastIOException : 잘못된 형 변환 시도
- ArithMeticIOException : 수학적으로 불가능한 연산 시도(0으로 나누기)
CheckedException
💡
컴파일 시점에 체크되는 예외 유형으로, Exception의 서브 클래스지만, RuntimeException의 서브 클래스는 아니다.
- 특징
- 컴파일 시점에서 체크
- 컴파일러에 의해 체크되며, 이 예외를 처리하지 않으면 컴파일 오류가 발생
- 이런 예외를 처리하기 위해 try-catch 블록을 사용하거나, throws를 사용하여 예외를 호출한 메서드로 던져야 한다.
- 예측 가능한 예외
- 프로그램의 외부 요인으로 발생하는 것이 일반적
- 파일 시스템 오류, 네트워크 문제, 데이터베이스 연결 오류
- 컴파일 시점에서 체크
- 주요 예외
- IOException : 파일 입출력 작업 시 발생
- SQLIOException : 데이터베이스 연결 시 발생
- FileNotFoundIOException : 존재하지 않는 파일에 접근할 때 발생
사용자 정의 예외 클래스
💡
개발자가 특정한 애플리케이션 요구에 맞게 사용자 정의 예외 클래스를 만들 수 있도록 하며, 이를 통해 더 명확하고 구체적인 예외 처리가 가능
예외 클래스 만들기
💡
사용자 정의 예외 클래스를 만들 때는 기존의 Exception 클래스나 그 하위 클래스를 확장하여 새로운 클래스를 정의하면 됩니다.
- 예외를 unchecked로 만들고 싶을 땐 RunTimeException을 상속
- 예시
- InvalidRangeException 예외 만들기
- 사용자가 입력한 값이 특정 값의 범위를 넘어갈 때 예외 발생
// Exception을 상속받아 사용자 정의 예외 생성 public class InvalidRangeException extends Exception { // 생성자 public InvalidRangeException(String message) { // 부모 클래스인 Exception의 생성자를 호출하여 예외 메시지를 설정 super(message); } }
public class Main { public static int getUserInput() { int num = sc.nextInt(); //150입력 return num; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); try { int userInput = getUserInput(); if (userInput < 0 || userInput > 100) { // 임의로 예외 발생 시키기 throw new InvalidRangeException("입력한 값이 유효한 범위를 벗어났습니다."); } } catch (InvalidRangeException e) { // 예외 처리 System.out.println(e.getMessage()); } } }
- InvalidRangeException 예외 만들기
예외 처리 하기
try-catch 구문 사용
try{
//예외가 발생할 수 있는 코드
}catch(예외 예외객체){
// try 블록에서 발생한 예외 처리
}finally{
// 생략 할 수 있으며, 예외 발생 여부와 관계 없이 실행되는 코드
}
예외 떠넘기기(thorws)
💡
메서드가 발생시킨 예외를 처리하지 않고, 그 메서드를 호출한 상위 메서드에 예외 처리를 위임하는 방법
@기본 구조
메소드 thorws 예외
@기본 구조
메소드 thorws 예외
- 사용 이유
- 책임의 분리
- 예외 처리는 호출한 상위 메서드에 위임하여 메서드는 기능의 실행만 집중
- 코드의 간결성 유지
- 메서드 내에서 예외 처리 시 그 메서드의 주된 기능과 관련 없는 코드가 추가되어 코드가 길고 복잡해질 수 있다.
- 따라서 예외를 떠넘기면 메서드는 더 간결하고 명확하게 유지된다.
- 재사용성 및 유지 보수성 향상
- 예외 처리 로직을 특정 메서드에만 구현하면, 다른 상황에서 동일한 예외 처리가 필요할 때 코드를 중복하여 작성해야 한다.
- 예외를 상위 메서드로 넘김으로써, 재사용성을 높이고, 유지 보수를 용이하게 만든다.
- 흐름 제어
- 예외가 발생했을 때 예외를 떠넘기면, 프로그램의 흐름을 상위 레벨로 쉽게 이동 가능
- 프로그램의 흐름을 더 효과적으로 제어할 수 있다.
- 책임의 분리
- 예시
- 파일을 읽어오는 메서드에서 파일이 존재하지 않는 경우 FileNotFoundException을 발생
public class Main { public static void main(String[] args) { try { readFile("non_existent_file.txt"); } catch (FileNotFoundException e) { System.out.println("파일을 찾을 수 없습니다: " + e.getMessage()); } } // throws를 사용하여 해당 메서드를 호출한 곳에서 예외 처리하도록 위임 public static void readFile(String fileName) throws FileNotFoundException { File file = new File(fileName); Scanner scanner = new Scanner(file); // 파일 읽기 작업 수행 } }
예외 발생시키기
💡
개발자가 정의한 예외를 발생시키는 특정 조건을 만족할 시 프로그램의 흐름을 인위적으로 중단하는 것
@기본 구조
thorws new 예외(”오류메시지”);
@기본 구조
thorws new 예외(”오류메시지”);
- 예외를 발생시키는 상황
- 비정상적인 상황 식별
- 프로그램 실행 중 특정 조건에서 정상적인 흐름을 유지하기 어려울 때 사용
- ex) 잘못된 입력, 파일 미 존재, 네트워크 연결 실패
- 프로그램 무결성 유지
- 프로그램의 정확성과 안정성을 유지하기 위해, 허용되지 않거나 기대하지 않은 동작이 발생할 때 예외 발생
- 코드의 로직 오류나 잠재적 문제를 미리 방지 가능
- 비정상적인 상황 식별
- 예시
- 사용자가 입력한 값이 특정 조건을 만족하지 않을 때 예외 발생
public class Main { public static void main(String[] args) { try { int userInput = getUserInput(); if (userInput < 0 || userInput > 100) { // IllegalArgumentException 예외 발생 시키기 throw new IllegalArgumentException("입력한 값이 유효한 범위를 벗어났습니다."); } System.out.println("입력한 값은 유효합니다."); } catch (IllegalArgumentException e) { // 예외 처리 System.out.println(e.getMessage()); } } public static int getUserInput() return 150; } }
728x90