작성자: Joydip Kanjilal (누굴까? ㅡㅡ;;)
번역 작성일: 2006년 12월 27일
역자: 웹지니™
원문 보기: http://www.aspaliance.com

독자 여러분의 편의를 위해 원문은 삭제하고 번역문만 기재합니다. 원문이 궁금하신 분은 상단의 [원문 보기] 링크를 클릭해 주세요.
커넥션 풀링은 데이터베이스 액세스 성능을 크게 향상시킵니다. 이 기사에서는 커넥션 풀링이 무엇인지, 어떻게 데이터베이스 액세스 성능을 향상시키는지 그리고 .NET 환경에서 어떻게 커넥션 풀을 생성하고 커넥션 객체를 추가하거나 제거하는지 설명합니다.


Introduction
데이터베이스 연결은 상당히 리소스 집약적이며 상대적으로 느린 작업입니다. 하지만 매우 중요한 일이지요. 커넥션 풀이란 이미 열려져 있으며 재활용 가능한 커넥션 객체들의 컨테이너 입니다. 커넥션 풀은 마지막 커넥션 객체가 닫힐 때 메모리에서 해제됩니다. 커넥션 풀링을 이용할 때의 가장 기본적인 이점은 성능의 향상과 확장성이며 가장 중요한 단점은 실제로 사용되지 않는 커넥션이 열린 상태로 보관된다는 점입니다.
.NET의 데이터 프로바이더들은 기본적으로 커넥션 풀링이 활성화되어 있습니다. 만일 커넥션 풀링을 비활성화 하려면 연결 문자열에 Pooling=false라고 명시적으로 지정해야 합니다. 커넥션 풀링은 매번 데이터베이스 연결이 필요할 때마다 커넥션 객체를 생성하는 대신 이미 만들어져 있고 연결된 상태로 재활용할 수 있는 커넥션 객체를 제공합니다.
커넥션 객체가 닫히거나 메모리에서 해제될 때 이 커넥션 객체는 커넥션 풀로 되돌아가 다시 데이터베이스 연결이 필요해 질 때까지 대기하게 됩니다. 우리가 커넥션 풀링을 효과적으로 사용한다면 데이터베이스 액세스 작업에 필요한 리소스는 비교적 줄어들게 됩니다. 이 기사에서는 커넥션 풀링이 대체 무엇인지, 그리고 응용 프로그램의 성능과 확장성을 향상시키기 위해 커넥션 풀링을 어떻게 효율적으로 활용할 것인지를 설명합니다.


How does Connection Pooling work?
사실 커넥션 풀은 이미 열려져 있고 재사용 가능한 연결들을 보관하는 일종의 컨테이너입니다. 동시에 동일한 응용 프로그램 도메인 내에 여러 개의 풀이 존재할 수 있지만 커넥션 풀은 서로 다른 응용 프로그램 도메인 사이에서 공유될 수는 없습니다. 중요한 것은 하나의 연결 문자열을 위한 하나의 커넥션 풀이 생성된다는 점입니다. (역자 주: 즉, 서로 다른 연결 문자열 2개를 사용하는 응용 프로그램에서는 두 개의 커넥션 풀이 생성되게 됩니다. 연결 문자열이 단 한글자만 틀려도 커넥션 풀은 서로 다른 연결 문자열로 인식한다는 것에 주의해야 합니다.)
커넥션 풀은 어떤 연결 문자열을 이용해서 데이터베이스 액세스가 처음 시도될 때 생성됩니다. 또한 다른 연결 문자열을 이용해서 데이터베이스에 액세스하려는 요청이 들어오면 이 때는 또 다른 커넥션 풀이 생성됩니다. 그래서 우리는 데이터베이스 당 하나의 커넥션 풀이 아니라 연결 문자열 하나 당 하나의 커넥션 풀을 갖게 되는 것입니다. 다음 예제는 이러한 상황을 재현해 줍니다.

Listing 1

//연결 풀이 생성됩니다.
SqlConnection sqlConnection = new SqlConnection();
sqlConnection.ConnectionString = "Server=localhost;Database=test;User ID=joydip;Password=joydip;Trusted_Connection=False";
sqlConnection.Open();     

Listing 2
//연결 문자열이 다르기 때문에 또 다른 커넥션 풀이 생성됩니다.
SqlConnection conn = new SqlConnection();
sqlConnection.ConnectionString =
"Server=localhost;Database=test;User ID=test;Password=test;Trusted_Connection=False";
sqlConnection.Open();  

Listing 3
// 연결 문자열이 Listing 1에서 사용된 것과 같기 때문에 새로운 커넥션 풀이생성되지 않습니다..
SqlConnection conn = new SqlConnection();
sqlConnection.ConnectionString =
"Server=localhost;Database=test;User ID=joydip;Password=joydip;Trusted_Connection=False";
sqlConnection.Open();   
 

