login register Sysop! about ME  
qrcode
    최초 작성일 :    2000년 05월 15일
  최종 수정일 :    2001년 07월 20일
  작성자 :    Taeyo
  편집자 :    Taeyo (김 태영)
  읽음수 :    119,389

강좌 목록으로 돌아가기

필자의 잡담~

이번 강좌는 월간 마이크로 소프트웨어에 투고한 기사로써, 사용자의 사이트 접속통계를 내는 간단한 통계 프로그램입니다...  ^_____^ 이 기사는 2000년 4월호 마소 쥬니어에 실린 기사임을 밝힙니다요~~

인터넷이 일상에 자연스럽게 들어와 있는 지금, 자신의 웹사이트에 얼마나 많은 사용자들이 방문하며, 또한 그들이 어느 시간대에 어떤 분포를 가지고 접속하고 있는지 궁금할 것입니다. ASP를 이용한 웹사이트 카운터 기능을 구현해 자신의 사이트를 스스로 진단해 보고자 합니다.

ASP로 운영중인 사이트가 늘어나면서 그만큼 ASP의 인기도 높아지고 있습니다.  도대체 'ASP로 구현이 불가능한 것은 무엇인가?' 라는 의문이 들 정도로 수많은 사이트들이 ASP를 사용해 제작되고 있죠. 물론 ASP만으로는 구현이 불가능한 것들도 있지만, 서버 DLL과 컴포넌트로 보완해 나가며 ASP는 강세를 보이고 있습니다.

ASP로 할 수 있는 여러 가지 매력적인 일 중 Global.asa를 통한 카운터 제작에서 흥미를  찾을 수 있습니다. 사실상 카운터 자체만은 큰 매력을 주지 못하지만(솔직히 필자는 그러함다) 카운터 제작에 중요한 Global.asa를 익힐 수 있는 좋은 예가 됩니다.

Global.asa은 사이트 전체에 대한 어떤 제어를 해야 할 경우 상당히 유용하게 사용될 수 있으며 , 이제부터 우리가 같이 해나갈. '웹사이트의 접속자 통계'와 같은 것을 제작할 경우에 가치가  드러날 것입니다. <화면 1>은 앞으로 제작하게 될 접속통계의 예를 보여주고 있으며 <화면2>는 접속 통계를 테이블 형태로 분석하고 있습니다.

<화면 1> Gfew의 접속 통계 

<화면 2> 사이트 주소의 접속 통계 테이블 레코드

참고로 ASP를 이용한 카운터는 서적이나 연재에서 많이 다뤄졌지만 우리는 카운터 제작이 아닌 Global.asa라는 파일에 익숙해지는 쪽으로 비중을 둬 진행하려 합니다.

집중 탐구! Global.asa

Global.asa은 상당히 독특한 파일입니다. 하나의 웹사이트(웹애플리케이션) 전반에 걸쳐 적용되며, 4가지의 이벤트 메쏘드가 존재하지만 임의로 호출할 수 없습니다. 그리고, 반드시 웹 애플리케이션 루트에 존재해야 합니다. 만약 다른 곳에 위치할 경우 이 파일은 전혀 동작하지 않으므로 루트에 존재하지 않는 Global.asa는 전혀 의미가 없는 파일이라 할 수 있죠. 일단 Global.asa가 뭔가 중요한 역할을 수행한다는 느낌이 오셨죠?

하지만 사실 이 파일은 있어도 그만 없어도 그만인 파일입니다(놀림을 당하는 느낌?). 왜냐하면 여러분은 ASP를 공부하기 위해서 Internet Information Server(이하 IIS) 상에서 가상 디렉토리(홈 디렉토리)를 지정하고, 여러 ASP 코드들을 테스트했겠죠. 그러나 여러분이 Global.asa라는 파일을 신경 쓰지 않아도 테스트에 아무런 문제가 없었죠. 이것은 Global.asa라는 파일 자체가 존재하지 않아도 여러분의 웹애플리케이션에는 아무런 문제도 발생하지 않는다는 것을 의미하며, 또한 이 파일은 일종의 옵션적인 파일이라는 것을 이야기합니다.

