본문 바로가기

Language/Java

Exception (예외) 의 개념과 사용 이유

반응형

Exception 은 '예외'라는 뜻이다. Exception에 대해 정리하기 전에 궁굼증이 생겼다.

 

"예외와 오류의 차이는 뭐지?"

 

위의 물음을 해결하고자 예외와 오류의 차이를 먼저 정리하고 가겠습니다. 

 

0. Exception (예외) 와 Error (오류) 의 차이

 

 

 

Exception (Java SE 15 & JDK 15)

All Implemented Interfaces: Serializable Direct Known Subclasses: AbsentInformationException, ActivationException, AgentInitializationException, AgentLoadException, AlreadyBoundException, AttachNotSupportedException, AWTException, BackingStoreException, Ba

docs.oracle.com

Java Documatation 을 확인해봐도 Exception과 Error는 다르다고 가지 치기를 해놓은걸 확인 할 수 있습니다. 

 

예외와 오류의 가장 큰 차이는 발생후 처리 가능성이다.

 

그 말인 즉슨, 예외의 경우 프로그램적으로 처리가 가능하기 때문에 일반 개발자가 핸들링이 가능하고 오류의 경우는 프로그램 자체가 종료 될 수 있고 개발자가 핸들링 할 수 없는 부분이다. 

 

그럼 좀더 나아가 예외의 종류에 대해 짚고 넘어 가겠습니다. 

 

1. 예외의 종류

 

예외의 종류는 아래의 표와 같이 정리 할 수 있습니다. 

 

예외 구분 설명 종류
일반적인 예외(Checked Exception) 컴파일시에 발생하는 예외
반드시 예외 처리를 해야한다.
FileNotFoundException
InterruptedException
실행시 예외(Unchecked Exception) 프로그램이 실행되다가 발생하는 예외
예외처리를 하지 않아도 컴파일에는 문제가 없다.
ArrayIndexOutBoundsException
ArithmeticException

 

즉, 둘의 차이를 한줄로 정리하젼 '컴파일 전/후 알 수 있는가' 이다. 

 

그럼 이제 예외의 경우에는 개발자가 핸들링이 가능하다고 했기 때문에 핸들링 하는 방법에 대해 정리하겠습니다. 

 

2. 예외 처리 방법

 

try {
//  예외가 발생할 여지가 있는 소스코드위치
} catch (Exception ex) {
//  예외가 발생시 처리내역
} finally {
// try-catch  절이 끝난 뒤 마지막으로 처리할 내역
}

 

자바에서 사용하는 예외 처리를 위한 소스 코드의 기본 문법입니다. 

 

try catch finally
예외가 발생할 여지가 있는 소스코드 작성 예외 발생시 처리내역 예외 발생 유무 상관없이 무조건 수행하는 소스코드

 

 

3. 예외처리는 왜 하는가?

 

회원가입을 위한 비즈니스 로직을 예로 들어 보겠습니다. 회원 가입을 하기 위해서 개발자는 아래에서 정의한 5개의 로직을 수행하는 프로그램을 작성해야 합니다. 

 

[1] 아이디 중복 검증을 해야한다.

[2] 이메일 검증을 해야한다.

[3] 패스워드가 설정한 기준에 부합하는 검증해야한다.

[4] 휴대폰 검증을 해야한다.

[5] 데이터베이스에 회원정보를 저장한다. 

 

만약 아래의 로직을 작성하기 위해 try catch문을 사용하지 않고 조건문을 사용한다고 가정하면 아래의 코드 처럼 작성 할 것이다. 

 

if 아이디 중복체크 검증을 통과 했는가 {
	if  이메일 검증을 통과 했는가 {
		if  비밀번호 검증을 통과 했는가 {
			if 휴대폰 검증을 통과 했는가 {
            	데이터베이스에 회원정보를 저장한다.
            }	
           	else {
            	휴대폰 검증을 통과 하지 못했을 때
            }
        }
        else {
            비밀번호 검증을 통과 하지 못했을 때 
        }		
    }
    else {
        이메일 검증을 통과 하지 못했을 때 
    }		
}
else {
	아이디 중복체크 검증을 통과 하지 못했을 때 
}

