이번 강좌는 ASP.NET HTTP 런타임의 내부(Internal)에 관한 이야기입니다. 읽는 이에 따라 이번 강좌의 난이도는 달리 느껴질 수 있겠지만, 보편적으로는 중급이상의 이야기가 아닌가 합니다. 다소 어렵게 느껴지는 이야기일 수도 있겠지만, 전반적으로 ASP.NET이 돌아가는 것을 파악하기에는 도움이 될만한 강좌가 되지 않을까 생각해 봅니다. 그러면, 시작해 볼까요?
사실, 이번 강좌는 이어질 HttpModule 개발하기 강좌를 위한 초석으로 설명 드리는 것이기에 ASP.NET 내부를 아주 구체적으로 파고들지는 않습니다. 전반적으로 흘러가는 모습을 주욱 훑어보는 정도입니다. 더욱 구체적인 내부가 궁금하신 분들은 다음 MS 링크를 참고하시기 바래요. |
ASP.NET 런타임의 실행 흐름
ASP.NET 런타임의 실행을 이해하기 위해서, 우선 간단하게나마 웹 요청이 IIS 서버로 들어왔을 경우의 처리 흐름을 간략하게 살펴보도록 하겠습니다. 아래의 그림은 ASP.NET 페이지에 대한 요청이 IIS(Internet Information Server)로 들어올 경우의 상황을 보여줍니다.
그림에서 보이다시피, 모든 요청은 기본적으로 IIS를 통해서 수신이 됩니다. 그리고, 그 요청은 ASP.NET과 관련된 것들에 한해 ASPNET_ISAPI.dll 에게로 건네지게 되지요. 기존 asp 파일에 대해서는 ASP.dll이 응답을 했지만, ASP.NET과 관련된 파일은 ASPNET_ISAPI.dll이 담당하게 된다는 것입니다. 우리의 관심사는 asp가 아닌 aspx(ASP.NET)이므로, 여기서는 ASPNET_ISAPI.dll이 요청을 받을 경우 어떠한 처리를 이어가는지 알아보도록 하겠습니다. 다음 그림을 주목해 주세요 ^^
ASP.NET 관련 파일(aspx, asmx 등)에 대한 요청이 있는 경우, ASPNET_ISAPI.dll은 ASP.NET Worker 프로세스를 시작하면서, 요청을 ASP.NET 엔진 쪽으로 넘기게 됩니다. 그러한 .NET 요청은 .NET의 CLR을 기반으로 하여 구동이 되어야 하기에 aspnet_wp.exe 쪽으로 그 처리가 넘어오게 되는 것이죠. 이렇게 함으로써, 접수된 요청은 ASP.NET Runtime을 시작으로 하여 실제적인 처리가 이루어지게 됩니다. (사실, 구체적으로 들어가자면 ISAPI에서 CLR로 들어서면서 내부적으로 처리되는 작업이 더 있습니다만, 여기서는 이 정도의 설명만으로도 충분할 듯 합니다. 구체적인 자료를 원하시는 분은 다음 링크를 참고해 보세요 ^^
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/dngrfTheASPNETHTTPRuntime.asp
(히힛. 위에 있던 링크와 동일한 링크 맞습니다... 눈치도 빠르셔~ ^^;)
ASP.NET 요청의 실제적인 처리는 위에서 언급했듯이 HttpRuntime을 서두로 하여 시작되는데요. 이제는 여기서부터의 과정을 살펴보도록 하겠습니다.
전체적인 내부처리 흐름인 HTTP 파이프라인(pipeline)은 HttpRuntime을 선두로 하여 시작됩니다. 이는 다음 그림과 같은 흐름으로 진행이 됩니다. 이 그림은 고급 프로그래머로 가기 위해서는 반드시 기억해 둘 필요가 있는 그림이 아닌가 합니다.(헛? 그렇다면, 태오는 고급 프로그래머??? -_-;;; 그럴리가요. 저도 이 그림을 외우고 있지는 못한걸요)
제일 첫 번째 단계로 놓여져 있는 HttpRuntime은 요청을 처리하는데 도움을 주는 수많은 내부 개체들을 초기화하는 역할을 합니다. 그러한 개체에는 Cache 관리자(Cache 개체)와 소스 파일이 변경되었는 지를 감지하는데 사용되는 내부 파일 시스템 모니터 같은 것들이 있습니다. 또한, HttpRuntime은 요청에 대한 컨텍스트(Context)를 만들고, 이를 현재 요청에 대한 HTTP 정보들로 채웁니다. 그림에서 보이는 것처럼, 이 컨텍스트는 HttpContext의 인스턴스로서 노출됩니다. 그리고, 이 컨텍스트는 파이프라인 내내 살아 있어서 언제든 컨텍스트 정보를 얻기 위해서 접근이 가능합니다.
위의 과정을 통해서 HttpRuntime이 초기화되고 나면, 그 다음에는 요청을 실행하기 위한 어플리케이션 개체를 찾게 됩니다(참고로, Global.asax의 내부 클래스도 HttpApplication입니다). HttpApplication를 찾기 위해서 사용되는 친구는 HttpApplicationFactory 인데요. 이 친구는 위의 그림에는 표기되어 있지 않지만, 요청을 처리하기 위한 HttpApplication 개체를 찾아서 반환하는 역할을 합니다. 즉, HttpApplication의 풀(Pool)을 관리하면서, 노는 HttpApplication 개체가 있으면 그 녀석을 반환하고, 노는 녀석이 없으면 새로이 HttpApplication 개체를 만들어서 반환하는 역할을 수행한다는 것이죠. 그 뿐만이 아닙니다. HttpApplicationFactory는 제일 첫 번째 요청이 들어올 경우에는, 어플리케이션의 형식(type)에 대한 정보를 추출해서 어플리케이션 상태(State)를 만들고, Application_OnStart 이벤트를 발생시키는 역할도 합니다(사실은 이 작업이 HttpApplication 개체를 찾는 작업보다 우선적으로 수행됩니다)
이러한 과정을 거쳐서 요청의 처리가 HttpApplication 개체에게 까지 넘어오게 되었습니다. 그러면, HttpApplication는 어떠한 역할을 하는 것일까요? 궁금하죠? 그렇다면, 알려드리겠습니다. 우선 이 친구는 현재 웹 어플리케이션에 등록된 모든 HTTP 모듈들(HttpModule)에게 요청을 전-처리할 수 있는 기회를 줍니다. 등록되어 있는 모든 전-처리기들이 동작하고 난 다음에는, 처리 과정의 마지막 단계로서, 어떤 처리기(hander)가 요청을 처리하는데 제일 적합한 지를 찾아보기 시작하죠. 이 과정은 요청된 파일의 확장자를 기반으로 하여 구분합니다. 즉, 확장자가 aspx면 그에 알맞은 처리기를 찾는 것이고, 확장자가 asmx라면 역시나 그에 맞는 처리기를 찾을 것입니다. 그러한 매핑은 기본적으로는 machine.config에 이미 설정되어 있는데요. 여러분은 이를 web.config에서 재 정의할 수도 있습니다.
조금 어렵나요? 그렇다면, 요청이 HttpApplication 쪽으로 넘어온 다음의 실행 과정만을 다시금 살펴보도록 하겠습니다. 그 부분이 개발자의 입장에서는 실질적인 ASP.NET 처리로 인식되곤 하는 부분이니까요. 사실, 현재 강좌 다음으로 이어지는 강좌가 바로 HttpModule 개발강좌이고, 이번 강좌를 준비한 이유도 실은 HttpModule 프로그램을 소개하려고 작성한 것이거든요. 해서, ASP.NET HTTP 런타임의 실행 아키텍처 중 이들과 직접적으로 관련된 부분을 좀 더 상세히 살펴보려 하는 것입니다. 아래 그림은 위에서 설명한 복잡한 부분은 모두 빼고, 이후에 알아 볼 HttpModule과 HttpHandler을 중심으로 그려진 그림입니다(복잡한 부분은 뺐다고 했음에도 조금은 복잡해 보일 수도 있으니 심약자는 주의바랍니다 ^^;).
그림에서 보이는 것처럼 HttpApplication 안에는 수많은 HttpModule들이 존재하고 있고, 각각의 접수된 ASP.NET 요청들은 그러한 모듈들을 거치고 난 다음에야 실질적으로 페이지 요청을 처리하는 HttpHandler 쪽으로 넘어가게 됩니다. 사실, 개발자 입장에서는 이 사실만을 알고 있어도 충분합니다. 즉, ASP.NET 요청이 처리될 경우 모든 요청은 HttpModule을 거치고, 그 후에야 실제 페이지를 실행하는 HttpHandler를 거치게 된다는 사실을 말입니다. 그 이전 단계(HttpRuntime이나 HttpContext)는 사실상 눈에 직접적으로 보여지는 부분도 아니고, 개념적인 부분이라 사실 아무리 설명을 들어도 피부에 크게 와 닿지 않곤 하니까요(^^;).
ASP.NET 런타임은 이러한 내부 처리 흐름을 가지고 있으며, 항상 이러한 과정에 따라서 .NET 요청을 처리합니다. 하지만, ASP.NET 런타임은 이러한 처리 흐름 중간에 개발자들이 끼어들어 자신만의 작업을 처리할 수 있게 하는 실행 어플리케이션 런타임도 제공하고 있습니다. 일종의 후킹(Hookimg)을 가능하게 한다는 것이죠. 그렇게 할 수 있는 대표적인 것으로 HttpModuel과 HttpHandler가 있는데요. 이를 통해서, 개발자들은 ASP.NET 런타임을 기반으로 하여 자유롭게 어플리케이션을 확장할 수 있는 것입니다. 즉, 기존 ASP.NET의 실행 모듈을 없애고 자신이 구축한 모듈로 바꿀 수도 있고, 새로운 모듈을 ASP.NET 런타임의 구동 안에 끼워 넣을 수도 있다는 것이죠.
웹의 처리 방식은 모든 종류의 인터넷 요청(일반적으로 웹 페이지)에 대한 응답으로 이루어지는 것이기에, ASP.NET 런타임은 또한 각각의 페이지 요청 동안에 내부적으로 동작하는 모든 은밀한 개체들이라고도 볼 수 있습니다. 이들이 바로 위에서 설명한 HttpRuntime, HttpApplication, HttpContext, HttpModule, HttpHandler인데요. 이 개체들이 사실상 ASP.NET 런타임의 모든 것이나 크게 다름이 없기에 이들을 ASP.NET 런타임이라고 개념적으로 이야기하곤 하기도 합니다. |
하지만, 이 중 ASP.NET 개발자들이 쉽게(?) 확장이 가능한 것은 HttpModule과 HttpHandler 정도입니다. 그리고, 이들이 이어지는 강좌에서 직접 개발해 볼 것들이기도 하죠.
사실, 첨언하자면, .NET이 나오기 전에는, 이러한 런타임 확장 작업을 하려면 C/C++을 이용해서 ISAPI(Internet Services Application Programming Interface) 프로그래밍을 해야만 했습니다. 혹시 태오 사이트를 예전부터 오셨던 분들은 강좌로 있었던 ISAPI Extension 강좌를 보신 분들도 있었겠네요(태오 사이트는 사실 MFC 사이트로 첫 출발을 했었습니다. 1998년 초에 말이죠)
이제는 .NET 세상이기에 예전처럼 VC++과 같은 다루기 어려운(?) 언어로 이러한 개발을 할 필요가 없어졌습니다. .NET 프레임워크와 .NET 언어를 이용하면 훨씬 간단하게 향상된 기능들을 구현할 수가 있으니 말입니다. 물론, 그렇다 하더라도 이번 강좌에서 함께 할 이야기들이 쉬운 수준의 것이라고 말하기는 어려울 듯 합니다. 지금까지는 ASP.NET이 제공하는 재미난 기능들을 이용했다면, 이번에 하려는 것은 ASP.NET의 내부 안 쪽에서 구동되는, 쉽게 건드릴 수 없는 부분을 다루려 하는 것이니까요.
즉, 페이지가 실행될 때 어떤 기능들을 처리하고자 하는 것이 아니라(지금까지의 강좌는 주로 이와 관계된 것이었습니다), 실제적인 페이지의 처리가 수행되기 전에 ASP.NET 런타임이 구동되는 시점 즈음에서 어떤 특별한 처리를 수행하고자 할 경우를 이야기 하고자 하는 것입니다.
'.net' 카테고리의 다른 글
웹에서의 비동기 호출 : XMLHTTP (0) | 2007.05.03 |
---|---|
HttpModule 구현 및 적용 (0) | 2007.05.03 |
유효성 검사 후 별도 스크립트 실행하기 (0) | 2007.05.03 |
날짜 문자열을 (0) | 2007.05.03 |
Bound Controls (0) | 2007.05.03 |