하지만, Global.asa를 여러분이 사용하겠다고 결정하고, 생성시켜주면 또 다른 세상이 펼쳐집니다. 웹애플리케이션 상에서 일종의 통과절차가 되는 거죠. 다시 설명하자면 <그림 1>처럼 여러분의 웹사이트를 둘러싸고 있는 마 치 일종의 캡슐막처럼 존재합니다.(마치!라는 것을 기억하세요.. 마치 논리적으로 그렇다는 것이랍니다)  따라서 사이트로 접근하는 사용자들이나 그 사이트를 빠져나가는 사용자들이 반드시 거쳐가야 하는 일종의 '피해갈 수 없는 길'이라는 거죠. 이번 기회에 간단한 시나리오를 통해 Global.asa의 역할과 필요성에 대해 알아보도록 하죠

누드 공개! Global.asa의 코드를 벗겨라

Global.asa는 모두 4개의 이벤트 메쏘드로 구성돼 있으며 각각의 특정 이벤트가 일어나면  자동으로 메쏘드가 발생하지만 임의로 호출할 수는 없습니다. 아래의 소스는 일반적인 Global.asa의 코드를 보여 줍니다. 

<SCRIPT LANGUAGE=VBScript RUNAT=Server>
    Sub Application_OnStart 
    End sub

    Sub Session_OnStart 
    End sub

    Sub Session_OnEnd
    End sub 

    Sub Application_OnEnd
    End sub
</SCRIPT>

Application_OnStart라는 이벤트는 웹애플리케이션이 서비스를 시작하고  첫 번째 사용자가 입장할 경우 발생하며, Application_OnEnd는 현재의 사이트에서 가장 마지막 사용자가 빠져나간 후 그 사용자의 세션이 끝날 때 발생합니다. Session_OnStart 이벤트의 경우에는 모든 사용자 개개인이 사이트에 입장할 때마다  발생하게 되며, 이 때 모든 사용자는 자신도 모르게 서버로부터 SessionID를 부여받게 됩니다. 또한 서버는 SessionID로 각각의 사용자를 구분하게 되며, SessionID는 사용자의 세션이 끊기기 전까지는 계속 유지가 되지만 재발급 되지는 않습니다.

IIS는 기본적으로 20분의 세션 유지 시간을 가지고 있어 20분 동안 서버에 아무런 요청을 하지 않으면 자동으로 세션은 사라지고 그 때에 Session_OnEnd 이벤트가 발생하게 됩니다. 특히 세션은 사용자 단위로 생성하므로 사이트에 입장, 퇴장하는 모든 사용자들은 자신만의 Session_OnStart, Session_OnEnd 이벤트를 발생하게 되는 거죠(<그림 2>).

이벤트 활약상을 헤쳐본다

'사용자가 사이트를 빠져나가면 Session_OnEnd 이벤트는 발생하는가?'라는 질문에 여러분은 어떻게 답하겠습니까? 이것에 대한 대답은 '아니다' 입니다. 많은 사람들이 착각하고 있는 것 중 하나가 바로 사용자가 브라우저를 종료하면 Session_OnEnd가 일어난다고 생각하는 것이죠. 그러나 서버 입장에서 생각하면 쉽게 이해할 수 있습니다. 서버는 클라이언트가 브라우저를 종료했는지, 아니면 다른 사이트로 이동했는지를 알아낼 방법이 없습니다. 클라이언트의 존재 여부는 사용자가 ASP나 HTML 페이지를 서버에 요청하느냐, 하지 않느냐에 달려있습니다. 따라서 페이지 요청이 있을 경우에는 요청한 페이지를 돌려주며, '아∼, 이 친구는 아직 우리 사이트에 머물고 있구나'라고 판단합니다.

