본문 바로가기

RDBMS/SQL Server

SQL 2005에서 웹 서비스 구현하기

SQL Server 2005만으로 웹 서비스를 구현할 수 있다는 것을 알고 있는가? 애초에 웹 서비스 자체가 뭐냐고 물으신다면야 별로 할 말은 없고 ... 이 글을 읽는 사람이 일단 웹 서비스(ASP.NET 환경이면 더 좋고)와 T-SQL에 대해서 알고 있다고 가정하고 이야기를 시작해 보겠다.

SQL Server 2005를 사용하고 있다면, 마이크로소프트의 웹 개발 환경인 ASP.NET의 웹 서비스를 이용하지 않고서도 웹 서비스를 구현하는 것이 가능하다. 뭐 서설이야 어찌 됐든 개발자는 코드를 봐야 아는거니까 일단 코드를 보자. 먼저 SQL Server 2005에 Adventureworks 데이터베이스(기본으로 제공되는 샘플 데이터베이스)가 있는지 확인한 후, 다음 코드를 입력한다 :

USE AdventureWorks
GO

-- EmployeeOrderCount 함수를 작성한다
CREATE FUNCTION EmployeeOrderCount(@EmpID INT)
RETURNS INT
AS
BEGIN
RETURN
(
SELECT COUNT(*) AS 'Employee Order Count' 
FROM Purchasing.PurchaseOrderHeader
WHERE EmployeeID = @EmpID
GROUP BY EmployeeID
)
END

-- 웹서비스를 만들 http 네임스페이스를 예약한다
EXEC sp_reserve_http_namespace N'http://localhost:80/AdvEnd'

-- 엔드포인트(SQL Server가 외부하고 통신하기 위한 단위인데.. 몰라도 상관은 없다)를 생성, 아까 만든 함수를 웹 서비스에 추가한다
CREATE ENDPOINT AdvEnd
STATE = STARTED 
AS HTTP 
(
SITE = 'localhost', 
PATH = '/AdvEnd',
AUTHENTICATION = ( INTEGRATED ),
PORTS = ( CLEAR )
)
FOR SOAP 
(
WEBMETHOD 'GetEmployeeOrderCount'

NAME = 'AdventureWorks.dbo.EmployeeOrderCount',
SCHEMA = STANDARD
),
WSDL = DEFAULT,
BATCHES = ENABLED,
DATABASE = 'AdventureWorks'
)

대충 살펴보면 SQL Server의 EmployeeOrderCount 사용자 정의 함수를 GetEmployeeOrderCount라는 이름의 웹 서비스 메서드에 매핑하는 의미라는 것을 알 수 있을 것이다.

그럼 이제, 이렇게 만들어진 웹 서비스를 사용하려면? 아까 입력했던 주소, http://localhost/AdvEnd?WSDL를 열어보자.

뭔가 막 나오는데... 어쨌든 웹 서비스를 사용할 준비가 되었다는 이야기이다. 그럼 이번에는 당연히 이렇게 만들어진 웹 서비스를 사용해봐야 겠지만, 그 이전에 ASP.NET과의 비교를 위해서 동일한 ASP.NET 웹 서비스를 만들어 보겠다. 소스는 다음과 같다 :

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data.SqlClient;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service () {

    }

    [WebMethod]
    public int GetEmployeeOrderCount(int EmployeeID)
    {
        string connectionString =
            "Data Source=localhost;Initial Catalog=AdventureWorks;Integrated Security=True";
        SqlConnection conn = new SqlConnection();
        conn.ConnectionString = connectionString;
        SqlCommand comm =
            new SqlCommand("select AdventureWorks.dbo.EmployeeOrderCount(@EmpID)", conn);
        comm.Parameters.Add("@EmpID", System.Data.SqlDbType.Int);
        comm.Parameters["@EmpID"].Value = EmployeeID;
        conn.Open();
        int result = (int)comm.ExecuteScalar();
        conn.Close();
        return result;
    }
}

뭐 간단해서 별로 설명할 것도... GetEmployeeOrderCount 함수 부분만 입력하면 될 것이다.

이제 위에서 만든 두 개의 웹 서비스를 사용한 프로그램을 콘솔 프로젝트를 사용해 만들 것이다. 비주얼 스튜디오 사용법은 다들 아실거고... 웹 참조 추가를 이용해서 각 서비스의 URL을 추가하면 된다.

위와 같은 식으로 추가해주면 된다. 이름은 알아서... 케냘의 경우에는 aspnet_ws, sql_ws로 붙였다.

그리고 웹 서비스를 사용하는 프로그램을 만들어 보자. 다음 코드는 각각의 웹 서비스에서 GetEmployeeOrderCount 함수를 3천회씩 호출하는 코드이다 :

using System;
using System.Collections.Generic;
using System.Text;

namespace wsClient
{
    class Program
    {
        static void Main(string[] args)
        {
            aspnet_ws.Service s1 = new wsClient.aspnet_ws.Service();
            sql_ws.AdvEnd s2 = new wsClient.sql_ws.AdvEnd();

            // IIS의 인증 권한 위한 부분. 알아서 ...
            s2.Credentials =
                new System.Net.NetworkCredential("Administrator", "______");
            int i, result;
            System.DateTime s;
            System.TimeSpan ts;

            s = DateTime.Now;
            for (i = 0; i < 1000; i++)
            {
                result = s1.GetEmployeeOrderCount(164);
                result = s1.GetEmployeeOrderCount(198);
                result = s1.GetEmployeeOrderCount(223);
            }
            ts = DateTime.Now - s;
            Console.WriteLine(
                string.Format("aspnet takes {0} ms", ts.TotalMilliseconds)
            );

            s = DateTime.Now;
            for (i = 0; i < 1000; i++)
            {
                result = s2.GetEmployeeOrderCount(164).Value;
                result = s2.GetEmployeeOrderCount(198).Value;
                result = s2.GetEmployeeOrderCount(223).Value;
            }
            ts = DateTime.Now - s;
            Console.WriteLine(
                string.Format("sql takes {0} ms", ts.TotalMilliseconds)
            );

        }
    }
}

실행 결과는 다음과 같다 (컴퓨터의 성능이나 여러 요인에 따라 결과가 다를 수 있음) :

#1
aspnet takes 470.6768 ms
sql takes 1402.016 ms

#2
aspnet takes 480.6912 ms
sql takes 1422.0448 ms

결론을 내자 :

이렇게 구현한 SQL Server 2005 기반의 웹 서비스는 무슨 잇점이 있을까? 뭐 생각나는대로 들어보자면 :

  • IIS가 없어도 된다.
  • Visual Studio가 없어도 된다.
  • 배포가 간단하다. (쿼리 한 번 돌려주면 끝이다)

단점은 없나?

  • T-SQL 디버깅에 능하지 않은 이상 디버깅이 괴롭다.
  • 이런저런 기능 구현하려면 골아프다.
  • 느리잖아!

알아서 장단점을 비교한 후 적절한 곳에 사용하도록 합시다. 짠짠.


:: 참고할만한 것들
http://codebetter.com/blogs/raymond.lewallen/archive/2005/06/23/65089.aspx
http://channel9.msdn.com/Showpost.aspx?postid=129656
http://www.eggheadcafe.com/articles/20040730.asp
http://msdn2.microsoft.com/en-us/library/ms345123.aspx
http://www.microsoft.com/malaysia/techedsea2007/downloads.mspx ; Using Web Services with Microsoft SQL Server 2005