Silverlight를 설치하려면 여기를 클릭합니다.*
Korea 대한민국변경|Microsoft 전체 사이트
MSDN
|개발자 센터
MSDN Home   MSDN Home
MSDN 홈 > MSDN Magazine > 2002년 기사 > ASP.NET으로 전자 상거래
ASP.NET으로 전자 상거래

전자 상거래 응용 프로그램을 강화하기 위해 ASP.NET의 인증 및 양식 유효성 검사 기능 사용

Jason Lefebvre and Robert Lair (저자의 기타 기사?)
이 기사에서는 사용자가 ASP.NET 및 Visual Basic .NET을 익숙하게 사용한다고 가정합니다.
난이도 1 2 3
요약 ASP.NET을 사용하면 전자 상거래 사이트를 매우 쉽게 작성할 수 있습니다. 다양한 기능을 추가하기 위해 기존 컨트롤을 확장하여 사용할 수 있습니다. 이 기사에서는 양식 기반 인증을 사용하여 사용자 ID를 확인하고 체크 아웃 페이지 등과 같이 권한이 없는 사용자가 액세스할 수 없는 특정 영역의 사이트를 만듭니다. CustomValidator 컨트롤을 통해 주소를 확인하는 Web Service에 연결하여 강력한 유효성 검사 컨트롤의 기능 및 융통성을 제공합니다. 그런 다음 DataGrid를 사용하여 ASP.NET에 장바구니가 구현되며, 마지막으로 신용 카드 인증 및 대금 청구 작업이 실행됩니다.
웹 전자 상거래를 시작하기 전에 제공할 상품 및 서비스 카탈로그를 정의해야 합니다. ASP.NET으로 해당 사이트의 실제 카탈로그 내용을 작성하지는 못하지만 일괄적인 카탈로그 탐색 및 사용자 컨트롤이 있는 관리 시스템을 작성하는 데 도움이 됩니다. 사용자 컨트롤을 사용하여 단일 위치에 있는 논리적 웹 사이트 기능을 캡슐화할 수 있습니다. 이 점은 ASP 3.0의 포함 파일과 대체로 비슷합니다. 메뉴 시스템에 대한 코드를 응용 프로그램의 각 페이지에 추가하지 않고 하나의 파일에 코드를 지정한 다음 메뉴 사용자 컨트롤을 필요한 곳에 추가할 수 있습니다. 이렇게 하면 메뉴를 수정할 단일 위치가 지정되어 응용 프로그램의 모든 페이지마다 같은 내용을 변경하지 않아도 됩니다. ASP.NET의 사용자 컨트롤과 ASP 3.0의 포함 파일 간에는 몇 가지 중요한 차이점이 있습니다. 첫째, 사용자 컨트롤은 실제 컨트롤로 취급됩니다. 사용자 컨트롤에서 값을 전달하거나 전달받을 수 있으며 컨트롤이 제공하는 모든 공용 메서드를 호출할 수 있습니다. 또한 사용자 컨트롤의 출력을 캐시함으로써 응용 프로그램의 성능을 향상시킬 수 있습니다. 사용자 컨트롤을 사용하면 포함 파일을 사용했을 때보다 훨씬 융통성있는 응용 프로그램을 디자인할 수 있습니다. 사용자 컨트롤 디자인의 첫 번째 단계는 캡슐화할 사이트 기능을 결정하는 것입니다. 카탈로그 메뉴의 경우 이러한 결정을 쉽게 할 수 있습니다. 그림 1은 작성한 메뉴 사용자 컨트롤을 보여줍니다. 그림에서와 같이, 사용자 컨트롤은 사용자가 웹 사이트의 다양한 제품 범주를 탐색할 수 있는 간단한 가로 메뉴입니다. 그림 2에는 그림 1의 가로 메뉴를 표시하는 사용자 컨트롤에 대한 코드가 있습니다.

그림 1 가로 메뉴
그림 1 가로 메뉴

Web Form과 마찬가지로 메뉴 사용자 컨트롤에는 세 개의 논리적 섹션이 있습니다. 첫째, 언어를 지정하고 네임스페이스를 가져오는 지시문 집합이 파일 상단에 있습니다. 둘째, 두 가지 기능이 있는 서버측 스크립트입니다. 즉, 요청 컬렉션에서 현재 선택한 링크를 처리하여 메뉴에서 선택한 항목을 강조 표시하는 기능과, 데이터베이스에서 범주 목록을 검색하여 DataList 웹 컨트롤에 바인딩하는 기능이 있습니다. 셋째, 해당 컨트롤에 대한 사용자 인터페이스로 마지막 코드 섹션이며 DataList 웹 컨트롤을 사용합니다. DataList는 정의된 템플릿을 바탕으로 HTML을 출력합니다. 템플릿은 특수 태그를 사용하여 DataList에 정의됩니다. DataList에는 일곱 개의 템플릿을 정의할 수 있는데, 템플릿마다 각기 다른 항목에 영향을 미칩니다.

  • AlternatingItemTemplate
  • EditItemTemplate
  • FooterTemplate
  • HeaderTemplate
  • ItemStyleTemplate
  • SelectedItemTemplate
  • SeparatorTemplate

