Tiny Star

🪄Interview/✏️Study

[CS STUDY INTERVIEW] 11주차 - Error & Exception

청크 2024. 5. 11. 19:57

CS 스터디 11주차 

 

Error & Exception


Error & Exception

 

프로그래밍에서 "Error"와 "Exception"은 코드 실행 중 발생할 수 있는 문제들을 지칭하는 두 가지 주요 용어이다.

이러한 문제들은 프로그램의 흐름을 방해하고, 예상치 못한 결과를 초래하기 때문에 예외처리 등 다양한 방법으로

개발자가 오류를 명시적으로 던지거나 잡아주기도 한다.

 

두 용어는 종종 혼용되기도 하지만, 각각의 특성과 처리 방식에는 분명한 차이가 있다.


Throwable 클래스

Java에서 Throwable 클래스는 예외 처리 체계의 최상위 클래스로, 모든 오류(Error)와 예외(Exception)의 슈퍼클래스이다.

Throwable 클래스는 Java의 java.lang 패키지에 속해 있으며,

이 클래스의 객체는 Java 가상 머신(JVM) 또는 Java 프로그램에 의해 "던져지는"(thrown) 모든 문제를 표현할 수 있다.

 

Throwable 클래스의 주요 하위 클래스

Throwable 클래스는 두 개의 주요 하위 클래스를 갖고 있다.

Exception

프로그램이 처리할 수 있는 조건을 나타내며,

개발자가 이를 사용하여 정상적인 응용 프로그램 흐름을 관리할 수 있다.

Exception 클래스 자체는 여러 다른 하위 클래스를 가지고 있는데,

이 중에서 RuntimeException은 특별히 관리되는 하위 클래스로,

주로 프로그래밍 오류를 나타낸다. (예: NullPointerException, IndexOutOfBoundsException).

Error

이 클래스는 시스템에 심각한 문제를 나타내며, 일반적으로 개발자가 처리할 수 없거나 처리하지 않아야 하는 것들로

예를 들어, OutOfMemoryError나 StackOverflowError는 JVM 내부의 심각한 문제를 반영한다.

 

Throwable 클래스의 주요 메소드

Throwable 클래스는 예외 처리에 유용한 여러 메소드를 제공한다.

이러한 메소드들은 예외의 원인을 파악하고, 문제를 보고하며, 프로그램의 오류 처리를 돕는데 큰 도움이 된다.

1. getMessage()

예외에 대한 설명을 반환하는 메서드로 이 메시지는 예외가 생성될 때 제공되는 설명이다.

예외의 원인을 이해하는 데 도움이 된다.

2. printStackTrace()
콘솔에 예외의 스택 트레이스를 출력하는 이 메소드는 예외가 발생한 메소드 호출 순서와 위치를 보여 주어

디버깅에 매우 유용하다.
3. getCause()

예외의 원인이 되는 다른 Throwable 객체를 반환하는 이 메소드는 예외 체이닝을 사용할 때 특히 유용하며,

한 예외가 다른 예외를 발생시킨 경우 해당 원인 예외를 추적할 수 있다.
4. getStackTrace()
예외와 관련된 스택 트레이스를 StackTraceElement 배열로 반환하는 메서드로

이 배열은 프로그램의 실행 경로를 자세히 파악할 수 있게 해 주며,

프로그래밍적으로 스택 트레이스를 분석할 때 사용할 수 있다.


Error(에러)

문제가 발생할 때 에러가 발생했다고 표현하곤한다.

하지만 프로그래밍에서 에러는 개발자를 공포에 떨게 만드는 단어라 함부로 쓰면 안된다는(?) 얘기를 들었었다.

 

에러는 시스템 레벨에서 발생하여 주로 프로그램의 실행을 방해하는 심각한 문제로  회복이 불가능한 것들을 의미한다.

이는 시스템 레벨에서 발생하는 문제이기 때문에 대부분의 에러는 개발자가 제어하거나 예측하기 어려우며

에러가 발생할 경우 프로그램은 종종 강제종료되기도 한다.

 

보통 자바 컴파일 시 문법적인 오류나 런타임 시 널포인트 참조 등 프로세스에 심각한 문제를 야기 시킨다.

 

대표적인 에러 유형

OutOfMemoryError

자바 가상 머신(JVM)에서 사용 가능한 메모리가 부족할 때 발생하는 에러로

주로 힙 메모리가 부족하거나, 과도한 클래스 로드, 네이티브 메소드에 의한 큰 메모리 요구 등으로 인해 발생할 수 있다.