다시 설명하자면 서버의 세션 타임아웃에 해답이 있습니다. 20분의 기본적인 타임아웃 시간 동안 다른 요청이 없으면 우리 사이트를 떠났거나, 브라우저를 종료했다고 판단하고 사용자의 Session_OnEnd 이벤트를 발생시킵니다.

<그림 3>는 Global.asa의 적용

<그림 3>는 Global.asa를 적용한 사이트가 웹서비스를 시작한 뒤, 이벤트가 발생하는 시점을 이해하기 쉽도록 나타내고 있습니다. 여러분은 Global.asa 내의 4가지 이벤트가 동작하는 시점을 더욱 쉽게 파악할 수가 있을텐데, <그림3>을 통해 살펴보도록 하죠.

먼저, 웹서비스가 Start된 다음, 12시에 방문자A가 사이트에 입장한다고 그림과 같이 가정하지요. 이 때, 이 방문자A는 Application_OnStart 이벤트를 발생시키겠죠. 웹서비스 후 가장 처음 방문자니까요. 그리고, 방문자A는 자신의 Session_OnStart 이벤트도 발생시킬 것입니다. 약간의 시간이 흐른 후 12시 5분. 방문자B는 갑작스런(?) 방문을 시도합니다. 이 사용자는 어떤 이벤트를 발생시킬까요? 자신의 Session_OnStart 이벤트겠죠.  그러나 Application_OnStart는 발생시키지 않습니다. 5분 전에 방문자A가 이미 애플리케이션을 시작시켜 애플리케이션은 동작 상태에 있으니깐요.

모두들 열심히 우리 사이트에서 서핑을 하다가 방문자A가 자신의 볼 일(?)을 마치고 14시에 사이트를 빠져나간다고 가정합시다. 여기서 나갔다는 의미는 그 시간에 우리 사이트에 마지막으로 특정 ASP 페이지의 요청을 했다는 것을 의미합니다.(꼭 기억하세요) 방문자A는 다른 사이트로 이동했을 수도 있고, 브라우저를 종료했을 수도 있지만 서버는 그것을 알 수 없습니다.

하지만 14시에 그 사용자가 사이트를 나갔다고 하더라도 서버는 아직 그 사용자가 사이트 내에 존재한다고 일단 가정합니다. 그러다가 14시 20분이 되면 서버는 14시 이후 서버에 그 어떠한 요청도 없는 방문자 A를 우리 사이트 내에 더 이상 존재하지 않는 사용자라고 판단하고 그 친구의 Session_OnEnd를 발생시킵니다.

14시 30분 방문자B도 투덜거리며 우리 사이트를 빠져나가는 순간(즉, 마지막 페이지의 요청이 있는 순간) 방문자의 Session_OnEnd이 일어날까요? 물론, 아닙니다. 방문자A의 경우와 마찬가지로 방문자B도 그가 우리의 사이트를 빠져나간 뒤 20분(기본 지정 시간)이 지난 14시 50분이 돼야 이벤트가 발생하겠죠. 그리고, 방문자B는 현재 사이트의 마지막 사용자이므로 Session_OnEnd를 발생시키자마자 Application_OnEnd 이벤트도 발생합니다. Application_OnEnd 이벤트는 사이트 내에서의 마지막 세션이 끊기는 경우 발생하니깐요.

만일, 방문자B가 나간 뒤(현재 14시 30분), 19분 59초가 지난 상태에서 다시 들어오면 어떻게 될까('다시 들어온다'는 의미는 브라우저를 종료하지 않고 다른 사이트로 갔다가 되돌아오는 경우를 의미하며 브라우저를 종료하고, 다시 새 브라우저로 접근한다면 전혀 새로운 사용자로 취급됩니다)?

그렇게 되면 방문자B의 세션은 계속 유지되며, 이 사용자는 우리 사이트에서 빠져나간 적이 없던 것처럼 생각되겠죠. 아직 20분은 지나지 않았고, 그 20분이 채워지기 전에 방문자B는 서버에게 웹페이지를 요청했으니 서버는 지금까지 '이 사용자는 사이트 내에 있었다'고 생각하죠.  그리고 앞으로도 최소한 20분간 세션은 종료되지 않으며, 애플리케이션도 종료되지 않습니다. 애플리케이션은 마지막 세션이 끝나는 시점에서 같이 끝나죠.

 세션은 골칫거리?

