try-catch-finally 문을 try-with-resource 문으로 변경할 수 있는 방법이 있을까요?

21.07.15 22:54 작성 조회수 270

0

버퍼스트림이나 파일스트림같은 경우에는 자동으로 `try()` 내부에 선언되어 있을 경우 `close()`를 호출해주는 것으로 알고 있습니다.

public static void main(String args[]) {
    try (
        FileInputStream is = new FileInputStream("file.txt");
        BufferedInputStream bis = new BufferedInputStream(is)
    ) {
        int data = -1;
        while ((data = bis.read()) != -1) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}



제가 궁금한 점은 TheadLocal.remove() 메서드가 위와같이 호출이 되는지와 만약 안되면 따로 이 처리에 대한 메서드를 구현시켜서 동작시켜야하는지가 궁금합니다.

답변 2

·

답변을 작성해보세요.

1

안녕하세요. 제로입니다.


JDK 7 이상부터 지원하는 try-with-resource 는 
try-catch-finally 의 복잡함을 해소시켜주는 구문입니다.



문의하신 내용을 가지고
try-with-resource 동작하도록 만들어보면 아래 코드가 되는데요.


try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("file.txt"))) {
// bis
// 1 bis.close()
} catch (Exception ex) {
// 2 ex.printStackTrace();
ex.printStackTrace();
}

bis 객체 사용중 Exception 이 발생되면 
1. bis.close() 처리후
2 ex.printStackTrace() 구문이 실행되어
개발자가 명시적으로
자원에 대한 close 를 신경쓰지 않아도 되는
장점이 있습니다.

그런데
BufferedInputStream 객체와 다르게 
첫번째로 추상화된 공통기능인 객체 Box 는
유틸성 클래스인 ThreadLocal 를 사용해
Box 를 다른 모듈에 전달합니다.

그래서 try-with-resource 가 동작하기 위해선 
Box 가 아닌 static 메소드로 구성된 ThreadLocal 클래스에
AutoCloseable 를 구현해야 하는데
static 메소드로 나열된 ThreadLocal 에 적용하는건 모호합니다.

그리고 remove() 처럼 다른 개발자에게 감춰야 하는 메소드에
public 으로 표현되는 close() 메소드를  적용하는것도 객체지향원칙에 맞지 않구요.

그리고 가장 중요한 문제가 있습니다.
try-with-resource 처리흐름과 try-catch-finally 처리흐름은 다릅니다.
섹션 2 에서 사용된 코드를 간단하게 표현하면 아래와 같은데

ThreadLocal.set(new BoxHttp(request));
try (

} catch (Exception ex) {
// 1 오류가 발생했을때 에러 표현
// err.jsp 호출
errView(ex);
} finallay{
// 2 쓰레드에서 Box 객체 제거
  ThreadLocal.remove();
}


프레임워크는 서비스 로직에서 발생된 예외(Exception)도
개발자가 신경쓰지 않도록 표현하거나 처리해줘야 합니다.

만약
try-with-resource 를 사용해 예외(Exception)를 표현하기전
Box  객체가 ThreadLocal 에서 제거된다면 (ThreadLocal.remove() 호출)

에러를 표현하기 위해 호출되는 뷰에선
Box 를 사용할 기회가 없어지게 되는 문제가 생깁니다.

따라서 AOP 관점으로 제공되는 공통기능인 Box 와 Transaction 2가지 객체는


try-with-resource 구문을 사용하기 보단
try-catch-finally 를 사용해

예외처리시 Box 와 Transaction  객체를 사용할 기회를 준다고 생각하면 됩니다.

쓰다보니 어렵게 표현을 했는데

쉽게 정리하면 2가지로 압축할 수 있네요.
1. 자동으로 close 를 하기 위해 구현해야 하는 AutoCloseable 인터페이스 를 ThreadLocal 에 적용하는건 애매하고
2. ThreadLocal 을 통해 제공하는 공통기능은 try-catch-finally 처리흐름이 필요합니다.

따라서 ThreadLocal 를 사용할 경우
try-with-resource 보단
try-catch-finally  를 사용해 finally  구문에  ThreadLocal.remove() 를 호출하는게 맞습니다.

0

와 매우 친절한 답변 감사드립니다. 

try-catch-finally와 비교해서 try-with-resource가 좋다는 얘기만 들었지 이렇게 비교하면서 적재적소에 활용한다는 개념이 부족했던 것 같습니다.

위에 말씀하신대로 try-catch-finally와 try-with-resource의 처리 흐름이 다르니 저런 케이스를 염두해가면서 사용하는게 좋겠네요. 

AutoCloseable 인터페이스 관련한 답변도 매우 상세하게 해주셔서 감사합니다 :)