프로그래밍백엔드 개발자

Java에서 try-with-resources란 무엇이며 전통적인 try-catch-finally 블록과의 차이점은 무엇인가요? 언제 사용해야 하나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

Java의 try-with-resources의 주요 목적은 리소스의 자동적이고 올바른 해제를 보장하는 것입니다. 이 구문이 Java 7에 도입되기 전에는 프로그래머가 finally 블록에서 리소스를 수동으로 닫아야 했습니다. 이는 코드의 중복과 빈번한 오류 발생으로 이어졌습니다.

문제의 역사

Java 6 이전에는 리소스(열린 파일, 스트림, 연결)를 finally를 통해 수동으로 관리해야 했기 때문에 종종 리소스 누수가 발생했습니다.

문제점

수동으로 작성된 리소스 종료 코드로 인해 버그가 발생하기 쉬우며, 특히 여러 예외와 복잡한 catch 블록 계층을 다룰 때 더욱 그렇습니다. 오류 발생 시 close() 호출이 보장되지 않습니다.

해결책

Java 7부터는 try-with-resources 구문이 도입되어, AutoCloseable 인터페이스를 구현하는 각 리소스에 대해 close() 메소드를 자동으로 호출하도록 보장합니다.

코드 예제:

try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) { String line = reader.readLine(); System.out.println(line); } catch (IOException e) { e.printStackTrace(); } // reader는 자동으로 닫힙니다.

주요 특징:

  • 모든 리소스는 예외 발생 시에도 반드시 닫힙니다.
  • AutoCloseable 인터페이스를 구현한 객체만이 try-with-resources에서 사용할 수 있습니다.
  • 템플릿 코드를 단순화하고 줄이며, 리소스 누수 가능성을 줄입니다.

함정 질문들.

질문 1: 리소스가 try-with-resources를 위해 구현해야 할 인터페이스는 무엇인가요?

AutoCloseable. 이 인터페이스(또는 Closeable)를 구현하는 모든 객체는 해당 구조에서 사용할 수 있습니다.

질문 2: 여러 개의 리소스가 try-with-resources에 있을 경우, 어떤 순서로 리소스가 닫히나요?

리소스는 선언된 반대 순서로 닫힙니다 (스택-LIFO):

try (A a = new A(); B b = new B()) { ... } // b.close()가 먼저 호출되고, 그 다음 a.close()가 호출됩니다.

질문 3: AutoCloseable 구현이 없는 비표준 객체(예: 네트워크 연결)에 try-with-resources를 사용할 수 있나요?

아니요, 그러나 자신의 클래스에서 AutoCloseable을 수동으로 구현할 수 있습니다. 이렇게 하면 객체가 try-with-resources와 호환됩니다.

전형적인 오류 및 안티-패턴

  • close()에서 발생하는 예외를 처리하는 것을 잊음
  • AutoCloseable을 구현하지 않은 클래스와 try-with-resources를 사용함
  • 오래된 코드는 기존의 finally를 사용하므로 리소스가 닫히지 않음

실제 사례

부정적 사례

개발자들은 JDBC Connection과 Statement를 finally를 통해 수동으로 닫았습니다. 두 번째 예외가 발생하면 Statement가 닫히지 않았고, 연결이 "중단"되고 오류를 숨겼습니다.

장점:

  • 종료 순서에 대한 제어.
  • 리소스에 대한 명시적 관리.

단점:

  • 리소스를 닫는 것을 잊을 위험.
  • 연결 누수.

긍정적 사례

파일 로드 모듈에 try-with-resources를 도입한 후 모든 스트림이 자동으로 닫히고 코드가 훨씬 짧아졌으며 파일 설명자의 누수 버그가 사라졌습니다.

장점:

  • 신뢰성.
  • 코드의 간결성.
  • 간편한 테스트.

단점:

  • AutoCloseable의 구현 요구.
  • 이전 버전의 Java에서는 즉시 사용할 수 없음.