https://howtodoinjava.com/best-practices/java-exception-handling-best-practices/#1
JAVA Exception 처리
1. JAVA의 예외 유형
Checked exceptions
대부분 네트워크나 파일 시스템에서 외부 시스템을 사용하려고 할때 발생한다.
올바른 응답은, 나중에 다시 시도하거나, 사용자에게 입력을 수정하라는 메시지를 표시한다.
메소드의 throws 절에서(메서드의 이름 옆) 선언해야 하는 예외.
정상적인 시스템 작동 중에 발생할 수 있는 예상되는 문제점을 나타낸다.
Unchecked exceptions
throws 절에서 선언 할 필요가 없는 예외.
JVM은 프로그래밍 오류로 인해 런타임에 주로 생성되므로 처리하지 않아도 된다.
RuntimeException을 확장한다. 예를들어 NullPointerException.
재시도 해서는 안되며, 일반적으로 아무것도 하지 않고 메서드와 실행 스택을 표시하여 개발자가 접근 할 수 있어야 한다.
Error
복구할 수 없는 심각한 Runtime환경문제. 예를들어 OutOfMemoryError, LinkageError및 StackOverflowError..
올바른 로깅 방법만을로 정확한 오류 원인을 파악할 수 있다.
2. 사용자 정의 예외
사용자가 자신의 응용 내에서 특정한 예외를 사용하길 원한다면 새 클래스를 만들고 만든 예외를 사용 할 수 있다.
// 직접 Exception을 던지거나..
throw new DaoObjectNotFoundException("Couldn't find dao with id " + id);
//catch로 잡아서 던질 수도 있다.
// 이 방법의 장점은 stack추적 및 메시지를 유지하면서 사용자가 임의로 메시지/문맥 정보를 추가하여 사용자에게 추가 정보를 제공할 수 있다는 점이다.
catch (NoSuchMethodException e) {
throw new DaoObjectNotFoundException("Couldn't find dao with id " + id, e);
}
3. JAVA 예외처리시 고려해야 할것
1) catch 블럭에서 예외를 먹어버리지 말자.
catch (NoSuchMethodException e) {
return null;
}
이런식이라면 예외를 처리하거나 윗단으로 던지는 대신 단지 Null을 반환할 뿐만 아니라 예외의 원인을 잃어버려 오류를 분석하기가 어렵다.
2) throw절에서 Exception을 던질때 Exception으로 뭉뚱그리지 않고 특정예외를 던진다.
public void foo() throws Exception { //Incorrect way
}
메서드가 던질 수 있는 특정한 예외를 선언해야 한다. 해당 메서드에서 점검하려는 Exception이 너무 많으면 예외를 랩핑하고 예외 메시지에 정보를 추가해야 한다.
public void foo() throws SpecificException1, SpecificException2 { //Correct way
}
3) 마찬가지로 catch에서 Exception을 잡을때도 Exception으로 뭉뚱그리지 않고 하위 Exception을 특정하여 잡는다.
try {
someMethod();
} catch (Exception e) {
LOGGER.error("method has failed", e);
}
4) Stack추적이 손실되지 않도록 항상 사용자 정의 예외에서 예외를 올바르게 랩핑하자.
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " + e.getMessage()); //Incorrect way
}
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " , e); //Correct way
}
5) 로그를 남기면서 예외를 던지지 않는다.
catch (NoSuchMethodException e) {
LOGGER.error("Some information", e);
throw e;
}
로그파일에 여러개의 동일한 로그메시지를 남기면 찾기 어려울 수 있다.
6) finally 블록에서 Exception을 던지지 않는다.
try {
someMethod(); //Throws exceptionOne
} finally {
cleanUp(); //If finally also threw any exception the exceptionOne will be lost forever
}
cleanUp이 예외를 발생하지 않는 한 괜찮다. someMethod()가 예외를 throw하고 finally에서도 예외를 던지면 첫번째 발생한 예외가 영원히 손실된다..
finally 블록에서 호출하는 코드에서 예외가 발생할 수 있으면 처리하거나 기록해야 한다.
7) 실제로 처리할 수 있는 예외만 잡기
catch (NoSuchMethodException e) {
throw e; //Avoid this as it doesn't help anything
}
예외를 처리하거나 예외 상황에 대한 추가 context정보를 제공하려는 경우에만 예외를 잡기. 다시 던지기 위해 잡는것이 아니여야 한다.
8) printStackTrace()문 또는 유사한 메서드를 사용하지 말기.
9) 예외를 처리하지 않으려면 catch블록 대신 finally 블록을 사용하기
try {
someMethod(); //Method 2
} finally {
cleanUp(); //do cleanup here
}
10) 빨리 던지고 늦게 잡는 원칙을 기억하자.
정보를 올바르게 처리할 수 있을 때까지 기다려야 한다.
문제를 처리할 수 있는 충분한 추상화 수준에 도달할 때까지 예외적으로 스택추적을 여러 수준으로 올리게 된다.
11) 컨트롤러에 도달하기 전, 요청 처리 초기에 사용자 입력의 유효성을 검증한다.
12) 가능한한 모든 정보를 예외에 전달한다.
로그에 가능한 많은 정보를 담아야 한다.
13) 중단된 스레드를 종료하기
while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
break;
}
}
doSomethingCool();
14) try-catch 반복에 템플릿 방법 사용하기
class DBUtil{
public static void closeConnection(Connection conn){
try{
conn.close();
} catch(Exception ex){
//Log Exception - Cannot close connection
}
}
}
public void dataAccessCode() {
Connection conn = null;
try{
conn = getConnection();
....
} finally{
DBUtil.closeConnection(conn);
}
}
'Today I learned' 카테고리의 다른 글
2020 07 30 (0) | 2020.07.30 |
---|---|
힘내봐요! Vuex의숲 (0) | 2020.07.28 |
2020년 7월 20일 (0) | 2020.07.20 |
2020년 07월 17일 금요일 (0) | 2020.07.17 |
2020년 07월 16일 목요일 (0) | 2020.07.16 |
댓글