12 오류 대비하기
오류와 에러
자바에서 오류는 크게 컴파일 오류와 런타임 오류로 나눌 수 있습니다. 이 두 가지 오류는 발생 시점과 원인이 다르며, 각각의 처리 방법이 다릅니다. 또한, 런타임 오류는 Error
와 Exception
으로 구분됩니다.
1. 컴파일 오류 (Compile-time Error)
발생 시점: 컴파일 오류는 코드가 컴파일될 때 발생합니다. 즉, 프로그램을 실행하기 전에 컴파일러가 코드를 번역하는 단계에서 발생합니다.
원인: 컴파일 오류는 주로 문법적인 오류, 타입 불일치, 존재하지 않는 변수나 메소드 사용 등과 같은 문제 때문에 발생합니다. 컴파일 오류가 있는 경우, 컴파일러는 프로그램을 바이트코드로 변환하지 못하므로 실행할 수 없습니다.
예시: 컴파일 오류
edu.ch12. error패키지
위 코드에서는 int
타입의 변수에 문자열을 할당하려고 하기 때문에 타입 불일치 오류가 발생하여 컴파일이 되지 않습니다.
2. 런타임 오류 (Runtime Error)
발생 시점: 런타임 오류는 프로그램이 실행되는 동안 발생하는 오류입니다. 컴파일러는 코드를 번역할 때 이 오류를 감지하지 못하며, 실행 중에 특정 조건이 발생했을 때 나타납니다.
원인: 주로 잘못된 사용자 입력, 파일의 부재, 배열의 인덱스 초과, null 참조, 네트워크 연결 문제 등과 같이 실행 중에 예측할 수 없는 상황에서 발생합니다.
런타임 오류의 종류: Error
와 Exception
Error
와 Exception
런타임 오류는 자바에서 Error
와 Exception
으로 분류됩니다. 이 두 가지는 모두 Throwable
클래스를 상속받지만, 그 목적과 처리 방법이 다릅니다.
1. Error
Error
설명:
Error
는 자바 프로그램에서 복구할 수 없는 심각한 문제를 나타냅니다. 일반적으로 애플리케이션이 처리할 수 없으며, 개발자가 직접 예외 처리(try-catch)를 하지 않습니다. 이러한 오류는 주로 JVM의 심각한 문제에서 발생합니다.예시:
OutOfMemoryError
: 메모리가 부족할 때 발생합니다.StackOverflowError
: 스택 메모리가 가득 차서 더 이상 메소드를 호출할 수 없을 때 발생합니다.InternalError
: JVM 내부에 문제가 발생했을 때 발생합니다.
처리 방법: 일반적으로
Error
는 프로그램에서 직접 처리하지 않습니다. 이는 시스템 수준의 심각한 문제이기 때문에 프로그램이 강제 종료되는 것이 대부분의 대응 방식입니다.
Error
예시
Error
예시edu.ch12. error패키지
위 코드에서는 메소드가 무한히 재귀 호출되기 때문에 StackOverflowError
가 발생합니다. 이는 스택 메모리의 한계로 인한 오류로 복구할 수 없습니다.
2. Exception
Exception
설명:
Exception
은 프로그램이 실행되는 동안에 발생할 수 있는 예외적인 상황을 나타냅니다. 대부분의 경우 개발자가 예외를 예측하고 처리할 수 있습니다.종류:
체크 예외(Checked Exception): 컴파일러가 예외 처리를 요구하는 예외로, 컴파일 시점에 예외 처리를 강제합니다. 예를 들어, 파일 입출력 시 발생하는
IOException
등이 있습니다.언체크 예외(Unchecked Exception, 런타임 예외): 컴파일러가 예외 처리를 강제하지 않는 예외로, 주로 프로그래밍 실수에 의해 발생합니다. 예를 들어,
NullPointerException
,ArrayIndexOutOfBoundsException
등이 있습니다.
처리 방법:
Exception
은 주로 try-catch 블록을 사용하여 처리하거나, 메소드에throws
키워드를 사용하여 호출자에게 예외를 전달할 수 있습니다.
Exception
예시 (체크 예외)
Exception
예시 (체크 예외)edu.ch12.exception 패키지
위 코드에서는 존재하지 않는 파일을 열려고 시도하기 때문에 FileNotFoundException
이 발생합니다. 이 예외는 체크 예외이므로 컴파일러가 예외 처리를 요구하며, try-catch
블록으로 예외를 처리해야 합니다.
Exception
예시 (언체크 예외)
Exception
예시 (언체크 예외)edu.ch12.exception 패키지
위 코드에서는 배열의 유효한 인덱스 범위를 벗어난 인덱스에 접근하려고 하기 때문에 ArrayIndexOutOfBoundsException
이 발생합니다. 이는 언체크 예외이므로 컴파일러가 예외 처리를 강제하지 않습니다.
3. Error
와 Exception
의 차이
Error
와 Exception
의 차이특성
Error
Exception
발생 시점
주로 시스템 수준에서 발생하는 심각한 문제
애플리케이션 수준에서 발생하는 예외 상황
복구 가능성
대부분 복구 불가능
예외 처리를 통해 복구 가능
예외 처리
일반적으로 처리하지 않음
try-catch
로 처리 가능
예시
OutOfMemoryError
, StackOverflowError
IOException
, NullPointerException
등
4. 예외 처리 방법
자바에서는 주로 try-catch-finally
블록을 사용하여 예외를 처리합니다.
예외 처리 예시
edu.ch12.exception 패키지
5. 정리
컴파일 오류: 코드를 컴파일할 때 발생하며, 주로 문법적인 오류로 인해 발생합니다.
런타임 오류: 프로그램 실행 중에 발생하며, 주로 실행 중인 환경이나 입력 값에 의해 발생합니다. 이는 다시
Error
와Exception
으로 분류됩니다.Error
: 프로그램이 복구할 수 없는 심각한 시스템 수준의 문제입니다. 개발자가 직접 처리하지 않으며,OutOfMemoryError
,StackOverflowError
등이 있습니다.Exception
: 프로그램이 예측하고 처리할 수 있는 예외 상황입니다.IOException
과 같은 체크 예외와NullPointerException
과 같은 언체크 예외로 나뉩니다.
예외 정의하고 발생시키기
throw
키워드를 사용하여 사용자 정의 예외를 발생시키는 방법을 예시를 통해 알아보겠습니다. 예외를 직접 발생시키고 싶을 때 throw
를 사용하며, 이를 통해 특정 조건에서 예외를 발생시켜 프로그램의 흐름을 제어할 수 있습니다.
예외 떠넘기기 (Throwing an Exception)
예외를 직접 처리하지 않고, 호출한 곳에서 처리하도록 던지는 것.
메소드 선언에
throws
키워드를 사용하여 떠넘길 예외를 명시.예외를 처리하는 책임을 메소드를 호출한 곳으로 넘깁니다.
용도: 메소드에서 발생한 예외를 즉시 처리하지 않고, 호출한 곳에서 처리해야 할 때 사용됩니다.
예시: 예외 떠넘기기
edu.ch12.exception.handlingAnException 패키지
코드 설명
checkAge
메소드:throws InvalidAgeException
으로 해당 메소드가InvalidAgeException
을 던질 수 있음을 명시합니다. 이 메소드에서 예외가 발생하면 메소드를 호출한 곳으로 예외를 떠넘깁니다.main
메소드:try-catch
블록에서checkAge
메소드를 호출하고, 떠넘겨진 예외를 받아서 처리합니다.
출력 결과
예외 되던지기 (Rethrowing an Exception)
예외를 잡아서 일부 처리한 후, 다시 예외를 던져 호출한 곳에서도 추가 처리를 할 수 있도록 하는 것.
내부에서 예외를 처리하면서 로깅, 정리 작업 등을 수행한 후에 예외를 다시 던집니다.
호출한 쪽에서 추가적인 예외 처리가 필요한 경우에 유용합니다.
용도: 메소드 내부에서 예외를 일부 처리하거나 기록한 후에, 호출한 쪽에서 나머지 처리를 할 수 있도록 예외를 다시 던질 때 사용됩니다.
예시: 예외 되던지기
edu.ch12.exception.handlingAnException 패키지
코드 설명
checkAge
메소드: 내부에서 예외를 발생시키고 처리한 뒤,throw e;
를 통해 예외를 다시 던집니다. 이는 호출한 곳에서 추가적으로 예외 처리를 할 수 있도록 합니다.main
메소드:try-catch
블록에서checkAge
메소드를 호출하고, 다시 던져진 예외를 받아서 처리합니다.
출력 결과
예외의 버블링(Exception Bubbling)
예외의 버블링은 메소드에서 발생한 예외가 처리되지 않고 호출된 상위 메소드로 전달되는 과정을 의미합니다.(거품처럼 올라간다 하여 버블링) 예외는 처음 발생한 곳에서 처리되지 않으면, 해당 예외를 호출한 메소드로 전달되고, 계속해서 상위 메소드로 전파됩니다. 이런 과정은 스택 트레이스(Stack Trace)를 통해 역추적할 수 있습니다.
예외의 버블링은 특정 예외가 발생했을 때 하위 메소드가 아닌 상위 메소드에서 예외를 처리하고자 할 때 사용됩니다. 이를 통해 코드를 간결하게 유지하고, 예외 처리를 중앙화할 수 있습니다.
예외 버블링의 작동 방식
예외가 발생하면, 해당 예외를 처리할 수 있는
try-catch
블록을 찾습니다.예외를 처리할 수 있는
catch
블록이 없다면, 예외는 발생한 메소드의 호출 스택에서 상위 메소드로 전파됩니다.이 과정이 계속 반복되며, 최종적으로
main
메소드까지 도달합니다.main
메소드에서도 예외를 처리하지 않으면, 프로그램이 비정상 종료되고 스택 트레이스가 출력됩니다.
예시: 예외의 버블링
다음 코드는 여러 메소드에서 예외를 발생시키고, 상위 메소드에서 처리하는 예시를 보여줍니다.
edu.ch12.exception.handlingAnException 패키지
코드 설명
checkAge
메소드: 나이가 음수인 경우InvalidAgeException
을 발생시키고 예외를 떠넘깁니다.processAge
메소드:checkAge
메소드를 호출하지만 예외를 직접 처리하지 않고 떠넘깁니다.main
메소드: 최상위 메소드로,processAge
를 호출하면서 예외를 처리합니다.checkAge
에서 발생한 예외가 버블링되어main
메소드까지 도달하여 처리됩니다.
출력 결과
버블링의 장점
중앙 집중식 예외 처리: 예외 처리를 코드의 최상위 또는 논리적으로 처리하기 적절한 위치에서 수행할 수 있습니다.
코드 가독성 향상: 메소드 내부에서 예외를 직접 처리하지 않고 상위 메소드로 예외를 던져, 하위 메소드를 간결하게 유지할 수 있습니다.
재사용성: 하위 메소드에서 세부적인 예외 처리를 강제하지 않음으로써, 재사용이 용이합니다.
주의사항
모든 예외를 최상위 메소드로 떠넘기지 마세요: 모든 예외를 버블링으로 처리하면 프로그램의 예외 처리 논리가 복잡해질 수 있습니다. 상황에 따라 적절한 곳에서 예외를 처리해야 합니다.
적절한 예외 처리 위치 결정: 어디에서 예외를 처리할 것인지는 코드의 목적과 흐름에 따라 결정해야 합니다. 중요한 것은 예외를 적절한 곳에서 처리하여 프로그램의 안정성을 유지하는 것입니다.
Chained Exception (연쇄 예외)
연쇄 예외(Chained Exception)는 한 예외가 다른 예외의 원인이 될 때 이를 체인 형태로 연결하는 기능입니다. 예외가 발생하는 상황에서, 어떤 예외가 새로운 예외의 원인이 되었는지를 추적하는 데 사용됩니다. 이 방식은 문제의 근본 원인을 파악하는 데 도움이 되며, 예외 처리에 있어 더욱 자세한 정보를 제공할 수 있습니다.
자바에서는 Throwable
클래스에서 제공하는 원인 예외(cause exception) 설정을 통해 연쇄 예외를 구현할 수 있습니다. 즉, 하나의 예외가 발생하면 그 예외의 원인으로 다른 예외를 연결하여 예외 발생의 원인을 추적할 수 있습니다.
1. 연쇄 예외 사용법
자바에서 연쇄 예외를 구현하는 방법은 다음과 같습니다:
예외 생성자의 인수로 원인 예외를 전달하여 연쇄 예외를 생성할 수 있습니다.
Throwable
클래스의initCause(Throwable cause)
메소드를 사용하여 원인 예외를 설정할 수 있습니다.getCause()
메소드를 통해 원인 예외를 얻을 수 있습니다.
2. 연쇄 예외의 사용 예시
edu.ch12.exception.handlingAnException 패키지
코드 설명
readFile
메소드:NullPointerException
을 발생시킵니다. 이 예외는 파일 객체가 null일 때 발생한다고 가정합니다.catch
블록에서 새로운Exception
을 발생시키면서NullPointerException
을 원인 예외(cause)로 전달합니다.새로운 예외는 "파일을 읽는 중에 예외가 발생했습니다."라는 메시지를 가지고 있으며,
NullPointerException
을 원인으로 포함합니다.
main
메소드:readFile
메소드를 호출하고, 연쇄된 예외를 처리합니다.getMessage()
로 최종 예외의 메시지를 출력하고,getCause()
로 원인 예외를 출력합니다.
출력 결과
연쇄 예외 사용이유
근본 원인 파악: 예외가 여러 단계의 메소드 호출을 거쳐 발생할 때, 연쇄 예외를 사용하면 문제의 근본 원인을 파악할 수 있습니다.
추적 용이성: 예외를 처리하는 과정에서 원인 예외를 포함함으로써 스택 추적 정보를 보존하고, 디버깅을 쉽게 할 수 있습니다.
의미 있는 예외 전환: 하위 레벨의 예외를 상위 레벨의 의미 있는 예외로 전환하면서도, 원래의 예외를 유지할 수 있습니다.
try-with-resources
try-with-resources
구문 사용법
try-with-resources
구문 사용법try
블록의 괄호 안에 닫아야 하는 자원을 선언합니다. 이 자원은AutoCloseable
인터페이스를 구현해야 합니다.try
블록이 끝나면 자원이 자동으로 닫힙니다.기존의
try-catch-finally
구문보다 훨씬 간결하고 안전한 방식으로 자원을 관리할 수 있습니다.
try-with-resources
기본 구조
try-with-resources
기본 구조try-with-resources
예제: 파일 읽기
try-with-resources
예제: 파일 읽기다음 예제에서는 try-with-resources
를 사용하여 파일을 읽는 작업을 수행하고, 사용된 자원(BufferedReader
)을 자동으로 닫아줍니다.
edu.ch12.exception.handlingAnException 패키지
코드 설명
try
구문:BufferedReader
자원을try
괄호 안에 선언하여 자동으로 자원을 닫도록 합니다.catch
블록: 파일을 읽는 도중 발생할 수 있는IOException
을 처리합니다.자원 자동 닫힘:
try
블록이 끝나면BufferedReader
가 자동으로 닫힙니다. 수동으로br.close()
를 호출할 필요가 없습니다.
try-with-resources
와 기존 try-catch-finally
비교
try-with-resources
와 기존 try-catch-finally
비교try-with-resources
를 사용하지 않고 기존의 try-catch-finally
를 사용하여 자원을 닫는 경우는 다음과 같습니다:
edu.ch12.exception.handlingAnException 패키지
비교
코드 길이:
try-with-resources
를 사용하면finally
블록이 필요 없으므로 코드가 훨씬 간결해집니다.자원 닫힘 보장:
try-with-resources
는 예외 발생 여부와 상관없이 항상 자원을 닫아줍니다.에러 처리 단순화: 기존 방식에서는 자원을 수동으로 닫는 과정에서 예외가 발생할 수 있으며, 이를 추가로 처리해야 하지만,
try-with-resources
에서는 자동으로 처리됩니다.
AutoCloseable
인터페이스
AutoCloseable
인터페이스try-with-resources
구문에서 사용할 수 있는 자원은 반드시 AutoCloseable
인터페이스를 구현해야 합니다. AutoCloseable
인터페이스에는 close()
메소드가 선언되어 있어, 자원이 더 이상 필요하지 않을 때 자동으로 호출됩니다.
사용자 정의 자원 클래스와 try-with-resources
try-with-resources
사용자 정의 클래스에서도 AutoCloseable
또는 Closeable
인터페이스를 구현하면 try-with-resources
를 사용할 수 있습니다.
edu.ch12.exception.handlingAnException 패키지
출력 결과
NullPointerException와 Optional
NPE (NullPointerException)
NPE는 NullPointerException
의 약자로, 자바에서 가장 흔하게 발생하는 런타임 오류 중 하나입니다. 이 예외는 널(null) 참조에 대해 메소드 호출, 필드 접근, 배열 접근 등의 작업을 수행하려고 할 때 발생합니다.
1. NullPointerException
발생 예시
NullPointerException
발생 예시edu.ch12.exception.nullAndOptional 패키지
위 코드에서는 str
변수가 null
이므로 str.length()
를 호출하면 NullPointerException
이 발생합니다.
2. NPE 방지 방법
널 체크: 객체를 사용하기 전에 반드시
null
체크를 하는 습관을 들입니다.삼항 연산자 사용:
null
일 경우에 대한 처리 로직을 포함하여 안전하게 사용할 수 있습니다.Optional
클래스 사용: 자바 8에 추가된 **Optional
*을 사용하면 NPE를 방지하고, 더 안전하게 코드를 작성할 수 있습니다.
Optional 클래스
Optional
은 자바 8에서 도입된 클래스입니다. 이는 null이 될 수 있는 객체를 감싸는 컨테이너로, 객체가null
인지 여부를 명시적으로 처리할 수 있게 도와줍니다.Optional
을 사용하면 NPE를 예방하고, 명시적인 null 처리를 할 수 있어 코드의 안정성과 가독성을 향상시킵니다.
4. Optional
생성 및 사용 방법
Optional
생성 및 사용 방법Optional
생성:Optional
은 주로 정적 팩토리 메소드인of()
,ofNullable()
,empty()
를 사용하여 생성합니다.
edu.ch12.exception.nullAndOptional 패키지
5. Optional
의 주요 메소드
Optional
의 주요 메소드edu.ch12.exception.nullAndOptional 패키지 OptionalExample 클래스
isPresent()
: 값이 존재하는지 여부를 반환합니다.isEmpty()
: 값이 비어있는지의 여부를 반환합니다.ifPresent(Consumer<? super T> action)
: 값이 존재하면 해당 값에 대해 동작을 수행합니다.orElse(T other)
: 값이 존재하면 해당 값을 반환하고, 그렇지 않으면 기본 값을 반환합니다.orElseGet(Supplier<? extends T> other)
: 값이 존재하지 않을 때, 람다식이나 메소드를 통해 기본 값을 제공합니다.orElseThrow(Supplier<? extends X> exceptionSupplier)
: 값이 존재하지 않을 때 예외를 던집니다.map(Function<? super T, ? extends U> mapper)
: 값을 변환하여 새로운Optional
을 반환합니다. 만약 값이 존재하지 않으면 빈Optional
을 반환합니다.
6. Optional
을 이용한 NPE 방지 예시
Optional
을 이용한 NPE 방지 예시NPE 위험이 있는 코드
edu.ch12.exception.nullAndOptional.prevetionNPE 패키지
Optional
을 사용한 안전한 코드
Optional
을 사용한 안전한 코드edu.ch12.exception.nullAndOptional.prevetionNPE 패키지
Last updated