Error와 Exception는 같은 것일까요?
"다릅니다."
Error는 컴파일 시 문법적인 오류와 런타임 시 널포인트 참조와 같은 오류로 프로세스에 심각한 문제를 야기해 프로세스를 종료할 수 있는 것을 의미합니다.
Exception은 컴퓨터 시스템의 동작 도중 예기치 않았던 이상 상태가 발생하여 수행 중인 프로그램이 영향을 받는 것으로, 개발자에 의해 의도한 문제를 의미합니다.
즉, Error를 방지하기 위해 Exception을 만들 수 있으며, Java에서는 try-catch문이나 throw를 통해 Exception Handling으로 관리할 수 있습니다.
Error의 종류
조금 더 자세히 알아보겠습니다.
1. 컴파일 에러(Compillation Error)
컴파일 단계에서 발생되는 오류를 의미합니다. 주로 문법 오류에 인해 발생합니다.
ex) 맞춤법, ';' 의 부재, 선언되지 않는 변수를 사용한 경우 등
이 경우 Tool에서 보통 컴파일을 처리하면서 에러의 발생여부를 알려줍니다.
따라서 개발자는 이에 맞춰 코드를 수정하게 됩니다.
2. 런타임 에러(Runtime Error)
런타임 단계에서 발생되는 오류를 의미합니다.
3. 논리 에러(Logic Error)
컴파일, 런타임 모두 정상적으로 작동하지만, 결과가 예상과 달라 사용자가 의도한 작업을 수행하지 못하는 것을 의미합니다.
이 경우, 에러 메세지가 없어서 수정에 어려움을 겪습니다.
보통 로그인할때 비밀번호를 검토하는 작업이나, 토큰이 일치하는 여부를 확인한 뒤 그에 맞는 에러를 보내게 되죠.
만약 이러한 처리가 되어 있지 않다면 제대로 된 처리를 하지 못하게 되겠죠!
cf) 자바 에러 역시 클래스로 관리가 됩니다.
Throwable는 Object의 상속을 받습니다.
그리고 에러(Error)와 예외(Exception)는 Throwable의 상속을 받습니다.
Error는 JVM에 설정된 메모리의 한계가 벗어난 상황일 때 발생하는 OutOfMemoryError처럼
개발자가 어떻게 조치할 수 없는 수준을 의미합니다.
Exception은 개발자가 구현한 로직에서 발생하며 개발자가 다른 방식으로 처리 가능한 것들로 JVM은 정상 동작하는 것을 의미합니다.
Exception
- Checked Exception : 예외처리가 필수이며, 처리하지 않으면 컴파일 되지 않습니다.
- Runtime Exception 이외 모든 예외
- IOException, SQLException 등
- Unchecked Exception : 컴파일 때 체크되지 않고, Runtime에 발생하는 Exception을 말합니다.
- Runtime Exception 하위 모든 예외
- NullPointerException, IndexOutOfBoundException 등
Unchecked Exception 종류
1) ArithmeticException
0으로 나누게 되었을 때 사용되는 예외입니다.
2) NullPointerException
null값을 가지고 있는 참조 변수로 접근제한자인 '.'를 사용했을 때 발생하는 에러입니다.
객체가 없는 상태로 객체를 사용하려고 했지만 해당 객체가 없어서 생기는 에러입니다.
헤깔리니 예외로 알아보겠습니다.
public class Test {
public static class main(String[] args) {
String data = null;
System.out.println(data.toString()); // null.toString? -> error
}
}
3) ArrayIndexOutOfBoundsException
배열의 인덱스 범위를 초과했을 때 발생하는 에러입니다.
4) IllegalArgumentException
넣은 값이 변수와 맞지 않은 경우 발생하는 에러입니다.
이것도 예를 들어서 확인해보겠습니다.
int a = 2147483649; // 실제 값이 너무 큽니다.
int a = -2147483649; // 실제 값이 너무 작습니다.
String date="08-07-1990"; // 날짜 포맷이 dd-MM-yyyy입니다.
Date format=new SimpleDateFormat("dd/MM/yyyy").parse(date);// 포맷이 다릅니다.
5) FileNotFoundException
존재하지 않는 파일에 접근하는 경우 발생하는 에러입니다.
6) ClassNotFoundException
존재하지 않는 클래스를 사용할 때 발생하는 에러입니다.
7) NumberFomatException문자열을 수치로 전환할때 발생하는 에러입니다.
unchecked Exception의 경우 따로 체크하지 않아도 IDE에서 실행을 하면 에러가 발생합니다.
따라서 따로 확인을 하지 않아도 실행이 되지 않기에 알아내기 쉽습니다.
하지만 checked Exception의 경우 Runtime에 알 수 있기에 테스트 코드를 통해 확인해야만 합니다.
예외 처리
예외가 발생했을 경우 발생하지 않도록 2가지 방법을 주로 사용합니다.
1. try .. catch .. finally 구문을 사용
try 예외가 발생할 수 있는 코드를 넣습니다.
catch 예외가 발생했을 때 실행시킬 코드를 넣습니다.
finally 마지막에 반드시 실행시킬 코드를 넣습니다.
public class trycatchTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
int [] num = new int[3];
System.out.println("num 배열의 최대 길이는 3입니다.");
num[4] = 0;
System.out.println("num[4] 에 값을 입력했습니다.");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("배열 길이가 맞지 않습니다.");
} finally {
System.out.println("00")
}
}
}
// num 배열의 최대 길이는 3입니다.
// 배열의 길이가 맞지 않습니다.
// 00
num[4] = 0 과 "num[4] 에 값을 입력했습니다" 경우는 모두 실행되지 않습니다.
클래스 관계에 따른 컴파일 에러입니다.
catch를 통해 예외로 처리할 수 있습니다. 하지만 여기서는 컴파일 에러가 먼저 발생하겠죠
Unreachable catch block이 발생할 것입니다.
Throwable 메서드
Throwable의 메서드들에 대해 알아보겠습니다.
1) String getMessage() : 예외에 대한 설명을 반환
2) void printStackTrace() : 예외에 대한 정보를 반환 // 에러 메시지가 모두 출력됩니다.
ex)
public static void main(String[] args) {
int A[] = new int[5];
try {
A[7] = 100;
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
}
// Exception message : index 7 out of bounds for lengh 5
2. throws 사용
method를 호출한 곳으로 예외를 떠넘기는 것입니다.
이름만 봐도 던져주겠다는 의지가 다분하죠 ㅎㅎ
하지만 이것을 사용하는데에도 이유가 있습니다!!
만약 예외가 발생하는 API들이 발생한 예외를 모두 처리해버린다면 API를 사용하는 애플리케이션에는 어떤 문제가 발생했는지 전혀 알 수 없게 됩니다.
하지만 개발자에게 예외를 전달함으로써 예외 처리를 강요할 수 있고, 개발자는 자신이 작성한 애플리케이션에서 예외 상황에 대한 적절한 처리가 가능해집니다.
기본 형태부터 알아보겠습니다.
타입 메소드명(매개변수, ...) throws 예외클래스1, 예외클래스2, ... { }
타입 메소드명(매개변수, ...) throws Exception { }
이렇게 throws가 붙어있는 메소드는 반드시 try 블록 내에서 호출되야 합니다.
public void method1() {
try {
method2(); // 에러 발생시 여기에서 처리합니다.
} catch(ClassNotFoundException e) {
System.out.println("클래스가 존재하지 않습니다.");
}
}
public void method2() throws ClassNotFoundException {
// ClassNotFoundException이 발생하게 되면 호출한곳에서 예외처리
Class a = Class.forName("java.lang.String");
}
프로젝트를 만들다보면 이미 try catch로 에러를 처리하고 있는데 특정 에러로 보낼 필요가 있습니다.
이럴 경우 throws를 사용하게 된다면 중간에 에러를 보내기 때문에 해당 메서드에서 에러를 관리하게 되고, catch에서 같은 에러 명을 사용하면, 그 에러를 정확하게 관리할 수 있게 됩니다.
비록 throw new Exception(e); 이렇게 에러로 처리해버릴 수도 있겠지만
원하는 로직을 처리하고 excption을 처리할 수도 있겠죠
마지막으로 예외를 만들어보도록 하겠습니다.
예외 생성
예외를 만들때 사용되는 것 throw입니다.
자바 기준으로는 문제되지 않지만 개발자의 의도에서 예외를 발생시키기 위해서 사용됩니다.
저는 개인적으로 개발할 때, 가장 식별하기 쉬운 방법이라고 생각합니다.
1번째 예입니다.
public static void main(String[] args) {
try {
exceptionMethod(105);
} catch (Exception e) {
}
public static void exceptionMethod(int score) throws Exception {
if(score < 0 || score > 100) {
throw new Exception("점수 입력 오류");
} else {
}
}
}
2번째 예입니다.
class MyException extends Exception { // 예외 생길경우 사용하는 곳에서 예외 처리하도록 하기
int x;
MyException(int x) {
this.x = x;
} // x를 인수로 하는 MyException 만들기
public String toString() {
return x + "는 100 보다 큽니다"
}
}
public class Test {
public static void main(String[] args) {
MyException score = new Exception(105); // 점수 105점 넣기
try {
System.out.println("예외 처리 전");
throw score;
} catch(MyException e) {
System.out.println(e);
} finally {
System.out.println("예외 처리 후");
}
}
}
// 예외 처리 전
// 105는 100 보다 큽니다
// 예외 처리 후
이 방법을 이용하면 웹제작에서도 예외처리를 할 수 있어요!!
주의사항!
혹시 웹제작을 할 때, 예외처리를 너무 자세하게 하게된다면,
그건 또 문제가 됩니다. 백에서 프론트로 예외처리를 할 경우, console을 통해 해킹을 할 수있기 때문에
대부분의 경우는 기본적인 에러 annotation에 따라 처리하는 것을 권장합니다.
하지만, 다양한 에러를 사용해서 예외에 따른 다른 로직을 동작시켜야 한다면, 예외를 커스텀해서 사용할 필요도 있습니다.
저는 BusinessException과 같은 이름으로 사용하지만, 사람마다 회사마다 다양한 방법으로 커스텀해서 사용하고 있죠 ㅎㅎ
hmm.. 제가 그린 무당벌레와 함께 글을 마칠게요 ~!! ㅎㅎ 이번 여름도 cool하게~!
참고자료 : 규글 깃허브(github)
참고 자료 : [자바] 예외 처리(2) throws /throw 왜 쓸까?/ 위임/ Exception/일부러 발생시키는 오류 (tistory.com)
참고 자료 : 자바 예외에 관한 모든 것 - 자바 얀 사이트 (javagyansite.com)
참고 자료 : [JAVA] 자바 오류, 에러 (Error) 종류 (tistory.com)
'기술 스텍 > Java' 카테고리의 다른 글
[Java] 접근 제어자 (2) | 2024.04.21 |
---|---|
[Java] 인터페이스 vs 추상클래스 용도 차이 (3) | 2024.04.21 |
[Java] Reflection이란? (4) | 2024.04.13 |
[Java] 컴포지션이란? (60) | 2024.04.12 |
[Java] Interned String (1) | 2024.04.05 |