관리 메뉴

새로운 시작, GuyV's lIfe sTyle.

닷넷 게시판 만들기 Part 8 - 방문객 카운터 만들어보기 본문

ⓟrogramming/asp.net 게시판

닷넷 게시판 만들기 Part 8 - 방문객 카운터 만들어보기

가이브 2011. 1. 12. 18:12

2010/11/16 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 1
2010/11/18 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 2
2010/12/08 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 3
2010/12/16 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 4
2010/12/16 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 5
2010/12/22 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 6
2011/01/04 - [ⓟrogramming/.net] - 닷넷 게시판 만들기 Part 7

1. 닷넷 개발환경 준비, 테스트
2. 닷넷 알아보기 [6/..]
3. 게시판 글쓰기
4. 게시판 글목록
5. 게시판 글읽기
6. 다듬기

(정리하지 않고 즉석으로 쓰는 이유로, 뒤죽박죽 강의가 되버린듯 하네요. ㅠㅠ)


앞시간에서 메서드를 실제로 만들어보았다. 네임스페이스, 클래스, 메서드는 앞으로 여러분들이 수없이 설계해서 만들어야 하는 것들이다. 게시판 만들 때 역시 사용할 일이 있으니, 꼭 알고 넘어가도록 하자. 복습하는 가장 좋은 방법은, 자신이 직접 "뭘 만들 수 있을지 생각 해보고 키보드로 쳐 보는 것"이다. 완성따윈 하지 않아도 괜찮다. 언젠가는 완성시킬 수 있기 때문이다.

이번 시간에는 예고했듯이, 방문객 카운터를 만들어보도록 하자.

Part 6 에서 MSDN을 뒤적거렸던 내용을 기억하는가? (당시 즐겨찾기를 하지 않았다면 다시 Part 6을 정독하시길 바라며, 즐겨찾기 사이트는 여기를 클릭하자.)

방문객 카운터는, 홈페이지에 몇 명이 방문했었는지를 꾸준하게 기록하는 기능이다.
방문객이 생길 때마다 0명에서 1명으로, 1명에서 2명으로.. 이렇게 숫자가 증가할 것이다.

Part 6에서 다음과 같은 과정으로 볼 수 있다고 했다.

1. 방문객이 왔다.
2. 카운터로 계산된 파일을 연다. (Open)
3. 파일에서 카운트를 읽고(Read), 파일을 닫는다. (Close)
4. 읽은 카운트에서 +1을 한다.
5. 누적된 카운트를 파일에 저장(Open, Save) 후, 닫는다. (Close)

그리고 다음과 같은 디자인도 완성했었다.


 
빨간색 숫자가 실제 방문객 수이다.

그렇다면, 이 방문객의 정보는 어디에 저장되는가? 답을 말한다면, 지금 우리가 웹 서버를 구축한 c:\home 폴더, 즉 웹서버의 폴더 어딘가에 저장이 될 것이다. (물론, 웹서버 폴더와 아무 관련없는 곳에 저장도 가능하다)


여러분들께 죄송하지만, 여기서 또 잠시 중요하고 간략한 이야기를 하고 넘어가야 될 것 같다.
'인터넷'이라고 불리지만, 인터넷 서비스 중 하나인 웹(Web)에 대해서 설명을 하려고 한다. 부디 재밌게 읽어주길 바란다.

필자는 IE8을 자주 이용하지만, 다른 사람들도 IE6 또는 7,8 등.. 그리고 firefox, chrome 등 여러종류의 웹브라우저(Web Browser)를 이용하여 웹(Web)을 탐색한다. 인터넷에 연결되어 있는 상태라면 인터넷 주소(aaa.com 따위)를 이용하게 된다.

지금 이 글을 읽고 있는 웹브라우저의 주소를 보자.

http://

라는게 앞에 붙어있는 것을 볼 수 있다. 웬만하면 생략해도 웹브라우저가 붙여주는 녀석인데, HTTP라는 것은 바로 Web이라는 서비스에서 사용하는 프로토콜(Protocol, 규약)이다.

한 마디로, HTTP(HypertextTransfer Protocol)를 통해 Web을 이용하게 된다. 그것을 쉽고 편리하게 도와주는 것이 웹브라우저이다.

