[Java/Kotlin] try-with-resources으로 자원 해제 처리하기

박희중·2023년 5월 6일
2

잡기술

목록 보기
1/2
post-thumbnail

내가 알고 있는 개념 혹은 회사생활에서 고민했던 부분들을 기록해두면 좋겠다고 생각했었다.
하지만 기록하면 좋겠다는 주제 리스트가 자꾸만 늘어나기만 하고 그동안 너무 미루고 있었던 것 같다.

그래서 지금이라도 하나씩 기록해볼까한다.



일반적으로 자원(resource)를 사용하고 난 후에는 해당 자원을 해제해야한다.

간단하게 설명하자면 자원을 다 쓰고 난 후에도 불필요한 해당 자원을 해제하지 않으면 자원 누수가 발생하면서 메모리 부족과 같은 상황이 발생할 수 있다.

따라서 자원(ex. stream)을 다 쓰고 난 후에는 close와 같은 자원 해제를 해줘야한다.


Java 7버전 이전에는 사용하고 난 자원를 반납하기 위해 try-catch-finally 구문을 사용했었다.

Java 7버전부터 추가된 try-with-resources 구문은 try블록에서 리소스를 선언하고 try블록이 종료되면 자동으로 반납(close)해주는 구문이다.
이에 대해 자세하게 이야기해보겠다.



Try-catch-finally

finally블록은 예외가 발생하더라도 항상 실행되는 블록이므로, 자원 해제 코드를 작성하면 자원을 항상 안전하게 해제할 수 있다.

FileInputStream input = null;
try {
    input = new FileInputStream("file.txt");
    // 파일에서 데이터를 읽어오는 코드
} catch (IOException e) {
    // 예외 처리 코드
} finally {
    if (input != null) {
    	input.close(); // FileInputStream을 닫는 코드
    }
}

위의 코드 예시에서는 FileInputStream 클래스를 사용하였고 FileInputStream 클래스는 자원을 사용하므로, 이를 사용한 후에는 해제해줘야 한다.

finally 블록에서 close() 메서드를 호출하여 자원을 해제한다.

이처럼 try 블록에서 exception이 발생하더라도 finally블록은 항상 실행되므로 예외 유무와는 상관없이 자원 해제 처리를 할 수 있다.



Try-with-resources

try-with-resources 구문은 자원을 사용한 후 자동으로 닫아주는 기능을 제공한다.

try (FileInputStream input = new FileInputStream("file.txt")) {
    // 파일에서 데이터를 읽어오는 코드
} catch (IOException e) {
    // 예외 처리 코드
}

try 블록에서 자원(여기에서는 FileInputStream)을 선언하고, try 블록이 끝나면 자동으로 해당 자원이 해제된다. 이를 위해선 자원이 AutoCLoseable 인터페이스를 구현하고 있어야 한다.

try-with-resources 구문을 사용하면 코드가 간결해지고, 자원 해제가 자동으로 이루어지므로 예외 처리 코드도 간편해진다.



Try-catch-finally vs Try-with-resources

try-catch-finally 구문을 사용한 코드에서는 FileInputStream 객체를 직접 생성하고 finally 블록에서 이를 닫는 코드(close)를 작성해야한다.


반면에, try-with-resources 구문을 사용한 코드에서는 FileInputStream 객체를 try 블록 안에서 선언하고, try 블록이 끝나면 자동으로 객체가 닫히기때문에 따로 close 해줄 필요가 사라진다.

그로인해 try-with-resources 구문을 사용하면, 자원을 해제하는 코드가 간결해진다.


개발자의 입장에서도 try-catch-finally은 close를 직접 해줘야해서 혹시 실수로 close를 빠뜨린다면(물론 잘 안 빠뜨리겠지만 개발자는 인간이므로...) 자원 누수가 발생할 수 있다.

하지만 try-with-resources는 자동으로 자원 해제를 하기때문에 자원 누수 실수에 있어서 자유로울 수 있다고 생각한다.


따라서 자원을 사용할 상황이 생겼을 때 가능하면 try-with-resources 구문을 사용하는 것이 좋다.

하지만 AutoCloseable 인터페이스를 상속받지 않는 클래스로 자원을 생성하려면 try-with-resources 구문을 사용할 수 없다. 그럴 땐 try-catch-finally 방식으로 자원을 수동 해제해주면 된다.



Kotlin의 use함수

코틀린에서는 자바에서의 try-with-resources 구문 기능을 함수로 제공하고 있다.

FileInputStream(fileName).use { inputStream ->
	// 파일에서 데이터를 읽어오는 코드 
}

Kotlin에서는 use 함수를 사용하여 try-with-resources 기능을 할 수 있다.

use 함수는 자원을 열고 사용한 후 자동으로 닫아주는 기능을 제공한다.

use 함수를 사용하면 FileInputStream 객체를 생성하고, 해당 객체를 블록 안에서 사용한 후 자동으로 닫아준다.

물론 자바의 try-with-resources 구문과 마찬가지로 use 함수는 객체가 AutoCloseable 인터페이스를 구현하고 있어야 한다.
FileInputStream 클래스는 AutoCloseable 인터페이스를 상속받고 있으므로 use 함수를 통해 자원을 생성하면 된다.

이렇듯 코틀린에서는 use 함수만으로 간결하게 자원을 생성할 수 있다.

-> FileInputStream과 같이 Stream 종류들이나 또한 자원을 생성해야한다면 use를 사용해서 자원을 생성하자!

profile
백엔드 엔지니어 박희중입니다.

0개의 댓글