<프로그래밍의 오류(Error) 종류는 발생 시점에 따라 크게 3가지로 나뉜다.>
1.논리 오류(Logic Error) / 실행은 되지만 의도와 다르게 동작하는것
: 이른바 '버그' 라고 생각하면 된다. 프로그램이 실행하고 작동하는데는 아무런 문제가 없는 오류이지만, 결과가 예상과 달라 사용자가 의도한 작업을 수행하지 못하게 되어 서비스 이용에 지장이 생길 수 있다. 논리적 오류는 컴퓨터 입장에서는 프로그램이 멀쩡히 돌아가는 것이니 에러 메시지를 알려주지 않는다. 따라서 개발자는 프로그램의 전반적인 코드와 알고리즘을 체크 필요가 있다.
예를 들어 재고량이 음수가 나오면 안되는데 음수가 나와버리는 경우, 게임 캐릭터가 피가 0이어도 죽지 않는 경우를 들 수 있다.
2.컴파일 오류(Compillation Error) / 컴파일 시에 발생하는 에러
: 컴파일 에러는 컴파일 단계에서 오류 발견하면 컴파일러가 에러 메시지 출력해주는 것을 말한다. 컴파일 에러 발생의 대표적인 원인으로 문법 구문 오류(syntax error)를 들 수 있다. 심각하게 볼 오류 종류는 아니다. 이는 즉 프로그램이 만들어지지 않아 프로그램 실행 자체가 불가하기 때문이다. 따라서 개발자는 차후에 일어날 에러를 컴파일러가 미리 멘토링한다고 생각하며 코드를 수정하면 될 일이다.
3.런타임 오류(Runtime Error) / 실행 시에 발생하는 에러
: 프로그램 실행 중에 에러가 발생해서 잘못된 결과를 얻거나, 혹은 외부적인 요인으로 기계적 결함으로 프로그램이 비정상적으로 종료될 수 있다. 이것이 우리가 집중적으로 파헤쳐 봐야 할 실행 오류(런타임 에러)이다.
대체로 개발 시 설계 미숙(논리적)으로 발생하는 에러가 대부분이며, 런타임 에러 발생 시 프로그래머가 역추적해서 원인 확인해야 한다. 따라서 이러한 잠재적인 런타임 에러를 방지하기 위해서는 프로그램의 실행 도중 발생할 수 있는 경우의 수를 고려하여 이에 대한 대비를 철저히 해야 한다.
실행 시 발생할 수 있는 오류(runtime error)를 '에러(error)'와 '예외(exception)' 두가지로 구분한다.
3-1.오류(Error) :
프로그램 코드에 의해서 수습될 수 없는 심각한 오류, 즉 개발자가 대처할 방법이 없다.
3-2.예외(Exception) :
프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류, 즉 개발자가 대응 코드를 미리 작성해 놓음으로써 어느정도 프로그램의 비정상적인 종료 혹은 동작을 막을 수 있다. 이 예외에 대한 대응 코드가 바로 우리가 배울 자바의 예외 처리 문법(try - catch, finally)이 되겠다.
<코드 실행 관점👁️에서 예외(Exception)의 종류>
1.런타임 에러(예외)
프로그램이 실행 시 맞닥뜨리게 되는 예외, 우리가 주로 다루게 될 에러(예외)
2.컴파일 에러(예외)
사용자의 실수와 같은 외적인 요인에 의해 발생하는 컴파일 시 발생하는 에러(예외)
대부분 개발자가 자바 프로그래밍 언어의 규칙을 지키지 않았기 때문이다. 해결 방법은 문법에 맞게 다시 작성하는 것이다.
<예외처리 관점👁️에서 예외(Exception)의 종류>
1. Checked Exception(확인된 예외) / 컴파일 시점에 확인, 반드시 예외 처리를 해줘야 하는 예외이다.
Checked Exception이 발생할 가능성이 있는 메소드라면 반드시 로직을 try - catch로 감싸거나 throws로 던져서 처리해야 한다.
⚠️
컴파일 시점에 확인하는 예외라는 문구 때문에, 컴파일 에러와 헷갈리 시면 안 된다! 우리가 이미 특정한 문제를 인지하고 있어서, 해당 예외를 정의해두었고, 정의해두었기 때문에 컴파일 하는 동안 이 예외에 대한 예외 처리를 했는지 확인(Check) 할 수 있는 예외이다. ”즉 Checked Exception에 대한 예외 처리를 하지 않으면 컴파일 에러가 발생한다.”
2.Unchecked Exception(미확인된 예외) / 런타임 시점에 확인되는 예외, 예외 처리가 반드시 필요하지 않은 예외이다.
개발자의 충분한 주의로 미리 회피할 수 있는 경우가 대부분이라 그나마 상대적으로 미약한 예외로 처리되어 자바 컴파일러는 별도의 예외 처리를 하지 않도록 설계 되어 있기 때문이다. 따라서 에러를 일부러 일으키는 코드가 있더라도 try - catch 처리하지 않더라도 컴파일도 되고 실행까지 가능하다.
=> 앞서 checked exception은 반드시 try - catch 문으로 감싸야된다고 했다.
하지만 코드마다 일일히 예외처리하는 것도 귀찮고 오히려 가독성을 해친다고 생각할 경우, 그냥 unchecked exception으로 변환시켜 컴파일에게 예외처리를 강제하지 않게 할 수 있다. 이미 수많은 구현체들이 있고, 거의 대부분의 상황에 맞는 에러들은 이미 구현되어 있다. 명시적으로 어떠한 에러를 내보낼지는 찾아보고 결정하면 된다. 만약 정 찾아봤는데, 없다면 특정 에러를 더 구체화해서 내가 직접 “정의” “구현”하면 된다.
<정리>
우리가 프로그래밍을 하다 보면 “문제” 상황에 직면하고, 맞닥뜨린 문제를 “회복 가능 여부”에 따라 “Error”와, “Exception”으로 나누고, 예외와, 에러를 컴파일/런타임과 같은 여러 가지 기준에 따라 구체적으로 “정의”했다.
결론적으로 우리는 맞닥뜨리는 “문제” 상황을 추상화, 일반화, 구체화해서 정의해뒀다.
- 가장 추상적인 “문제”
- 그것보다는 조금 더 구체적인 “오류”, “예외”
- 그것보다 더 구체적인 “Checked Exception”, “Unchecked Exception” 과 같이 정의를 할 수 있다.
<오류 클래스 계층 구조>
자바에서는 오류를 Error와 Exception으로 나누었고 이들을 클래스로 구현하여 처리하도록 하였다. JVM은 프로그램을 실행하는 도중에 예외가 발생하면 해당 예외 클래스로 객체를 생성하고서 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해준다. Error 클래스는 외부적인 요인으로 인해 발생하는 오류이기 때문에 개발자가 대처 할 수는 없다. 따라서 우리가 중점적으로 봐야할 클래스는 바로 Exception 클래스이다
오류와 예외 모두 자바의 최상위 클래스인 (1)Object를 상속받는다.
그리고 그 사이에는 (2)Throwable 클래스와 상속관계가 있는데, Throwable 클래스의 역할은 오류나 예외에 대한 메시지를 담는 것이다. 대표적으로 getMessage() 와 printStackTrace() 메서드가 바로 이 클래스에 속해 있다.
당연히 Throwable을 상속받은 (3)Error 클래스와 (3)Exception 클래스에서도 위 두 메서드를 사용할 수 있게 된다.
자바에서 다루는 모든 예외 오류는 Exception 클래스에서 처리한다.
즉, Exception 클래스는 다시 (4)RuntimeException 클래스(런타임 에러를 다룸)와 그 외의 (4)Exception 및 자식 클래스 그룹(컴파일 에러를 다룸)으로 나뉘게 된다.
*RuntimeException 클래스 종류
ArrayIndexOutOfBoundsException : 배열의 범위를 넘어선 인덱스를 참조할 때 발생하는 에러
IllegalArgumentException : 메서드의 전달 인자값이 잘못된 경우 방생하는 에러
ArithmeticException : 정수를 0으로 나눌 때 발생하는 에러
NullPointException : null 객체에 접근해서 method를 호출하는 경우 발생하는 에러
NumberFormatException : 정수가 아닌 문자열을 정수로 변환할 때 예외 발생
InputMismatchException : 의도치 않는 입력 오류 시 발생하는 예외
등
*Exception 및 하위 클래스 종류
IOException : 입력 함수를 사용할 때 발생할 수 있는 예외
FileNotFoundException : 파일에 접근하려고 하는데 파일을 찾지 못했을 때 발생하는 에러
SQLException : 데이터 소스에 액세스하는 동안 발생하는 오류 및 경고
등
<예외 발생과 try-catch, finally 문>
1.예외 정의하기
class OurBadException extends Exception {
public OurBadException() {
super("위험한 행동을 하면 예외처리를 꼭 해야합니다!");
}
}
2.클래스를 만들고, 메서드를 만들며 우리의 메서드가 위험하다고 알리기(throw, throws)
class OurClass {
private final Boolean just = true;
public void thisMethodIsDangerous() throws OurBadException {
if (just) {
throw new OurBadException();
}
}
}
3.우리가 위험한 메서드를 사용한다면, 예외를 handling 하기
public class StudyException {
public static void main(String[] args) {
OurClass ourClass = new OurClass();
try {
// 1. 위험한 메소드의 실행을 "시도" 해 봅니다.
// "시도" 해보는 코드가 들어가는 블럭입니다.
ourClass.thisMethodIsDangerous();
} catch (OurBadException e) {
// 2. 예외가 발생하면, "잡아서" handling 합니다.
// 예외가 발생하는경우 "handling" 하는 코드가 들어가는 블럭입니다.
// 즉 try 블럭 내의 구문을 실행하다가 예외가 발생하면
// 예외가 발생한 줄에서 바로 코드 실행을 멈추고
// 여기 있는 catch 블럭 내의 코드가 실행됩니다.
System.out.println(e.getMessage());
} finally {
// 3. 예외의 발생 여부와 상관없이, 실행시켜야 하는 코드가 들어갑니다.
// 무조건 실행되는 코드가 들어가는 블럭입니다.
System.out.println("우리는 방금 예외를 handling 했습니다!");
}
}
}
- catch 단어의 **“잡는다”**라는 의미에 맞게 중괄호{} 안에는 try 안에 있는 코드를 실행하다가 예외가 났을 때 실행할 코드를 담는다.
- catch 는 소괄호()를 통해 어떤 예외 클래스를 받아서 처리할지 정의해 주어야 한다.
- catch로 모든 예외를 다 받고 싶으면 Exception 을 넣어주면 된다.
- catch로 일부 예외만 받아서 처리하고 싶으면 해당 예외 클래스명을 넣어주면 된다.
- 1개의 try 문에 catch 문은 여러 개 사용할 수 있다. ex) 1 try : 4 catch
▶ 용어 다시 정리해 보기
- 우리는 방금 예시에서 Checked Exception을 다뤘다.
- 예외가 발생하는 상황을 “인지” 했고, 어떠한 에러인지 “정의” 했다.
- 우리는 메서드를 선언할 때 예외가 발생하는 위험한 메서드라는 것을 “알렸다 (throws/throw)”.
- 우리가 checked exception을 정의하고, 알렸으니 이 메서드를 사용할 때 예외 처리를 하지 않으면 컴파일 에러가 발생한다!
'개발 > 부트캠프' 카테고리의 다른 글
본캠프 : 개인 과제(키오스크 만들기) 트러블 슈팅 (2) | 2025.01.20 |
---|---|
본캠프 : 베이직반 특강_1회차 세션 정리 (0) | 2025.01.19 |
본캠프 : 개인 과제(계산기 만들기)_1:1 피드백 (0) | 2025.01.16 |
본캠프 : 개인 과제(키오스크 만들기)_Scanner 값 입력 복습 (0) | 2025.01.15 |
본캠프 : 개인 과제(키오스크 만들기)_for문 복습 (0) | 2025.01.14 |