반응형
해당 글에서는 예외 처리(Exception Handling)에 대해서 상세히 알아봅니다.
1) 예외처리(Exception Handling)
💡 예외처리(Exception Handling)
- 프로그램의 실행 도중에 발생할 수 있는 오류나 예기치 않은 상황에 대한 대비를 위해 코드를 작성하는 것을 의미합니다.
- 이를 통해 실행 중인 프로그램의 갑작스러운 비정상 종료를 방지하고 정상적인 실행 상태를 유지할 수 있도록 하는 목적이 있습니다.
1. 에러의 종류
에러의 종류 | 설명 |
컴파일 에러(Compile Error) | 컴파일 시에 발생하는 에러를 의미합니다 |
런타임 에러(Runtime Error) | 실행 시에 발생하는 에러를 의미합니다. |
논리적 에러(Logical Error) | 실행은 되지만 의도와 다르게 동작을 하는것을 의미합니다. |
[ 더 알아보기 ]
💡 에러(Error)와 예외(Exception)의 차이는?
- 에러는 ‘프로그램 코드에 의해 수습될 수 없는 심각한 오류’를 의미합니다.
- 예외는 ‘프로그램 코드에 의해 수습될 수 있는 다소 미약한 오류’를 의미합니다.
2. 예외처리 종류
💡 예외처리 종류
1. 확인된 예외(Checked Exception)
- 컴파일러가 강제로 처리하도록 하는 예외를 의미합니다.
- try-catch 블록이나 throws 키워드를 사용하여 명시적으로 처리해야 합니다.
- 주로 입출력, 네트워크 연결 등의 외부 리소스와 관련된 예외가 여기에 해당합니다.
2. 확인되지 않은 예외(Unchecked Exception)
- 개발자의 실수나 예상치 못한 상황 등으로 발생하는 예외를 의미합니다.
- 컴파일러가 강제로 처리하지 않으며, 예외가 발생하면 프로그램이 중단됩니다.
- 주로 배열 인덱스 오류, 널 포인터 오류 등의 런타임 에러가 여기에 해당합니다.
예외 처리의 종류 | 설명 |
확인된 예외(Checked Exception) | 컴파일러가 강제로 처리하도록 하는 예외를 의미합니다 |
확인되지 않은 예외(Unchecked Exception) | 개발자의 실수나 예상치 못한 상황등으로 발생하는 예외를 의미합니다. |
[ 더 알아보기 ]
💡 IntelliJ와 같은 IDEA 툴에서 오류라고 보이는 것은 컴파일 오류인가?
- 맞습니다. IDEA 툴에서 표시되는 경우는 컴파일 오류이며 코드에 문제가 있어 컴파일을 할 수 없음을 나타냅니다.
- 그러나 때로 IDEA 툴이 잘못된 경고를 표시할 수도 있으므로 실제로 코드가 정상적으로 실행되는지 확인을 해야 합니다.
2) 예외처리 오류 -1 : 확인된 예외 처리(Checked Exception) : try-catch, throws
💡 확인된 예외 처리(Checked Exception) : try-catch, throws
- 컴파일 시점에서 확인되는 에러이며 개발자가 이를 처리하지 않으면 컴파일 오류가 발생합니다.
- 외부 리소스와 상호작용하는 작업에서 발생할 수 있는 예외로 파일 입출력, 네트워크 통신 등이 대표적인 예입니다.
💡 사용 예시
- 아래에서는 JSON 데이터를 파싱 하는 예시를 보여주는 예시입니다.
- 해당 파싱 과정에서 컴파일 단계에서 ParseException 오류가 발생할 수 있음을 알려주고 있습니다. 이렇게 컴파일 시점에 발생하는 오류를 ‘확인된 오류 처리’라고 합니다.
public void jsonParserExample() {
String jsonString = "{\\" name\\":\\" John\\", \\" age\\":30, \\" city\\":\\" New York\\"}";
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(jsonString);
String name = (String) jsonObject.get("name");
long age = (Long) jsonObject.get("age");
String city = (String) jsonObject.get("city");
}
1. try - catch - finally
💡 try-catch-finally
- 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것을 의미합니다.
try - catch - finally | 설명 |
try 블록 | 예외를 발생시킬 수 있는 코드를 포함하고 있습니다. |
catch 블록 | 예외의 종류를 지정하고 특정 예외가 발생하였을 때 실행될 코드를 포함하고 있습니다. |
finally 블록 | 선택적으로 사용되며, 예외가 발생했는지 여부에 상관없이 실행될 코드를 포함하고 있습니다. |
1.1. 기본구조와 예시
💡 try - catch - finally 기본 구조
// 예외가 발생할 수 있는 코드
try {
//
}
// 예외 처리 코드 -1
catch (IndexOutOfBoundsException e) {
//
}
// (선택) 예외 처리 코드 -2
catch (ParseException e) {
//
}
// 항상 실행되는 코드
finally {
//
}
💡 try - catch - finally 사용예시
public void jsonParserExample() {
String jsonString = "{\" name\":\" John\", \" age\":30, \" city\":\" New York\"}";
JSONParser parser = new JSONParser();
JSONObject jsonObject = null;
try {
jsonObject = (JSONObject) parser.parse(jsonString);
} catch (ParseException e) {
throw new RuntimeException(e);
}
String name = (String) jsonObject.get("name");
long age = (Long) jsonObject.get("age");
String city = (String) jsonObject.get("city");
log.debug("name :: " + name + " age :: " + age + " city :: " + city);
}
1.2. Exception으로 모든 에러를 잡아도 되지 않을까?
💡 Exception으로 모든 에러를 잡아도 되지 않을까?
- 모든 에러를 잡기 위해 Exception을 사용하는 것은 일반적으로 권장되지 않습니다.
- 모든 예외를 잡으려면 특정 유형의 오류를 식별하고 처리하기가 어려워져 코드에서 잠재적인 문제와 예기치 않는 동작이 발생할 수 있습니다.
- 일방적으로 예상하는 특정 예외를 잡고 해당 예외를 적절히 처리하는 것이 더 좋습니다.
💡 사용예시 -1
- 일괄적으로 Exception을 처리하는 예시
/**
* 일괄 Exception으로 처리하는 방법
*/
// 예외가 발생할 수 있는 코드
try {
}
// 일괄 예외처리 코드
catch (Exception e) {
}
💡 사용예시 -2
- 세부적으로 Exception을 처리하는 예시
/**
* 세부적으로 예외 처리를 하는 방법
*/
// 예외가 발생할 수 있는 코드
try {
//
}
// 예외 처리 코드 -1
catch (IndexOutOfBoundsException e) {
//
}
// (선택) 예외 처리 코드 -2
catch (ParseException e) {
//
}
2. throws
💡 throws
- 메서드가 예외를 던질 수 있다는 것을 선언하는 데 사용합니다. 이에 처리하는 책임은 호출하는 코드나 호출 스택의 상위 메서드에 위임이 됩니다.
- 메서드 시그니처에서 사용되며 메서드가 특정 타입의 예외를 발생시킬 수 있다는 것을 나타냅니다.
💡 throws 기본 구조
// 메서드에 시그니처 인 throws를 사용후 관련 Exception에 대해 입력합니다.
public void exceptionMethod() throws IndexOutOfBoundsException {
}
// 메서드에 시그니처인 throws를 사용후 여러개의 Exception에 대해 입력합니다.
public void exceptionMethod() throws IndexOutOfBoundsException, ParseException {
}
💡 throws 사용예시
public void jsonParserExample() throws ParseException {
String jsonString = "{\" name\":\" John\", \" age\":30, \" city\":\" New York\"}";
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(jsonString);
String name = (String) jsonObject.get("name");
long age = (Long) jsonObject.get("age");
String city = (String) jsonObject.get("city");
log.debug("name :: " + name + " age :: " + age + " city :: " + city);
}
3. try - catch - finally와 throws 비교
분류 | try-catch-finally | throws |
사용 방법 | try 블록 내에서 예외 처리 | 메서드 선언부에 예외 선언 |
처리 방식 | 예외를 처리하고 예외 발생 시 코드 실행 | 예외를 호출한 곳으로 전달 |
예외 처리 위치 | 예외가 발생한 지점에서 처리 | 호출한 메서드로 전달 |
다중 예외 처리 | 가능 | 불가능 |
실행 여부 | 예외 발생 여부에 관계없이 실행 | 예외 발생 시 실행되지 않음 |
4. 컴파일 단계에서 발생하지 않은 예외처리는 어떻게 처리하는가?
💡 컴파일 단계에서 발생하지 않은 예외처리는 어떻게 처리하는가?
1. 런타임 예외 처리
- 실행 중에 발생할 수 있는 예외를 처리하는 코드를 작성합니다.
- 이를 통해 예외가 발생하더라도 프로그램이 비정상적으로 종료되는 것을 방지할 수 있습니다. try-catch 문을 사용하여 예외를
캐치하고 적절한 조치를 취할 수 있습니다.
2. 오류 코드 반환
- 함수 또는 메서드에서 발생하는 예외를 호출자에게 알리기 위해 오류 코드를 반환할 수 있습니다.
- 호출자는 이를 확인하고 예외 상황에 대한 적절한 조치를 취할 수 있습니다.
3. 로그 기록
- 예외 상황을 기록하는 로그 메커니즘을 구현하여, 예외가 발생한 이유와 상세 정보를 기록합니다.
- 이를 통해 디버깅 및 문제 해결에 도움을 줄 수 있습니다.
4. 문서화
- 예외가 발생하지 않는 경우에도 코드의 동작과 예외 처리 방법을 문서화하여 다른 개발자들이 이를 이해하고 적절한 예외 처리를 수행할 수 있도록 합니다.
3) 예외처리 오류 -2 : 확인되지 않은 예외(Unchecked Exception)
💡 확인되지 않은 예외(Unchecked Exception)
- 컴파일러가 해당 예외를 확인하거나 처리하지 않는 예외를 의미합니다.
- RuntimeException 클래스의 하위 클래스로 분류되며 개발자가 강제로 예외처리를 수행해야 합니다.
- 이러한 예외처리는 개발자가 예외처리를 하지 않고 무시할 수 있으나 실행 시 예외가 발생할 수 있으며 예외가 처리되지 않을 경우 프로그램의 비정상적인 동작을 초래 할 수 있습니다.
💡 런타임 오류의 종류
오류 유형 | 설명 |
NullPointerException | 프로그램이 null인 객체 참조를 접근하거나 조작하려고 할 때 발생합니다. |
ArrayIndexOutOfBoundsException | 배열 인덱스가 범위를 벗어날 때 발생합니다. (음수이거나 배열 크기보다 큰 경우) |
ClassCastException | 호환되지 않는 타입으로 캐스트하려고 할 때 발생합니다. |
IllegalArgumentException | 메서드나 생성자에 잘못된 인수가 전달될 때 발생합니다. |
IllegalStateException | 객체의 상태가 요청된 작업에 적합하지 않을 때 발생합니다. |
NoSuchMethodError | 클래스나 슈퍼클래스에서 참조된 메서드를 찾을 수 없을 때 발생합니다. |
OutOfMemoryError | Java 가상 머신 (JVM)이 메모리를 다 사용했을 때 발생합니다. |
StackOverflowError | 재귀 호출로 인해 호출 스택이 제한을 초과할 때 발생합니다. |
4) 예외처리 전략
💡 예외처리 전략
- 소프트웨어 개발이나 시스템 운영에서 예외 상황을 다루기 위한 방법을 의미합니다.
- 예외 상황은 예상치 못한 문제 또는 오류로 발생할 수 있으며 이러한 상황을 대비하여 적절한 대응 방법을 갖추는 것이 중요합니다.
1. 예외 처리 복구(Exception Handling and Recovery)
💡 예외 처리 복구(Exception Handling and Recovery)
- 예외 상황을 처리하고, 정상적인 실행 흐름으로 복귀하는 방법을 의미합니다.
- 예외가 발생했을 때 해당 예외를 처리하고 문제를 해결하여 프로그램의 실행을 계속할 수 있도록 합니다.
💡 예외 처리 예시
- try 블록을 사용하여 예외가 발생할 수 있는 코드를 포함하고 있습니다.
- 코드는 FileReader 객체를 사용하여 파일을 읽으려고 시도합니다. 파일이 찾을 수 없는 경우(FileNotFoundException) 해당 예외 유형의 catch 블록이 실행되고 파일을 찾을 수 없다는 메시지가 출력됩니다.
- 파일을 읽는 도중에 오류가 발생한 경우(IOException), IOException에 대한 catch 블록이 실행되고, 파일을 읽는 도중에 오류가 발생했다는 메시지가 출력됩니다.
try {
FileReader fileReader = new FileReader("file.txt");
// 파일을 읽는 작업
fileReader.close();
} catch (FileNotFoundException e) {
System.out.println("파일을 찾을 수 없습니다.");
} catch (IOException e) {
System.out.println("파일을 읽는 도중에 오류가 발생했습니다.");
}
2. 예외 처리 회피(Exception Handling and Avoidance)
💡 예외 처리 회피(Exception Handling and Avoidance)
- 예외가 발생할 수 있는 상황을 사전에 예방하거나 회피하는 방법입니다.
- 이는 예외를 발생시키는 코드를 변경하거나 예외가 발생할 가능성이 있는 조건을 사전에 체크하여 예외가 발생하지 않도록 합니다.
💡 예외 처리 예시
- 사전에 예외가 발생할 수 있는 input 변수가 null이 아니고 비어있지 않은지 확인합니다.
- 그렇지 않을 경우, "올바른 형식의 입력을 제공해 주세요."라는 메시지가 출력됩니다.
if (input != null && !input.isEmpty()) {
// 유효한 입력 처리
} else {
System.out.println("올바른 형식의 입력을 제공해주세요.");
}
3. 예외 처리 전환(Exception Handling and Propagation)
💡 예외 처리 전환(Exception Handling and Propagation)
- 예외를 다른 형태로 변환하여 처리하는 방법을 의미합니다.
- 예외를 발생시킨 위치와 예외 처리를 담당하는 위치를 분리시킴으로써 코드의 가독성과 유지보수성을 향상할 수 있습니다.
💡 예외 처리 예시
- 하위 레벨에서 발생한 예외를 상위 레벨로 전달하여 상위 레벨에서 예외처리를 할 수 있도록 전환할 수 있습니다.
try {
// 하위 레벨에서 발생한 예외
throw new SQLException("데이터베이스 연결 오류");
} catch (SQLException e) {
throw new DataAccessException("데이터 액세스 오류", e);
}
4. 예외 처리 무시 (Exception Handling and Ignoring)
💡 예외 처리 무시 (Exception Handling and Ignoring)
- 예외를 무시하고 그냥 넘어가는 방법을 의미합니다.
- 프로그램이 예외를 처리하지 않고 그냥 계속 실행됩니다. 주의할 점은 예외를 무시하면 예외가 발생한 이유를 파악하기 어렵고 예외가 실제로 문제를 야기할 수 있다는 점 있습니다. 가능한 예외처리 무시는 피하는 것이 좋습니다.
💡 예외 처리 예시
- 해당 예시에서는 try 단계에서 발생한 오류를 catch 내에서 처리를 무시하고 실행하는 방법입니다.
try {
// 예외가 발생할 수 있는 코드
} catch (Exception e) {
// 예외 처리 무시
}
💡 [참고] 추가적인 Exception에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
종류 | 링크 |
Global Exception : Controller Exception | https://adjh54.tistory.com/79 |
Bussiness Exception : Service Exception | https://adjh54.tistory.com/89 |
오늘도 감사합니다. 😀
반응형
'Java > 이론 및 문법' 카테고리의 다른 글
[Java] Enum(Enumerated type) : 열거형 이해하기 -1 : 정의, 주요특징, 메서드, 활용 예시 (0) | 2024.02.16 |
---|---|
[Java] @Transactional 어노테이션 상세 이해하기 : Checked, Unchecked Exception Rollback (2) | 2024.01.03 |
[Java] 접근 제한자/제어자(Access Modifier) 이해하기 : public, private, protected, default (0) | 2023.12.24 |
[Java] API 캐시와 세션 이해하기 (1) | 2023.10.22 |
[Java] JVM(Java Virtual Machine) 이해하기 -3 : 가비지 컬렉터(GC, Garbage Collector) (0) | 2023.10.09 |