Menu
Coddy logo textTech

Try With Resources 패턴

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 62번째.

파일 스트림이나 데이터베이스 연결과 같은 리소스를 작업할 때는 작업이 끝난 후 항상 닫아야 합니다. 그렇지 않으면 메모리 누수 위험이 있습니다. 전통적인 방식은 finally 블록을 사용하지만, 이는 코드가 장황해지고 오류가 발생하기 쉽습니다.

Java의 try-with-resources 문은 블록이 완료될 때 리소스를 자동으로 닫습니다. AutoCloseable 인터페이스를 구현하는 모든 클래스는 이 구문과 함께 사용할 수 있습니다:

// 전통적인 방식 - 장황하고 위험함
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
} finally {
    if (reader != null) {
        reader.close();  // 여기서도 예외가 발생할 수 있습니다!
    }
}

// Try-with-resources - 깔끔하고 안전함
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // 여기서 자동으로 닫힘

세미콜론으로 구분하여 여러 리소스를 관리할 수 있습니다. 리소스는 선언된 역순으로 닫힙니다:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // 두 리소스 모두 사용
}  // br이 먼저 닫히고, 그 다음 fr이 닫힘

자신만의 auto-closeable 클래스를 만들려면 AutoCloseable 인터페이스와 그 단일 close() 메서드를 구현하십시오:

public class DatabaseConnection implements AutoCloseable {
    public DatabaseConnection() {
        System.out.println("Connection opened");
    }
    
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

이 패턴은 처리 중에 예외가 발생하더라도 리소스가 항상 적절하게 해제되도록 보장합니다.

challenge icon

챌린지

쉬움

try-with-resources의 강력함을 보여주는 리소스 관리 시스템을 구축해 봅시다! 연결과 세션을 관리하는 것을 시뮬레이션하는 사용자 정의 auto-closeable 클래스를 만들어, 리소스가 항상 적절하게 정리되도록 할 것입니다.

코드는 세 개의 파일로 구성됩니다:

  • Connection.java: 데이터베이스 연결을 시뮬레이션하는 클래스를 만듭니다. Connection 클래스는 AutoCloseable을 구현해야 합니다. 연결 이름(String)을 위한 private 필드, 이름을 매개변수로 받아 [name] connection opened를 출력하는 생성자, Executing on [name]: [sql]을 출력하는 query(String sql) 메서드, 그리고 [name] connection closed를 출력하는 필수 close() 메서드가 필요합니다.
  • Session.java: 사용자 세션을 시뮬레이션하는 또 다른 auto-closeable 클래스를 만듭니다. Session 클래스 또한 AutoCloseable을 구현해야 합니다. 사용자 이름(String)을 위한 private 필드, 사용자 이름을 매개변수로 받아 Session started for [username]을 출력하는 생성자, [username] performed: [action]을 출력하는 performAction(String action) 메서드, 그리고 Session ended for [username]을 출력하는 close() 메서드를 포함하세요.
  • Main.java: 리소스 관리 시스템을 하나로 합칩니다! 연결 이름, 사용자 이름, 수행할 작업이라는 세 가지 입력을 받게 됩니다.

    먼저, 단일 리소스 관리를 보여줍니다. === Single Resource ===를 출력한 다음, try-with-resources를 사용하여 주어진 이름으로 Connection을 생성합니다. try 블록 내부에서 query("SELECT * FROM users")를 호출하세요. 블록이 끝나면 연결이 자동으로 닫혀야 합니다.

    다음으로, 다중 리소스를 보여줍니다. 빈 줄을 하나 출력한 후, === Multiple Resources ===를 출력합니다. 세미콜론으로 구분하여 Connection(동일한 이름 사용)과 Session(사용자 이름 사용)을 순서대로 선언하여 try-with-resources를 사용합니다. try 블록 내부에서 먼저 연결의 query("INSERT INTO logs")를 호출한 다음, 세션의 performAction을 입력받은 작업과 함께 호출하세요. 리소스가 선언된 역순으로 닫히는 것을 확인해 보세요!

연결 이름(String), 사용자 이름(String), 작업(String) 순으로 세 개의 입력을 받게 됩니다.

try-with-resources가 어떻게 명시적인 close 호출과 finally 블록의 필요성을 없애는지 주목하세요. 예외가 발생하더라도 리소스는 반드시 닫히며, 여러 리소스는 선언된 역순으로 닫힙니다!

치트 시트

try-with-resources 문은 블록이 완료되면 자동으로 리소스를 닫습니다. AutoCloseable을 구현하는 모든 클래스를 사용할 수 있습니다:

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // 여기서 자동으로 닫힘

여러 리소스는 세미콜론으로 구분하여 관리할 수 있습니다. 리소스는 선언된 역순으로 닫힙니다:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // 두 리소스 모두 사용
}  // br이 먼저 닫히고, 그 다음 fr이 닫힘

사용자 정의 auto-closeable 클래스를 만들려면 AutoCloseable 인터페이스와 해당 close() 메서드를 구현하세요:

public class DatabaseConnection implements AutoCloseable {
    public DatabaseConnection() {
        System.out.println("Connection opened");
    }
    
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

직접 해보기

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String connectionName = scanner.nextLine();
        String username = scanner.nextLine();
        String action = scanner.nextLine();
        
        // === Single Resource ===
        // TODO: 헤더를 출력하세요
        // TODO: try-with-resources를 사용하여 Connection을 생성하세요
        // TODO: try 블록 내부에서 query("SELECT * FROM users")를 호출하세요
        
        // === Multiple Resources ===
        // TODO: 빈 줄과 헤더를 출력하세요
        // TODO: Connection과 Session 모두에 try-with-resources를 사용하세요
        // TODO: try 블록 내부에서:
        //       - connection에서 query("INSERT INTO logs")를 호출하세요
        //       - session에서 입력받은 action으로 performAction을 호출하세요
        
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