이펙티브 코틀린 Item 9: use를 사용하여 리소스 닫기

woga·2023년 3월 26일
0

코틀린 공부

목록 보기
12/54
post-thumbnail
  • InputStream, OutputStream

  • java.sql.Connection

  • java.io.Reader(FileReader, BufferedReader, CSSParser)

  • java.new.Socket, java.util.Scanner

이 친구들은 더 이상 필요하지 않을 때, close 메서드를 사용해서 명시적으로 닫아야 한다.
물론 더 다양한 것들이 있을 수 있지만 대표적인 것들이다

이러한 리소스들은 AutoCloseable을 상속받는 Closeable 인터페이스를 구현하고 있다.

그리고 이런 애들은 리소스에 대한 레퍼런스가 없어질 때 GC가 처리한다. 그치만 굉장히 느리며 리소스를 유지하는데 비용이 많이 들어간다.
그렇기 때문에 사용이 끝나면 명시적으로 close 메서드를 호출해서 닫아주는게 좋다

그럼 이 때 명시적으로 호출을 보통 아래처럼 사용할 것이다.

fun countCharactersInFile(path: String): Int {
	val reader = BufferedReader(FileReader(path))
    try {
    	return reader.lineSequence().sumBy { it.length }
    } finally {
    	reader.close()
    }
}

그치만 이렇게 예외처리하면 try 블록과 finally 블록 내부에서 오류가 발생하면, 둘 중 하나만 전파된다. 둘 다 전파될 수 있게 구현한다면 코드가 길고 복잡해진다.

코틀린엔 이런 코드를 직접 표준 라이브러리에 함수로 넣어둔게 있는데 바로 use다.

fun countCharactersInFile(path: String): Int {
	val reader = BufferedReader(FileReader(path))
    reader.use {
    	return reader.lineSequence().sumBy { it.length }
    }
} 

심지어 람다 매개변수로 리시버가 전달되는 형태도 있다.

fun countCharactersInFile(path: String): Int {
    BufferedReader(FileReader(path)).use { reader ->
    	return reader.lineSequence().sumBy { it.length }
    }
} 

또한, 파일을 리소스로 사용하는 경우가 많고 한 줄씩 읽어 들이는 경우도 많으므로 코틀린 표준 라이브러리는 useLines 함수도 제공한다.

fun countCharactersInFile(path: String): Int {
    File(path).use { lines ->
    	return lines.sumBy { it.length }
    }
} 

이렇게 처리하면 메모리에 파일의 내용을 한 줄씩만 유지하므로 대용량 파일도 적절하게 처리할 수 있다. 물론 한 줄 씩 읽기 때문에 특정 줄을 두 번 이상 읽고 싶으면 두 번 파일을 열어야하는 단점도 있다.

정리

  • 해당 리소스들을 처리할 때 use를 사용해서 쉽고 안전하게 처리하자
  • 파일 처리는 useLines가 좋다

나는 지금까지 try/catch 문으로 처리하는 거만 알았는데 해당 함수가 있다는 걸 처음 알았다! 이렇게 표준 라이브러이에 편리한 함수가 많아서 코틀린이 더 편하게 쓰이는 듯 하다

profile
와니와니와니와니 당근당근

0개의 댓글