예외처리 꼭 해야하나요??

LSM ·2022년 3월 9일
0

1. 프로그램에서의 오류

먼저 해당 글은 Java의 오류처리를 기반으로 설명한다!

자바 프로그래밍 중 발생하는 오류를 크게 2가지 범주로 나누면, 아래 2가지로 나눌 수 있다.

  1. 컴파일 오류(compile error)
    프로그램 코드 작성 중 발생하는 문법적 오류이다.
    최근에는 개발 환경(eclipse,intelij)에서 대부분의 컴파일 오류는 detection 된다.
  1. 실행 오류(runtime error)
    실행 중인 프로그램이 의도 하지 않은 동작(bug)을 하거나 프로그램이 중지 되는 오류
    실행 오류는 비정상 종료가 되는 경우 시스템의 심각한 장애를 발생할 수 있다.

2. 예외 처리 꼭 해야 하나요?

예외처리는 개발자 입장에서 보면, 참으로 귀찮은 작업인듯하다...

하지만 예외처리 만큼 중요한 작업도 없다!!

예외처리를 통해 개발자는 프로그램이 비정상 종료를 피하도록 하여 시스템이 원할이 실행되도록 하기 때문이다.

그렇다면 모든 에러를 어떻게 예측할것인가??....

개발자가 compile time에서가 아닌 runtime 시 발생한 오류의 경우 오류의 과정을 재현하는 것은 현실적으로 힘들다

따라서 개발자들은 생각했다 기록(log)을 남기자!

log 분석을 통해 그 원인을 파악하여 bug를 수정하는 것이다.

3. 오류와 예외는 다르다!

  • 시스템 오류(error) : 가상 머신에서 발생, 프로그래머가 처리 할 수 없는 오류임
    동적 메모리가 없는 경우, 스택 메모리 오버플로우등
  • 예외(Exception) : 프로그램에서 제어 할 수 있는 오류이다.
    읽어들이려는 파일이 존재하지 않거나, 네트웍이나 DB연결이 안되는 경우, Null Pointer 등

자바는 안전성이 중요한 언어로 대부분 프로그램에서 발생하는 오류에 대해 문법적으로 예외 처리를 해야한다!

4. Java의 Exception Class

그림에서 나타내듯, 모든 예외 클래스의 최상위 클래스는 Exception 클래스이다.

자바에서는 다양한 예외들에 대해 그 처리를 위한 클래스가 제공되고 있기 때문에 이는 다 정리할 수 없을 듯 하다. 필요하면 그때 그때 찾아보면서 해결하는 걸로!!

만약 내가 발생시키고 싶은 에러가 없다면...? 예외처리를 상속받은 CustomClass를 생성하자 !

5. Java의 다양한 try catch 문법들

try-catch 문

일반적으로 우리가 알 고 있는 try catch 문법이다.

try-catch-finally 문

public class FileExceptionHandling {

	public static void main(String[] args) {
		FileInputStream fis = null;
		try {
			fis = new FileInputStream("a.txt");
		} catch (FileNotFoundException e) {
			System.out.println(e);
			return;
		}finally{
			if(fis != null){
				try {
					fis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println("항상 수행.");
		}
	}
}

위의 코드를 예시로 든다면, 파일 작업이 필요할 때, 개발자는 파일을 열고 작업을 한다.
그런데 예외가 발생한다고 해서 열어둔 파일을 닫지 않는 것은 메모리 낭비이다!

따라서 이와 같은 경우 처럼 항상 수행 되어야 하는 경우

finally {} 내부에 정의하면, 위와 같이 catch {} 내부에 return 이 있다고 한들 항상 finally는 실행이 된다

try-with-resources문

이 문법은 자바 7부터 제공되고 있는 문법이다.

위와 같이 리소스에 대한 접근이 있고 항상 close가 필요한 경우에 사용할 수 있다!

리소스를 try() 내부에서 선언해야만 하며, close()를 명시적으로 호출하지 않아도 try{}블록에서 열린 리소스는 정상적인 경우나 예외가 발생한 경우 모두 자동으로 해제된다.

해당 리소스 클래스가 AutoCloseable 인터페이스를 구현 해야 함

FileInputStream의 경우에는 AutoCloseable을 구현하고 있다고 한다!

자바 9 부터 리소스는 try() 외부에서 선언하고 변수만을 try(obj) 와 같이 사용할 수 있음

코드 예시)

public class AutoCloseObj implements AutoCloseable{