우리가 웹 브라우저로 주소를 치게된다. 웬만해서는 구차하게 aaa.com/home/ggg.html 과 같이 복잡하게 치고 들어가는 것을 원하지 않는다. 대부분 .com .net 등으로 끝나게 된다. 이것이 바로 이 강의에서 열고 있는 127.0.0.1 와 다르지 않다. 여튼, 이렇게 주소를 요청하면 우리가 이전에 IIS(인터넷 서비스 관리자)를 설정했듯이, 해당 서버의 특정 폴더의 특정 파일 단 1개만 열게된다. (우리의 서버에서는 default.aspx를 열고 있지 않는가..)

이것은 HTTP 규약상 네이버,다음,네이트, 어디든 예외가 될 수 없다. 서버에서는 웹브라우저에게 특정폴더의 단 1개의 파일만 전송해준다.


        [나]         ---- www.naver.com ---->       naver.com 
     
        [나]        <---- 달랑 HTML 1개  ----       naver.com 

물론, 달랑 1개 전송하는게 꼭 HTML이라는 법은 없다. hwp파일이 될 수도, mp3 파일이 될 수도 있다. 

웹브라우저가 달랑 1개 받은 파일이 HTML 형식으로 인식하게 되면, 그 HTML파일을 열심히 해석하기 시작한다. 태그를 번역한다고 보면 되겠다. 뒤져보니 이것저것 많다. <img>태그도 있고<script src=xxx> 태그도 있고.. 이렇게 HTML을 해석하니 이미지(gif,jpg..), 플래쉬(swf) 등 또 가져와야 되는 것들이 많다. 해석이 끝나면 또 하나하나 naver.com 에 요청하기 시작한다. 없으면 그게 바로 우리가 말하는 "엑박"이 뜨게 된다.

        [나]        ---- img1.jpg 내놔  ---->       naver.com 
        [나]        ---- img2.jpg 내놔  ---->       naver.com 
        [나]        ---- img_menu1.gif 내놔  ---->       naver.com 
                                    ..
                                    ..
                                    ..

        [나]       <--- 옛다 img1.jpg   -----       naver.com 
        [나]       <--- 옛다 img2.jpg   -----       naver.com 
        [나]       <--- 옛다 img_menu1.gif   -----       naver.com 
                                    ..
                                    ..
                                    ..

그리고 웹브라우저는 다시 요청한 것들을 처음 받은 HTML의 자리에 끼워넣어 문서를 완성하게 되는 것이다. 또한, 이 모든 요청한 것들은 웹브라우저에서 지정된 임시폴더에 저장해 놓는다. 즉, 오른쪽버튼이 막혀서 소스가 안보이니, 이미지 저장이 안되니 하는 것들은 결국 조금 불편하지만, 이미 우리의 컴에 다 저장되어 있는 것들이니 퍼갈 수 있다. 이것이 HTTP프로토콜의 특징이다. 전송되는 모든 HTML소스, 자바스크립트(js)소스, 이미지파일 등이 개방형이다.

그렇다면, aspx와 같은 닷넷 소스나 그런 것들은?
Part 4를 벌써 까먹으셨는가? 

        [나]         ---- www.naver.com ---->       naver.com 

                              (요청한 파일의 확장자가 aspx라면 컴파일하여 html형식으로 변환)     

        [나]        <---- 달랑 HTML 1개  ----       naver.com 

이 과정이 하나 들어가게 되곘다. 당연히 소스가 있는지 없는지 실제 서버의 파일을 직접 메모장으로 열어보지 않는 이상은 알 수 없다. Part 4에서 친구에게 전화를 걸 수 있는 이유가 바로 이 때문이다.

여기까지가 중요하고 간략한 이야기의 끝이다.

다시, 방문객의 정보를 저장하는 곳은 웹서버라고 했는데, 당연히 저장되는 곳은 웹프로그래머는 해당 언어의 기능을 십분 활용하여 결과물을 HTML등으로 만들어 원하는 결과를 사용자에게 던져주면 되는 것이다.

그 범위는 꼭 화면에 보이는 웹의 태그문이 아니라, 지금 만드는 방문객 수를 저장하기 위해 파일을 생성하거나, 폴더를 만드는 등을 기능을 사용할 수 있고, 혹시 웹서버에 USB로 캠이 꽂혀 있다면 그 캠의 사진을 전송하여 보여주는 기능도 만들 수 있다. 기상청 날씨정보를 긁어와서 날씨정보를 보여줄 수 있고, 네이버 최신 뉴스를 가져와서 보여줄 수도 있다. 단, 그 한계가 HTTP라는 제한된 장소라는 것 뿐이다. 또한 요청이 있어야지만 보여준다는 개념이므로, 지속적인 정보 전달에 아무래도 한계가 있다고 볼 수 있다. (많은 꽁수가 나와있기도 하다)

