코틀린 스터디/이펙티브 코틀린

아이템9) use를 사용하여 리소스를 닫아라

막이86 2024. 2. 28. 14:49
728x90

이펙티브 코루틴을 요약한 내용입니다

  • 더 이상 필요하지 않을 때, close 메서드를 사용해서 명시적으로 닫아야 하는 리소스가 있음
    • InputStream, OutputStream
    • java.sql.Connection
    • java.io.Reader(FileReader, BufferedReader, CSSParser)
    • java.new.Socket, java.util.Scanner
  • AutoCloseable을 상속받은 Closeable 인터페이스를 구현하고 있음
  • 모든 리소스는 최종적으로 리소스에 대한 레퍼런스가 없어질 때 가비지 컬렉터가 처리
    • 굉장히 느리며 리소스를 유지하는 비용이 많이 발생
  • 명시적으로 close를 호출하는 것이 좋음
    • try-catch
    fun coutCharactersInFile(path: String): Int {
    	val reader = BufferedReader(FileReader(path))
    	try {
    		return reader.lineSequence().sumBy { it.length }
    	} finally {
    		reader.close()
    	}
    }
    
  • try-catch 코드는 복잡하고 좋지 않음
    • 리소스를 닫을 때 예외가 발생할 수 있지만 따로 처리하지 않음
    • try 블록과 finally 블록 내부에 오류가 발생하면 둘 중 하나만 전파 됨
      • 둘다 처리하기에는 코드가 복잡해짐
  • use라는 이름의 함수를 사용해서 코드를 변경하면 좋음
    • 모든 Closeable 객체에 사용할 수 있음
    fun coutCharactersInFile(path: String): Int {
    	val reader = BufferedReader(FileReader(path))
    	reader.use {
    		return reader.lineSequence().sumBy { it.length }
    	}
    }
    
  • 람다 매개변수로 리시버가 전달되는 형태도 있으므로 줄여서 사용할 수 있음
  • fun coutCharactersInFile(path: String): Int { BufferedReader(FileReader(path)).use { reader -> return reader.lineSequence().sumBy { it.length } } }
  • 파일을 한 줄씩 처리할 때 활용할 수 있는 useLines 함수도 제공
    • 파일의 줄을 한 번만 사용이 가능한 단점
    fun coutCharactersInFile(path: String): Int {
    	File(path).useLines { lines ->
    		return lines.sumBy { it.length}
    	}
    }
    
    • 여러번 읽어야 할 경우
    fun coutCharactersInFile(path: String): Int = 
    	File(path).useLines { lines ->
    		lines.sumBy { it.length}
    	}
    
    

정리

  • use를 사용하면 Closeable/AutoCloseable을 구현한 객체를 쉽고 안전하게 처리 할 수 있음
728x90