이 중에서 ItemTemplate과 SelectedItemTemplate 두 개의 템플릿을 살펴보겠습니다. ItemTemplate에는 DataList에 있는 모든 항목에 대한 HTML 레이아웃이 있습니다. SelectedItemTemplate에는 선택된 DataList에 있는 해당 항목에 대한 레이아웃이 있으며 ItemTemplate은 무시합니다. 다음은 정의된 ItemTemplate 및 SelectedItemTemplate이 있는 DataList입니다.

<asp:DataList id="MyDataList" runat="server">
    <ItemTemplate>
        <h1>항목</h1>
    </ItemTemplate>
    <SelectedItemTemplate>
        <h1>선택 항목</h1>
    </SelectedItemTemplate>
</asp:DataList >
DataList가 포함된 페이지를 요청하는 경우, DataList가 여러 개의 레코드가 있는 DataSource에 바인딩됩니다. 각 레코드에서 DataList는 태그 내에 정의된 HTML을 사용하여 새 항목을 생성합니다. 현재 선택된 항목에서 DataList는 태그 내에 정의된 HTML을 사용하여 새 항목을 생성합니다.
그림 2 메뉴 사용자 정의 컨트롤
<%@ Control Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="server">

    void Page_Load(Object sender, EventArgs e) 
    {       
        // 현재 목록 선택을 설정
        String selectionId = Request.Params["selection"];

        if (selectionId != null) 
        {
            MyList.SelectedIndex = Int32.Parse(selectionId);
        }

        // 메뉴 범주 목록을 가져와서 목록 컨트롤로 데이터 바인딩
        SqlConnection conn = new SqlConnection("Server=(local);
           User Id=sa;Password=!nt3ns!ty;Initial Catalog=Northwind;");
        SqlCommand cmd = new SqlCommand(
                                "SELECT * FROM Categories", conn);

        // 데이터베이스 연결 열기
        conn.Open();
        
        // 데이터를 검색하여 DataList로 바인딩
        MyList.DataSource =            
                  cmd.ExecuteReader(CommandBehavior.CloseConnection);
        MyList.DataBind();              
    }

</script>

<table width="100%">
 <tr>
  <td>
   <asp:DataList id="MyList" runat="server" 
    RepeatDirection="Horizontal" RepeatColumns="8" 
    cellpadding="3" cellspacing="0">

    <ItemTemplate>
     <asp:HyperLink cssclass="MenuUnselected" id="HyperLink1"
        Text='<%# DataBinder.Eval(Container.DataItem, "CategoryName") %>'
        NavigateUrl='<%# "DefaultNew.aspx?CategoryID=" + 
        DataBinder.Eval(Container.DataItem, "CategoryID") + 
        "&selection=" + Container.ItemIndex %>' runat="server" />
    </ItemTemplate>

    <SelectedItemTemplate>
     <asp:HyperLink cssclass="MenuSelected" id="HyperLink2" 
       Text='<%# DataBinder.Eval(Container.DataItem, "CategoryName") %>'
       NavigateUrl='<%# "DefaultNew.aspx?CategoryID=" + 
       DataBinder.Eval(Container.DataItem, "CategoryID") + 
       "&selection=" + Container.ItemIndex %>' runat="server" />
    </SelectedItemTemplate>

   </asp:DataList>
   </td>
  </tr>
</table>


?

그림 2의 코드를 응용 프로그램 루트에 있는 menu.ascx라고 하는 파일에 지정하면, 응용 프로그램의 모든 Web Form의 메뉴 컨트롤를 사용하여 두 가지 단계만 실행하면 됩니다. 첫째, 해당 양식 상단에서 페이지 지시문을 사용하여 컨트롤을 등록합니다.

<%@ Register TagPrefix="IBuySpy" TagName="Menu"
  Src="_MenuNew.ascx" %>
컨트롤을 등록하면, 표준 XML 표기법을 사용하여 Web Form에서 원하는 위치에 컨트롤을 지정할 수 있습니다.

<Widgets:Menu id="Menu1" runat="server" />
그림 3 Web Form에 메뉴 사용자 정의 컨트롤 배치
<%@ Page Language="C#" Debug="true" %>
<%@ Register TagPrefix="Widgets" TagName="Menu" Src="_MenuNew.ascx" %>

<html> <body>
  <table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tr>
      <td>
      <Widgets:Menu id="Menu1" runat="server" />
      </td>
    </tr>
    <tr>
      <td>
      <!-- 여기에 페이지 내용을 넣습니다. -->
      Welcome to Widgets online!
      <!-- 페이지 내용 끝 -->
      </td>
    </tr>
  </table></body>
</html> 
?

그림 3은 Web Form에 메뉴를 지정하는 메뉴 사용자 컨트롤 사용 방법을 보여줍니다.

사용자 인증

사용자 인증 처리는 전자 상거래에서 일반적인 작업입니다. 사용자가 해당 사이트를 찾는 동안 쿠키 또는 세션 개체의 모든 정보를 저장할 수 있지만, 사용자가 등록 또는 제품 구매를 원하는 경우 사용자를 인증하고 일부 상세 정보를 저장해야 합니다. 사용자를 인증해야 하는 세 가지 시점이 있습니다. 즉, 사용자가 해당 사이트를 탐색하는 즉시, 사용자가 장바구니에 항목을 추가하기 직전, 사용자가 체크 아웃할 때입니다. 사용자 인증 시점에 관계없이 ASP.NET을 사용하여 양식 기반 인증을 구현하는 것은 매우 쉽습니다. 해당 사이트에서 사용자가 항목을 탐색하여 장바구니에 추가할 수 있지만 체크 아웃하기 전에 인증해야 한다고 가정해 봅시다. 이 작업을 하려면 응용 프로그램의 Web.config 파일의 system.Web 섹션에 있는 다음과 같은 코드를 지정하여 양식 기반 인증을 설정해야 합니다.

<authentication mode="Forms">
  <forms name="ApplicationAuth"
         loginUrl="login.aspx"
         protection="All"
         path="/" />
</authentication>
체크 아웃 페이지가 CheckOut.aspx인 경우, 구성 섹션에 있는 Web.Config 파일에 이 코드를 추가합니다.

<configuration>
  <!--구성 파일의 나머지 부분-->
  <location path="CheckOut.aspx">
    <system.web>
      <authorization>
        <deny users="?" />
      </authorization>
    </system.web>
  </location>
</configuration>
이제, 인증되지 않은 사용자가 CheckOut.aspx에 액세스할 때마다 login.aspx 페이지에 연결됩니다. 이 페이지는 사용자를 인증하는 여러 가지 방법 중 하나를 사용하게 됩니다. 예를 들어, RADIUS(Remote Authentication Dial-in User Service) 서버에 연결하거나 LDAP(Lightweight Directory Access Protocol)를 통해 인증하거나 SQL 데이터베이스에 대해 간단한 사용자 이름/암호 확인을 실행할 수 있습니다. 어떤 인증 방법을 선택하든지, 일단 사용자가 인증되면 다음과 같은 정적 메서드가 호출되어 사용자가 원래 액세스하려는 페이지에 연결합니다.

FormsAuthentication.RedirectFromLoginPage(
                          username,
                          createPersistantCookie)
첫 번째 인수는 사용자를 확인하는 문자열입니다. 두 번째 인수는 작성된 쿠키가 영구적인지 나타내는 부울 값입니다. 실패한 사용자 인증 작업은 원하는 방법으로 처리할 수 있습니다. 이 작업에 대한 일반적인 솔루션은 메시지를 표시하거나 다른 페이지에 사용자를 연결하는 것입니다. 나중에 인증된 사용자의 이름이 필요하면 User.Identity.Name을 사용하여 RedirectFromLoginPage 메서드의 사용자 이름 인수로 저장한 값을 검색할 수 있습니다. 이렇게 하면 특정 사용자를 대상으로 하는 광고를 작성할 수 있습니다.

사용자 입력 확인 그림 4 Web Service에서 CustomValidator 컨트롤 사용

<%@ Page Language="VB" Debug=true %>
<%@ Import Namespace="ZipCodeResolver" %>
<html>
<head>
   <script runat=server>
   
      Sub ValidateBtn_OnClick( sender As object, e As EventArgs ) 
         If Page.IsPostBack then
            If Page.IsValid Then 
               lblOutput.Text = "Address validation succeeded."
            Else 
               lblOutput.Text = "<font color=red>Address validation " + 
                 "failed! Please fill out all required fields and "  +  
                 "make sure you have entered " + _
                 "your correct zip code.</font>"
            End If
         End If
      End Sub
      
      Public Sub ServerValidation( source As object, _
                                   args As ServerValidateEventArgs )
         Dim sResults as String
         
         '폼 값 가져오기
         Dim sAddress as String = txtAddress1.Text
         Dim sCity as String = txtCity.Text
         Dim sState as String = txtState.Text
         Dim sZip as String = txtZip.Text
         
         'ZipCodeResolver 개체의 인스턴스 만들기
         Dim zipChecker as New ZipCodeResolver()
         
         '원격 메서드 호출(Eraserver Web Service)
         sResults = zipChecker.ShortZipCode( 9999, _
                                          sAddress, sCity, sState )
         
         'Web Service에서 반환된 우편 번호가
         '사용자가 입력한 우편 번호와 일치하면 유효성 검사가 성공합니다.
          
If sResults = sZip then
            args.IsValid = True
         Else
            args.IsValid = False
         End If         
      End Sub
   </script>  
</head>

<body>
<form runat="server">

   <asp:Label id=lblOutput runat="server" 
        Text="Please enter your ship-to address:" 
        Font-Name="Verdana" 
        Font-Size="10pt" />
   <p>
   <table>
      <tr>
         <td>Name: </td>
         <td><asp:TextBox id="txtName" runat="server"/></td>
         <td><asp:RequiredFieldValidator runat="server" 
                  ErrorMessage="Name field cannot be left blank"
                  InitialValue=" "
                  ControlToValidate="txtName" 
                  Display="Dynamic">
               <font color=red>*</font>
             </asp:RequiredFieldValidator>
         </td>
      </tr>
      <tr>
         <td>Address1:</td>
         <td><asp:TextBox id="txtAddress1" runat="server"/><br></td>
         <td><asp:RequiredFieldValidator runat="server" 
                  ControlToValidate="txtAddress1" 
                  Display="Static">
               <font color=red>*</font>
             </asp:RequiredFieldValidator>
         </td>
      </tr>
      <tr>
         <td>Address2:</td>
         <td><asp:TextBox id="txtAddress2" runat="server"/><br></td>
         <td></td>
      </tr>
      <tr>
         <td>City:</td>
         <td><asp:TextBox id="txtCity" runat="server"/><br></td>
         <td><asp:RequiredFieldValidator runat="server" 
                  ControlToValidate="txtCity" 
                  Display="Static">
               <font color=red>*</font>
             </asp:RequiredFieldValidator>
         </td>
      </tr>
      <tr><td>State:</td>
         <td><asp:TextBox id="txtState" runat="server"/><br></td>
         <td><asp:RequiredFieldValidator runat="server" 
                  ControlToValidate="txtState" 
                  Display="Static">
               <font color=red>*</font>
             </asp:RequiredFieldValidator>
         </td>
      </tr>
      <tr>
         <td>Zip Code(5 digit):</td>
         <td><asp:TextBox id="txtZip" maxlength=5
                  runat="server"/><br></td>
         <td><asp:RequiredFieldValidator runat="server" 
                  ControlToValidate="txtZip" 
                  Display="Static">
               <font color=red>*</font>
             </asp:RequiredFieldValidator>
         </td>
      </tr>
   </table>
   
   <asp:CustomValidator id="CustomValidator1"
      ControlToValidate="txtZip"
      OnServerValidate="ServerValidation"
      Display="Static"
      ErrorMessage="Your shipping address appears invalid!<br>
                    Please recheck all fields and make sure that..."
      Font-Color="red"
      runat="server"/><br>
   
   <asp:Button id="Button1"
     Text="Validate" 
     OnClick="ValidateBtn_OnClick" 
     runat="server"/><br>

</form>
</body>
</html>
?

사용자 입력을 잘못 확인하면 고객의 주문을 제 때 처리하지 못하게 됩니다. 거의 모든 전자 상거래 사이트에서는 클라이언트측 입력 사항의 유효성을 검사해야 합니다. 기본으로 제공되는 Microsoft.NET Framework 유효성 검사 컨트롤을 통해 입력 사항을 쉽게 확인할 수 있습니다.

유효성 검사 컨트롤을 사용하면 고객이 필수 필드를 비워두지 않도록 할 수 있으며, 입력된 5자리 또는 9자리의 ZIP 코드를 확인하고, 신용 카드 번호 또는 전자 상거래 사이트에 필요한 다른 모든 입력 내용을 확인할 수 있습니다. 유효성 검사 컨트롤은 그 밖의 다른 곳에서도 사용되지만 그림 4의 코드는 새로운 방식을 제공합니다. 즉, Web Service에서 사용자 지정 유효성 검사기를 사용하여 USPS 데이터베이스에 대한 고객 주소를 확인하는 방법을 제공합니다.

ZIP Code Resolver Web Service는 http://webservices.eraserver.net? 의 EraServer .NET에서 제공됩니다. 이 URL로 이동하여 ZipCodeResolver Web Service를 선택하면 Web Service에서 네 가지 방법을 볼 수 있습니다. ZIP 코드 및 주소를 확인하는 기능은 각 방법마다 조금씩 다릅니다. ShortZipCode 방법을 사용하여 유효성 검사 작업을 실행해 봅니다. 이 방법은 http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?op=ShortZipCode? 로 이동하여 액세스 코드(테스트용 코드인 "9999" 사용), 주소, 시/도를 입력한 다음 호출을 클릭하여 직접 테스트할 수 있습니다. Web Service는 입력한 주소에 대한 ZIP 코드가 있는 XML 패키지에서 문자열을 반환합니다.

Web Service를 호출하기 전에, Web Service의 메서드 및 인수에 대한 컴파일러를 알려야 합니다. 이 작업은 Microsoft .NET Framework와 함께 제공되는 WSDL.exe 유틸리티를 사용하여 프록시 클래스를 생성하여 실행합니다. 생성한 프록시 클래스는 읽을 수 있으며(직접 확인) Web Service에 대한 로컬 메서드 호출을 다시 라우팅하는 데 필요한 코드를 제공합니다. 또한 프록시 클래스는 Web Service가 반환하는 XML에서 반환 값을 스트립하기 때문에 코드의 XML을 구문 분석할 필요가 없습니다. WSDL.exe는 매우 쉽게 사용할 수 있습니다. 다음 명령줄을 사용하여 현재 디렉터리에 Visual Basic.NET 프록시 클래스를 작성합니다.

wsdl http://webservices.eraserver.net/zipcoderesolver/
   zipcoderesolver.asmx /language:vb
이러한 인수가 있는 명령을 실행하면 WSDL 명령줄 유틸리티가 ZipCodeResolver Web Service에 연결되어 XML WSDL 계약을 분석하고 현재 디렉터리에 있는 ZipCodeResolver.vb라고 하는 Visual Basic .NET 파일을 만듭니다. 이 파일을 사용하려면 이 파일을 라이브러리에 컴파일한 다음 웹 응용 프로그램 루트에 있는 /bin 디렉터리에 저장합니다.

다음 명령줄을 사용하여 ZipCodeResolver.vb 파일을 라이브러리 DLL에 컴파일할 수 있습니다.

C:\Temp>vbc /target:library
/out:ZipCodeResolver.dll zipcoderesolver.vb
/r:System.Web.Services.dll /r:System.XML.dll
/r:System.Web.dll /r:System.dll /r:System.Data.dll
이 명령을 통해 ZipCodeResolver.dll이라고 하는 현재 디렉터리에 파일을 작성합니다. 이 파일을 웹 응용 프로그램 루트에 있는 /bin 디렉터리에 저장합니다. 이제, 모든 로컬 클래스를 액세스하는 것과 같은 방법으로 Web Service의 메서드에 액세스할 수 있습니다. 그림 4의 코드는 ZipCodeResolver Web Service를 사용하여 유효성 검사 작업을 하는 CustomValidator 컨트롤이 있는 전체 Web Service를 보여줍니다.

이 양식을 브라우저에 로드하면 그림 5와 같이 됩니다. CustomValidator 컨트롤은 목록 끝 부분에 있습니다. 이 컨트롤은 Web Form의 ZIP 코드 필드를 확인합니다. 해당 양식을 서버에 제출하면 ServerValidation 메서드가 호출됩니다.

그림 5 양식 실행
그림 5 양식 실행

이 메서드는 방금 작성한 프록시 클래스가 제공하는 것처럼 ZipCodeResolver 개체의 인스턴스를 작성합니다. 개체에 액세스하려면 그림 4 상단에 표시된 대로 지시문 가져오기를 통해 ZipCodeResolver 네임스페이스를 가져와야 합니다. 그런 다음 ServerValidation 메서드가 ZipCodeResolver Web Service의 ShortZipCode 메서드를 호출하고 사용자가 입력한 ZIP 코드와 Web Service가 반환한 ZIP 코드가 일치하는지 확인합니다. 일치하는 경우, 유효성 검사가 성공적으로 이루어지며 CustomValidator 컨트롤의 IsValid 속성이 true로 설정됩니다. ZIP 코드가 일치하지 않는 경우, IsValid 속성이 false로 설정되어 페이지 유효성 검사 작업이 실패로 되며 그림 6과 같은 오류 메시지가 표시됩니다. ZIP 코드를 올바르게 입력하면 유효성 검사 작업이 제대로 실행되어 그림 7과 같은 화면이 표시됩니다.

그림 6 오류 메시지
그림 6 오류 메시지

그러나 이 예제는 제품 전자 상거래 사이트에는 적합하지 않습니다. EraServer .NET의 ZipCodeResolver 서비스는 USPS 웹 사이트를 사용하여 주소 정보를 검색하기 때문에 개인적인 용도로만 사용됩니다. 이 예제를 제품에 사용할 수 없는 또 다른 이유가 있습니다. USPS 데이터베이스에 오류가 발생하거나 고객이 주소를 새로 작성한 경우, 사용자가 직접 해결할 수 없는 오류 메시지가 사용자에게 전달되어 업무를 지속할 수 없게 됩니다. 많은 전자 상거래 점포에서는 고객이 한 주문을 실제로 처리하기 전에 비즈니스 논리의 일부로서 해당 사이트에 대해 고객 주소 유효성 검사 작업을 실행합니다. 페이지에서 이러한 종류의 유효성 검사를 실행함으로써 잠재적으로 문제점이 있는 고객에게 경고를 할 수 있으며 잘못된 주소가 입력되는 횟수를 줄일 수 있습니다.


그림 7 유효성 검사 성공

장바구니 구현

장바구니가 없으면 전자 상거래 사이트가 완료되지 않습니다. 장바구니는 고객이 구매하려는 항목에 대한 임시 저장소 역할을 합니다. 고객이 체크 아웃할 때 장바구니의 항목 수량이 계산되고 값이 지불된 후 배달됩니다.

물론, 모든 전자 상거래 개발자가 알고 있듯이 이러한 프로세스 이외에 많은 프로세스가 있습니다. 체크 아웃할 때, 장바구니의 항목이 임시 장바구니에서 주문 정보가 있는 테이블 집합 등 좀 더 영구적인 저장소로 이동해야 합니다. 또한 주문한 항목이 고객에게 배달되기 전에 고객의 신용 카드를 인증하고 대금 청구를 해야 합니다.

강력한 DataGrid 웹 컨트롤을 통해 ASP.NET에 장바구니를 쉽게 구현할 수 있습니다. ASP 3.0에서는 레코드 집합을 테이블로 페이지에 표시하려는 경우, 행마다 레코드 집합을 반복하고 테이블을 만드는 데 필요한 HTML 구문을 직접 작성해야 했습니다. DataGrid는 이러한 작업을 자동으로 실행합니다. 레코드 집합을 DataSource 속성의 ADO.NET DataTable에 전달하여 바인딩하면 테이블이 자동으로 작성되어 많은 작업을 해야 하는 수고를 덜 수 있습니다. CSS(cascading style sheets)를 사용하여 DataGrid의 표시 형식을 쉽게 변경할 수 있습니다.

자세한 내용은 http://samples.gotdotnet.com/quickstart/aspplus/? 를 참조하십시오.

다음은 간단한 DataGrid가 있는 코드입니다. AutoGenerateColumns가 true로 설정되어 있기 때문에 DataGrid에 전달하는 DataSet의 데이터를 모두 표시합니다.

<asp:DataGrid runat="server"
         id="MyList"
         AutoGenerateColumns="true">
</asp:DataGrid>
이 코드로 사용자에게 데이터를 표시하기에는 충분하지만 장바구니이기 때문에 좀 더 세밀하게 제어해야 합니다. 예를 들어, 장바구니의 항목 수량은 수정할 수 있어야 합니다.

DataGrid는 다양한 열과 표시 형식을 제어할 수 있는 기능을 제공합니다. 첫 번째 단계는 AutoGenerateColumns를 false로 설정하는 것입니다. 그러면 DataGrid 내에 있는 태그에 데이터 열을 지정하여 DataGrid 열을 액세스할 수 있습니다. 이 작업을 어렵게 보일 수도 있지만 사실을 쉬운 작업입니다. 다음 코드는 제품 이름 및 모델 두 개의 열만 표시합니다. 이 필드는 편집할 수 없으며 특수한 서식 지정을 하지 않아도 되므로 BoundColumn 웹 컨트롤을 사용하여 열을 정의할 수 있습니다.

<asp:DataGrid runat="server" id="MyList" AutoGenerateColumns="False">
  <Columns>
<asp:BoundColumn HeaderText="모델 이름" DataField="ProductName"/>
<asp:BoundColumn HeaderText="모델 번호" DataField="ProductID"/>
  </Columns>
</asp:DataGrid>
이 코드의 DataGrid는 그림 8과 같이 출력을 작성합니다. 태그를 사용하여 DataGrid 컨트롤의 열 컬렉션에 항목을 직접 추가하게 되면 작업이 훨씬 쉬워집니다.

그림 8 DataGrid 출력
그림 8 DataGrid 출력

첫 번째 위치에서 열 작업을 해야 하는 이유는 사용자가 DataGrid 컨트롤에서 항목 수량을 수정할 수 있도록 해야 하기 때문입니다. BoundColumns는 이 기능을 제공하지 않습니다. 대신, TemplateColumn이라고 하는 다른 유형의 열이 열 컨텐트 및 표시 형식을 좀 더 세밀하게 제어할 수 있는 기능을 제공합니다. 이전 예제를 작성할 때, 수량을 수정할 수 있는 텍스트 필드가 있는 다른 열을 추가하려면 그림 9와 같이 컬렉션에 TemplateColumn을 추가하면 됩니다.

그림 9 바운드 및 템플릿 열 사용

<asp:DataGrid runat="server" id="MyList" AutoGenerateColumns="true">
  <Columns>
    <asp:BoundColumn HeaderText="Product Name" DataField="ModelName" />
    <asp:BoundColumn HeaderText="Model" DataField="ModelNumber" />
    <asp:TemplateColumn HeaderText="Quantity">
      <ItemTemplate>
        <asp:TextBox runat="server" id="Quantity"  
          Text='<%# DataBinder.Eval(Container.DataItem, "Quantity") %>' 
          width="40px" />
      </ItemTemplate>
    </asp:TemplateColumn>
  </Columns>
</asp:DataGrid>
?

TextBox 웹 컨트롤이 있는 그림 9의 코드로 새 열이 작성됩니다. 이 그림에 표시된 DataBinder.Eval 메서드는 데이터베이스에 있는 올바른 수량을 TextBox로 출력합니다. 이 트릭을 사용하여 다른 웹 컨트롤 작업뿐만 아니라 CheckBox 및 Label 웹 컨트롤 작업도 할 수 있습니다. 지금까지 편집할 수 있는 텍스트 필드를 DataGrid 웹 컨트롤의 열에 추가하는 방법을 설명했습니다. 하지만 변경 사항을 데이터베이스의 텍스트 필드에 다시 적용하지 못하면 소용이 없습니다. 그림 9에 표시된 TextBox 컨트롤의 ID가 Quantity로 설정되어야 합니다. 따라서 사용자가 장바구니 Web Form을 제출한 후 해당 값에 액세스하려면 Quantity.Text에 액세스할 수 있어야 합니다. 맞습니까?

그 대답은 아니오입니다. 해당 값에 쉽게 액세스할 수 있는 방법은 없습니다. 업데이트된 값을 데이터베이스에 다시 저장하는 가장 간단한 방법은 항목 컬렉션을 사용하여 행마다 DataGrid를 반복하고 FindControl 메서드를 사용하여 TextBox를 찾고 TextBox 값을 얻으며 ADO.NET을 사용하여 데이터 소스에 해당 값을 다시 저장하는 것입니다.

   Dim i As Integer
   For i = 0 To MyList.Items.Count - 1
     ' 행의 컨트롤에 대한 참조 얻기
     Dim quantityTxt As TextBox = _
        CType(MyList.Items(i).FindControl
        ("Quantity"), TextBox)

     ' *** 이제 quantityText.Text 값에 
     ' 액세스할 수 있으며 ***
     ' *** 이 값을 사용하여 
     ' 데이터 소스에 다시 저장할 수 있습니다.    ***
   Next
이 기사에서는 데이터베이스에 데이터를 저장하는 데 필요한 ADO.NET 코드는 다루지 않습니다. 전체 예제를 보려면 http://www.ibuyspy.com? 에서 IBuySpy 저장소 데모를 다운로드하십시오. DataGrids의 일반적인 내용에 대해서는 Dino Esposito의 MSDN Magazine의 Cutting Edge? 칼럼을 참조하십시오.

신용 카드 처리 센터 통합

고객이 체크 아웃할 때 고객이 구매한 제품의 대금을 지불할 수 있는지 확인해야 합니다. 제품을 배달하지 않고 신용 카드 대금을 청구하는 것은 불법이며 고객이 지불 능력이 있는지 확인하지 않고 제품을 배달하는 것은 좋지 않은 비즈니스 습관이므로, 신용 카드 처리 회사는 카드를 신속하게 인증하는 방법을 제공합니다. 신용 카드가 인증되면 몇 가지 제한된 경우(예를 들어, 신용 카드가 인증되고 대금이 청구되는 사이의 짧은 시간 안에 취소되는 경우)를 제외하고 제품 배달 후 대금이 지불될 것이라는 보장을 할 수 있습니다.

대부분의 온라인 신용 카드 처리 회사는 그 회사 서버에 대한 연결을 처리하고 신용 카드 인증을 실행하는 ActiveX DLL을 제공합니다. 이러한 회사들은 사용자의 Visual Studio.NET 또는 ASP.NET 프로젝트에 직접 연결되는 어셈블리를 조만간 제공할 것입니다. 현재로서는 COM 상호 운용성을 사용할 수 있습니다.

COM 상호 운용성을 통해 ASP.NET 응용 프로그램의 COM 개체를 사용할 수 있습니다. ASP.NET의 COM 개체에 액세스할 수 있는 가장 쉬운 방법은 런타임에 바인딩을 사용하는 것입니다. ASP 3.0에서와 같이, ASP.NET의 서버 개체는 시스템에 등록된 모든 COM 개체의 인스턴스를 반환하는 CreateObject 메서드를 제공합니다. 따라서 구성 요소에 대한 ProgID가 MyComponent.Authorize인 경우, 다음과 같이 ASP.NET의 해당 개체를 사용하여 그러한 개체를 작성할 수 있습니다.

Object oAuthor = Server.CreateObject("MyComponent.Authorize")
그러면 ASP 3.0 또는 Visual Basic 6.0에서와 같이 개체의 속성 및 메서드에 액세스할 수 있습니다.

심각한 성능 장애를 일으키는 런타임에 바인딩을 사용하는 대신 COM 개체에 대한 프록시 클래스를 작성할 수 있습니다. 프록시 클래스에는 COM 개체와 연결하는 데 필요한 모든 통로가 있으며 해당 개체의 메서드 및 속성에 대한 컴파일러를 표시합니다. Visual Studio .NET 사용자의 경우, 이러한 기능을 사용하여 개체에 대한 IntelliSense도 얻을 수 있습니다. Microsoft .NET Framework는 프록시 클래스를 자동으로 작성하는 tlbimp.exe(Type Library Importer)라고 하는 유틸리티와 함께 제공됩니다. 이 유틸리티는 명령 프롬프트에서 쉽게 사용할 수 있습니다.

tlbimp OriginalDLL.dll /out:MyNewDLL.dll
새 DLL을 응용 프로그램 루트의 /bin 디렉터리에 저장하면 ASP.NET의 다른 개체와 마찬가지로 COM 개체를 작업할 수 있습니다.

성능 및 최적화

ASP.NET은 전자 상거래 사이트의 성능을 조정하기 위해 몇 가지 도구를 제공합니다. 이러한 도구 중 하나가 데이터 캐싱입니다. ASP.NET을 사용하여 비용이 많이 드는 개체를 메모리에 저장할 수 있습니다. 예를 들어, 사이트 성능을 향상시키려면 제품 세부 정보와 같이 자주 변경되지 않는 항목에 대한 데이터베이스에 반복적인 호출을 캐시할 수 있습니다.

캐시 작업은 모든 키 값 기반 사전 개체를 사용하는 것과 똑같이 사용할 수 있습니다. 비용이 많이 드는 DataSet의 경우, 필요할 때마다 DataSet을 작성하지 않고 다음과 같은 코드를 사용하여 처음으로 DataSet에 액세스할 때 캐시에 저장합니다.

Cache("Categories") = dsCategories
그러면 다음과 같이 캐시에서 읽을 수 있습니다.

myDataSet = Ctype(Cache("Categories"), DataSet)
할당하기 전에 Ctype 메서드를 사용하여 DataSet을 입력하여 캐시에서 반환된 개체를 캐스팅합니다. 캐시가 개체를 반환하기 때문에 이 작업이 필요합니다. 이러한 방법으로 캐시에 저장된 개체는 응용 프로그램을 다시 시작하거나 캐시를 직접 플러시할 때까지 사용할 수 있습니다.

그림 10 DataSet 캐시
public static void GetCategoryData()
{

  // DataSet이 캐시에 있는 경우
  if( Page.Cache["Categories"]!= null )

        //캐시된 DataSet 반환
        return (DataSet)Page.Cache["Categories"];

  // 그렇지 않은 경우 데이터베이스에서 DataSet 가져오기
  else 
  {
        //ADO.NET connection 개체 및 command 개체 만들기 
      SqlConnection conn = new SqlConnection(
            ConfigurationSettings.AppSettings["ConnectionString"]);
      SqlCommand cmd = new SqlCommand("SELECT * FROM Categories", 
            conn);        

        //DataAdapter 개체 및 DataSet 개체 만들기
      SqlDataAdapter myAdapter = new SqlDataAdapter(myCommand);    
      DataSet ds = new DataSet();
                              
        //데이터베이스 연결 열기
      conn.Open();

        //DataSet 채우기
      myAdapter.Fill(ds, "AllDomains");

        //데이터베이스 연결 닫기
      conn.Close();

        //캐시에 DataSet 저장
        context.Cache["AllDomains"] = ds;

        //DataSet 반환
      return ds;                        
  }
}
그림 10은 호출을 데이터베이스에 캐시하는 방법을 보여줍니다.

구성 요소에 캐싱을 구현하는 경우, HttpContext 개체에서 Cache 개체의 현재 인스턴스를 찾아야 합니다.

HttpContext context = HttpContext.Current;
이렇게 하면 context.Cache["CachedItem"] 명령을 사용하여 캐시에 액세스할 수 있습니다.

지금까지 가장 간단한 양식의 Cache 개체를 사용하는 방법에 대해서만 설명했습니다. Cache 개체의 Insert 메서드를 사용하여 캐시에 새로운 항목을 추가함으로써 캐시된 항목에 대한 종속성 및 만료 시간을 추가할 수 있습니다. 예를 들어, 웹 사이트 루트에 XML 파일 형식으로 메뉴를 저장하고 해당 메뉴에 처음으로 액세스할 때 캐싱한다고 가정해 봅니다(SQL Server™를 사용할 수 없거나 응용 프로그램의 메뉴에 XML의 손쉬운 구성이 필요한 경우도 있습니다). 원래 파일이 변경되면 해당 메뉴가 이러한 변경 사항을 자동으로 반영합니다. Insert 메서드를 사용하여 캐시에 메뉴 데이터를 추가하여 파일 자체에 캐시된 개체의 종속성을 만들 수 있습니다. 파일이 변경되면 캐시에서 메뉴가 제거되고 다음에 액세스할 때 메뉴가 다시 추가됩니다. 캐시에 메뉴를 삽입하려면 다음과 같이 Cache 개체의 Insert 메서드를 사용합니다.

Cache.Insert("mainMenu", sXMLMenu, new CacheDependency
   ("C:\Inetpub\wwwroot\myCommerceSite\mainMenu.xml"))
첫 번째 인수는 캐시된 항목의 이름을 정의합니다. 두 번째 인수는 캐시될 내용을 정의합니다. 마지막 인수는 CacheDependency 형식으로서 캐시된 항목이 종속되는 파일의 위치를 정의합니다.

ASP.NET은 개별적인 데이터 청크를 캐시하는 기능 이외에 출력 캐싱 기능도 제공합니다. 페이지의 출력을 캐시할 수 있는 경우, 메모리에서 해당 페이지가 직접 출력됩니다. 코드 또는 디스크 액세스를 실행하지 않아도 됩니다. 이 기능은 좀처럼 변경되지 않는 응용 프로그램의 페이지에서 사용하면 좋습니다. 페이지에 사용자에 맞게 설정된 환영 메시지와 같은 동적 콘텐트가 전혀 없는 경우에는 출력 캐싱 기능을 사용하지 않습니다. 이 경우, 각 페이지 버전이 별도로 캐시되어 전자 상거래 사이트 성능에 나쁜 영향을 주게 됩니다.

출력을 캐싱하는 몇 가지 방법이 있습니다. 가장 쉬운 방법은 다음과 같은 페이지 지시문을 사용하는 것입니다.

<%@ OutputCache Duration="60" %>
이 코드를 페이지 상단에 지정하면 전체 응답이 캐시됩니다. 기간 특성이 초 단위로 측정됩니다.

결론

본 기사에서는 ASP.NET을 사용하여 더욱 빠르고 향상된 전자 상거래 사이트를 작성하는 방법에 대해 설명했습니다. ASP.NET을 통해 UserControls 및 DataList 웹 컨트롤을 사용하여 온라인 카탈로그에서 탐색할 수 있는 메뉴를 작성하는 방법, 양식 기반 인증 사용 방법, 사용자 입력 유효성 검사 방법, 장바구니 작성하는 방법, 다른 전자 상거래 작업 중 일부를 실행하는 방법과 함께 ASP.NET의 새로운 기능을 사용하여 전자 상거래 사이트를 작성하는 방법을 설명했습니다.


관련 기사:

ASP Column archive?

배경 정보:

http://samples.gotdotnet.com/quickstart/aspplus/doc/wsbehavior.aspx?

http://www.gotdotnet.com/team/tools/web_svc/?


Jason Lefebvre는 Intensity Software Inc.의 공동 창립자이자 부회장입니다(http://www.intensitysoftware.com? ). 그는 IBuySpy 예제 응용 프로그램의 NetCOBOL 변환 작업을 해왔으며, Teach Yourself ADO.NET in 24 Hours(Sams, 2002년)의 공동 저자입니다.

Robert Lair는 Intensity Software Inc.의 대표 이사이자 사장입니다. 그와 Jason은 Pure ASP.NET(Sams, 2001년)을 함께 저술했습니다. Robert Lair는 IBuySpy 데모 응용 프로그램 작업을 했던 2001년 초부터 Microsoft .NET에서 근무했습니다. robertlair@asppages.com을 통해 저자와 연락할 수 있습니다.


2002년 8월 자 MSDN Magazine? 에서 발췌


최종 수정일: 2002년 10월 7일
Top of Page Top of Page


Microsoft