달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

ASP.NET 2.0 내부 변경 사항

Jayesh Patel, Bryan Acker, Robert McGovern
Infusion Development

2004년 8월

적용 대상:
   Microsoft ASP.NET 2.0

요약: ASP.NET 2.0은 이전 버전인 ASP.NET 1.1과 완벽하게 호환되지만, ASP.NET의 많은 요소들이 내부적으로 변경되었습니다. 변경된 요소에는 코드 모델, 컴파일, 페이지 주기 등이 있습니다. 이 기사에서는 이러한 변경 사항에 대해 간단히 설명합니다(21페이지/인쇄 페이지 기준).

목차

소개
코드 모델
컴파일
실행 중에 전체 컴파일(코드 디렉터리)
페이지 주기
확장성
고급 캐싱 기술
성능
결론

소개

전문 ASP.NET 개발자에게 있어서 ASP.NET 2.0의 큰 문제점은 내부 변경 사항과 연관되어 있습니다. 새로운 기능을 배우는 것은 흥미롭고 재미있습니다. 더욱이, ASP.NET 핵심 구조의 변경 사항은 해당 기술을 숙달하고자 하는 개발자에게 보다 큰 흥밋거리로 다가옵니다. 이 백서에서는 버전 1.x 이후의 ASP.NET 2.0 내부 구조 변경 사항에 대해 알아봅니다.

이 백서에서 다루는 항목은 성능을 중요시하는 개발자 및 기술 설계자가 응용 프로그램을 미세 조정하는 데 유용합니다. 특히 코드 모델, 컴파일, 페이지 주기, 확장성, 성능 및 캐싱과 같은 주요 영역에 대해 살펴봅니다.

이 문서에 사용된 대부분의 예를 이해하려면 ASP.NET, Visual Basic .NET 및/또는 C# 구문에 익숙해야 합니다. 해당하는 경우에는 특정 주제에 대한 자세한 설명을 볼 수 있도록 참조 문서가 제공되어 있습니다.

코드 모델

ASP.NET 2.0에서 가장 명백하게 나타나는 내부 변경 사항은 ASP.NET 웹 페이지를 만드는 방법입니다. 이 섹션에서는 코드 숨김 모델의 변경 사항 및 이 변경 사항이 ASP.NET 개발에 미치는 영향에 대해 설명합니다.

ASP.NET 1.x의 코딩 모델

ASP.NET 1.x에서는 개발자가 Web Form을 개발할 때 선택할 수 있는 두 가지 주요 옵션이 있었습니다. 첫째로, 개발자는 일반 ASP 모델에 따라 ASPX 페이지에서 직접 코드를 작성할 수 있었습니다. 코드 인라인이라는 이 과정은 단순한 명령에는 적합합니다. 그러나 보다 복잡한 코드의 경우 코드 인라인을 작성하면 표현(HTML)과 기능(코드)이 혼합된 웹 페이지를 읽기가 어려워집니다. ASP.NET의 기본 코딩 작업은 이러한 문제를 해결하기 위해 변경되었습니다. 코드 숨김 파일이라는 별도의 코드 전용 파일에서 비즈니스 논리 및 이벤트 처리 코드를 작성할 수 있습니다. 코드 숨김 모델은 프레젠테이션 태그가 포함된 ASPX 파일에 코드 전용 파일을 연결합니다. 표현과 코드를 분리함으로써 개발 팀에서 디자이너는 프레젠테이션 파일에서 작업하고 개발자는 코드 파일에서 작업하도록 하여 보다 신속하게 작업할 수 있습니다.

그림 1. ASP.NET 1.x 코딩 모델

코드 숨김 모델의 주요 문제점은 코드 숨김 파일을 ASPX 페이지와 동기화하는 방법이었습니다. 프로그래밍 관점에서 볼 때 ASPX 페이지가 코드 숨김 파일에서 상속되는 경우에도, 사실 두 파일은 더욱 복잡한 관계로 연결되어 있었습니다.

ASP.NET 1.x의 코드 숨김 모델에 대한 자세한 내용은 MSDN Library 기사 Web Forms 코드 모델 을 참조하십시오.

상속의 복잡성

ASP.NET의 디자인 패러다임은 개발자가 Microsoft Visual Studio .NET을 사용하여 컨트롤을 ASPX 페이지에 끌어 놓는 것이었습니다. 그러면 Visual Studio에서 코드 숨김 파일에 적합한 지원 코드를 자동으로 생성합니다. 컨트롤을 ASPX 페이지에 추가하면 새 코드를 코드 숨김 파일에 추가해야 합니다. 즉, 코드 숨김 파일이 ASPX 페이지에서 상속되는 경우에도 ASPX 페이지는 실제로 코드 숨김 파일의 디자인을 사용합니다.

컴파일의 복잡성

동기화의 두 번째 문제는 파일 컴파일 방법이었습니다. 모든 코드 숨김 파일은 지원 클래스와 함께 어셈블리로 컴파일되어 웹 응용 프로그램의 /bin 디렉터리에 저장됩니다. 컴파일 단계는 응용 프로그램 배포 이전에 이루어지는 반면, ASPX 페이지는 페이지를 처음 요청할 때 실행 중에 컴파일됩니다. ASP.NET 런타임은 실제로 ASPX 페이지를 고유한 임시 어셈블리로 컴파일합니다.

이 과정에서 발생하는 문제는 코드 숨김 어셈블리가 업데이트되지 않는 상태에서 ASPX 페이지를 변경할 수 있다는 점입니다. 즉, 개발자는 배포 후 ASPX 페이지에서 속성을 수정하거나 컨트롤의 형식을 변경할 수 있습니다. 이때 코드 숨김 파일은 업데이트되지 않으며 응용 프로그램 어셈블리도 다시 컴파일되지 않습니다. 이러한 경우 코드 숨김 파일과 연결된 ASPX 페이지가 일치하지 않기 때문에 응용 프로그램에서 예기치 않은 오류가 발생할 수 있습니다.

ASP.NET 2.0의 코딩 모델

ASP.NET 2.0에서도 코드 인라인 및 코드 숨김 코딩 모델을 모두 제공합니다. 코드 인라인 모델의 경우 Microsoft Visual Studio 2005에서 단일 파일 개발을 지원하는 방식을 제외하고는 거의 변경된 것이 없습니다. Visual Studio 2005의 변경 사항 및 코드 인라인 처리 방법에 대한 자세한 내용은 이 기사 를 참조하십시오.