	@Override // 구현체
	public void close() throws Exception {
		System.out.println("리소스가 close() 되었습니다");
	}
}
public class AutoCloseTest {
	
	public static void main(String[] args) {
		
	    AutoCloseObj obj = new AutoCloseObj();
    	try (obj){
			throw new Exception();
		}catch(Exception e) {
			System.out.println("예외 부분 입니다");
		}
	}
}

6. 예외 처리 미루기 throw

예외 처리는 위와 같이 예외가 발생하는 문장에서 try-catch 블록으로 처리하는 방법과 이를 사용하는 부분에서 처리하는 방법 두 가지가 있다!

throws를 이용하면 예외가 발생할 수 있는 부분을 사용하는 문장에서 예외를 처리할 수 있다

이 또한 코드를 통해 이해하자

class ThrowsException {

	// 클래스 객체 반환 함수
	public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException{
		FileInputStream fis = new FileInputStream(fileName); //FileNotFoundException 발생
		Class c = Class.forName(className);  //ClassNotFoundException 발생
		return c;
	}

	public static void main(String[] args) {

		ThrowsException test = new ThrowsException();
		
		try {
			test.loadClass("a.txt", "java.lang.String");
		
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

위 와 같은 구조로 오류가 발생할 수 있는 메서드 내부에서 발생하는 오류를 메서드 내에서 처리하지 않고 메인 메서드로 예외처리를 위임하는 것이 throw 이다!

7. 로그를 남기자!!

앞에서도 로그의 중요성에 대해 언급했던 것 같은데.. 다시 한번 짚고 넘어가겠다

로그(log)란? 시스템 운영에 대한 기록이다 (error 상황만 기록하는 것은 아님)

  • 오류가 발생 했을 때 그 오류에 대한 기록을 남겨 디버깅을 용이하게 함
  • 로그 파일에 기록하는 코드를 추가하여 필요한 정보가 로그로 남을 수 있도록 한다
  • (목적) 디버깅, 시스템 에러 추적, 성능, 문제점 향상들을 위해 사용

어느정도 까지 로그를 남겨야 하나요~?

정해진 것은 없다. 다만

너무 적은 로그는 어떠한 에러의 발생 이후, 정확한 시스템의 상황을 파악하기 어렵다

반면,

너무 많은 로그는 빈번한 file I/O가 발생으로 인한 오버헤드와 로그 파일의 백업 문제등 다양한 추가작업이 존재한다는 수고스럼움이 있다.

음... 적당량의 로그를 남기며 부족하면 늘리고 많다면 줄이면서 합의점을 찾아야 하는 듯 하다.

Java에는 java.util.logging 이 있다!

자바에서 기본적으로 제공되는 log package이며, 파일이나 콘솔에 로그 내용을 출력할 수 있다!

jre/lib/logging.properties 파일을 편집하여 로그의 출력방식 로그 레벨을 변경 할 수 있다고 한다.

logging 패키지에서 제공하는 로그 레벨은 severe, warning, info, config, fine, finer, finest 이며 상황에 맞게 적절한 로그 레벨을 부여하자!

나 같은 경우에는 Springboot 개발에서는 오픈소스로는 log4j 를 많이 사용하고 있다!!


8. 정리

성가시고 귀찮기만한 Error Handling 하지만 이보다 중요한 것은 없다!!

오늘은 자바에서의 예외처리에 대해 정리하고 알아보는 시간을 가졌다.

다음번에는 Log4j 와 같은 흔히 사용하는 로깅 오픈소스에 대해서 한번 까봐야 겠다 ㅎㅎ


참고자료

fastcampus : 한번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online. ch6/9-11

profile
개발 및 취준 일지

0개의 댓글