count.aspx


<%@ Page Language="C#" runat="server" %>
<script language="C#" runat="server">

void Page_Load()
{
}


</script>

 


<html>
<head>
 <title>방문자는?</title>
</head>

<body>

<center><font color="red">392</font> 번째 방문객입니다.</center>


</body>

</html>


위의 소스를 count.aspx 파일로 저장해 놓고, 다음의 링크를 새 창으로 열자.

http://msdn.microsoft.com/ko-kr/library/3saad2h5(v=VS.80).aspx

저번에 봤던 파일관련 클래스인 System.IO 네임스페이스에 속한 File 클래스이다. 파일처리를 위해서는 이 녀석을 이용해야 된다고 앞에서 함께 찾아봤지 않았던가?

밑으로 쭉 내려보자. "예제"를 찾을 수 있는데, 파일 클래스를 이용한 예제이다.
이해할 수 없는 코드가 존재한다. 그러나, 한줄한줄 읽어보면 뭔지는 모르겠지만 결국 File 이라는 클래스의 메서드 호출을 이것 저것 해서 원하는 결과를 내는 것을 확인할 수 있다.

File 클래스는 생성자가 없는 static (정적) 클래스이다.
그러므로, 바로 사용가능하다고 했다.

맨 하단에 "File 멤버"링크를 클릭해보자. (http://msdn.microsoft.com/ko-kr/library/system.io.file_members(v=VS.80).aspx)

CreateText() 메서드를 클릭해보자.


위와 같은 설명을 볼 수 있는데,

예전에 언급했던 메서드의 형식을 그대로 사용할 수 있다. C# 항목을 보면,

public static StreamWriter CreateText (
                   String path
)

이렇게 되어 있는데,

이 메서드의 리턴형은 어떤것인가? 메서드명 바로 앞에 붙은 녀석이기 때문에,

StreamWriter

형식인 것을 알 수 있다. 무엇인지는 모르겠지만, 여튼 저걸 리턴한다고 한다.
그리고 CreateText() 메서드의 인수는 1개를 넣어야 되며, 그 인수는 path 라는 이름인 것을 보아하니, "생성할 텍스트파일의 경로"인 것 같다.

즉, CreateText("파일의 경로"); 이렇게 하면 될 것 같다는 생각이 들며,

StreamWriter aaa = System.IO.File.CreateText("파일의 경로");

이렇게 사용하면 코드상 아무런 문제가 없을 것 같다.

그리고 조금 더 밑으로 내려가 "설명"을 꼭 읽고 넘어가자.

메서드는 append 매개 변수가 false로 설정된 StreamWriter(String,Boolean) 생성자 오버로드와 동일합니다. path로 지정된 파일이 없으면 만들어집니다. 파일이 있으면 내용을 덮어씁니다. 파일이 열려 있으면 다른 스레드에서도 파일을 읽을 수 있습니다.

다른 것은 모르겠지만 중요한건 만약 파일이 있다면 엎어버린다고 한다.

System.IO는 네임스페이스이다. 네임스페이스를 참조(reference)하기 위해 aspx 파일의 두번째 줄에 다음을 추가하자.
count.aspx


<%@ Page Language="C#" runat="server" %>
<%@ Import Namespace = "System.IO" %>
<script language="C#" runat="server">

void Page_Load()
{
}


</script>

...
...
(이후 html 코드 후략)


이렇게 되면 앞에 System.IO를 붙이지 않고 File 클래스를 이용할 수 있게 된다.

#참고
소스상에 클래스명이 있으면 컴파일러는 기본적으로 참조한 네임스페이스 순서대로 찾게된다. 만약에 클래스명이 중복되면 네임스페이스를 명시적으로 붙여줘서 구분되게 해야한다. 예로,


System.Custom 네임스페이스의 Test 클래스
System.Namespace 네임스페이스의 Test 클래스

이렇게 Test 이름의 클래스가 각각 다른 네임스페이스에 있고, 이들이 참조되었다면 어떤 Test의 클래스를 이용할지 명확하지 않게 된다는 말이다. 닷넷에서 제공하는 클래스는 웬만하면 중복되는 것을 지양하고 있지만 중복될 경우에는 이렇게 사용해야 한다는 것을 일고만 있자.


이제 CreateText("파일의 경로") 메서드를 이용해 파일을 열어보도록 하자.
파일의 경로의 기준은 절대경로 또는 상대경로이다. 절대경로는 최상위부터 모두 지정하는 경로로, 현재 우리는

c:\home

폴더에 웹서버로 지정해서 작업을 하고 있다. 그러므로,

c:\home\count.txt

정도가 절대경로로 지정될 수 있을 것 같다. 

다른 경로 표기방법으로는 "상대경로"라고 있는데, 현재 경로 기준으로 하위/상위로 찾아들어가는 개념이다. (이것들은 따로 공부합시다)


count.aspx


<%@ Page Language="C#" runat="server" %>
<%@ Import Namespace = "System.IO" %>
<script language="C#" runat="server">

void Page_Load()
{
     string count_path = "c:\\home\\count.txt";
     StreamWriter sw = File.CreateText(count_path);
}


</script>


count.aspx 파일에 페이지가 열리면 자동으로 실행하는 Page_Load() 메서드에 두 줄을 추가한다. count_path 라는 스트링변수는 경로를 지정하기 위해 만들었다. CreateText(string path) 이와같이 경로는 string 형이기 때문에 그대로 사용할 수 있다. 그런데, 경로에 백슬래쉬(\)가 2개 들어간 것을 볼 수 있다. string 형에서 대괄호 안의 값 중에 백슬래쉬가 붙으면 특수문자로 간주된다.

\t : 탭문자
\n : 개행문자
등등..

그러므로, 그냥 경로를 뜻하는 백슬래쉬를 그대로 사용하려면 2개를 붙여준다. 또는 

     string count_path = @"c:\home\count.txt";

이렇게 상수 앞에 골뱅이(@)를 붙여줘서 이 문자에는 특수문자가 없음을 명시할 수 있다.
어떤 형식을 이용하든 상관없겠다.

#참고
ASP.NET 에서의 현재 경로는 c:\[윈도우폴더]\system32 이다. 참고하도록 하자. IIS에서 홈으로 지정된 폴더가 아니다. 그러므로 대개 절대경로를 사용한다. 

그러나, Server.MapPath("") 라는 유용한 메서드가 있다. 이 메서드는 현재 홈디렉터리를 기준으로 상대경로를 지정하여 직관적으로 경로를 줄 수 있다.


string Server.MapPath("상대경로");

빈번하게 사용하니 알아만 놓자. 또한 여기를 눌러서 해당 MSDN 문서도 읽어보도록 하자.



이 코드를 실행해보자. 오랜만에 실행하니 떨리지 않는가? (-_-)
*주의: 딱 한번만 열도록 한다.





앞에서 디자인한 페이지 그대로 잘 나오는가?
이 말은 우리가 작성한 코드가 오류없이 잘 실행되었다는 의미가 된다. 문법에 맞게, 그리고 해당 코드가 문제가 없다는 말이다.

여기서, 우리가 지정한 경로로 가보자. (c:\home)
count.txt 파일이 자동으로 생성된 것이 보이는가? 유추해보건데, File.CreateText() 메서드에서 파일을 자동으로 생성시킨 것 같다. (파일 크기도 0 byte 이다)

이 상태에서 count.txt 파일을 삭제해보자.


삭제시 이렇게 오류가 발생하게 된다.
이유는 코드에서 파일을 열어놓았기 때문이다. 윈도우에서는, 어떤 파일이 누군가에 의해 열려있는 동안에는, 파일을 닫지 않으면 계속 점유하게 된다. 이는 asp.net 에서 aspx를 해석하는 해석기가 이 파일을 열고 있기 때문에 발생하는 문제이다. 앞으로 파일 관련 코드를 작성할 때는 꼭 파일을 닫도록 하자.

우리의 소스에서 파일을 닫기 위해서는, StreamWriter 라는 클래스가 파일의 정보를 가지고 있으므로, 이 클래스를 이용해 닫아야 한다.

sw.Close();

count.aspx 파일에 열린 파일을 닫는 코드를 추가하자.


count.aspx


<%@ Page Language="C#" runat="server" %>
<%@ Import Namespace = "System.IO" %>
<script language="C#" runat="server">

void Page_Load()
{
     string count_path = "c:\\home\\count.txt";
     StreamWriter sw = File.CreateText(count_path);


 
  sw.Close();

}


</script>


이제 다시 실행해보자. 아무런 문제가 없다. 잘 실행되었고, 생성된 count.txt 파일을 삭제해보자. 파일 삭제도 잘 될것이다. 다음 실행시에도 파일을 무조건 생성할 것이다. (MSDN의 메서드의 설명에서 무조건 파일을 엎어버린다고 했었다.)

이제 파일을 써보도록 하자.
파일은 이제 StreamWriter로 제어가 되기 때문에, StreamWriter 클래스를 MSDN에서 찾아보자.

http://msdn.microsoft.com/ko-kr/library/system.io.streamwriter(v=VS.80).aspx

그리고 "모든 멤버"를 열어서 어떤 메서드, 프로퍼티가 이 클래스에 존재하는지 읽어보도록 한다.

필자에게는 Write() 와 WriteLine() 메서드가 눈에 띈다. 여러분은 어떤가?
메서드 명만 봐도 무언가를 쓴다는 의미가 있지 않을까?

WriteLine()은 줄을 쓰니, Write()는 줄이 아니라 그냥 내용만 쓰는 것 같다.
WriteLine()을 클릭해서 이 메서드의 사용법을 읽어보자.

방대한 "오버로드 목록"이 나온다.
Part 6에서 오버로드를 설명에 대해 읽어본 기억이 떠오르는가? ^____^

오버로드된 메서드들이라고 하면, 클래스의 메서드명은 같은데(즉, 기능은 같지만)

WriteLine1()
WriteLine2()
WriteLine3()
..

이렇게 여러개를 만들지 말고, 받는 인수 자료 형식만 달리 하는 것이다.

WriteLine()
WriteLine(Boolean)
WriteLine(char)
..
..(후략)

인수가 없는 것 부터해서 웬만한 자료형은 다 사용할 수 있게 해놓았다.

어떤걸 골라쓸지는 여러분들의 몫이다. string 이 만만하니

WriteLine(string) 을 클릭해보자. (다른 오버로드된 메서드들도 설명은 같을 수 밖에 없을 것이다)

"문자열과 줄 종결자를 차례로 텍스트 스트림에 씁니다"

우리가 원하는 그대로다. "줄 종결자"는.. 누군가가 번역을 이렇게 해놓으신건데(-_-) 엔터를 친 효과를 말하는 것이다. 눈에는 보이지 않지만, 엔터를 치면 개행문자가 하나 들어가게 된다. 윈도우에서는 1byte를 사용하는 "\n" 문자이다. 이 문자를 끝에 붙여준다는 말이다.

그렇다면 생각해보길, Write() 메서드 역시 거의 똑같지만 끝에 엔터문자를 붙여주지 않을 뿐일 것 같지 않은가? (확인해보시기 바란다. 저는 확신이 들어 확인하지 않겠다 -_-)

자~ 그럼 드디어 count.txt 파일에 내용을 써보자!


count.aspx


<%@ Page Language="C#" runat="server" %>
<%@ Import Namespace = "System.IO" %>
<script language="C#" runat="server">

void Page_Load()
{
     string count_path = "c:\\home\\count.txt";
     StreamWriter sw = File.CreateText(count_path);
   
   sw.WriteLine("여기에 카운터 ㅜㅜ");
 
     sw.Close();

}


</script>


진하게 표시된 줄이 추가된 소스이다. 저장 후 실행, count.txt 를 열어보자.
우리가 작성한 string 이 잘 작성되었는가? 그리고 엔터문자가 들어갔는지도 확인해보자. 커서키를 내려보면 다음줄에 커서가 위치한다면 엔터 문자가 들어간 것을 확인할 수도 있겠다.

여기서 WriteLine()을 Write()로도 고쳐서 실행해보고 열어보자.
프로그래밍은 호기심으로 시작되면 아주 좋은 결과물을 낼 수 있다. 오류가 나더라도, 실행이 잘 되더라도.. 늘 이런 저런 생각과 상상을 하며 키보드로 쳐보고 눈으로 확인하도록 하자. 버릇처럼..


내용이 아주 길어진 것 같으므로, 카운터의 마무리는 다음회로 넘거야 될 것 같다.


필자가 프로그래밍 공부시 중요시 여기는 것을 다시 말씀드리겠다.

결과는 언젠가는 나오게 되어있다. 
지금처럼 처음 공부하실 때 꼭 상기해놓으시기 바란다.
조급해하지 마시고, 재밌게 즐기시길!

반응형
Comments