본문 바로가기

ASP.net with C# (웹폼)

C# using과 try catch finally의 차이점

여러분도 try catch 구문을 많이 사용하시죠? DBConnection과 같이 반드시 닫아주어야 하는 객체를 사용할 땐 finally를 꼬박꼬박 작성하고 있을겁니다. using은 이 try finally와 동일하게 동작하는 구문인데요. try finally구문과 비교해 어떤 잇점이 있는지 사용법에 대해 알아보도록 하겠습니다.

 

MS Docs엔 다음과 using구문에 대해 다음과 같이 설명하고 있습니다. (원문보기)

using구문은 using블록 내에서 어떤 예외적인 상황이 발생한다 하더라도 Dispose가 호출되는 것을 보장합니다. 이는 여러분이 try블록 내에 객체를 두고 finally블록에서 Dispose를 호출 하는 것과 동일한 결과를 얻어낼수 있음을 의미합니다. 이것은 실제로 using구문이 컴파일러에 의해 어떻게 해석되는지를 보여줍니다.

 

결국은 using을 사용하는 것은 try finally구문을 사용하는 것과 결과 적으로 동일합니다. 하지만 using의 사용에서 오는 잇점은 위에서 설명한 것과 같이 "using블록 내에서 어떤 예외적인 상황이 발생한다 하더라도 Dispose가 호출되는 것을 보장"한다는 것입니다. 이 부분은 우리가 흔히 엑셀파일을 열고 닫는데에서 발생하곤 합니다. 보통 엑셀을 열다가 에러가 발생하면 엑셀객체가 소멸되지 않고 GC도 말을 듣지 않습니다. 이는 파일은 Unmanaged리소스이기 때문입니다.

전 과거 클래식ASP 시절부터 엑셀을 열고 닫고 할 일이 많았습니다. 이 엑셀이 워낙 기능이 많아 프로그램에서 열어 사용하다가 예상치 못한 에러가 발생해서 객체를 제대로 닫지 못하고 메모리상에 남아있는 경우가 많이 있었죠. 이렇게 메모리 누수가 쌓이면 결국엔 서버가 죽곤 했습니다. 

그럼 엑셀파일을 열고 닫는 다음의 예제를 통해 두 구문의 차이를 확인해 보겠습니다.

  • using

string conStr = @"provider = Microsoft.ACE.OLEDB.12.0; Data Source = 'C:\sample.xls'; Extended Properties=\"Excel 12.0 Xml;HDR=Yes;IMEX=1;\"";

using (var excelConnection = new System.Data.OleDb.OleDbConnection(conStr))
{
    excelConnection.Open();
    string strSQL = "SELECT * FROM [Sheet1$]";

    using (var dbCommand = new System.Data.OleDb.OleDbCommand(strSQL, excelConnection))
    {
        using (var dataAdapter = new System.Data.OleDb.OleDbDataAdapter(dbCommand))
        {
            DataTable dt = new DataTable();
            dataAdapter.Fill(dt);
         }
     }
 }
  • try finally

string conStr = @"provider = Microsoft.ACE.OLEDB.12.0; Data Source = 'C:\sample.xls'; Extended Properties=\"Excel 12.0 Xml;HDR=Yes;IMEX=1;\"";

var excelConnection = new System.Data.OleDb.OleDbConnection(conStr)
excelConnection.Open();

try
{
    string strSQL = "SELECT * FROM [Sheet1$]";
	var dbCommand = new System.Data.OleDb.OleDbCommand(strSQL, excelConnection)
    var dataAdapter = new System.Data.OleDb.OleDbDataAdapter(dbCommand)

    DataTable dt = new DataTable();
    dataAdapter.Fill(dt);
    
    dataAdapter.Dispose();
    dbCommand.Dispose();
}
finally
{
    excelConnection.Close();
    excelConnection.Dispose();
}

위의 예제에서와 같이 using을 사용하면서 확실하게 객체를 소멸해 주고 코드가 간결해 진다는 것입니다.

 

프로젝트의 성공을 기원합니다.