GC가 메모리를 알아서 정리해주는데 왜 명시적으로 리소스를 정리해줘야하는지 이 때, disposable 패턴이 어떻게 사용되는지 알아보자
C#의 GC는 모두가 잘 알고있다시피 Heap에 생성된 객체 중 더 이상 참조되지 않는 객체들을 자동으로 수거해준다.
하지만 GC가 수거하지 않는 대상이 있다. 바로 unmanaged resource 인데, 이런 리소스들은 실제로는 OS 레벨에서 핸들링되는 OS 자원이고 GC는 그 내부에 열려있는 소켓이나 리소스 동작에 대해 알 수 없기 때문에 해당 리소스가 랩핑된 객체 정도만 수거할 수 있다.
unmanaged resource
파일 핸들 (FileStream)
DB 커넥션 (SqlConnection)
네트워크 소켓 (TcpClient)
허브/웹소켓 커넥션 (HubConnection)
타이머, 쓰레드, 핸들, 윈도우 핸들 등 OS 리소스
따라서 위 리소스들을 명시적으로 해제해주지 않으면 소켓이 열려있거나, db 커넥션 풀을 다 써버리거나 리소스 누수로 이어져 심하면 OOM 등 전체 프로세스에 큰 영향을 줄 수가 있다.
그래서 등장한 것이 바로 IDisposable 패턴이다.
C# 에서의 자원 해제
C#의 using 구문은 IDisposable을 구현한 객체에 대해 블록 종료 시 자동으로 Dispose()를 호출한다.
try (
FileInputStream is = new FileInputStream("file.txt");
BufferedInputStream bis = new BufferedInputStream(is)
) {
int data;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
}
ByteArrayInputStream(byteArray).use { stream ->
}
// 내부적으로 AutoCloseable.close() 호출. java7 try-with-resources 와 동일