사실이 그렇습니다. 세션을 편리하다고 느끼고, 그 사용을 장려(?)하는 분들은 조금 주의해야 합니다. 세션이 상당히 유용하고, 다루기 편리할 뿐 아니라 보안성이 높다 하더라도 상당히 머리를 아프게 하는 여러 가지 버그들이 존재합니다. 우리가 알고 있는 대로 100% 완벽하게 움직이지는 않습니다. 예를 들면, 새 창을 띄웠을 경우 세션이 사라지는 경우가 대표적이며, 간혹 브라우저를 종료하고, 새로운 브라우저로 다시 접속했을 때도 이전 세션이 유지 되는 버그들이 있습니다. 또한, 세션 사용은 서버 측에 부하를 주기에 사용을 최소화하는 것이 좋으며 아주 필요한 경우가 아니라면, 가능하다면 사용을 자제할 것을 권합니다.

바로 이런 시점들을 체크해 주고, 개발자가 그 시점에 원하는 작업을 할 수 있도록 도와주는 파일이 Global.asa입니다. 우리는 단지 그 필요한 시점의 이벤트 함수에다가 코딩해주면 되죠. 요약하자면 Global.asa라는 파일은 파일 내부의 4개의 이벤트를 통해 특정한 시점에 자동으로 이벤트를 발생시켜 우리가 해당 시점에 서버에서 원하는 처리를 가능하도록 도와주는 파일이라 할 수 있습니다.

 본격적으로 Global.asa를 사용해보자

Global.asa이 하는 역할과 그 구성을 어느 정도 알게 됐습니다. 이제 개념을 파악했으니 실제 예를 통해 특별한 친구와 조금 더 친해져 보도록 합시다. 준비됐나요? 사용상 주의해야 할 점은 Global.asa는 조금이라도 코드를 잘못 작성하면 사이트 내의 어떠한 페이지로도 접근이 불가능하게 됩니다. 사이트의 내부로 들어가는 입구와 같은 파일이기에 문제가 생기면 당연히 사이트 내에 어떠한 파일로도 접근이 이루어질 수가 없게 되죠.

디버깅도 쉬운 편이 아니기에 에러가 발생할 경우는 차근히 코드를 살펴보며 확인해야 합니다. 그러니, 사용상 각별한 주의가 필요합니다. 다음과 같은 Global.asa 코드를 작성하고 테스트 해 보도록 합시다. 

<SCRIPT LANGUAGE=VBScript RUNAT=Server>
    Sub Application_OnStart
        Application.lock
        Application("visit") = 0
        Application.unlock
    End sub 

    Sub Session_OnStart 
        Application.lock
        Application("visit") = Application("visit") + 1
        Application.unlock
    End sub 

    Sub Session_OnEnd
    End sub 

    Sub Application_OnEnd
    End sub 
</SCRIPT>

코드 작성이 완료됐으면 일단 여러분의 가상 디렉토리 Root에 위치시킵니다. 그러나 가능하다면 홈 디렉토리에 위치시키고 테스트를 하세요. 만약 가상 디렉토리에서 테스트하는 경우 디렉토리가 웹애플리케이션으로 지정돼있지 않으면 Global.asa는 전혀 동작하지 않습니다. 에러도 없고, 전혀 무의미한 파일로 취급되는 거죠. 그리고,  다음과 같은 default.asp 페이지를 만들어 역시 같은 곳에 위치시킵니다. 필자의 경우 홈 디렉토리(wwwroot)에 위치시켰습니다(<화면3>).

default.asp

<HTML><BODY>
사이트 전체 방문회수:<%= application("visit")%> </BODY></HTML>

<화면 3> Global.asa의 위치 & default.asp 


주의 

