본문 바로가기
개발&프로그래밍

[JAVA] try-with-resources와 AutoCloseable 인터페이스

by 재아군 2024. 11. 4.

[JAVA] try-with-resources와 AutoCloseable 인터페이스

[JAVA] try-with-resources와 AutoCloseable 인터페이스

 

자바 7에서 도입된 try-with-resources는 자원 관리를 훨씬 쉽고 안전하게 만들어주는 기능이다.

기존의 try-finally 구문을 대체하며, 코드의 가독성과 안정성을 크게 향상시킨다.

 

 

기존 방식의 문제점

전통적인 자원 관리 방식은 다음과 같은 문제가 있다:

FileInputStream fis = null;
try {
    fis = new FileInputStream("file.txt");
    // 파일 처리 로직
} catch (IOException e) {
    // 예외 처리
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            // close() 메서드의 예외 처리
        }
    }
}

 

이 코드의 문제점:

  • 중첩된 try-catch 블록으로 인한 복잡성
  • close() 호출 시 발생하는 예외 처리 누락 가능성
  • 여러 리소스 사용 시 코드가 더욱 복잡해짐

 

try-with-resources 사용법

같은 기능을 try-with-resources로 구현하면 훨씬 간단해진다:

try (FileInputStream fis = new FileInputStream("file.txt")) {
    // 파일 처리 로직
} catch (IOException e) {
    // 예외 처리
}

 

여러 리소스를 함께 사용할 때:

try (FileInputStream fis = new FileInputStream("input.txt");
     FileOutputStream fos = new FileOutputStream("output.txt")) {
    // 파일 처리 로직
} catch (IOException e) {
    // 예외 처리
}

 

AutoCloseable 인터페이스 구현

커스텀 리소스 클래스를 try-with-resources와 함께 사용하려면 AutoCloseable 인터페이스를 구현해야 한다:

public class CustomResource implements AutoCloseable {
    private boolean resourceInUse;

    public CustomResource() {
        this.resourceInUse = true;
        System.out.println("리소스 할당");
    }

    public void doSomething() {
        if (!resourceInUse) {
            throw new IllegalStateException("리소스가 이미 해제됨");
        }
        System.out.println("리소스 사용 중");
    }

    @Override
    public void close() {
        if (resourceInUse) {
            resourceInUse = false;
            System.out.println("리소스 해제");
        }
    }
}

 

사용 예제:

try (CustomResource resource = new CustomResource()) {
    resource.doSomething();
    // 자동으로 close() 호출
}

 

 

실전 활용 예제

데이터베이스 연결 관리

public class DatabaseConnection implements AutoCloseable {
    private Connection conn;

    public DatabaseConnection(String url) throws SQLException {
        this.conn = DriverManager.getConnection(url);
    }

    public void executeQuery(String sql) throws SQLException {
        try (Statement stmt = conn.createStatement()) {
            ResultSet rs = stmt.executeQuery(sql);
            // 결과 처리
        }
    }

    @Override
    public void close() throws SQLException {
        if (conn != null && !conn.isClosed()) {
            conn.close();
        }
    }
}

 

파일 처리 유틸리티

public class FileProcessor implements AutoCloseable {
    private BufferedReader reader;
    private BufferedWriter writer;

    public FileProcessor(String inputPath, String outputPath) throws IOException {
        this.reader = new BufferedReader(new FileReader(inputPath));
        this.writer = new BufferedWriter(new FileWriter(outputPath));
    }

    public void processLines() throws IOException {
        String line;
        while ((line = reader.readLine()) != null) {
            writer.write(processLine(line));
            writer.newLine();
        }
    }

    private String processLine(String line) {
        return line.toUpperCase();
    }

    @Override
    public void close() throws IOException {
        try (reader; writer) {
            // Java 9부터 가능한 try-with-resources 향상된 문법
        }
    }
}

 

주의사항과 팁

  1. 예외 처리 우선순위
    • try 블록에서 예외가 발생하고, close()에서도 예외가 발생하면 try 블록의 예외가 전파됨
    • close()의 예외는 suppressed 예외로 추가됨
try (CustomResource resource = new CustomResource()) {
    throw new RuntimeException("try 블록 예외");
} catch (Exception e) {
    // try 블록의 예외가 잡힘
    Throwable[] suppressed = e.getSuppressed();
    // suppressed 예외 처리
}
  1. Null 리소스 처리
  2. // null 리소스는 안전하게 무시됨 try (FileInputStream fis = shouldCreateStream() ? new FileInputStream("file.txt") : null) { if (fis != null) { // 파일 처리 } }
  3. 자원 해제 순서
    • 선언된 순서의 역순으로 close() 호출
    • 가장 마지막에 생성된 리소스부터 해제

실무 적용 시 장점

  1. 코드 간결성
    • finally 블록 없이도 안전한 리소스 해제
    • 중첩된 try-catch 블록 제거
  2. 안정성
    • 실수로 리소스를 해제하지 않는 상황 방지
    • 모든 예외가 적절히 처리됨
  3. 유지보수성
    • 리소스 관리 로직이 분리되어 비즈니스 로직에 집중 가능
    • 표준화된 방식으로 리소스 관리

 

댓글