Java에서 파일, 네트워크 소켓 등과 같은 자원(Resource)을 사용할 경우, 자원 누수(Resource Leak) 방지를 위해 사용 후 반드시 닫아야 한다. 기존 try-catch-finally 구문에서 finally 블록 내 자원 해제(close()) 호출은 추가적인 예외 처리가 필요하며, 이는 코드의 복잡성을 증가시키는 문제점을 가졌다. Java 7부터 도입된 try-with-resources 문법은 이러한 문제를 해결하며, 자원 관리의 효율성과 코드 가독성을 크게 향상시킨다. 본 글에서는 try-with-resources의 필요성과 사용법을 다룬다.
전통적인 Java 자원 관리 방식은 try-catch-finally 구문을 활용한다. 다음은 FileWriter와 BufferedWriter를 사용한 예시이다.
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class ResourceHandlingLegacy {
public static void main(String[] args) {
BufferedWriter bw = null;
FileWriter fw = null;
try {
fw = new FileWriter("test1.txt"); // 파일이 없으면 자동으로 생성됨
bw = new BufferedWriter(fw);
bw.write("test 1111111");
} catch (IOException e) {
throw new RuntimeException("파일 쓰기 중 오류 발생", e);
} finally {
// 자원 해제는 역순으로 진행하는 것이 일반적임
try {
if (bw != null) bw.close(); // BufferedWriter 닫기
} catch (IOException e) {
// close() 중 발생한 예외 처리 필요
throw new RuntimeException("BufferedWriter 닫기 중 오류 발생", e);
}
try {
if (fw != null) fw.close(); // FileWriter 닫기
} catch (IOException e) {
// close() 중 발생한 예외 처리 필요
throw new RuntimeException("FileWriter 닫기 중 오류 발생", e);
}
}
}
}
상기 로직은 외부 텍스트 파일에 내용을 쓰고 자원을 닫는 기능을 구현한다. 그러나 finally 문 내 close() 동작 자체에서도 IOException이 발생할 수 있으므로, 해당 부분에 대한 추가적인 예외 처리가 필요하다. 이는 코드의 가독성을 저해하고 불필요한 번거로움을 유발하는 문제점을 가진다. 특히, 여러 자원을 사용하는 경우 finally 블록 내에 중첩된 try-catch 구문이 반복되어 더욱 복잡해진다.
Java 7부터는 try-with-resources 문법을 통해 이러한 자원 관리 문제를 간편하게 해결할 수 있다.
try-with-resources는 try 문에서 자원 객체를 선언하여 사용하며, try 블록이 끝날 때 해당 자원을 자동으로 종료시켜주는 기능을 제공한다. 이때 try 문 내에서 선언된 자원은 반드시 java.lang.AutoCloseable 인터페이스를 구현한 객체여야 한다. 대부분의 Java I/O 자원 클래스들은 AutoCloseable 인터페이스를 구현하고 있어 try-with-resources 문법과 함께 활용 가능하다.
try (자원 객체 생성 및 초기화 명령문) {
// 자원 사용 로직
} catch (Exception e) {
// 예외 처리 로직
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class ResourceHandlingTryWithResources {
public static void main(String[] args) {
try (FileWriter fw = new FileWriter("test1.txt"); // 첫 번째 자원 선언
BufferedWriter bw = new BufferedWriter(fw)) { // 두 번째 자원 선언 (세미콜론으로 구분)
bw.write("test 1111111");
System.out.println("파일에 내용 작성을 완료했습니다.");
} catch (IOException e) {
System.err.println("파일 I/O 중 오류 발생: " + e.getMessage());
}
}
}
상기 예시와 같이 try-with-resources를 사용하면 close() 메서드를 명시적으로 호출할 필요가 없다. try 블록을 벗어나는 순간(정상 종료 또는 예외 발생 시) 자원 객체의 close() 메서드가 자동으로 호출된다. 이는 코드의 복잡성을 줄이고, 자원 누수 위험을 최소화하며, 가독성을 크게 향상시킨다. 여러 개의 자원을 선언할 경우 세미콜론(;)으로 구분하여 하나의 try 블록 내에서 관리할 수 있다.
try-with-resources는 Java에서 자원을 안전하고 효율적으로 관리하기 위한 강력한 문법이다. 불필요한 finally 블록의 close() 호출과 그에 따른 예외 처리 로직을 제거함으로써 코드의 간결성, 가독성, 그리고 견고성을 동시에 확보할 수 있다. AutoCloseable 인터페이스를 구현하는 모든 자원에 대해 try-with-resources를 적극적으로 활용하여 보다 안정적인 Java 애플리케이션을 개발하는 것이 권장된다.