새로운 커넥션에 대한 요청이 들어오면 새로운 커넥션을 생성하지 않고 커넥션 풀에 보관되어 있던 재사용 가능한 커넥션 객체가 사용됩니다. 이 방법은 여러분의 응용 프로그램 성능과 확장성을 향상 시킵니다. 응용 프로그램이 커넥션을 닫으면 커넥션 객체는 커넥션 풀로 되돌아가 재연결 제한 시간이 지날 때까지 대기합니다. 연결 제한 시간이란 커넥션 객체가 동일한 연결 문자열로 동일한 데이터베이스에 다시 액세스할 필요가 있을 때까지 대기하는 시간입니다. 이 제한 시간 내에 새로운 요청이 들어오지 않으면 데이터베이스에 대한 연결은 닫히고 커넥션 객체는 커넥션 풀에서 제거됩니다.
새로운 커넥션 풀이 생성되면 커넥션 객체는 커넥션 풀에 보관되고 커넥션 풀과 커넥션 객체는 언제든지 사용할 수 있는 상태가 됩니다. 커넥션 풀은 연결 문자열에 지정된 최대 개수만큼의 커넥션 객체를 보관하고 있습니다. 커넥션 객체들은 비활성화된 상태로 장시간 커넥션 풀에 보관되거나 지정된 시간이 지나거나 또는 실제로 데이터베이스 연결이 가능하지 못한 상태가 될 때까지 커넥션 풀에 보관됩니다.
커넥션 풀은 내부적으로 커넥션 풀 관리자에 의해 관리됩니다. 지속적인 연결 요청이 들어오면 커넥션 풀 관리자는 커넥션 풀에서 사용 가능한 커넥션 객체를 찾아 응용 프로그램에 리턴합니다. 다음의 사항들은 커넥션 풀 관리자가 어떻게 동작하는지를 보여주며 새로운 커넥션 객체에 대한 요청이 들어왔을 때 동작을 시작합니다.
사용되지 않는 커넥션 객체가 커넥션 풀에 존재하면 이 커넥션 객체를 리턴합니다. 모든 커넥션 객체가 사용 중이면 새로운 커넥션 객체를 생성하고 커넥션 풀에 추가합니다. 커넥션 객체의 수가 커넥션 풀의 최대 객체 수에 도달하면 사용 가능한 커넥션 객체가 커넥션 풀로 되돌아올 때까지 요청이 대기하게 됩니다.

커넥션 풀을 제어하는데 필요한 연결 문자열의 매개 변수들은 아래와 같습니다.

Connection Timeout
MinPoolSize
MaxPoolSize
Pooling

커넥션 풀링을 보다 효과적으로 사용하기 위해서는 사용이 끝난 커넥션 객체의 Close 메서드를 반드시 호출해서 커넥션 객체가 커넥션 풀로 돌아갈 수 있도록 해야 합니다.


Improving Connection Pooling Performance
우리는 늘 최대한 늦게 커넥션을 열고 최대한 빨리 커넥션을 닫아야 합니다. 즉, 사용이 끝난 즉시 커넥션을 닫아야 하는 것이지요. 커넥션 객체는 실제로 사용되는 동안에만 열려있어야 합니다. 커넥션 객체가 오래도록 열려 있어서 커넥션 풀 내의 사용 가능한 커넥션 객체의 수를 줄이고 그에 따라 커넥션 풀의 성능에 영향을 미쳐서는 안됩니다. 커넥션 객체는 사용이 끝난 즉시 해제되어야 합니다. 이는 커넥션 객체가 재빨리 커넥션 풀로 되돌아가 재사용 가능한 상태로 만들어 줍니다. 아래 예제는 응용 프로그램 내에서 커넥션 객체를 효율적으로 열고 닫는 방법을 보여줍니다.


Listing 4
SqlConnection sqlConnection = new SqlConnection(connectionString);
try
{
  sqlConnection.Open();
  //실행될 코드
}
finally
{
  sqlConnection.Close();
}
Listing 4의 코드는 아래와 같이 "using" 키워드로 바꿔 쓸 수 있습니다.


Listing 5
using(SqlConnection sqlConnection = new SqlConnection(connectionString))
{
  sqlConnection.Open();
  //실행될 코드
}
Listing 5에서 사용된 using 키워드는 컴파일 시 try ~ finally 구문으로 변환된다는 것을 기억할 필요가 있습니다. 아래는 커넥션 풀링을 보다 효율적으로 활용하기 위한 방법입니다.

데이터베이스 연결은 항상 필요할 때 열고 사용이 끝나면 곧바로 닫아줍니다. 커넥션 객체를 닫기 전에 사용자 정의 트랜잭션을 항상 먼저 닫아줍니다. 최소한 하나 이상의 열려진 커넥션 객체가 커넥션 풀에 있도록 합니다.
연결 문자열에서 Integrated Security 특성을 이용하는 경우 커넥션 풀리의 사용을 피합니다. 커넥션 풀의 상태는 아래와 같은 방법으로 모니터링 할 수 있습니다.

sp_who 또는 sp_who2 저장 프로시저를 실행합니다. SQL Server Profiler를 사용합니다. 성능 모니터와 성능 카운터를 사용합니다.


References
- Tuning Up ADO.NET Connection Pooling in ASP.NET Applications
- Connection Pooling for the .NET Framework Data Provider for SQL Server
- The .NET Connection Pool Lifeguard
- ADO.NET Connection Pooling Explained
 

Conclusion
커넥션 객체의 컨테이너인 커넥션 풀은 활성화 되어 있거나 열려진 커넥션 객체가 존재하는 한 지속적으로 존재합니다. 새로운 연결 요청이 연결 문자열과 함께 들어오면 그에 따른 새로운 커넥션 풀이 생성됩니다. 우리는 응용 프로그램이 동일한 연결 문자열을 사용하도록 하여 응용 프로그램의 성능과 확장성을 향상시킬 수 있습니다. 그러나 우리는 커넥션 풀링을 적절히 사용하여야 하며 그렇지 못하면 응용 프로그램의 전반적인 성능에 악영향을 미칠 수 있습니다.
MSDN에는 "커넥션 풀링은 응용 프로그램의 성능을 향상시킬 수 있는 매우 강력한 기능이지만 효율적으로 관리하지 못하면 응용 프로그램에 악영향을 미칠 수 있다"라고 표기되어 있습니다.
이 기사를 통해 커넥션 풀링과 응용 프로그램 성능 향상을 위해 이를 어떻게 효율적으로 활용할 것인지를 알게 되었습니다.

+ Recent posts