Global.asa 파일을 새로 만들거나, 수정하고 나면 반드시 웹서버를 재시작해야 합니다. 그래야만 수정된 Global.asa가 새롭게 적용되죠. 윈도우 98에서는 웹서버를 재시작으로 수정된 Global.asa가 적용되지 않는 경우도 있으니 그때는 리부팅을 하면 제대로 수정 사항이 반영됩니다.

서버를 다시 가동하면 브라우저를 열고 로컬 경로가 아닌 URL을 통해 default.asp라는 파일로 접근합니다(ASP 페이지를 구동하기 위해서는 로컬 경로로 접근 금지). Global.asa가 제대로 적용됐다면 <화면4>와 같은 결과를 볼 수 있습니다.

<화면 4> 카운터의 결과화면



<화면4>와 같은 결과를 보여주기 위해 서버는 조금 분주하게 동작합니다. 그럼, 서버의 Global.asa가 동작한 내용을 살펴보죠. 여러분이 default.asp 페이지로 접근하면 웹사이트가 작동한 뒤의 첫 방문이므로,  Application_OnStart 이벤트가 동작하며, 그 이벤트는 여러분 사이트에 Application("visit")라는 변수를 만들고, 그 값을 0으로 세팅합니다. 그리고, Session_OnStart 이벤트가 발생해 이 값을 1 증가시킵니다.

그 결과 현재 Application("visit")의 값은 1이 됩니다. 결과적으로 두 개의 이벤트가 발생했죠. 이제 이 카운터 값을 하나 더 증가시키려면 어떻게 할까요? 만일, 카운터 값을 증가시키기 위해서 '새로 고침' 버튼을 눌렀다면 다시 생각해해야 합니다. 카운터 값이 증가하려면 Session_OnStart 이벤트가 발생해야만 하기 때문이죠.

Session_OnStart 라는 이벤트는 새로운 사용자가 사이트로 들어올 경우 발생하고 이미 사이트에 접속해서 세션을 할당받은 사용자는 더 이상 이벤트를 발생시킬 수 없습니다. 따라서 카운터를 1 증가시키려면 새로운 세션이 접근해 들어와야만 합니다. 브라우저를 종료하고 새로운 브라우저를 열어 다시 default.asp 페이지로 접근합니다.  그렇다면 여러분은 새로운 사용자로 취급돼 서버에 Session_OnStart 이벤트를 발생시키고, 카운터는 2가 됩니다. 

  질문) 잠깐! 잠깐! 이상합니다. 그렇게 해도 2가 아니라 여전히 1이어야 하지 않나요? 
           Appication_OnStart가 다시 동작하면서 0에서 시작하니까요.

  답) 그건 말이죠. 브라우저를 종료했다고 Session_OnEnd 이벤트가 발생하지 않으므로 Applicaton_
       OnEnd 이벤트도 발생할 리가 없죠. 현재 사이트에서  하나의 세션은 20분 동안 연결중입니다.
      서버는 접속자가 있다고 판단하고, 새로운 브라우저로 연결을 하면 새로운 사용자 접속을 하게되고,
      Session_OnStart만이 동작하므로 총 카운터 값은 2가 됩니다. 

애플리케이션변수와 세션변수 :

애플리케이션변수는 웹애플리케이션 전체에 걸쳐 사용이 가능한 일종의 전역변수이며, 사이트 내 모든 페이지에서 값을 변경할 수 있는 일종의 공유변수입니다. 반면, 세션변수는 웹애플리케이션 전체에 걸쳐 사용이 가능한 일종의 전역변수라는 부분에 대해서는 애플리케이션 변수와 비슷하지만 사용자 개개인별로 값이 존재하므로 자신만이 변경할 수 있는 변수입니다. 즉, 애플리케이션변수는 모든 사용자가 하나의 변수를 공유할 수 있는 공간이지만 세션변수는 공유할 수 없는 자신만의 값을 담아두는 개별 공간으로 존재한다.

