Written by 안재우(Jaewoo Ahn), 닷넷엑스퍼트(.netXpert)
예전 Voice of .NETXPERT 2003 행사 때, 저희 회사의 김유철 책임이 발표했던 내용인 '아무도 가르쳐 주지 않는 .NET 애플리케이션 개발 Tips 18가지'를 정리해서 올립니다.
세번째로 ADO.NET 관련 팁 2가지입니다.
Tip 6. Strict Typed Parameter 사용하기
데이터액세스 작업을 수행하다보면 Parameterized Query나 SP를 사용하는 경우, SqlParameter와 같은 Parameter Class를 사용하여 매개변수를 전송해야 하는 경우가 많습니다.
SqlParameter를 만드는 방법에는 여러가지가 있지만, 일반적으로 다음 생성자를 사용하는 경우가 많습니다.
SqlParameter(string parameterName, object value);
매개변수명/값 쌍으로만 전달하면 되므로, 다음과 같이 작성하기만 하면 되어서 전반적으로 매우 편리하기 때문입니다.
SqlParameter param = new SqlParameter("@ProductID", "50"); // Case1
SqlParameter param = new SqlParameter("@ProductID", 50); // Case2
둘 중 어느 것을 사용하더라도 상관은 없습니다. 그런데, 이 두개만 하더라도 실제 SQL 프로파일러로 찍어보면 결과가 서로 다른 것을 알 수 있습니다.
exec...@ProductID',N'@ProductIDnvarchar(4000)', @ProductID = N'50' // Case1
exec...@ProdcutID',N'@ProductIDint', @ProductID = 50 // Case2
이러한 결과가 나타나는 이유는 ADO.NET이 매개변수의 값으로부터 매개변수의 Type을 추론해내기 때문입니다. 명시적으로 지정을 하든, 지정을 하지 않든 Type은 어느 경우나 반드시 필요합니다. 위의 예에서는 Case2가 좀 낫긴 하지만, 만약 ProductID가 int가 아닌 다른 숫자형이었다면?
결론적으로 가장 바람직한 것은 매개변수의 Type을 정확하게 지정해주는 것이 좋다는 것입니다. 그러므로 매개변수명/값 쌍 형태보다는 다음과 같이 매개변수명/Type 쌍으로 생성한 후, 값을 따로 지정해주는 것이 보다 바람직합니다. Type 외에도 Size, Precision 등이 있는 경우, 이를 지정해주면 더욱 더 좋습니다.
SqlParameter param = new SqlParameter("@ProductID", SqlDbType.Int);
param.Value = 50;
프로파일링을 해보면 알 수 있지만 보다 많은 사항을 명시적으로 지정해줄 수록 서버 측 리소스를 절감해서 쿼리 속도 및 성능이 개선되는 것을 알 수 있습니다. 정리하자면 개발자의 편의성과 성능은 반비례한다는 것이 되겠죠. ^^
Tip 7. ADO Recordset으로부터 DataSet 만들기
기존 시스템이 ASP로 되어 있었고, ADO Recordset을 반환하는 비즈니스 로직 컴포넌트를 호출해서 데이터를 가져오는 3-Tier 구조로 되어 있었다고 가정합시다.
그러던 어느날 프리젠테이션 부분을 ASP.NET으로 교체한다고 회사에서 결정을 내렸습니다. 윗 사람은 이미 비즈니스 로직은 다 작성되어 있어서 프리젠테이션 부분만 작성하면 되니깐 금방 하겠다고 하면서 프로젝트 일정을 말도 안되게 짧게 잡아 놓았습니다. 안된다고 말을 할려니, 이전에 3-Tier 구조의 장점을 역설했던 일이 거짓말이 되어버리게 생겼습니다. 그렇다고 기존 Recordset을 그대로 사용하려니 ASP.NET에서의 데이터바인딩과 같은 장점을 전혀 사용할 수가 없습니다. 어쩔수 없이 밤을 새서라도 기존 비즈니스 로직 컴포넌트를 .NET으로 재작성하려고 생각을 했는데, 엎칱데 덮친 격으로 기존 컴포넌트에 해당하는 소스가 현재 나한테 없습니다. 이러한 경우, 도대체 어떻게 해야 할까요?
이러한 경우, 기존의 Legacy 로직을 재사용하는 것으로 방향을 잡는 것이 바람직합니다. 처음부터 재작성을 하기에는 시간과 비용이 모자라기 때문입니다.
이때 유용한 것이 바로 OleDbDataAdapter의 Fill 메서드입니다. 다른 DataAdapter들과는 다르게, OleDbDataAdapter의 Fill 메서드에는 다음과 같은 오버로딩이 존재합니다.
public int Fill(DataSet dataSet, object ADODBRecordSet, string srcTable);
이 메서드는 ADODBRecordSet의 내용을 DataSet 내에 srcTable이라는 이름의 DataTable로 채워 넣는 역할을 수행합니다. 이렇게 하여 RecordSet의 내용을 DataSet으로 옮길 수 있게 됩니다.
이렇게 할 때 장점은 다음과 같습니다.
첫째, 기존 Legacy 로직을 수정/변경 없이 그대로 재사용이 가능합니다.
둘째, 기존 Recordset이 Connection 기반이더라도 이를 통해 Disconnected 모델로 전환이 가능합니다.
셋째, 기존 Recordset의 커서 타입에 관계없이 자유롭게 Disconnected 모델에서 사용이 가능합니다.
넷째, 기존 Legacy 로직을 XML 웹 서비스나 .NET 리모팅으로 쉽게 재사용할 수 있게 만들 수 있습니다.
단, 이렇게 할 경우, 재사용을 통해 시간과 비용을 절감할 수는 있겠지만, 성능적인 측면에서는 오히려 저하될 수도 있다는 것에 주의해야 합니다.
다음 번에는 ASP.NET 관련 팁일듯 합니다. ^^