StackOverflowError

이 에러는 메소드 호출에 의한 스택 메모리 고갈 때 발생하는 에러로

재귀적 메소드 호출이 깊어질 때 주로 발생하며, 호출 스택의 한계를 넘어서게 된다.


SystemError
운영 시스템에서 비정상적인 상황이 발생할 때 나타나는 에러로

하드웨어 오류, 시스템 자원의 부족 등이 원인일 수 있다.


Exception(예외)

에러와 비슷해보이지만 다른 의미인 예외는 프로그램의 정상적인 실행 흐름을 방해하지만

대부분의 경우는 개발자가 예측할 수 있기 때문에 명시적으로 예외처리를 할 수 있는 상황을 의미한다.

 

즉, 수습이 가능한 덜 심각한 오류에 해당하며

예외는 발생하더라도 적절한 예외 처리 로직을 통해서 JVM은 정상적으로 동작한다.


Exception 주요 유형과 대표적인 Exception Class

 

Java에서는 다양한 예외 상황을 다루기 위해 많은 종류의 예외 클래스들을 제공한다.

대부분 java.lang.Exception 클래스에서 파생된 것들로, 특정한 예외 상황에 맞춰져 있다.


Checked Exception

Java에서 Checked Exception은 예외 처리를 강제하는 예외 유형으로 컴파일 시점에서 반드시 처리해야 하는 예외이다.

이 예외들은 일반적으로 외부 시스템과의 상호작용 과정에서 발생할 수 있는 예외들로, 개발자가 이를 명시적으로 처리해야만 한다.

여기에 속하는 예외는 컴파일 시점에서 체크되며, 컴파일러는 메소드가 이 예외들을 처리하거나 던지고 있음을 선언해야 함을 요구하는데

이는 프로그램의 안정성을 높이고, 런타임 중 발생할 수 있는 예기치 않은 상황에 대비하도록 개발자에게 강제하는 메커니즘이다.

 

Checked Exception의 특징

1. 처리 강제성

Checked Exception이 메소드에서 발생할 수 있다면, 이를 반드시 처리하거나 선언해야 하는데

try-catch 블록을 사용하여 예외를 처리하거나, throws 키워드를 메소드 선언에 포함시켜 호출자에게

예외 처리 책임을 전가하는 방법으로 이루어진다.
2. 예측 가능성

이 유형의 예외는 주로 외부 시스템의 상호작용(파일 시스템, 네트워크, 데이터베이스 등)에서 발생한다.

따라서, 이러한 상호작용이 필요한 코드 블록에서 예외 발생을 예측할 수 있다.
3. 안정성 향상

프로그램이 외부 요인으로부터 영향을 받을 수 있는 상황에서 예외 처리를 강제함으로써, 더 안정적인 소프트웨어를 개발할 수 있도록 한다.

 

대표적인 Checked Exception

1. IOException

입출력 작업 중에 발생하는 예외로, 파일 읽기/쓰기, 네트워크 I/O 오류 등이 포함된다.

파일이 존재하지 않거나, 읽을 수 없는 파일을 읽으려 할 때 발생할 수 있으며  FileNotFoundException, EOFException 등이 이 범주에 속한다.

2. SQLException
데이터베이스 접근 중 발생하는 예외로 SQL 쿼리 실행 중 문제가 생기거나, 데이터베이스 연결에 문제가 있을 때 발생한다.

3. ClassNotFoundException

지정된 클래스를 찾을 수 없을 때 발생하는 예외로 클래스 로더가 동적으로 특정 클래스를 로드할 때 그 클래스를 찾을 수 없는 경우 발생한다.

이는 주로 설정 오류나 환경 문제로 인해 발생할 수 있다.

4. InterruptedException

쓰레드가 잠자고 있거나 대기 상태에 있을 때 다른 쓰레드가 그 쓰레드를 중단시키려 할 때 발생하는 예외로

멀티쓰레드 프로그래밍에서 쓰레드 간의 상호작용을 관리할 때 중요하다.

 

Unchecked Exception(Runtime Exception)

Java에서 Unchecked Exception, 또는 런타임 예외(Runtime Exception)는 컴파일 시점에 체크되지 않고, 

프로그램 실행 중에만 발견되는 예외를 말한다. 이 예외들은 java.lang.RuntimeException 클래스를 상속받으며,

주로 프로그래머의 실수로 인해 발생한다.

 