Global.asa를 이해하고 나면 사이트 전체를 바라보는 눈도 넓어지게 됩니다. 모든 웹서버에는 기본 문서가 존재합니다. 윈도우 NT의 IIS 경우 기본 문서는 default.htm으로 지정돼 있어 사용자들이 사이트를 접속하면 자동으로 default.htm을 사용자의 브라우저에 건네줍니다. 그러나 웹서버에 따라 이러한 기본 문서는 다릅니다. 경우에 따라 index.html, home.html 등으로 달라질 수 있습니다. 물론, 기본 문서의 이름은 서버에서 다른 이름으로 바꿔줄 수도 있죠.

만일 여러분 사이트의 기본 문서를 main.htm으로 지정하고 싶다면 웹서버 상에서 세팅을 바꾸면 가능하지만, Global.asa를 배우고 있으니 Global.asa를 사용하기로 하죠. 먼저 Global.asa의 Session_OnStart 이벤트에 다음과 같은 한 줄의 코딩을 합니다.

Response.Redirect "main.htm"

모든 사용자는 사이트에 접속하는 순간, 이 Redirect 메쏘드에 의해서 무조건 main.htm으로 이동하게 됩니다. 

!!! Global.asa 이벤트는 ASP 페이지가 요청될 경우 호출

사용자가 사이트에 접속해 htm 페이지를 요청해도 Global.asa의 Session_OnStart  이벤트는 동작하지 않습니다. 그러므로 Session_OnStart에서의 리다이렉트(Redirect)를 통한 페이지 이동은 사이트에 처음 접속할 경우 반드시 발생하는 것은 아닙니다.  사이트 내에서 처음 ASP 페이지를 호출할 경우에 발생하게 됩니다.

예를 들면, 사이트의 기본 문서가 default.htm으로 지정돼 있고, 우리가 Session_OnStart 이벤트에 리다이렉트 'main.htm'을 지정했다고 가정하죠. 사용자가 http://www.A.com으로 여러분의 사이트를 접속할 경우 여러분은 자동으로 main.htm 페이지가 로딩될 것이라고 생각할 수 있지만,   사실은 그렇지 않습니다. 사이트에 처음 입장하더라도 htm 페이지가 요구되면 Global.asa는 동작하지 않으며 default.htm이 사용자에게 로딩됩니다. 만일, 여러분이 default.asp 페이지를 기본문서로 지정한다면 그 때에는 제대로 동작하겠죠.

Global.asa 업그레이드하기

현재의 소스를 그대로 카운터로 사용하기에는 문제가 조금 있습니다. 현재로서는 웹서비스가 재 시작할 때마다 모든 카운트를 날려버리고,  카운트는 0에서 시작하게 됩니다. 이 부분을 해결하기 위해서는 카운터 수를 저장할 어떤 장소가 필요한 데, 그 장소로 대부분 텍스트 파일이 자주 사용됩니다.  ASP에서는 FileSystemObject(이하 FSO) 라는 스크립팅 객체를 통해 서버 측에서  파일을 아주 쉽게 제어할 수가 있죠. 그러면, 지금부터 Global.asa를 FSO를 사용해 이러한 문제를 해결해 보도록 하죠.

** FSO를 이용한 Global.asa **

<SCRIPT LANGUAGE="VBScript" RUNAT="Server">
    Sub Application_OnStart
        Application("Filepath") = Server.MapPath(".")+"/visit.txt"
        Set FileObject = Server.CreateObject("Scripting.FileSystemObject")
        Set Out = FileObject.OpenTextFile(Application("Filepath"),1)

        Application("visit")=Out.ReadLine
    End Sub

    Sub Application_OnEnd
        Set FileObject = Server.CreateObject("Scripting.FileSystemObject")
        Set Out = FileObject.CreateTextFile(Application("Filepath"))

        Application.Lock
        Out.WriteLine(Application("visit"))
        Application.UnLock
    End sub

    Sub Session_OnEnd

    End Sub

    Sub Session_OnStart
        Application("visit")= Application("visit")+1

        If Application("visit") MOD 10 = 0 Then
            Set FileObject = Server.CreateObject("Scripting.FileSystemObject")
            Set Out = FileObject.CreateTextFile(Application("Filepath"))

            Application.lock
            Out.WriteLine(Application("visit"))
            Application.unlock
        End If
    End Sub