위의 코드는 한눈에 보기도 힘들 뿐더러, 지금은 회원가입을 위한 비즈니스 로직이 저것보다 더 많아 진다고 하면 해당 프로그램의 소스코드를 유지보수 하는 측면에서 비효율적인 코드일 것입니다. 

 

때문에 예외처리를 사용해야 하는 것입니다. 

 

try {
	아이디 검증

	이메일 검증

	비밀번호 검증

	전화번호 검증
} catch (아이디 검증이 실패 했을 때) {

} catch (이메일 검증이 실패 했을 때) {

} catch (비밀번호 검증이 실패 했을 때) {

} catch (전화번호 검증이 실패 했을 때) {

}  
finally {
	예외처리와 관계없이 수행할 로직
}

 

try catch문으로 예외처리를 한 경우 입니다. 

 

한눈에 봐도 예외 발생 시 마다 어떤 로직을 처리 하는지 한눈에 보기 쉽게 되어있습니다. 

 

try catch문을 작성할 때는 한가지 문법적 주의사항이 있습니다. 

 

"예외의 상위 클래스는 하위 클래스보다 catch문이 위에 있을 수 없다." 아래의 코드에서 'ArrayIndexOutBoundsException' 는 'Exception'을 상속받는 하위 클래스로 catch문을 작성할 때는 상위 클래스가 먼저 작성 될 수 없다는 것만 주의 하면 될것 같습니다.

 

catch(ArrayIndexOutBoundsException ex) {

}
catch(Exception ex) {

}

 

 

try catch문을 무분별하게 사용하면 오히려 OOP 적 관점을 해칠 수 있습니다. 코드의 재사용은 매우 OOP적 관점에서 중요한 개념이기 때문입니다. 예를 들어 다른 유형의 비즈니스 로직이 추가 된다고 가정해 봅시다 .

그럼 조건문을 여러개 사용했던 것 처럼 try catch 문도 여러개를 사용해야하는 경우가 발생합니다. 

 

이러한 상황을 지양하고자 등장한 개념이 throw 와 throws 입니다. 

 

 

4. throw 와 throws

 

 

public static void main(String [] args ) {
		
		try {
			아이디 검증
            		아이디 검증 예외시 호출 되는 메서드();
			
			이메일 검증
			
			비밀번호 검증
			
			전화번호 검증
			
		} catch (아이디 검증이 실패 했을 때) {
		
		} catch (이메일 검증이 실패 했을 때) {
			
		} catch (비밀번호 검증이 실패 했을 때) {
			
		} catch (전화번호 검증이 실패 했을 때) {
			
		}  
		finally {
			예외처리와 관계없이 수행할 로직
		}
		
	}
	
	public static void 아이디 검증 예외시 호출 되는 메서드 throws 아이디 검증이 실패 했을 때 {
		throw new Exception(); // 강제 예외 발생
	}

 

이런 식으로 사용되는데 구체적으로 하나 하나 뜯어서 설명 해보겠습니다. 

 

먼저 'throws'는 예외를 처리한다기 보다는 발생한 예외 객체를 양도하는 것이다. 

 

여기서는 아이디 검증시 예외가 발생했고 '아이디 검증 예외시 호출되는 메서드' 호출해 아이디 검증이 실패했을때 Exception 객체를 생성해 호출했던 위치로 전달하고 그 객체를 통해 catch문을 작성하는 것이다. 

 

굳이 이렇게 하는 이유는 try catch문을 남발 하는 것 보다 하나의 try catch문으로 다양한 예외 처리를 한곳에서 처리하는 게 훨씬 OOP 지향형 프로그래밍인데 그 이유는 코드를 재사용하기 용이 하기 때문입니다. 

 

 

정리하자면

 

1. 예외와 오류는 다르다.

2. 예외의 종류에는 일반적 예외와 실행시 예외가 있다.

3. 예외 처리를 하기 위해서 try catch문을 사용한다.

4. OOP를 지향한 예외 처리를 위한 코드를 사용해야만 한다.

반응형