ASP.NET 2.0에서는 코드 숨김 파일의 특성을 수정하여 코드 숨김 모델의 상속 및 컴파일 문제를 모두 해결했습니다. ASP.NET 2.0에서 코드 숨김 파일은 더 이상 System.Web.UI.Page 클래스의 완전한 구현이 아니며, 부분 클래스라는 새로운 구조로 되어 있습니다. 부분 클래스에는 사용자가 정의한 코드가 모두 포함되어 있지만, ASP.NET 1.x의 Visual Studio .NET에서 자동으로 생성된 모든 통로 및 연결 코드는 생략되어 있습니다. 새 코드 숨김 파일이 있는 ASPX 페이지를 요청하면 ASP.NET 2.0 런타임이 실제로 ASPX 페이지와 부분 클래스를 별도의 두 클래스가 아닌 단일 클래스로 결합합니다.

그림 2. ASP.NET 2.0의 코드 숨김 모델

부분 클래스에서는 새 키워드(Visual Basic의 Expands 또는 C#의 Partial)를 사용하여 실행 중에 클래스의 코드가 다른 클래스와 병합되도록 지정합니다. 마찬가지로, ASPX 페이지에서는 compilewith라는 새 지시문을 사용하여 코드 숨김 파일과 연결되도록 지정합니다.

코드 숨김 파일 비교

일반 ASP.NET 1.x 코드 숨김 파일에 친숙한 경우 Visual Studio에서 자동으로 생성된 컨트롤 선언 및 초기화 코드를 삽입한다는 것을 알고 있을 것입니다. 자동으로 생성된 이 코드는 코드 숨김 파일과 ASPX 파일이 양방향으로 동기화되어 직접적으로 생기는 결과입니다. 레이블이 있는 일반 ASPX 페이지에는 자동으로 생성된 여러 텍스트 줄로 구성된 해당 코드 숨김 파일이 있습니다.

목록 1. ASP.NET 1.x의 코드 숨김 파일

namespace WebApplication1{  public class WebForm1 : System.Web.UI.Page에서  {    protected System.Web.UI.WebControls.Label Label1;    private void Page_Load(object sender,       System.EventArgs e) {    }    #region Web Form Designer generated code      override protected void OnInit(EventArgs e)      {        InitializeComponent();        base.OnInit(e);      }      private void InitializeComponent()      {            this.Load += new System.EventHandler(this.Page_Load);      }      #endregion  }}

자동으로 생성된 코드는 레이블(굵게 표시된 줄)을 정의할 뿐 아니라 새 이벤트(페이지 로드)를 선언하고 자동으로 생성된 메서드 래퍼(Page_Load())에 이 이벤트를 자동으로 연결하기도 합니다.

이에 비해 ASP.NET 2.0에서 같은 ASP.NET 페이지는 훨씬 깔끔한 코드 숨김 파일을 생성합니다.

목록 2. ASP.NET 2.0의 코드 숨김 파일

namespace ASP {public partial class Webform1_aspx{}}

개발자는 Label1에 자동으로 액세스하여 필요에 따라 이벤트를 추가할 수 있습니다. 예를 들어 Page_Load 이벤트를 추가하여 레이블을 초기화할 수 있습니다.

목록 3. 새 코드 숨김 파일의 이벤트 추가 작업

namespace ASP {public partial class Webform1_aspx{  void Page_Load(object sender, EventArgs e)  {    Label1.Text = "Hello ASP.NET 2.0";  }}}

이벤트 구문은 Visual Studio .NET을 통해 생성할 수 있습니다. 결과로 생성되는 코드 숨김 파일은 길이가 훨씬 짧고 자동 생성 코드가 없습니다. ASP.NET 런타임은 코드 숨김 파일의 이벤트를 ASPX의 컨트롤에 자동으로 연결합니다. 즉, ASP.NET 런타임은 이제 Visual Studio에서 수행했던 코드 생성 작업을 자동으로 수행합니다.

상속의 복잡성

새 코드 숨김 모델에서는 상속의 복잡성이 크게 줄었습니다. ASPX 페이지가 코드 숨김 파일에서 직접 상속되지 않으므로, 코드 숨김 파일은 ASPX 페이지에서 정의되는 모든 컨트롤을 더 이상 정의 및 지원하지 않아도 됩니다. 마찬가지로 코드 숨김 파일은 ASP.NET 1.x에서는 필요했던 선언 코드가 없어도 ASPX 페이지에서 컨트롤에 자동으로 액세스할 수 있습니다. ASP.NET 런타임이 필요한 선언 및 이벤트 작성 코드를 컴파일된 최종 파일에 자동으로 삽입하기 때문에 이 모든 기능이 가능한 것입니다. 런타임이 이 작업을 처리하므로 코드 개발자나 웹 개발자는 이에 대해 신경쓰지 않아도 됩니다.

디자인하는 동안 링크는 Visual Studio 2005에서 관리됩니다. Visual Studio 환경에서는 ASP.NET 런타임 컴파일을 사용하여 코드 개발자와 웹 개발자가 동기화하면서 작업할 수 있도록 합니다.

컴파일의 복잡성

새 코드 숨김 파일은 ASPX 페이지에 결합되고 실행 중에 완전한 단일 클래스로 컴파일되기 때문에 컴파일이 전혀 복잡하지 않습니다. 즉, 코드 숨김 파일은 ASPX 페이지와 자동으로 동기화됩니다. 새 컴파일 모델을 사용해도 코드가 동기화되지 않을 수 있지만, 그 결과로 발생하는 예외가 훨씬 명확하기 때문에 문제점을 빨리 파악할 수 있습니다.

컴파일

ASP.NET 1.x에 도입된 페이지 모델로 인해 ASP.NET 웹 페이지의 컴파일 과정은 항상 두 단계로 나눠져 있었습니다. 먼저 코드 숨김 파일 및 기타 지원 클래스가 어셈블리로 컴파일된 다음, 실행 중에 개별 ASPX 파일이 컴파일됩니다. 이 모델에는 많은 장점이 있지만 몇 가지 단점도 있습니다. ASP.NET 2.0에서는 사용자의 특정 요구에 따라 보다 광범위한 컴파일 옵션을 제공함으로써 이 기본 모델에 대한 몇 가지 대안을 제공합니다.

ASP.NET 1.x의 컴파일

ASP.NET 1.x의 기본 컴파일 모델은 요청된 각 ASPX 페이지에 대해 하나의 응용 프로그램 어셈블리(컴파일된 모든 코드 숨김 파일 및 기타 소스 코드 포함) 및 하나의 임시 어셈블리를 만들었습니다. 일괄 처리와 같은 컴파일러 최적화로 인해 임시 ASPX 페이지가 동일한 어셈블리로 컴파일되는 경우도 있습니다. 두 가지 경우 모두 각 ASPX 페이지는 임시 어셈블리로 컴파일되기 때문에 ASP.NET 런타임으로 로드할 수 있습니다.

그림 3. ASP.NET 1.x의 컴파일

이 모델에는 장점도 있지만, 두 가지 주요 단점이 있습니다. 첫째로, ASPX 페이지는 읽을 수 있는 형식으로 웹 사이트에 배포해야 합니다. 개발자가 코드 인라인 모델을 사용한 경우에는 일부 또는 전체 비즈니스 논리를 프로덕션 서버에서 배포할 수도 있습니다. 원시 ASPX 페이지를 제공하지 않도록 IIS 및 ASP.NET을 구성한 경우에도, 기술력이 높은 공격자는 웹 서버 액세스를 통해 여전히 파일에 액세스할 수 있습니다. 둘째로, ASP.NET 런타임이 ASPX 페이지를 컴파일해야 하기 때문에 웹 페이지를 처음 요청할 때는 응답이 보통 때보다 늦습니다.

개발자가 이 프로세스에 대해 제어할 수 있는 유일한 사항은 ASPX 페이지 일괄 컴파일 여부입니다. ASP.NET 1.x에서는 <compilation> 태그를 수정하여 web.config 파일에서 일괄 컴파일을 구성할 수 있습니다.

목록 4. 일괄 컴파일 구성

<compilation    batch="true|false"  batchTimeout="시간(초)"              maxBatchSize="일괄 컴파일당 최대 페이지 수"  maxBatchGeneratedFileSize="일괄 컴파일당 생성되는    소스 파일의 최대 결합 크기(KB)"          </compilation>(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

일괄 컴파일을 사용하면 웹 페이지를 처음 요청할 때 시작 시간은 길어지는 대신 로드 시간이 줄어듭니다. 일괄 컴파일의 두 번째 장점은 모든 ASPX 파일이 페이지당 하나의 임시 어셈블리로 컴파일되지 않고 단일 임시 어셈블리로 컴파일된다는 점입니다.

ASP.NET 2.0의 컴파일

ASP.NET 2.0에서는 웹 응용 프로그램에 대해 다음과 같은 4가지 컴파일 모델을 제공합니다.

  • 일반(ASP.NET 1.x)-일반 ASP.NET 웹 응용 프로그램에서 코드 숨김 파일은 어셈블리로 컴파일되어 /bin 디렉터리에 저장됩니다. 요청 시 웹 페이지(ASPX)가 컴파일됩니다. 이 모델은 대부분의 웹 사이트에 적합합니다. 그러나 컴파일 프로세스로 인해 처음 ASP.NET 페이지를 요청할 때 후속 요청에 비해 속도가 느립니다. ASP.NET 2.0에서도 이 컴파일 모델을 지원합니다.
  • 일괄 컴파일-ASP.NET 2.0에서는 단일 URL 요청으로 응용 프로그램을 일괄 컴파일할 수 있습니다. ASP.NET 1.x를 사용할 때와 마찬가지로, 일괄 컴파일을 사용하면 처음 페이지를 요청할 때는 지연되지 않지만 시작 시 주기 시간이 길어집니다. 또한 일괄 컴파일을 사용하려면 여전히 코드 숨김 파일을 컴파일하여 미리 배포해야 합니다.
  • 미리 컴파일하여 배포-ASP.NET 2.0의 새 기능을 사용하면 배포하기 전에 프로젝트를 완전히 컴파일할 수 있습니다. 전체 컴파일에서 응용 프로그램의 크기와 컴파일 설정에 따라 모든 코드 숨김 파일, ASPX 페이지, HTML, 그래픽 리소스 및 기타 백엔드 코드가 실행 가능한 하나 이상의 어셈블리로 컴파일됩니다. 이 어셈블리에는 웹 사이트의 컴파일된 코드가 모두 포함되며, 리소스 파일 및 구성 파일이 수정되지 않고 복사됩니다. 이 컴파일 방법을 사용하면 성능과 보안을 최상으로 유지할 수 있지만 배포 후에 웹 사이트를 수정할 수는 없습니다. 굉장히 시각적이거나 안전한 웹 사이트로 작업하는 경우 이 옵션은 최종적으로 배포할 때 적합합니다. 그러나 로컬 인트라넷에서 실행되며 자주 변경되는 소규모 사이트를 만드는 경우 미리 전체를 컴파일하는 작업은 불필요합니다.
  • 실행 중에 전체 컴파일-미리 컴파일하여 배포하는 방법과 반대로, ASP.NET 2.0에서는 실행 중에 전체 응용 프로그램을 컴파일하는 새 메커니즘을 제공합니다. 즉, 컴파일되지 않은 코드 숨김 파일 및 기타 관련 코드를 새 코드 디렉터리에 배치한 다음 실행 중에 이 파일로부터 생성될 어셈블리의 참조를 ASP.NET 2.0에서 자동으로 만들어 유지하도록 할 수 있습니다. 이 옵션을 사용하면 가장 융통성 있게 웹 사이트 콘텐츠를 변경할 수 있지만 컴파일되지 않은 코드를 서버에 저장해야 합니다.

환경과 요구 사항에 가장 적합한 컴파일 옵션을 선택할 수 있지만, 컴파일 모델에는 항상 융통성이 있습니다. 코드 디렉터리를 사용하여 코드 숨김 파일을 저장하는 경우에도 전체 컴파일 방법을 사용하여 응용 프로그램을 배포할 수 있습니다.

일괄 컴파일

ASP.NET 2.0에서도 web.config 일괄 컴파일 설정을 사용할 수 있습니다. 일괄 컴파일의 장점은 첫 사용자가 페이지를 즉시 사용할 수 있으며, 일괄 컴파일 작업 중에 ASPX 페이지의 오류가 검색된다는 점입니다. 그러나 일괄 컴파일을 사용하면 응용 프로그램을 시작할 때 지연이 발생하며 web.config 파일에서 일괄 컴파일을 구성해야 합니다.

미리 컴파일하여 배포

미리 컴파일하여 배포하는 경우 웹 사이트의 실행 파일 버전인 어셈블리를 하나 이상 만들 수 있습니다. 그 결과로 생기는 어셈블리에는 웹 사이트의 컴파일 코드가 포함됩니다. HTML 페이지, 리소스, 구성 파일 및 ASPX 페이지는 별도로 복사됩니다.

미리 컴파일하여 배포하려면 aspnet_compiler.exe라는 명령줄 유틸리티를 사용해야 합니다. 이 유틸리티는 대상 배포 디렉터리를 만드는데, 이 디렉터리에는 다양한 ASPX 페이지의 어셈블리 및 스텁 파일이 있는 /bin 디렉터리가 포함되어 있습니다. 이 유틸리티를 사용하면 "magic page"(마법 페이지)를 호출하는 동작과 비슷하게 현재 위치에서 미리 컴파일할 수도 있습니다. 스텁 파일은 ASPX 페이지와 이름이 같지만 컴파일된 어셈블리로 호출되는 단순 코드를 포함하고 있습니다. 즉, ASPX 페이지는 완전한 기능을 갖춘 페이지라기보다는 단순히 빈 셸입니다.

웹 사이트를 미리 구성하여 배포하면 어셈블리를 디컴파일하지 않고서는 코드에 액세스할 수 없기 때문에 보안이 크게 향상됩니다. 보안을 더욱 향상시키려면 컴파일의 결과물인 어셈블리를 판독하기 어렵게 처리하여 웹 응용 프로그램을 더욱 안전하게 만들 수 있습니다. 미리 컴파일하여 배포하는 방법의 가장 큰 단점은 이 단계를 배포 전에 수행해야 하기 때문에 배포한 후에는 웹 사이트를 변경할 수 없다는 점입니다. 웹 사이트를 변경하려면 웹 사이트를 다시 컴파일하여 다시 배포해야 합니다.

미리 컴파일하여 배포하는 옵션은 웹 서버에 배포되는 원시 코드의 양을 줄이고 최고의 보안을 제공하기 때문에 대부분의 주요 웹 응용 프로그램에서 배포에 사용되는 메커니즘입니다. 생산성을 크게 저하시키지 않고 이 향상된 프로세스를 일반 개발/테스트/배포 주기에 포함할 수 있습니다.

실행 중에 전체 컴파일(코드 디렉터리)

지금까지 설명한 세 가지 컴파일 방법 모두, 배포하기 전에 모든 코드 파일(코드 숨김 파일 및 지원 클래스)을 컴파일해야 합니다. ASP.NET 2.0에서는 코드 디렉터리를 사용할 수 있습니다.

코드 디렉터리는 컴파일되지 않은 클래스를 보관하는 특수 디렉터리입니다. 실행 중에 ASP.NET 런타임은 응용 프로그램에서 ASPX 페이지가 자동으로 참조하는 어셈블리로 이 디렉터리의 콘텐츠를 컴파일합니다. 즉, 코드 디렉터리를 사용함으로써 지원 코드에 대해 별도의 어셈블리를 만들고 참조하지 않아도 됩니다. 코드 디렉터리의 장점은 프로젝트를 완전히 컴파일하지 않고 배포할 수 있으므로 잠재적인 불일치 문제를 줄일 수 있다는 점이며, 단점은 서버에서 컴파일되지 않은 코드가 노출된다는 점입니다.

이 옵션은 코드 숨김 파일 또는 외부 개체의 형식으로 지원 코드가 많이 필요하지 않은 ASP.NET 응용 프로그램에 적합합니다. 간단한 응용 프로그램의 경우에는 시스템을 빠르게 배포 및 테스트할 수 있는 방법을 사용하는 것이 보다 강력한 컴파일 방법을 사용하는 것에 비해 더 유리합니다.

페이지 주기

ASP.NET 2.0에서는 ASP.NET 페이지의 주기에서 두 가지 주요 사항이 변경되었습니다. 첫째로, ASP.NET 2.0에서는 새 이벤트를 제공하여 마스터 페이지, 개인 설정, 통합 모바일 장치 지원 등의 새 기능을 지원합니다. 둘째로, ASP.NET 2.0에는 Web Forms의 페이지 간 게시 기능이 도입되었습니다.

새 이벤트

ASP.NET 2.0에서는 ASP.NET 1.x에 비해 보다 세분화된 페이지 주기 메서드 스택을 제공합니다. 추가된 메서드는 웹 개발자에게 보다 향상된 제어 기능을 제공합니다. ASP.NET 페이지의 Page 개체를 통해 이러한 이벤트에 액세스할 수 있습니다.

표 1은 광범위한 메서드 목록을 보여 줍니다. 메서드 열에는 실제 이벤트 메서드 이름이 표시되며, 활성 열은 이벤트가 항상 활성 상태인지 아니면 PostBack 작업 동안에만 활성화되는지를 나타냅니다. 예를 들어 새 TestDeviceFilter 메서드를 사용하여 어떤 장치 필터가 있는지 확인할 수 있으며 이 정보를 통해 페이지 표시 방법을 결정할 수 있습니다. 반면에 새 LoadControlState 메서드는 포스트백(postback) 동안에만 활성화됩니다. SaveControlState와 함께 이 메서드를 재정의하여 포스트백(postback) 동안 컨트롤 상태를 저장 및 복원하기 위한 대체 serialization 구성표를 만들 수 있습니다.

표 1. 페이지 주기 메서드

메서드활성
Constructor항상
Construct항상
TestDeviceFilter항상
AddParsedSubObject항상
DeterminePostBackMode항상
OnPreInit항상
LoadPersonalizationData항상
InitializeThemes항상
OnInit항상
ApplyControlSkin항상
ApplyPersonalization항상
OnInitComplete항상
LoadPageStateFromPersistenceMediumPostBack
LoadControlStatePostBack
LoadViewStatePostBack
ProcessPostData1PostBack
OnPreLoad항상
OnLoad항상
ProcessPostData2PostBack
RaiseChangedEventsPostBack
RaisePostBackEventPostBack
OnLoadComplete항상
OnPreRender항상
OnPreRenderComplete항상
SavePersonalizationData항상
SaveControlState항상
SaveViewState항상
SavePageStateToPersistenceMedium항상
Render항상
OnUnload항상

페이지 주기에 대해 간단히 살펴보면, 테마와 개인 설정 같이 ASP.NET 2.0에서 사용할 수 있는 여러 기능이 자연스럽게 구현되는 위치를 볼 수 있습니다. 예를 들어 테마는 IntializeThemes 이벤트에서 처리되며 개인 설정 데이터는 LoadPersonalizationData에서 로드된 다음 나중에 ApplyPersonalization 메서드에서 적용됩니다. 어떤 UI 요소가 웹 응용 프로그램의 최종적인 모양과 느낌을 결정하는지와 관련하여 메서드 순서는 매우 중요합니다.

페이지 간 게시

페이지 주기의 두 번째 주요 변경 사항은 포스트백(post back) 이벤트 및 Web Forms 관련 사항입니다. ASP.NET 1.x에서는 Web Forms가 호스트 페이지로 자동 포스트백(postback)됩니다. 즉, 사용자가 양식을 제출하면 양식 데이터는 원래 양식이 포함된 페이지로 항상 다시 전송됩니다. 이 방법으로 디자인하면 컨트롤 상태를 쉽게 저장할 수 있지만 개발자가 보다 복잡한 작업을 수행하는 데 제한이 있습니다.

ASP.NET 2.0에서는 개발자가 양식 데이터를 제출하는 위치를 결정할 수 있는 새 속성이 Web Form 컨트롤에 포함되어 있습니다. 대부분의 경우에는 포스트백(postback) 메커니즘이 적합하므로 여전히 이 메커니즘이 기본값입니다. 그러나 이제 개발자는 다른 데이터를 다른 양식에 게시할 수도 있습니다.

그림 4. 포스트백(Postback) 및 페이지 간 게시

예를 들어 여러 가지 양식으로 구성된 다중 페이지 마법사를 만들 수 있습니다. 최종 유효성 검사가 발생할 수 있는 요약 페이지에 도달할 때까지 각 양식은 순서대로 다음 페이지로 제출됩니다. PreviousPage 개체를 사용하여 현재 컨텍스트에서 마지막 페이지의 데이터에 액세스할 수 있습니다. PreviousPage 개체는 현재 페이지에 사용할 수 있도록 이전 페이지에서 유효성을 검사한 데이터를 저장합니다. 이 개체 덕분에 페이지 간 게시를 사용할 때 컨트롤을 유지할 수 있습니다. 시퀀스에서 양식 한 개를 백업해야 하는 경우 페이지 데이터에 즉시 액세스할 수 있으며 모든 데이터를 다시 입력할 필요가 없습니다.

확장성

ASP.NET은 원래 개방형 프레임워크로 디자인되었습니다. 즉, ASP.NET을 구성하는 대부분의 모듈 및 구성 요소를 필요에 맞게 확장, 수정 또는 대체할 수 있습니다. ASP.NET 2.0에서는 이제 프레임워크의 표준이 된 새 HTTPHandlersHTTPModules를 통해 프레임워크의 확장성을 더욱 명확하게 확인할 수 있습니다.

요청 파이프라인

ASP.NET에서 요청은 웹 서버로부터 ISAPI(인터넷 서버 응용 프로그래밍 인터페이스) 필터를 통해 실제 ASP.NET 런타임으로 전달됩니다.

그림 5. 요청 파이프라인

IIS에서 요청을 받으면 IIS 설정에 따라 확장명이 ISAPI 필터에 매핑됩니다. .aspx, .asmx, .asd 등의 확장명은 aspnet_isapi.dll로 매핑됩니다. aspnet_isapi.dll은 ASP.NET 런타임을 시작하는 ISAPI 필터입니다. 요청이 발생하면 ASP.NET 런타임은 ASP.NET 웹 응용 프로그램의 호스트 역할을 하는 HTTPApplication 개체에서 시작됩니다. HTTPApplication 개체는 다음과 같은 동작을 수행합니다.

  1. 컴퓨터 및 응용 프로그램 수준의 구성 파일을 읽습니다.
  2. 하나 이상의 HTTPModule 인스턴스를 통해 요청을 전달합니다. 각 HTTPModule은 세션 유지 관리, 인증 또는 프로필 유지 관리와 같은 서비스를 제공합니다. 이 모듈은 요청을 다시 HTTPApplication으로 전달합니다.
  3. 동사 및 경로를 기준으로 요청을 HTTPHandler로 전달합니다. 동사는 요청(GET, POST, FTP 등)에 사용된 HTTP 동사를 참조하며, 경로는 응용 프로그램 내의 URL을 참조합니다. 처리기를 구성하는 방법에 따라 요청을 ASP.NET 페이지로 처리할 수도 있고, 요청으로 인해 모든 웹 페이지의 일괄 컴파일 등 다른 동작이 호출될 수도 있습니다(System.Web.UI.PageIHTTPHandler를 구현한 것이며 precomiplation.asd는 PrecompHandler를 호출함).

ASP.NET 2.0에서도 이 모델은 그대로 유지되지만, 다양한 모듈 및 처리기가 새로 추가되어 더 많은 서비스를 제공합니다. ASP.NET 1.x에서와 마찬가지로 모듈 또는 처리기 클래스를 확장, 대체 또는 재구성하여 사용자 지정 기능을 제공할 수 있습니다.

새 모듈

HTTPModules가 추가되어 ASP.NET 2.0에서 제공되는 새로운 서비스를 지원합니다. 특히 기본 모듈 설정이 지정된 ASP.NET 응용 프로그램에는 다음에 대한 새 모듈이 포함됩니다.

  • SessionID-ASP.NET 1.x 세션 모듈에서 세션 ID 메커니즘이 분리되어 쿠키, URL 다시 작성 및 기타 세션 ID 생성 양식을 보다 효과적으로 제어할 수 있습니다.
  • 역할 관리-새 모듈이 추가되어 새 사용자 ID 메커니즘을 지원하는 역할 기반 서비스를 제공합니다. 이 모듈을 사용하면 .NET 프레임워크에 구축된 역할 기반 보안에 ASP.NET 응용 프로그램을 쉽게 연결할 수 있습니다.
  • 익명 ID-새 개인 설정 기능은 익명 사용자를 지원합니다. 이 모듈을 사용하면 익명 사용자가 액세스할 수 있는 기능 및 요청 간에 이 기능이 유지 관리되는 방법을 파악할 수 있습니다.
  • 프로필-프로필 모듈은 새 프로필 서비스에 연결되며 사용자별 영구 데이터 저장소를 제공할 수 있도록 합니다.
  • 페이지 카운터-ASP.NET 2.0은 새 모듈을 통합하여 페이지 카운터에 연결하고 웹 트래픽의 통계 분석 기능을 향상시킵니다.

이러한 새 모듈 외에도, 일부 이전 모듈의 동작이 변경되었습니다. 예를 들어 출력 캐싱 모듈은 이 백서 뒷부분에 설명할 새 캐싱 기술을 지원합니다.

새 처리기

새 모듈 외에도, ASP.NET 2.0에는 응용 프로그램 구성 도구 및 일괄 컴파일 요청 등의 기타 새 기능을 지원하는 처리기가 새로 추가되었습니다. 새 처리기 중 가장 중요한 처리기에는 웹 사이트 관리 요청을 처리하는 ".axd" 패밀리가 있습니다. 이 처리기는 개발자가 ASP.NET 사용자 및 기타 설정을 구성할 수 있도록 하는 내부 관리 도구를 시작합니다. 이러한 관리 처리기는 다음과 같습니다.

  • 웹 관리-WebAdminHandler는 관리 웹 사이트의 기본 페이지입니다. 이 처리기를 사용하여 ASP.NET 2.0 웹 응용 프로그램 관리를 시작할 수 있습니다.
  • 추적-ASP.NET 1.x TraceHandler가 향상되었습니다. 이 처리기는 ASP.NET 1.x에서 사용할 수 있었던 유일한 "axd" 처리기입니다.
  • 웹 리소스-새 관리 도구 및 WebResourcesHandler를 통해 이제 웹 리소스를 배포 후에 구성할 수 있습니다.
  • 캐시된 이미지-CachedImageServiceHandler는 그래픽 구성 요소 캐싱을 지원합니다.
  • 카운터-SiteCountersHandler를 페이지 카운터 모듈과 함께 사용하여 ASP.NET 2.0 응용 프로그램의 액세스 통계를 제공합니다.
  • 미리 컴파일-앞에서 언급한 대로, PrecompHandler를 사용하여 ASP.NET 응용 프로그램의 모든 ASPX 페이지를 일괄 컴파일할 수 있습니다.
  • 웹 파트 내보내기-WebPartExportHandler는 웹 파트 레이아웃의 저장 및 전송을 지원합니다. 웹 파트는 포털형 웹 응용 프로그램의 모양과 콘텐츠를 개인 설정할 수 있는 새로운 메커니즘입니다.

일반적인 경우와 같이 HTTPForbiddenHandler는 반환해서는 안 되는 파일 형식에 연결됩니다. ASP.NET 2.0에서는 금지된 파일 형식의 범위가 보다 넓어져서 마스터 페이지, 스킨 파일 및 기타 새 개발자 구성 요소가 포함됩니다.

고급 캐싱 기술

웹 응용 프로그램의 성능을 향상시킬 수 있는 한 가지 방법은 메모리에서 정적 콘텐츠를 캐시하는 것입니다. 캐시된 콘텐츠는 새로 렌더링된 콘텐츠보다 항상 빠르게 반환됩니다. 하지만 단점은 캐시된 콘텐츠가 오래되어 내용이 부실해질 수 있다는 것입니다. ASP.NET 1.x에서는 다음을 비롯하여 여러 가지 캐싱을 지원합니다.

  • 페이지 수준-각 페이지를 전체적으로 캐시하거나 페이지에 액세스하는 데 사용된 매개 변수를 기반으로 캐시할 수 있습니다. 캐시된 페이지는 지정한 시간이 지나면 만료됩니다.
  • 페이지 조각-사용자 컨트롤(.ascx 파일)을 사용하여 페이지를 만든 경우 나머지 페이지 콘텐츠와 별도로 이 사용자 컨트롤을 캐시할 수 있습니다.
  • 프로그래밍 방식 캐싱-개발자는 캐시 API를 통해 개체를 캐시할 수도 있습니다. 캐시 API 사용의 확실한 이점은 캐시를 플러시해야 하는 경우를 위해 다른 종류의 종속성을 만들 수 있다는 것입니다.

ASP.NET 2.0에서는 페이지 수준의 캐싱 메커니즘이 확장되어 데이터베이스 종속성을 지원합니다. 데이터베이스 캐시 종속성을 사용하면 캐시된 페이지를 SQL Server 데이터베이스의 특정 테이블에 연결할 수 있습니다. 테이블이 변경되면 캐시가 자동으로 만료됩니다. 또한 개발자는 이제 사후 캐시 대체 기능을 사용하여 캐시된 콘텐츠의 일부를 새로 고친 콘텐츠로 바꿀 수 있습니다. 사후 캐시 대체를 사용하면 페이지의 일부를 동적으로 생성해야 하는 경우에도 응용 프로그램에서 페이지 수준의 캐싱을 사용할 수 있습니다.

데이터베이스 캐시 무효화

대부분의 데이터 기반 웹 사이트에서 캐싱은 어려운 문제일 수 있습니다. 특히 캐싱이 필요한 상황에서 최신 데이터가 필요한 경우에는 더욱 그러합니다. ASP.NET 1.x에서 페이지는 지정한 시간 동안 캐시할 수 있었으며, 입력 매개 변수(쿼리 문자열 또는 POST 매개 변수)에 의해 구성되었습니다.

목록 5. ASP.NET 1.x 출력 캐시 지시문

<%@ outputcache duration="3600" varybyparam="ProdID" %> 

예를 들어 목록 5의 코드는 ProdID 변수를 기반으로 한 시간 동안 메모리에서 페이지를 캐시합니다. 위의 예에서 발생하는 문제점은 관련 업무 데이터가 다른 곳에서 업데이트되는 경우 수행해야 하는 작업입니다. 예를 들어 제품 카탈로그 페이지가 제품 ID에 의해 캐시되는 경우를 가정해 봅시다. 가능한 수량이나 가격 등 이 제품에 대한 정보가 관리 사이트에서 업데이트되는 경우 잘못된 데이터가 캐시되어 고객에게 표시됩니다. 이전 버전의 ASP.NET에서 이 문제를 해결하려면 Response.RemoveOutputCacheItem을 사용하여 캐시에서 페이지를 수동으로 제거하거나 duration 시간이 만료될 때까지 기다린 후 시스템에서 자동으로 페이지를 업데이트하도록 해야 했습니다.

ASP.NET 2.0에서는 데이터베이스 캐시 종속성을 지원하므로 이러한 문제가 해결됩니다. SQL Server 7 및 2000에서 작업할 경우 테이블 수준 알림을 사용할 수 있으며, Microsoft SQL Server 2005에서는 보다 세분화된 수준으로 알림을 제공합니다. 예를 들어 다음 코드는 최대 한 시간 동안 제품 페이지를 캐시하지만 데이터베이스 테이블에 두 번째 종속성을 추가합니다.

목록 6. ASP.NET 2.0 데이터베이스 캐시의 예

<%@ outputcache duration="3600"   varybyparam="ProdID"   sqldependency="MyDatabase:Products" %>

sqldependency 특성을 사용하면 Products 테이블이 변경될 경우 캐시된 페이지가 만료됩니다. sqldependency 특성은 web.config 파일에서 구성된 datasource를 참조해야 합니다. datasource는 데이터베이스 연결 및 필요한 매개 변수를 식별하여 종속성 알림 작업을 수행합니다.

사용자 지정 캐시 종속성

ASP.NET 2.0에는 Microsoft SQL Server를 지원하는 단일 CacheDependency 구현인 SQLCacheDependency 클래스가 있습니다. 새 캐시 종속성을 구현하는 작업은 포함된 프로세스이지만, ASP.NET 2.0의 확장성으로 인해 구현이 가능합니다. 즉, 사용자 고유의 CacheDependency 클래스를 만들어 Oracle이나 Sybase 등의 다른 데이터베이스 시스템과 유사한 기능을 제공할 수 있습니다.

사후 캐시 대체

일부 페이지 요소는 동적으로 유지되지만 페이지에서 대부분의 요소가 캐시를 사용하는 경우, ASP.NET 2.0에서는 사후 캐시 대체라는 기능을 제공합니다. 사후 캐시 대체는 페이지를 사용자에게 표시하기 전에 캐시된 페이지에 있는 특정 요소를 다시 계산해야 함을 ASP.NET 런타임에 알리는 데 사용됩니다.

다음 두 가지 방법으로 이 기능을 사용할 수 있습니다.

  • Response.writeSubstitution 메서드를 호출하고 대체 콜백 함수에 대한 참조를 전달합니다.
  • 웹 페이지에 <asp:substitution> 컨트롤을 추가하고 methodname 특성을 콜백 함수의 이름으로 설정합니다.
  • 어떤 옵션을 사용하든지 종속성의 기간과 위치를 지정하는 @OutputCache 지시문을 페이지에 추가해야 합니다.

사후 캐시 대체 구현

사후 캐시 대체를 인식하는 컨트롤을 만들어 이 기능을 활용할 수 있습니다. 이러한 컨트롤의 예로는 AdRotator 컨트롤을 들 수 있습니다. 목록 7은 다음과 같은 페이지를 나타냅니다.

  • Pubs 데이터베이스의 작성자 테이블에서 데이터를 검색하는 페이지
  • 데이터를 GridView 컨트롤에 결합하는 페이지
  • AdRotator에서 광고를 표시하는 페이지
  • 레이블 컨트롤에 페이지를 만든 시간을 표시하는 페이지

목록에서 굵게 표시된 <asp:substitution> 컨트롤도 이 예에 추가되었습니다. 이 컨트롤은 문자열 출력(이 경우 현재 시간)을 반환하는 메서드인 uncachedUpdatemethodname 특성을 설정합니다. 이 대체 컨트롤은 캐시된 대상과 상관없이 정확한 시간을 반환합니다.

목록 7. PostCache.ASPX 소스 코드

<%@ Page language="c#" Codebehind="PostCache.ASPX.cs"   AutoEventWireup="true" Inherits="WebApplication1.PostCache" %><%@ outputcache duration="30" varybyparam="none" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ><HTML>  <HEAD>    <title>WebForm1</title>  </HEAD>  <body MS_POSITIONING="GridLayout">    <form id="Form1" method="post" runat="server">      <DIV style="DISPLAY: inline;        Z-INDEX: 101; LEFT: 32px; WIDTH: 160px;        POSITION: absolute; TOP: 24px; HEIGHT: 8px"        align="right" ms_positioning="FlowLayout">          this page was created at:      </DIV>      <asp:Label id="CreatedTime"        style="Z-INDEX: 102; LEFT: 200px; POSITION: absolute;        TOP: 24px" runat="server" Width="120px" Height="16px">      </asp:Label>      <asp:substitution id="UpdatedTime" methodname="uncachedUpdate"        style="Z-INDEX: 103; LEFT: 200px; POSITION: absolute;        TOP: 48px" runat="server" Width="112px" Height="11px">      </asp:substitution>      <DIV style="DISPLAY: inline; Z-INDEX: 104; LEFT: 32px;        WIDTH: 160px; POSITION: absolute; TOP: 48px;        HEIGHT: 16px" align="right" ms_positioning="FlowLayout">          and last updated at:      </DIV>      <asp:AdRotator id="Ads" style="Z-INDEX: 105; LEFT: 312px;        POSITION: absolute; TOP: 16px" runat="server"        Width="80px" Height="60px" AdvertisementFile="img/Ads.xml">      </asp:AdRotator>    </form>  </body></HTML>

이 페이지의 코드 숨김 파일에는 uncachedUpdate 메서드에서 사후 캐시 대체를 지원하는 데 필요한 이벤트가 포함됩니다. Page_Load 메서드는 페이지를 로드한 시간을 보고하므로 캐싱이 발생하는 시간을 파악할 수 있습니다.

목록 8. PostCache.ASPX.cs

using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;namespace WebApplication1 {  public class PostCache : System.Web.UI.Page  {    protected System.Web.UI.WebControls.Label CreatedTime;    protected System.Web.UI.WebControls.Label UpdatedTime;    protected System.Web.UI.WebControls.AdRotator Ads;    private void InitializeComponent()  {      this.Load += new System.EventHandler(this.Page_Load);    }    private void Page_Load(object sender, System.EventArgs e) {      CreatedTime.Text = DateTime.Now.ToShortTimeString();      }    protected String uncachedUpdate()  {      return DateTime.Now.ToShortTimeString();    }  }}

사후 캐시 대체 기능 사용

그림 6은 PostCache 페이지의 출력을 보여 줍니다. 응용 프로그램을 처음 실행할 때 "Page created time"과 "Last updated time"이 일치하는 것을 볼 수 있습니다.

그림 6. PostCache.ASPX의 출력

이후에 같은 페이지를 호출하면 사후 캐시 대체의 효과를 확인할 수 있습니다. Page created time과 이미지는 동일하게 유지되지만 Last updated time은 변경됩니다.

그림 7. 두 번째 요청 시 PostCache 출력

캐싱 지시문으로 인해 Page created time과 adRotator 이미지는 일정하게 유지됩니다. 페이지는 30초 동안 캐시됩니다. 이 시간이 지나면 다음 요청 시 Page created time과 adRotator가 업데이트됩니다. 그러나 uncachedUpdate() 메서드를 호출하는 <asp:substitution> 컨트롤은 캐시된 상태와 상관없이 페이지가 요청될 때마다 업데이트됩니다.

사후 캐시 대체를 적절히 사용하면 개발자는 페이지의 동적 부분만 업데이트함으로써 웹 응용 프로그램의 성능을 크게 향상시킬 수 있습니다. ASP.NET 2.0에서 개발한 웹 응용 프로그램을 데이터베이스 캐시 무효화 및 비동기 페이지 업데이트 기능과 함께 사용하면 웹의 일반 요청 및 응답 아키텍처로 인해 발생하는 여러 제한 사항을 없앨 수 있습니다.

성능

ASP.NET 2.0의 인프라 변경 사항 및 추가 기능에 대해 설명했습니다. 그러나 아직 ASP.NET 2.0의 성능에 관한 의문 사항이 남아 있습니다. ASP.NET 2.0이 아직 개발 중이기 때문에 성능 메트릭을 사용할 수는 없지만, ASP.NET 2.0 프레임워크의 모든 면에 걸쳐 성능을 유지하거나 향상시키는 데 많은 노력을 기울여 왔습니다.

향상된 요청 파이프라인

모든 개발자가 향상된 성능을 확인할 수 있는 영역은 요청 파이프라인입니다. 많은 이벤트가 새로 추가되었지만, 기본 ASP.NET 요청 스택은 ASP.NET 1.1의 요청 스택보다 최대 30% 빠릅니다. "Hello World"를 표시하는 간단한 페이지를 만들어 향상된 성능을 평가할 수 있습니다. 이 페이지에는 고급 기능이 없기 때문에 ASP.NET 2.0을 IIS에 연결하는 ISAPI 플러그 인을 비롯하여 HTTPHandlerHTTPModule 파이프라인을 직접 테스트할 수 있습니다. 보다 빠른 처리를 위해 이 코드가 최적화되었기 때문에 사용 중인 IIS 버전에 상관없이 향상된 성능을 확인할 수 있습니다.

IIS 6.0으로 향상된 메모리 관리

ASP.NET 2.0에서는 IIS 6.0을 함께 사용할 때만 성능이 향상되는 경우가 있습니다. 예를 들어 IIS 6.0의 경우 100명의 사용자가 동시에 여러 개의 컨트롤이 있는 페이지를 요청하는 로드 테스트에서 작업자 프로세스의 작업 집합이 약 50% 감소되었습니다. 이러한 결과는 지정된 서버의 경우 운영 체제에서 이전에 필요했던 리소스에 비해 절반 정도의 리소스만 사용함을 의미합니다.

어느 정도 복잡한 ASP.NET 페이지를 테스트한 결과, 같은 페이지를 IIS 5.0에서 실행했을 때에 비해 시스템 로드(메모리 및 CPU 사용량)가 크게 낮아졌습니다. 이러한 성능 향상은 관리 메모리에서 고유 메모리로 응답 버퍼를 이동함으로써 가능해진 것입니다. ASP.NET 2.0에서는 관리 메모리를 특정 응답에 고정할 필요가 없으므로 리소스 병목 현상이 없으며 각 요청에 대해 응답이 보다 빨리 생성됩니다.

기타 성능 향상은 IIS 6.0과 Windows 운영 체제 커널을 견고하게 통합하여 이룬 것입니다. IIS 6.0에서는 커널 수준에서 일부 캐싱 및 버퍼링을 수행하므로 ASP.NET을 비롯한 모든 웹 응용 프로그램의 성능이 향상됩니다.

기타 향상된 기능

개발자는 ASP.NET 2.0의 기능 수행 속도가 ASP.NET 1.x와 같거나 더 빠르다는 것을 알게 될 것입니다. 핵심 기능이 모두 포함된 최종 ASP.NET 2.0 릴리스에서는 더 많은 성능 향상을 확인할 수 있습니다.

결론

ASP.NET 2.0에서는 개발자의 생산성을 높이기 위해 다양한 구조적 기능이 향상되었습니다. 코드 모델이 향상되어 충돌을 줄이고, 컴파일 프로세스가 확장되어 웹 응용 프로그램을 컴파일 및 배포하는 옵션이 보다 다양하게 제공됩니다. ASP.NET 프레임워크의 확장성은 개인 설정, 마스터 페이지, 관리 사이트 등을 비롯하여 ASP.NET의 여러 가지 새 기능을 지원하는 새 HTTPModulesHTTPHandlers를 통해 다시 한 번 확인되었습니다. 데이터베이스 종속성과 사후 캐시 대체를 사용할 수 있도록 캐싱이 향상되었습니다. 내부적으로 ASP.NET 2.0에는 이전 버전에 비해 크게 향상된 기능이 포함되어 있습니다. ASP.NET 2.0의 새로운 구현 방식은 업계 최고의 방식을 따르는 동시에 다양한 개발자 중심의 향상된 기능을 통합합니다. ASP.NET 2.0에서는 복잡한 엔터프라이즈 웹 응용 프로그램 개발 작업을 처리할 수 있는 세계 최고의 웹 개발 플랫폼을 제공합니다.

관련 서적

 

Posted by tornado
|