</SCRIPT>

수정, 보강된 Global.asa 소스를 사용하기 위해서는 먼저 카운터를 저장할 파일인 visit.txt 파일을 만들어 둬야합니다. 물론 그 부분도 FSO를 통해 Global.asa에서 해결할 수 있지만, Global.asa에는 조금이라도 적은 코드를 사용하는 것이 유리하므로 visit.txt 파일은 직접 여러분이 만들어 주도록 하죠. 그리고, 해당 파일을 열어서 그 안에는 0이라는 숫자를 쓰고 저장합시다.(<화면5>).

<화면 5> Global.asa 파일의 위치와 visit.txt

사실, 현재의 소스를 이해하기 위해서는 FSO를 어느 정도 다룰 수 있는 기본 지식이 있어야 합니다. 그리고 애플리케이션, 세션 객체에 대한 지식도 필요하구요. 

MSDN사이트 : http://www.microsoft.com/korea/vbscript/ (<화면6>) 

<화면 6> FileSystemObject 관련 MS 사이트


업그레이드 소스 분석

업그레이드한 Global.asa 파일을 살펴보도록 하죠. 우리가 수정한 Global.asa의 Application_OnStart 이벤트에서는 기존에 저장된 카운터가 있는 visit.txt 파일을 열어서 저장된 값을 가져옵니다. FSO 객체의 인스턴스인 FileObject를 만들고, 지정한 파일인 visit.txt 파일의 핸들을 OpenTextFile 메쏘드를 통해 얻어오고 있음을 볼 수 있습니다.

Set Out =FileObject.OpenTextFile(Application("Filepath"),1)가 바로 그것인데, 여기서 Application("Filepath")은 visit.txt가 있는 물리적인 전체 경로를 나타내 줘야 합니다. 경로를 'C:\inetpub\wwwroot\....\visit.txt'와 같은 식으로 적어줘도 되지만,  개발자마다 visit.txt 파일이 있는 경로가 모두 틀릴 것이므로 Server.MapPath() 메쏘드를 사용해서 현재 Global.asa가 위치하는 그 물리적인 경로를 얻어오도록 합니다.

Server.MapPath(".")는 현재 이 메쏘드를 사용하는 파일이 존재하는 물리적인 경로를 돌려줍니다.

OpenTextFile() 메쏘드의 두 번째 인자는 파일 모드를 결정합니다.  또한 1은 읽기 전용 모드(ForReading), 8은 쓰기 모드(ForAppending)입니다. 

지금까지의 내용을 정리하면 Application_OnStart 이벤트는 visit.txt 파일을 읽기 모드로 열어서 그 파일에 저장된 카운터 값을 가져와 Application("visit")라는 변수에 저장을 합니다. 그리고 Application_OnEnd에서는 현재까지의 카운터를 visit.txt 파일에 저장하는 것을 볼 수 있습니다. 이 부분에서 CreateTextFile(Application("Filepath"))이라는 메쏘드를 사용했는데,  FSO의 CreateTextFile 메쏘드는 서버 상에 지정한 파일을 새로이 생성하는 메쏘드입니다.

기본적으로 같은 이름의 파일이 존재한다면 기존의 파일 위에 덮어쓰기(Overwrite)를 하게 됩니다. 물론, 기존의 파일을 열어서(Open TextFile) 기존의 값을 바꿔줘도 상관은 없겠지만, 좀더 확실한 방법을 선택해야겠죠.

이 두 가지의 이벤트 메쏘드를 보강함으로써, 카운터는 매번 웹애플리케이션이 종료할 때마다 visit.txt 파일에 그 때까지의 카운터가 저장되고, 웹애플리케이션이 다시 시작할 때마다  기존 카운터 값을 불러와 사용하게 됩니다. <화면 7>은 <리스트4>을 사용한 필자 사이트의 카운터 모습입니다.