Unchecked Exception은 명시적인 예외 처리를 요구하지 않기 때문에, 이들을 처리하는 코드를 작성하지 않아도 컴파일 에러가 발생하지 않는다.

 

Unchecked  Exception의 특징

1. 예측이 가능하지만 필수적으로 처리 할 필요가 없다.

여기에 속하는 예외는 대부분 프로그램의 로직 오류나 잘못된 데이터 사용에서 기인되기 때문에 발생 예방이 가능하다.

2. 컴파일러가 이 예외들을 처리하지 않는다.

프로그램의 유연성을 제공하지만 동시에 실행 중 예외가 발생할 수 있기 때문에개발자가 항상 예외 발생 가능성을 염두에 두고 작업을 해야한다.

3. 적절한 설계외 테스트를 통해 예방이 가능하다.

예를 들어, 메서드 입력 파라미터를 검증하거나 적절한 데이터 구조를 사용하여 많은 예외를 피할 수 있다.

 

대표적인 Unchecked Exception

1. NullPointerException
객체 참조가 null인 경우, 이 객체의 메소드나 속성에 접근하려고 할 때 발생한다.

아직 인스턴스화되지 않은 객체의 메소드를 호출하려고 시도할 때 이 예외가 발생할 수 있다.


2. ArrayIndexOutOfBoundsException
배열에서 유효하지 않은 인덱스를 사용하려고 할 때 발생하는 예외로

배열의 크기가 10인데, 11번째 요소에 접근하려고 시도할 때 이 예외가 발생한다.


3. ArithmeticException
수학적 계산 중 오류가 발생할 때 나타나는 예외로 가장 흔한 예는 정수를 0으로 나누려고 할 때 발생하는 ArithmeticException이다.

 

4. IllegalArgumentException

메소드에 부적절하거나 부적합한 인자가 전달될 때 발생한다.

음수를 전달하면 안 되는 메소드에 음수를 전달했을 때 이 예외가 발생할 수 있다.


5. ClassCastException
객체를 호환되지 않는 타입으로 강제 변환하려고 할 때 발생한다.


예외 처리

이렇게 다양한 예외들을 방지하기 위해 개발자가 명시적으로 예외처리를 할 수 있다.

예외처리를 통해 프로그램의 견고성을 높이고 예상치 못한 상황에 효과적으로 대응할 수 있는 중요한 기술이기도 하다.

 

예외 처리의 중요성

1. 신뢰성

예외 처리를 통해 프로그램은 예상치 못한 상황에서도 계속 실행될 수 있으며,

예외 상황을 적절히 처리함으로써 프로그램의 신뢰성을 높일 수 있다.
2. 오류 진단

예외 처리 로직을 통해 오류 발생 시 원인을 분석하고 로그를 남길 수 있어, 문제의 원인을 빠르게 찾아 해결할 수 있다.
3. 사용자 경험

사용자에게 예외 상황을 적절히 알리고, 가능한 해결책을 제공함으로써 사용자 경험을 개선할 수 있다.

 

예외 처리 기능

1. Try-Catch 블록

가장 기본적인 예외 처리 방법으로 예외가 발생할 가능성이 있는 코드를 try 블록 안에 작성하고

catch 블록에서 해당 예외를 처리한다.

try {
    // 예외 발생 가능한 코드
    int result = 10 / 0;
} catch (ArithmeticException e) {
    // ArithmeticException 처리 코드
    System.out.println("0으로 나눌 수 없습니다.");
}

 

2.  Finally 블록

try 또는 catch 블록이 실행된 후, 무조건 실행되어야 하는 코드(예: 리소스 해제, 파일 닫기 등)를 포함한다.

finally 블록은 예외 발생 여부와 관계없이 항상 실행된다.

try {
    // 예외 발생 가능한 코드
} catch (Exception e) {
    // 예외 처리 코드
} finally {
    // 항상 실행되는 코드
}

 

3.  Throws

메소드가 예외를 직접 처리하지 않고 호출한 측에 예외 처리를 위임할 때 사용하며,

메소드 선언부에 throws 키워드를 사용하여 처리해야 할 예외를 명시한다.

public void readFile(String fileName) throws IOException {
    // 파일 읽기 코드
}

 

4. Throw

프로그래머가 직접 예외를 발생시키고자 할 때 사용하며 주로 특정 조건에 따라 예외를 강제로 발생시킬 때 사용된다.

public void checkAge(int age) {
    if (age < 18) {
        throw new IllegalArgumentException("나이가 18세 미만입니다.");
    }
}