<화면 7> taeyo site의 카운터 적용모습


  질문) Session_OnStart 이벤트 안에 있는 If문의 의미는 무엇인가요? 

  답) If문의 의미는 카운터가 10으로 나누어져서 떨어질 때마다 visit.txt 파일을 새로이 만들며
       현재까지의 카운터를 저장하는 내용이다. 

  질문) 이러한 부분이 왜 필요한가요? 

  답) 서버의 비정상적인 종료에 대비하는 코드입니다.  예를 들어 웹서비스가 가동을 시작하고, 반년동안 
       한번도 서버는 쉬지않고 열심히 밤이고 낮이고 일을 했다고 가정하죠. 사이트는 많은 사람들이 계속
       방문했고, 그 카운터는 1,324,736이나 돼버렸죠. 그러던 어느 날 갑자기 서버에  문제가 생겨 비정상
       적으로 종료가 돼버렸습니다. 부랴부랴 서버를 병원으로 옮기고 잘 보살펴서, 서버는 곧 완쾌됐고,
       다시 일을 시작하려고 사이트를 열었죠. 여러분은 카운터가 1,324,736에서 시작할 것이라고 생각했
       겠지만 안타깝게도 카운터는 0(혹은 아예 데이터가 사라져서 아무 값도 없을 수도 없죠).
       사이트의 웹애플리케이션이 시작한 뒤, 단 한 번도 Application_OnEnd는 동작하지 않았기에 
       visit.txt라는 파일에 현재까지의 카운터를 저장할 일이 없었기 때문입니다. 이러한 현상을 보완하기
       위한 것이 Session_OnStart에서의 If문입니다.  10번마다 저장하도록 If문을 설정한 이유는 서버의
       부하를 조금이라도 줄여보려는 노력이란 걸 알겠죠?

Global.asa와 DB와의 만남

Global.asa의 동작을 이해하고, 직접 다뤄보니 쓰임새가 많다는 것을 깨달았을 것입니다. 이제 기본기를 익혔다면 실전으로 들어가죠. 다음 시간에는 Global.asa 페이지와 데이터베이스를 연동해 사이트의 방문자 접속 통계를 파악하는 간단한 예제를 다뤄 보려합니다. 다음 시간 동안 Global.asa에 대해 충분히 이해하시길 바랍니다. 

  Global.asa 사용시 주의할 점

  - 웹애플리케이션의 루트에 존재해야 한다.
  - Global.asa 파일 이름을 바꿔 사용할 수 없다.
  - 파일 수정시에는 반드시 웹서버를 재시작 해야한다.
  - ASP 내장 객체를 모두 사용할 수 있는 것은 아니다.

  Session_OnEnd 이벤트는 버그 라이프(?)

Session_OnEnd 이벤트에서 Response.Redirect나, Server.MapPath 등의 메쏘드는 동작하지 않습니다. 사실 Session_OnEnd 이벤트는 Request, Response,Server  객체를 지원하지 않죠. 오직 애플리케이션, 세션 객체만을 지원합니다. 따라서 Server.MapPath()를 사용해 파일 경로를 얻어와 Session_OnEnd 이벤트에서 어떤 처리를 해줄 경우에는 반드시 세션이 끝나기 전에 파일의 경로를 얻어와 애플리케이션변수에 저장해 두는 것이 좋습니다.  그렇지 않고 Session_OnEnd 에서 Server.MapPath를 통해 얻어온 파일의 경로로 작업을 한다면 그 결과를 장담할 수가 없죠.

상당히 엄청난(?) 버그인데요. Session_OnEnd 이벤트는 사실 그 이벤트가 100% 발생할 것이라는 것을 믿을 수가 없습니다. 이 버그는 아직까지 해결되지 않은 알려진 버그중에 하나로서 가능하면 Session_OnEnd에서는 중요한 처리를 하지 말기를 추천합니다. 


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})