반응형
반응형

 
이 포스트는 월간 마이크로소프트웨어에 기고한 원고를 재편집한 포스트입니다. 그러므로, 본의 아니게 반말로 진행되고 있습니다. 원래 싸가지가 없어서 그런 것이 아니니 무한 용서를... ^^;;
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.

블로그 관리자의 로그인/로그아웃 기능 구현

이제부터, 블로그를 관리하는 역할을 가진 관리자의 로그인 기능을 구현해보도록 하겠다. 우선 관리자 로그인이 된 경우와 로그인이 되지 않은 경우(Session값을 가지고 구분하게 된다), 메뉴 부분을 다르게 보여주기 위해서 마스터 페이지(BlogMasterPage.master)에 정의된 메뉴 부분을 <리스트 1>과 같이 변경한다.

        <div class="nav">
            <a href="Default.aspx">HOME</a> 
            <a href="About.aspx">ABOUT</a> 
            <a href="Tag.aspx">TAG</a>
            <a href="Rss.aspx">RSS</a> 
            <a href="Search.aspx">SEARCH</a> 
            <a href="GuestBook.aspx">GUESTBOOK</a>
            <asp:HyperLink ID="hlnkLogin" runat="server" 
                NavigateUrl="~/Login.aspx" Text="LOGIN"></asp:HyperLink>
            <asp:HyperLink ID="hlnkLogout" runat="server" 
                NavigateUrl="~/Logout.aspx" Text="LOGOUT"></asp:HyperLink>
            <asp:HyperLink ID="hlnkAdmin" runat="server" 
                NavigateUrl="~/Admin.aspx" Text="ADMIN"></asp:HyperLink>
            <div class="clearer">
                <span></span>
            </div>
        </div>
<리스트 1> BlogMasterPage.master 페이지의 소스 코드

또한, 블로그 마스터 페이지의 코드 비하인드 페이지에서는 Session값 중 "Admin"값을 확인하여, <리스트 1>에서 재구성한 HyperLink 컨트롤의 Visible 속성을 <리스트 2>와 같이 정의하게 된다.

    protected void Page_Load(object sender, EventArgs e)
    {
        // Session의 값이 없을 경우에는,
        // Logout과 Admin링크를 보여주지 않도록 한다.
        if (Session["Admin"] == null)
        {
            hlnkLogout.Visible = false;
            hlnkAdmin.Visible = false;
        }
        else
        {
            hlnkLogin.Visible = false;
        }
    }
<리스트 2> BlogMasterPage.master.cs 페이지의 소스 코드

<리스트 1>과 <리스트 2>의 코드로 인해, 관리자로 로그인했을 경우와, 관리자로 로그인하지 않은 경우의 메뉴 구조는 각각 <화면 6>, <화면 7>과 같게 된다.


<화면 6> 관리자로 로그인이 되지 않은 경우의 메뉴 구성


<화면 7> 관리자로 로그인이 된 경우의 메뉴 구성

이제, 메뉴의 "Login"을 클릭할 경우, 관리자 로그인을 하기 위한 페이지인 Login.aspx 페이지를 구성해보도록 하자. <리스트 3-1>과 <리스트 3-2>는 Login.aspx 페이지의 소스 코드 및 Login 버튼을 클릭했을 경우에 실행되는 소스 코드를 보여준다.

<%@ Page Language="C#" MasterPageFile="~/BlogMasterPage.master" AutoEventWireup="true" 
CodeFile="Login.aspx.cs" Inherits="Login" Title="Untitled Page" %>
 
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <script language="javascript" type="text/javascript">
        // ID, PWD 입력상자 유효성 검사
        function fnLoginValidation() {
            var txtAdminID = document.getElementById("<%=txtAdminID.ClientID%>");
            var txtAdminPassword = document.getElementById("<%=txtAdminPassword.ClientID%>");
 
            if (txtAdminID.value == "") {
                alert("ID를 입력하세요.");
                return false;
            }
 
            if (txtAdminPassword.value == "") {
                alert("PASSWORD를 입력하세요.");
                return false;
            }
 
            return true;
        }
 
        // ID, PWD 입력상자 초기화
        function fnClearInputText() {
            var txtAdminID = document.getElementById("<%=txtAdminID.ClientID%>");
            var txtAdminPassword = document.getElementById("<%=txtAdminPassword.ClientID%>");
 
            txtAdminID.value = "";
            txtAdminPassword.value = "";
 
            return false;
        }
    </script>
    <div class="left">
        <div class="content">
            <h1>LOGIN</h1>
            <div style="width:100%;text-align:center">
                <table width="80%" cellpadding="2" cellspacing="0" border="0">
                    <tr valign="middle" style="height:26px;">
                        <td class="td_left_input_width30">ID : </td>
                        <td class="td_right_input_width70">
                            <asp:TextBox ID="txtAdminID" runat="server" MaxLength="10" 
                                CssClass="txtCommon"></asp:TextBox>
                        </td>
                    </tr>
                    <tr valign="middle" style="height:26px;">
                        <td class="td_left_input_width30">PASSWORD : </td>
                        <td class="td_right_input_width70">
                            <asp:TextBox ID="txtAdminPassword" runat="server" MaxLength="10" 
                                TextMode="Password" CssClass="txtCommon"></asp:TextBox>
                        </td>
                    </tr>
                    <tr style="height:40px;" valign="middle">
                        <td style="width:100%" colspan="2" align="center">
                            <asp:Button ID="btnLogin" runat="server" Text="Login" 
                                OnClientClick="return fnLoginValidation()" OnClick="btnLogin_Click" />&nbsp;
                            <asp:Button ID="btnCancel" runat="server" Text="Clear" 
                                OnClientClick="return fnClearInputText()" />&nbsp;
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</asp:Content>
<리스트 3-1> Login.aspx 페이지의 소스 코드

    protected void btnLogin_Click(object sender, EventArgs e) 
    {
        BlogDataClassesDataContext blogContext 
            = new BlogDataClassesDataContext();
 
        var adminInfo = from USER in blogContext.BLOG_USERINFO select USER;
 
        string strAdminID = string.Empty;
        string strAdminPassword = string.Empty;
 
        // 관리자 정보가 있을 경우
        if (adminInfo != null)
        {
            foreach (BLOG_USERINFO userInfo in adminInfo)
            {
                strAdminID = userInfo.AdminID;
                strAdminPassword = userInfo.AdminPWD;
            }
 
            // 관리자 정보와 입력한 정보가 일치할 경우
            if (string.Compare(strAdminID, txtAdminID.Text.Trim(), true) == 0 && 
                string.Compare(strAdminPassword, txtAdminPassword.Text.Trim(), true) == 0)
            {
                Session["Admin"] = "admin";
                Response.Redirect("Default.aspx");
            }
            else 
            {
                string strNotCorrect 
                    = "alert('관리자 ID 또는 비밀번호가 틀립니다.');";
                Page.ClientScript.RegisterStartupScript(
                    this.GetType(), "notcorrect", strNotCorrect, true);
            }
        }
        else 
        {
            string strNotData = "alert('관리자 정보가 없습니다.');";
            Page.ClientScript.RegisterStartupScript(
                this.GetType(), "notdata", strNotData, true);
        }
    }
<리스트 3-2> Login 버튼을 클릭시의 소스 코드

<리스트 3>에서 보여지는 코드에 대해서 잠깐 설명하도록 하겠다. Login 버튼을 클릭하게 되면, BLOG_USERINFO 테이블에 저장되어 있는 관리자 아이디 정보와 비밀번호 정보를 LINQ 쿼리로 가져와서 변수에 할당한 후, 사용자가 입력한 값과 일치하는 지를 확인한다. 사용자가 입력한 값과 일치하게 되면 Session값 중 "Admin"값에 값을 할당한 후, 블로그의 초기 화면으로 이동시키게 되며, 일치하지 않을 경우는 아이디 또는 비밀번호가 틀렸다는 경고창을 보여주게 된다. "CTRL+F5키" 또는 디버그 메뉴의 "디버깅하지 않고 시작 메뉴"를 선택하여, 웹 브라우저로 지금까지 적용한 화면을 보도록 한다. 메뉴의 "Login"을 눌러 로그인 페이지로 이동 후에 아이디와 비밀번호에 임의의 글자를 입력한 후 로그인 버튼을 클릭하면 <화면 8>과 같은 경고창이 뜨게 되며, 정확하게 아이디와 비밀번호를 입력하게 되면 Default.aspx 페이지로 이동하게 되며 상단의 메뉴 구조가 <화면 7>과 같이 변경되게 된다.


<화면 8> 로그인이 실패했을 경우의 화면

로그인 부분이 완성되었으므로, 로그아웃 부분에 대해서 설명하도록 하겠다. 로그아웃은 별도의 페이지인 "Logout.aspx"를 사용하여 로그아웃 기능을 구현하도록 하며, 별다른 기능 없이 Session 값 중 Admin에 할당된 값을 초기화시키는 코드를 가지게 된다. 웹 사이트 이름에서 우측 마우스를 클릭하여 “새 항목 추가(Add New Item...)" 메뉴를 선택하여, "Logout.aspx"라는 이름의 페이지를 추가한다. 추가한 "Logout.aspx.cs" 페이지에 다음과 같은 코드를 추가한다.

    protected void Page_Load(object sender, EventArgs e)
    {
        Session["Admin"] = null;
        Response.Redirect("Login.aspx");
    }


관리자로 로그인했을 경우, 상단 메뉴의 "LogOut" 메뉴를 클릭하면, 세션값 중 Admin값은 null로 변경되며, 페이지는 "Login.aspx" 페이지로 이동하게 된다.

로그아웃 기능에 대해서 별도로 페이지를 만든 것에 대해서 의문점을 가지고 있는 독자들이 있을 줄로 안다. 물론, Visual Studio 2008부터는 기본적으로 ASP.NET AJAX 기능이 포함되어 있기 때문에 AJAX가 제공하는 기능 중 페이지 메소드나 웹 서비스를 이용하여 Session값에 대한 처리를 할 수도 있지만, 로그아웃에 관련된 별도의 페이지를 만들어 Session값에 대한 처리를 하는 것이 좀 더 편하기 때문에 필자는 이와 같이 로그아웃 페이지를 별도로 만들게 되었다.

또한, 관리자 아이디와 비밀번호를 저장하고 있는 BLOG_USERINFO 테이블 또한, AdminID와 AdminPWD 2개의 필드만을 염두에 두고 있지는 않았던 테이블이다. 블로그를 방문하는 방문자 중에서 블로그에 회원 가입을 하는 사용자들의 정보를 저장하기 위한 테이블로 구상하였으나, 지면상 회원 가입 부분에 관련되어서 설명을 별도로 드릴 수 없을 것 같기 때문에 AdminID와 AdminPWD, 이와 같이 2개의 필드로만 구성하였고 관리자의 아이디 정보와 비밀번호 정보를 담게 하였다. 회원 가입 부분에 관련되어서는 여러 ASP.NET 도서나 블로그 및 사이트를 참조하기 바란다.



Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

 
이 포스트는 월간 마이크로소프트웨어에 기고한 원고를 재편집한 포스트입니다. 그러므로, 본의 아니게 반말로 진행되고 있습니다. 원래 싸가지가 없어서 그런 것이 아니니 무한 용서를... ^^;;
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.

LINQ to SQL Classes의 생성

필자가 설명하는 블로그에서 데이터베이스에 포함된 각 테이블과의 연결은 Visual Studio 2008에 새로 추가된 템플릿 중의 하나인 "LINQ to SQL Classes"를 사용하도록 하겠다. "LINQ to SQL Classes"은 .NET Framework 3.5에 내장된 O/RM(object relational mapper)으로, .NET 클래스들을 사용하여 관계가 있는 데이터베이스로의 연결을 가능하게 해주는 템플릿이다. 웹 사이트 이름에서 우측 마우스를 클릭하여 “새 항목 추가(Add New Item...)" 메뉴를 선택하여 <화면 1>과 같이 "LINQ to SQL Classes" 템플릿을 선택하고, 템플릿의 이름을 "BlogDataClasses.dbml"로 변경한 후 "추가(Add)" 버튼을 클릭하여 "LINQ to SQL Classes" 템플릿을 추가한다. App_Code 폴더가 없으므로, App_Code 폴더로 추가할 것이냐는 알림 창이 뜨게 될 것이다. 확인 버튼을 클릭하면 App_Code 폴더가 생성되며, "BlogDataClasses.dbml" 파일이 App_Code 폴더 아래로 추가되게 된다.


<화면 1> "LINQ to SQL Classes" 템플릿 추가

"LINQ to SQL Classes" 템플릿을 추가하게 되면, 템플릿에 데이터베이스에 있는 테이블, 뷰, 저장 프로시저, 사용자 정의 함수 등을 추가할 수 있는 디자이너 화면이 나타나게 된다. 디자이너 화면은 2개의 영역으로 구분되어 있으며, 좌측의 영역에는 테이블 및 뷰를 추가할 수 있고 우측의 영역에는 저장 프로시저 및 사용자 정의 함수 등을 추가할 수 있다. 이제, 생성한 "BlogDataClasses.dbml" 파일로 사용할 테이블의 정보를 추가하기 위해서, "서버 탐색기(Server Explorer)"의 "데이터 연결(DataConnection)"에서 우측 마우스를 클릭하여, "연결 추가(Add Connection)" 메뉴를 선택한다. 그러면, 데이터 소스를 선택하는 <화면 2>가 보이게 된다.


<화면 2> 데이터 소스 선택 화면

데이터 소스 선택 화면에서 "Microsoft SQL Server"를 선택한 후, "계속(Continue)" 버튼을 클릭하면, <화면 3>과 같은 연결 추가 화면이 나타나게 된다.


<화면 3> 연결 추가 화면

연결 추가 화면에서 서버명(Server Name)은 SQL Server가 위치한 서버명을 입력하면 되고, 서버로의 로그온 방식(Log on to the server)는 윈도우 인증 또는 SQL Server 인증 방식 중 하나를 선택하면 되겠다. SQL Server 인증 방식을 사용할 경우에는 로그온할 사용자명과 비밀번호를 입력하여야 하며, 로그온 방식을 선택한 후에는 연결이 정확한 지를 확인하기 위해 화면 좌측 하단의 연결 테스트(Test Connection)을 눌러 연결이 정확하게 되는지를 확인한다. 연결이 정확한 것을 확인하였으면, 연결할 데이터베이스명을 선택 또는 입력한 후 "확인(OK)" 버튼을 클릭하여 연결 추가 화면을 종료하도록 한다. 서버 탐색기(Server Explorer)에 방금 추가한 연결 정보가 추가된 것을 <화면 4>와 같이 확인할 수 있으며, 지난 호에서 생성한 테이블들이 포함되어 있는 것을 확인할 수 있다.


<화면 4> 추가된 연결 정보 화면

<화면 4>에서 보여지고 있는 테이블들을 "BlogDataClasses.dbml" 파일 디자이너의 좌측 영역으로 드래그 앤 드랍하면, <화면 5>와 같이 "BlogDataClasses.dbml" 파일로 테이블의 스키마가 추가되게 된다. 이 때, 각 테이블간의 관계 등도 같이 표시되게 되며 필자는 "BlogDataClasses.dbml" 파일로 추가된 테이블 스키마 정보를 바탕으로 LINQ 쿼리를 사용하여, 블로그의 데이터 정보를 관리할 것이다.


<화면 5> "LINQ to SQL Classes" 템플릿 디자이너에 테이블이 추가된 화면

블로그 프로그래밍에 관련된 기본적인 정보를 2개의 테이블에 입력하도록 한다. 먼저, 관리자로 로그인하기 위한 정보를 입력하기 위해, 다음과 같은 쿼리를 실행하여 관리자 정보를 BLOG_USERINFO 테이블에 데이터를 입력한다.

INSERT INTO BLOG_USERINFO VALUES ('neostyx', 'neostyx')

또한, 포스트를 작성하는 경우 CategoryID값이 반드시 필요하게 되므로, 임의로 BLOG_CATEGORIES 테이블에 다음과 같은 쿼리를 실행하여 데이터를 입력한다.

INSERT INTO BLOG_CATEGORIES VALUES ('ASP.NET', 1, GETDATE(), NULL)



Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

 
이 포스트는 월간 마이크로소프트웨어에 기고한 원고를 재편집한 포스트입니다. 그러므로, 본의 아니게 반말로 진행되고 있습니다. 원래 싸가지가 없어서 그런 것이 아니니 무한 용서를... ^^;;
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.

블로그를 위한 데이터베이스의 생성 및 구성

이제부터는, 블로그에 관련된 데이터베이스 및 테이블들을 만들어보도록 하겠다. 우선 SQL Server Management Studio를 실행시킨 후, 새 데이터베이스 생성 메뉴를 통하여 “BlogDataBase"라는 새로운 데이터베이스를 만든다. 새로운 데이터베이스를 생성하였으면, 새로운 테이블들을 만들어보도록 하겠다. 우선, 관리자가 지정한 카테고리들의 목록이 저장되는 BLOG_CATEGORIES 테이블의 구성은 <표 2>와 같다.



다음으로는, 관리자가 작성한 이전 포스트의 목록을 작성일자(년-월)별로 표시하기 위한 BLOG_ARCHIVES 테이블의 구성은 <표 3>과 같다.



관리자가 지정한 즐겨찾는 사이트 및 블로그의 목록이 표시되는 BLOG_LINKS 테이블의 구성은 <표 4>와 같다.



작성한 포스트의 정보가 입력되는 BLOG_POSTS 테이블의 구성은 <표 5>와 같다.



블로그의 공지 사항을 저장하는 테이블인 BLOG_NOTICES 테이블의 구성은 <표 6>과 같다. BLOG_NOTICES 테이블의 구조는 BLOG_POSTS 테이블의 구성과 유사하다.



포스트에 대하여 사용자들이 등록하는 덧글 정보를 저장하는 BLOG_COMMENTS 테이블의 구성은 <표 7>과 같다.



포스트 작성시에 등록되는 태그들의 정보를 저장하는 BLOG_TAGS 테이블의 구성은 <표 8>과 같다.



<표 2>에서 <표 8>까지 설명한 테이블의 정보는 <화면 8>과 같다.


<화면 8> BlogDataBase에 속한 테이블들의 구성 정보

블로그 관리자 정보 페이지 구성 (About.aspx)

블로그를 관리하고 있는 관리자에 대한 정보를 사용자들이 조회하는 웹 페이지를 만들어보도록 하겠다. 특별하게 데이터베이스에서 쿼리를 하는 부분이 없는, 단순한 웹 페이지라고 할 수 있겠다. 앞에서 만든 웹 페이지 중 “About.aspx”에 <리스트 3>과 같은 코드를 추가한다.

<%@ Page Title="" Language="C#" MasterPageFile="~/BlogMasterPage.master" 
    AutoEventWireup="true" CodeFile="About.aspx.cs" Inherits="About" %>
 
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <div class="left">
        <div class="content">
            <h1>Neostyx는?</h1>
            <p><a href="http://www.neostyx.net" target="_blank">neostyx.net</a> 
            사이트를 운영하고 있는 닷넷 개발자입니다<br />
            2007년 Microsoft ASP.NET MVP로 활동중에 있으며 2008년부터 
            마이크로소프트웨어에 글을 개제하고 있습니다<br />
            앞으로도 많은 관심과 격려를 부탁드리겠습니다</p>
            <center>
                <img src="http://pds6.egloos.com/logo/200709/13/66/c0052366.png" alt="mvp 로고 />
            </center><br />
            <h1>Neostyx의 관심사</h1>
            <ul>
                <li>ASP.NET AJAX</li>
                <li>ASP.NET MVC Framework</li>
                <li>LINQ</li>
                <li>Microsoft Seminar</li>
                <li>Microsoft MVP</li>
        </ul>
        </div>
    </div>
</asp:Content>

<리스트 3> About.aspx 페이지의 소스 코드

또한 웹 브라우저의 타이틀을 변경하기 위하여, "About.aspx.cs" 코드 파일의 페이지 로드 이벤트에 다음과 같이 마스터 페이지의 타이틀을 변경하는 코드를 추가한다.

    protected void Page_Load(object sender, EventArgs e)
    {
        this.Master.Page.Title = "About Me";
    }


“About.aspx” 웹 페이지에 적용되어 있는 디자인을 보기 위하여, CTRL+F5키 또는 디버그 메뉴의 디버깅하지 않고 시작 메뉴를 선택한다. “About.aspx” 웹 페이지의 화면은 <화면 9>과 같다.


<화면 9> About.aspx의 웹 페이지 화면

이상으로, 블로그 정보를 저장하는 데이터베이스를 생성하고, 블로그를 구성하는 데에 사용되는 웹 사이트를 만들어보았다. 다음회에서는 로그인에 관련된 로직의 구성과 포스트 작성, 작성된 포스트의 목록을 조회하는 화면 등 블로그의 주요 기능들에 대한 설명을 하도록 하겠다.


Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

 
이 포스트는 월간 마이크로소프트웨어에 기고한 원고를 재편집한 포스트입니다. 그러므로, 본의 아니게 반말로 진행되고 있습니다. 원래 싸가지가 없어서 그런 것이 아니니 무한 용서를... ^^;;
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.

블로그 웹 사이트 구성

블로그에 적용할 디자인을 선택하였으므로, 이제부터 실제적으로 블로그를 만들어 보도록 하겠다. Visual Studio 2008을 실행시킨 후, 새 웹사이트 생성 메뉴를 이용하여 <화면 3>과 같이 “BlogProgramming"라는 이름의 새로운 웹 사이트를 만든다.


<화면 3> 새로운 웹 사이트의 생성

새로운 웹 사이트를 생성하였으면, 블로그에 사용할 스타일시트 파일 및 이미지 파일을 웹 사이트로 추가하여야 한다. 우선, "Img"라는 이름의 폴더를 새로 웹 사이트에 추가 후, 웹 사이트 이름에서 우측 마우스를 클릭하여 "기존 항목 추가(Add Existing Item...)" 메뉴를 선택하여, 이전에 다운로드 받은 블로그 디자인에 사용되는 Shades of Gray 폴더의 Img 폴더 아래에 위치한 이미지 파일들을 웹 사이트로 추가한다. 또한, 같은 방법으로 Shades of Gray 폴더의 default.css 스타일시트 파일을 웹 사이트로 추가한다. 그 후 default.css 스타일 시트 파일명을 “BlogStyleSheet.css”로 변경한다. <화면 4>는 현재까지 작업한 “BlogProgramming" 웹 사이트의 구조이다.


<화면 4> “BlogProgramming" 웹 사이트의 구조

<그림 1>에서 설명한 것과 같이 필자가 만드려고 하는 블로그는 4단 분류를 채택하고 있다. 이 중, <그림 2>와 같이 ① 상단 메뉴 영역, ② 우측 메뉴 영역, 그리고 ④ 하단 컨텐츠 영역은 모든 페이지에 공통적으로 적용되는 부분이므로, 마스터 페이지(MasterPage)를 이용하는 것이 블로그를 만드는데에 있어 효과적이라고 할 수 있겠다. 웹 사이트 이름에서 우측 마우스를 클릭하여 “새 항목 추가(Add New Item...)" 메뉴를 선택하여, 블로그에서 사용할 ”BlogMasterPage.master“라는 이름의 마스터 페이지를 생성하도록 한다.


<그림 2> 마스터 페이지의 적용 영역

생성된 ”BlogMasterPage.master“ 마스터 페이지에 블로그 디자인에 사용되는 Shades of Gray 폴더에 포함되어 있는 Index.html 파일의 소스 중 필요한 부분을 복사하도록 한다. <리스트 1>은 ”BlogMasterPage.master“ 마스터 페이지의 전체 소스이다.

<%@ Master Language="C#" AutoEventWireup="true" 
CodeFile="BlogMasterPage.master.cs" Inherits="BlogMasterPage" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="BlogStyleSheet.css" rel="stylesheet" type="text/css" />
    <asp:ContentPlaceHolder id="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body style="margin: 0 12%">
    <form id="form1" runat="server">
    <div class="container">
        <div class="header">
            <a href="Default.aspx"><span>Neostyx's Blog</span></a>
        </div>
        <div class="stripes"><span></span></div>
        <div class="nav">
            <a href="Default.aspx">HOME</a>
            <a href="About.aspx">ABOUT</a>
            <a href="Tag.aspx">TAG</a>
            <a href="Rss.aspx">RSS</a>
            <a href="Search.aspx">SEARCH</a>
            <a href="GuestBook.aspx">GUESTBOOK</a>
            <a href="Login.aspx">LOGIN</a>
            <a href="Admin.aspx">ADMIN</a>
            <div class="clearer"><span></span></div>
        </div>
        <div class="stripes"><span></span></div>
        <div class="main">
            <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
            </asp:ContentPlaceHolder>
            <div class="right">
                <div class="subnav">
                    <h1>Notices</h1>
                    <ul>
                        <li><a href="#">공지</a></li>
                    </ul>
                    <h1>Categories</h1>
                    <ul>
                        <li><a href="#">카테고리</a></li>
                    </ul>
                    <h1>Archives</h1>
                    <ul>
                        <li><a href="#">2008-02</a></li>
                    </ul>
                    <h1>Licently Posts</h1>
                    <ul>
                        <li><a href="#">최근포스트</a></li>
                    </ul>
                    <h1>Licently Comments</h1>
                    <ul>
                        <li><a href="#">최근댓글</a></li>
                    </ul>
                    <h1>Favorite Links</h1>
                    <ul>
                        <li><a href="#">즐겨찾기</a></li>
                    </ul>
                </div>
            </div>
        <div class="clearer"><span></span></div>
        </div>
        <div class="footer">
            <div class="bottom">
                <span class="left">&copy; 2008 <a href
                 ="http://www.neostyx.net">Neostyx.net</a>.</span>
               <span class="right">Template design by 
                    <a href="http://templates.arcsin.se">Arcsin</a></span>
                <div class="clearer"><span></span></div>
            </div>
        </div>
    </div>
    </form>
</body>
</html>

<리스트 1> BlogMasterPage.master 마스터 페이지의 소스

블로그 디자인의 수정을 위해, 앞에서 생성한 “BlogStyleSheet.css” 스타일 시트 파일에 정의된 스타일 중 <리스트 2>에 표시된 스타일들을 수정한다.

.header {
    background: #111;
    border-bottom: 1px solid #333;
    font: normal 2em sans-serif;
    height: 70px;
}
.header a {
    color: #888;
    display: block;
    line-height: 60px;
    text-decoration: none;
    width: 100%;
}
.subnav h1 {
    padding-top: 8px;
    background: url(img/bgh1.gif) repeat-x left bottom;
    margin-bottom: 10px;
    padding: 10px 0 4px;
}
.footer {
    background: #191919;
    border-top: 1px solid #444;
    color: #999;
    padding: 3% 3% 3%;
}


<리스트 2> 스타일의 수정

마스터 페이지만으로는 별도의 디자인을 웹에서 볼 수 없으므로, 웹 사이트 생성시에 기본적으로 생성되는 “Default.aspx" 웹 페이지를 삭제 후, 웹 사이트 이름에서 우측 마우스를 클릭하여 “새 항목 추가(Add New Item...)" 메뉴를 선택하여, 새로운 웹 폼을 추가하도록 한다. 새로운 웹 폼명은 ”Default.aspx"이며, 새로운 웹 폼을 생성 시 “마스터 페이지 선택” 항목을 체크하여, <화면 5>와 같이 마스터 페이지 선택 시 “BlogMasterPage.master”를 선택하도록 한다.


<화면 5> 마스터 페이지 선택 화면

새로운 웹 폼이 생성되었으면, “BlogMasterPage.master” 마스터 페이지에 적용되어 있는 디자인을 보기 위하여, CTRL+F5키 또는 디버그 메뉴의 디버깅하지 않고 시작 메뉴를 선택한다. “BlogMasterPage.master” 마스터 페이지의 화면은 <화면 6>과 같다.


<화면 6> “BlogMasterPage.master” 마스터 페이지의 화면

이제, 각 메뉴를 클릭 시에 이동할 페이지들을 미리 생성한다, 기본 페이지인 “Default.aspx" 페이지는 이미 생성했으므로, ”Default.aspx" 페이지를 생성할 때와 마찬가지의 방법으로 “About.aspx", "Tag.aspx", "Rss.aspx", "Search.aspx", "GuestBook.aspx", "Login.aspx", "Admin.aspx" 등의 7개 웹 페이지를 생성하도록 한다. <화면 7>은 현재까지 작업한 웹 사이트의 구조를 보여준다.


<화면 7> 웹 사이트의 구조


Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

이 포스트는 월간 마이크로소프트웨어에 기고한 원고를 재편집한 포스트입니다. 그러므로, 본의 아니게 반말로 진행되고 있습니다. 원래 싸가지가 없어서 그런 것이 아니니 무한 용서를... ^^;;
또한, .NET Framework 3.5 SP1이 적용되기 이전의 소스이므로, 현재의 개발 환경과 다를 수 있습니다. 마소에 제출한 블로그 소스는 블로그 소스 다운로드에서 다운로드하실 수있습니다.

(기획 의도) 웹 2.0의 시대를 이끌고 있는 가장 선도적인 주자는 블로그가 아닐 듯 싶다. 개발자라면 누구나 자신이 스스로 블로그를 만들어보고 싶은 욕구가 있을 것이라고 생각하지만, 블로그 프로그래밍에 관련된 정보를 찾을 수 없는 가장 큰 이유 때문에 자신만의 블로그를 만들지 못하고 있다고 생각한다. 이러한 이유로 자신만의 블로그를 만들지 못하고 있는 개발자들에게 약간의 도움을 주고자 블로그 프로그래밍에 관련되어 연재를 하고자 한다.

---------------------------------------------------------------------------------------------------

웹 2.0의 시대를 이끌고 있는 가장 선도적인 주자는 블로그가 아닐 듯 싶다. 개발자라면 누구나 자신이 스스로 블로그를 만들어보고 싶은 욕구가 있을 것이라고 생각하지만, 시간이 없거나 블로그 프로그래밍에 관련된 정보를 찾을 수 없는 등의 이유가 있기 때문에 대중화된 블로그를 제공하는 서비스를 이용하고 있는 것으로 생각한다. 혹시라도, 블로그 프로그래밍에 관련된 정보가 많이 없어 자신만의 블로그를 만드는 것을 미루고 있는 독자라면, 지금부터 시작되는 블로그 프로그래밍에 관련된 연재를 참고하길 바라며, 연재가 끝날 무렵에는 실제적으로 사용할 수 있는 블로그가 완성된 것을 확인할 수 있을 것이다.

블로그에 관련된 용어를 알고 있다면 블로그 프로그래밍을 하는 데에 있어 조금이나마 도움이 될 것이다.

● 블로거(blogger) : 블로그를 운영하는 사람을 의미한다.
● 블로깅(blogging) : 블로그를 보고, 덧글 및 방명록을 작성하는 행위를 의미한다.
● 포스팅(posting) : 블로그에 글을 작성하는 행위를 의미한다.
● 엔트리(entry, 포스트, post) : 블로그에 작성한 글을 뜻한다. 엔트리와 포스트 모두 동일한 말로써 블로그에 등록한 문서, 글, 게시물, 자료등이 엔트리 혹은 포스트를 의미하게 된다.
● 코멘트(comment, 덧글) : 엔트리 혹은 포스트에 몇 줄로 간단하게 작성된 사용자 의견을 의미한다.
● 트랙백(trackback) : 다른 사람의 글을 읽고 그 글에 직접 덧글을 올리는 대신에, 자신의 블로그에 글을 올리고 글의 일정 부분을 다른 사람의 블로그에 보이도록 하는 것을 의미한다.


블로그의 구조 이해

블로그 프로그래밍을 하기 전에 우선, 블로그는 어떤 구조로 되어 있는지를 확인해보도록 하겠다. 필자가 현재 운영하고 있는 블로그는 <화면 1>과 같이 구성되어 있다.


<화면 1> 필자가 운영하고 있는 블로그

<화면 1>에서 보는 것과 같이 블로그는 디자인에 따라 다르겠지만 크게 2단 분류와 3단 분류, 그리고 4단 분류로 나눌수 있으며, 일반적으로는 3단으로 분류된 디자인을 많이 사용하고 있다. 3단 분류는 크게 상단 메뉴 영역, 좌측(혹은 우측) 메뉴 영역, 우측(혹은 좌측) 컨텐츠 영역으로 나눌 수 있으며 각각의 분류는 <표 1>과 같은 메뉴 또는 컨텐츠가 들어가게 된다.



이와 같은 구조로 대부분의 블로그들이 이루어져 있으며, 기타 각 블로그 서비스마다 약간씩 다른 메뉴들을 제공하고 있다. 필자는 4단 분류를 사용하는 블로그를 만들 예정이며, 4단 분류는 3단 분류에 하단 컨텐츠 영역이 추가된 것으로 생각하면 된다. <그림 1>은 필자가 만들 블로그의 각 영역을 표시하고 있다.


<그림 1> 블로그의 각 영역

블로그의 디자인 선택

블로그를 최초로 사용자가 방문할 때 가장 먼저 접하게 되는 것이 블로그의 디자인이다. 보기 좋은 떡이 먹기도 좋다는 옛말처럼, 사용자의 관심을 끄는 디자인이 적용된 블로그라면 블로그를 재방문하도록 하는 효과를 얻을 수 있겠다. 블로그의 디자인은 블로그를 서비스하고 있는 업체에서 제공하는 각종 스킨 중 마음에 드는 스킨을 가지고 블로그를 구성하거나, 또는 저작권이 없는 공개된 블로그 디자인을 제공하는 사이트에서 제공하는 소스를 가지고 구성하면 된다. 필자는 Open Source Web Design(http://www.oswd.org/)에서 제공하는 무료 디자인 중 Shades of Gray(http://www.oswd.org/design/preview/id/3627) 디자인을 가지고 블로그를 구성하도록 하겠다. Shades of Gray의 화면은 <화면 2>와 같다.


<화면 2> Shades of Gray 화면

블로그 메뉴 구성

앞에서 설명한 대로 4단 분류의 틀을 유지하는 블로그를 만들 것이다. 먼저 상단 메뉴 영역에는 다음과 같은 메뉴들로 구성될 것이다.

● HOME : 블로그의 첫 화면으로 이동하기 위한 메뉴
● ABOUT : 블로그 관리자에 대한 정보를 보기 위해 이동하는 메뉴 (about.aspx로 이동)
● TAG : 포스트에 같이 등록된 태그들의 목록을 보기 위해 이동하는 메뉴 (tag.aspx로 이동)
● RSS : 포스트에 대한 RSS 정보를 보기 위한 메뉴 (rss.aspx로 이동 - 팝업 형식)
● SEARCH : 포스트를 검색하기 위해 이동하는 메뉴 (search.aspx로 이동)
● GUESTBOOK : 블로그에 방문하는 사용자들이 간단한 인사말을 남길 수 있는 방명록으로 이동하는 메뉴 (guestbook.aspx로 이동)
● LOGIN : 관리자가 로그인을 하기 위해 이동하는 메뉴 (login.aspx로 이동)
● ADMIN : 관리자 로그인이 성공했을 경우, 블로그를 관리하기 위한 관리자 화면으로 이동하는 메뉴 (admin.aspx로 이동)

또한, 우측 메뉴 영역은 다음과 같은 항목들로 구성될 것이다.

● Notices : 관리자가 작성한 공지사항의 목록이 표시된다.
● Categories : 관리자가 지정한 카테고리들의 목록이 표시된다.
● Archives : 관리자가 이전에 작성한 포스트의 목록이 작성일자(년-월)별로 표시된다.
● Licently Posts : 관리자가 작성한 포스트의 작성일자순으로 정렬된 최신 포스트의 목록이 표시된다.
● Licently Comments : 포스트에 대한 덧글이 작성일자순으로 정렬된 최신 덧글의 목록이 표시된다.
● Favorite Links : 관리자가 지정한 즐겨찾는 사이트 및 블로그의 목록이 표시된다.


Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

이 글은 월간 마이크로소프트웨어(일명 마소) 2008년 01월호 실전 강의실에 기고한 글입니다. 요즘 도통 포스팅을 할 수 없는 관계로 인해 대체합니다. ㅡ_ㅡ;; (하는 거 없이 바빠요~~~)


ASP.NET AJAX 코드와의 결합

CommonUtility 클래스의 코드까지 입력이 완료되었다면, 웹 폼에 ASP.NET AJAX 코드를 추가하도록 하겠다. 위에서, 웹 폼에는 divAddRss, divRssList, divPostList라는 id를 가진 3개의 <div>가 있다고 설명하였다. 우선, “AddUpdatePanel”, “RSSUpdatePanel”, “PostUpdatePanel”라는 id를 가진 UpdatePanel 컨트롤을 웹 폼에 생성한 후 UpdatePanel 컨트롤의 UpdateMode를 Conditional로 설정한다. 그리고, 이 3개의 <div>를 각각의 UpdatePanel 컨트롤의 하위로 이동시킨다. 또한, "AddUpdatePanel" UpdatePanel 컨트롤에는 “AddUpdateProgress"라는 id를 가지는 UpdateProgress 컨트롤을 추가하도록 한다. 새로운 UpdatePanel 컨트롤과, UpdateProgress 컨트롤을 추가한 후에 변경된 웹 폼의 소스는 <리스트 10>과 같다.

-------------------------------------------------------------------------------------------------------------------
<form id="RSSForm" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div id="content">
<asp:UpdatePanel ID="AddUpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div id="divAddRss" style="text-align:center;padding-bottom:20px;">
... ...
</div>
<asp:UpdateProgress ID="AddUpdateProgress" runat="server" AssociatedUpdatePanelID="AddUpdatePanel">
<ProgressTemplate>
<div style="text-align:center;padding-top:20px;padding-bottom:20px;">
<h5>처리중입니다</h5>
</div>
</ProgressTemplate>
</asp:UpdateProgress>
</ContentTemplate>
</asp:UpdatePanel>
<hr />
<asp:UpdatePanel ID="RSSUpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div id="divRssList" style="text-align:center;padding-bottom:20px;">
... ...
</div>
</ContentTemplate>
</asp:UpdatePanel>
<hr />
<asp:UpdatePanel ID="PostUpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div id="divPostList" style="text-align:center;padding-bottom:20px;">
... ...
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
-------------------------------------------------------------------------------------------------------------------
<리스트 10> 변경된 웹 폼의 소스 코드

코드 비하인드에서의 소스 코드 작성

마지막 작업으로, RssView.aspx의 코드 비하인드 파일인 RssView.aspx.cs 파일에 코드를 추가하도록 하겠다. using 선언부에 "using System.Xml;" 선언을 추가한 후, Page_Load 이벤트 핸들러에 현재 등록된 RSS 주소의 카운트를 가져오는 코드와, RSS 주소의 카운트가 0 이상일 경우에 주소 목록과 포스트 목록을 가져오는 <리스트 11>의 코드를 추가한다.

-------------------------------------------------------------------------------------------------------------------
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
lblCount.Text = CommonUtility.GetRssAddressCount();

if (int.Parse(lblCount.Text) > 0)
{
DisplayRssAddressList();
DisplayRssItemList("");
}
}
else
{
lblInValid.Visible = false
lblInValid.Text = string.Empty;
}
}
-------------------------------------------------------------------------------------------------------------------
<리스트 11> Page_Load 이벤트 핸들러 코드

다음으로는, 등록된 RSS 주소의 목록과 등록된 포스트(Item)의 목록을 가져오는 메소드를 <리스트 12>와 같이 정의한다.

-------------------------------------------------------------------------------------------------------------------
private void DisplayRssAddressList()
{
DataTable dtAddressList = CommonUtility.GetRssAddressList();

if (dtAddressList != null && dtAddressList.Rows.Count > 0)
{
gvRssList.DataSource = dtAddressList.DefaultView;
gvRssList.DataBind();
}

RSSUpdatePanel.Update();
}

private void DisplayRssItemList(string strLink)
{
DataTable dtItemList = CommonUtility.GetRssItemList(strLink);

if (dtItemList != null && dtItemList.Rows.Count > 0)
{
gvPostList.DataSource = dtItemList.DefaultView;
gvPostList.DataBind();
}

PostUpdatePanel.Update();
}
-------------------------------------------------------------------------------------------------------------------
<리스트 11> Page_Load 이벤트 핸들러 코드

다음으로는 가장 중요한, 추가 버튼을 클릭했을 때인 btnAddRssAddress_Click 이벤트 핸들러의 코드를 추가해보도록 한다. 우선 추가하고자 하는 RSS 정보에 대한 XmlDocument 정보를 CommonUtility 클래스의 GetRssData()메소드를 통해 얻어온다.

-------------------------------------------------------------------------------------------------------------------
XmlDocument xmlDoc = CommonUtility.GetRssData(txtRssAddress.Text.Trim());
-------------------------------------------------------------------------------------------------------------------

XmlDocument가 Null이 아닐 경우에는, 반환된 XmlDocument에서 channel 노드를 찾아서 xChannel 변수명을 가진 XmlNode에 값을 할당한 후, xChannel의 하위 노드 중에서 item 노드를 찾는다. item 노드가 없을 경우에는 lblInValid 변수명을 가진 Label 컨트롤에 Item이 없다는 메시지를 출력해준다.

-------------------------------------------------------------------------------------------------------------------
if (xmlDoc != null && xmlDoc.ChildNodes.Count > 0)
{
XmlNode xChannel = xmlDoc.SelectSingleNode("//channel");
XmlNodeList xItems = xChannel.SelectNodes("item");

if (xItems == null || xItems.Count == 0)
{
lblInValid.Visible = true;
lblInValid.Text = "추가하려는 RSS에 Item이 없습니다.<br /><br />"
}
}
-------------------------------------------------------------------------------------------------------------------

Item이 있을 경우에는, RSS에 대한 정보를 추가한다. 이 때, 이미 추가된 RSS 정보를 추가하려고 하면, lblInValid 변수명을 가진 Label 컨트롤에 입력된 RSS가 이미 존재한다는 메시지를 출력하도록 하고, 그렇지 않은 경우에는 Item 노드의 pubDate 노드의 날짜 정보를 변경 후에, Item 정보를 입력한다.

-------------------------------------------------------------------------------------------------------------------
string strAddChannel = CommonUtility.InsertRssAddress(strChannelTitle, strChannelLink, strChannelDesc);

if (string.Compare(strAddChannel, "EXIST", true) == 0)
{
lblInValid.Visible = true;
lblInValid.Text = "입력한 RSS 주소가 이미 존재합니다.<br /><br />"
}
else
{
xChannel = CommonUtility.ConvertToFitDateTime(xChannel);
string strAddItem = CommonUtility.InsertRssItems(strChannelLink, xChannel);
}

-------------------------------------------------------------------------------------------------------------------

정상적으로 데이터베이스에 데이터들이 입력이 되었으면, 등록된 RSS의 개수를 나타내는 lblCount 변수명을 가진 Label 컨트롤의 값을 +1 해주고, 추가된 RSS 정보에 대한 주소 목록과 포스트 목록을 다시 가져온다.

-------------------------------------------------------------------------------------------------------------------
txtRssAddress.Text = string.Empty;
lblCount.Text = (int.Parse(lblCount.Text) + 1).ToString();

DisplayRssAddressList();
DisplayRssItemList(strChannelLink);
-------------------------------------------------------------------------------------------------------------------

지금까지 설명한, btnAddRssAddress_Click 이벤트 핸들러의 코드의 전체 코드는 <리스트 12>와 같다.

-------------------------------------------------------------------------------------------------------------------
protected void btnAddRssAddress_Click(object sender, EventArgs e)
{
XmlDocument xmlDoc = CommonUtility.GetRssData(txtRssAddress.Text.Trim());

try
{
if (xmlDoc != null && xmlDoc.ChildNodes.Count > 0)
{
XmlNode xChannel = xmlDoc.SelectSingleNode("//channel");

string strChannelTitle = xChannel.SelectSingleNode("title").InnerText;
string strChannelLink = xChannel.SelectSingleNode("link").InnerText;
string strChannelDesc = xChannel.SelectSingleNode("description").InnerText;
XmlNodeList xItems = xChannel.SelectNodes("item");

if (xItems == null || xItems.Count == 0)
{
lblInValid.Visible = true
lblInValid.Text = "추가하려는 RSS에 Item이 없습니다.<br /><br />"
}
else
{
string strAddChannel = CommonUtility.InsertRssAddress(strChannelTitle, strChannelLink, strChannelDesc);

if (string.Compare(strAddChannel, "EXIST", true) == 0)
{
lblInValid.Visible = true
lblInValid.Text = "입력한 RSS 주소가 이미 존재합니다.<br /><br />"
}
else
{
xChannel = CommonUtility.ConvertToFitDateTime(xChannel);
string strAddItem = CommonUtility.InsertRssItems(strChannelLink, xChannel);

if (string.Compare(strAddItem, "OK", true) != 0)
{
lblInValid.Visible = true
lblInValid.Text = "Item 값을 입력하는 중 오류가 발생하였습니다.<br /><br />"
}
else
{
txtRssAddress.Text = string.Empty;
lblCount.Text = (int.Parse(lblCount.Text) + 1).ToString();

DisplayRssAddressList();
DisplayRssItemList(strChannelLink);
}
}
}
}
else
{
lblInValid.Visible = true
lblInValid.Text = "정상적인 RSS 주소값을 받지 못했습니다.<br /><br />"
}
}
catch (Exception ee)
{
lblInValid.Visible = true
lblInValid.Text = ee.Message + "<br />" + ee.InnerException + "<br /><br />"
}
}

-------------------------------------------------------------------------------------------------------------------
<리스트 12> btnAddRssAddress_Click 이벤트 핸들러 코드

마지막 코드인, 등록된 RSS 주소 목록을 선택할 경우, 포스트 목록이 변경되기 위한, gvRssList_RowCommand 이벤트 핸들러 코드는 다음과 같이 구성된다.

-------------------------------------------------------------------------------------------------------------------
string strChannelLink = e.CommandName;

DisplayRssItemList(strChannelLink);
-------------------------------------------------------------------------------------------------------------------

RSS Viewer 실행하기

Ctrl+F5 또는 디버그 메뉴의 디버깅하지 않고 시작을 선택하여, 브라우저에 Rss Viewer 화면을 실행시킨다.. 그리고, 새로운 RSS 주소인 ASP.NET News(http://www.asp.net/news/rss.ashx)를 입력한 후, 추가 버튼을 클릭하면, 등록된 RSS 주소 목록과 포스트 목록에 동시에 ASP.NET News에서 제공하는 정보가 나타나게 된다.


<화면 8> 새로운 RSS 정보가 추가된 화면

새로운 RSS 주소를 추가할 때, “처리중입니다...”라는 글자가 잠시 나타났다가 사라지는 것을 볼 수 있다. 이것은 btnAddRssAddress 변수명을 가진 ImageButton 컨트롤의 Click이벤트로 인하여 비동기 포스트백을 진행하고 있는 동안, AddUpdateProgress 변수명을 가진 UpdateProgress 컨트롤에 의해서 나타나게 되는 글자이다. UpdateProgress 컨트롤의 ProgressTemplate 안에 사용자에게 보여주고자 하는 글자 또는 이미지를 넣으면, 비동기 포스트백을 진행하고 있는 동안 사용자에게 보여지게 된다.


<화면 9> UpdateProgress 컨트롤에 의해 나타나는 진행 표시

계속적으로 ASP.NET Team Blogs(http://weblogs.asp.net/aspnet-team/rss.aspx)와 ASP.NET Weblogs(http://weblogs.asp.net/MainFeed.aspx?GroupID=4)를 추가한다. 그리고, 등록된 RSS 주소 목록의 목록에서 등록된 RSS 주소를 선택하면, <화면 10>과 같이 포스트 목록이 선택된 RSS 주소에 등록된 포스트의 목록으로 화면의 깜빡임 없이 변경되게 된다.


<화면 10> 선택된 RSS에 대해 포스트 목록이 변경되는 화면

포스트 정보 보기 기능 추가

RSS Viewer가 정상적으로 잘 동작하는 것을 볼 수 있다. 하지만, 포스트 목록에 나와있는 포스트를 누르면, 아무런 동작도 하지 않는다. 포스트 목록에 나와있는 포스트를 누를 경우 포스트에 대한 정보를 보여주도록 ASP.NET AJAX 컨트롤 툴킷 중 ModalPopUp Extender 컨트롤을 사용하도록 하겠다. 웹 폼에서, “panPopUp" 변수명을 가진 Panel 컨트롤을 찾은 다음에, 도구 상자의 AJAX Control ToolKit 탭에서 ModalPopUp Extender를 선택한 후, Panel 컨트롤 하단으로 추가시킨다. 그리고, 다음과 같이 소스를 변경한다.

-------------------------------------------------------------------------------------------------------------------
<cc1:ModalPopupExtender ID="modalItemInfo" runat="server"
TargetControlID="lblItemTitle" PopupControlID="panPopUp"
BackgroundCssClass="modalBackGround" CancelControlID="btnCancel">
</cc1:ModalPopupExtender>
-------------------------------------------------------------------------------------------------------------------
웹 폼을 저장하고, 다시 Ctrl+5 또는 디버그 메뉴의 디버깅하지 않고 시작 메뉴를 선택한 후, 포스트 목록에 나와있는 포스트명을 클릭하면 선택한 포스트에 대한 정보가 나타나게 된다.



<화면 11> 선택한 포스트에 대한 정보가 나타나는 화면

RSS Viewer의 활용

이것으로써, ASP.NET과 ASP.NET AJAX를 이용하여, RSS Viewer를 만드는 것에 대한 설명은 모두 끝났다. 만드는 프로그램 자체가 너무 단순하다는 생각을 지울 수는 없지만, ASP.NET과 ASP.NET AJAX를 사용하면 개발자가 많은 코딩 없이, 사용자에게 효과적인 인터페이스를 제공한다는 것을 보여주고자 했던 것인만큼, 이 글을 읽는 여러분이 ASP.NET AJAX를 사용해봐야겠다라는 불씨를 지핀 것으로만 만족하고자 한다. 앞으로도 기회가 된다면, ASP.NET AJAX를 이용한 실무에 도움되는 글을 여러분에게 제공한다는 말을 남기고 이만 줄이고자 한다. 혹, 이 글을 읽고 궁금한 점이 있거나, 좋은 아이디어가 있으신 분들은, 필자의 블로그(http://www.neostyx.net)으로 와서 글을 남겨주기 바란다.

-------------------------------------------------------------------------------------------------------------------
참고 자료
http://cyber.law.harvard.edu/rss/rss.html
http://www.asp.net/AJAX/Documentation/Live/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx
-------------------------------------------------------------------------------------------------------------------


Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

이 글은 월간 마이크로소프트웨어(일명 마소) 2008년 01월호 실전 강의실에 기고한 글입니다. 요즘 도통 포스팅을 할 수 없는 관계로 인해 대체합니다. ㅡ_ㅡ;; (하는 거 없이 바빠요~~~)


ASP.NET AJAX 웹 사이트 생성 및 웹 폼 구성

RSS 정보를 관리하는 데이터베이스가 만들어졌으므로, 이제 ASP.NET AJAX 웹 사이트를 만들어보도록 하겠다. Visual Studio 2005를 실행시킨 후, 새 웹사이트 메뉴를 선택한다. 새 웹 사이트를 만드는 창이 나타나면, <화면 5>와 같이 ASP.NET AJAX-Enabled Web Site 템플릿으로 선택한 후, 확인 버튼을 클릭하여, 새로운 웹 사이트를 생성한다.


<화면 5> 새 웹사이트의 생성

새롭게 웹 사이트가 생성이 되었으면, 새 항목 추가 메뉴를 이용하여 새로운 웹 폼을 추가한 뒤 웹 폼의 이름을 “RssView.aspx"라고 한다. 그리고, <head> 태그 사이에 웹 폼에서 사용할 스타일을 <리스트 6>과 같이 정의한다.

---------------------------------------------------------------------------------------------------
<style type="text/css">
td { font-size : 9pt font-family : "맑은고딕“ }
a img { border : 0 }
a:link { color : #636563 text-decoration : none font-weight : bold }
a:visited { color : #636563 text-decoration : none font-weight : bold }
a:active { color : #FFA600 text-decoration : none font-weight : bold }
a:hover { left : 1px color : #FFA600 position : relative top : 1px text-decoration : none }
.modalBackground { background-color : Gray filter : alpha(opacity=70) opacity : 0.7 }
#content { width : 500px padding : 10px margin-top : 50px margin-bottom : 20px margin-right : auto; margin-left : auto background : #ccc border : 3px solid #666 ; text-align:left }
.panPopUp { width : 450px height : 400px padding : 10px margin-top : 10px margin-bottom : 10px margin-right : auto; margin-left : auto background : #EEEEEE border : 3px solid #666 text-align : left vertical-align : middle overflow : auto }
</style>
---------------------------------------------------------------------------------------------------
<리스트 6> 웹 폼에서 사용하는 스타일 정의

또한, RSS 주소를 추가하기 위해 추가 버튼을 클릭할 경우, 추가할 RSS 주소를 입력했는지, 그리고 RSS 주소가 정확하게 “http://"로 시작하는지를 확인하기 위한 자바스크립트 함수를 <리스트 7>과 같이 <head> 태그 사이에 추가한다.

---------------------------------------------------------------------------------------------------
<script language="javascript" type="text/javascript">
function fnInputValid() {
var txtRssAddress = document.getElementById( "txtRssAddress" );

if ( txtRssAddress.value == "" ) {
alert( "URL을 입력하세요 );
txtRssAddress.focus();
return false;
} else {
if ( txtRssAddress.value.indexOf( "http://" ) < 0 ) {
alert( "http://로 시작하는 URL을 입력하세요" );
txtRssAddress.focus();
return false;
}
}

return true;
}
</script>
---------------------------------------------------------------------------------------------------
<리스트 7> 웹 폼에서 사용하는 자바스크립트 정의

스타일과 자바스크립트 코드를 웹 폼에 입력하였다면, 이제 실질적인 웹 폼 코드를 입력해보도록 하겠다. 웹 폼의 구조는 content라는 최상위의 div 태그 아래에 divAddRss, divRssList, divPostList라는 3개의 div 태그가 속한 구조로 되어 있다. <리스트 8>은 웹 폼의 전체 소스 코드를 보여준다.

---------------------------------------------------------------------------------------------------
<form id="RSSForm" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div id="content">
<div id="divAddRss" style="text-align:center;padding-bottom:20px;">
<h4>총<asp:Label ID="lblCount" runat="server" Text="0"></asp:Label>개의 주소가 등록되어 있습니다</h4>
추가할 주소를 입력하세요. :
<asp:TextBox ID="txtRssAddress" runat="Server" Width="200"></asp:TextBox>
<br /><br />
<asp:Label ID="lblInValid" runat="server" ForeColor="red" Visible="false"></asp:Label>
<asp:ImageButton ID="btnAddRssAddress" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/Images/btn_add.png"
OnClientClick="return fnInputValid()" OnClick="btnAddRssAddress_Click" />
</div>
<hr />
<div id="divRssList" style="text-align:center;padding-bottom:20px;">
<h4>등록된 주소 목록</h4>
<asp:GridView ID="gvRssList" runat="server" BackColor="White" BorderColor="#999999" BorderStyle="Solid"
BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical" ShowHeader="false"
AutoGenerateColumns="false" Width="100%" OnRowCommand="gvRssList_RowCommand">
<FooterStyle BackColor="#CCCCCC" />
<SelectedRowStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
<HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="#CCCCCC" />
<Columns>
<asp:TemplateField>
<ItemStyle HorizontalAlign="left" />
<ItemTemplate>
<asp:LinkButton ID="lbtnTitle" runat="server" Text='<%#Eval("title")%>'
CommandName='<%#Eval("link")%>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<hr />
<div id="divPostList" style="text-align:center;padding-bottom:20px;">
<h4>포스트목록</h4>
<asp:GridView ID="gvPostList" runat="server" BackColor="White" BorderColor="#999999" BorderStyle="Solid"
BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical" ShowHeader="false"
AutoGenerateColumns="false" Width="100%">
<FooterStyle BackColor="#CCCCCC" />
<SelectedRowStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
<HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="#CCCCCC" />
<Columns>
<asp:TemplateField>
<ItemStyle HorizontalAlign="left" />
<ItemTemplate>
<asp:Label ID="lblItemTitle" runat="server"><span style="cursor:hand"><%#Eval("title")%></span></asp:Label>
<asp:Panel ID="panPopUp" runat="server" Style="display:none">
<asp:Panel ID="panDesc" runat="server" CssClass="panPopUp">
<h4><a href="<%#Eval("link")%>" target="_blank"><%#Eval("title")%></a></h4>
<%#Eval("pubdate")%><br /><hr />
<%#Eval("description")%><br /><hr />
<center><asp:ImageButton ID="btnCancel" runat="server" ImageAlign="AbsMiddle"
ImageUrl="~/Images/btn_cancel.png" /></center>
</asp:Panel>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</div>
</form>
---------------------------------------------------------------------------------------------------
<리스트 8> 웹 폼의 전체 소스 코드

웹 폼에 관련된 코드 비하인드에서의 코드는 이후에, 순차적으로 소개를 하도록 하겠다. 우선 현재의 소스로 빌드를 해보면, 오류가 발생하게 될 것이다. 이러한 오류를 피하기 위해서, 웹 폼에 정의된 필요한 이벤트 핸들러들의 빈 코드를 다음과 같이 추가한다.

---------------------------------------------------------------------------------------------------
protected void btnAddRssAddress_Click(object sender, EventArgs e) { }
protected void gvRssList_RowCommand(object sender, GridViewCommandEventArgs e) { }
---------------------------------------------------------------------------------------------------

이제, 디버그 메뉴의 “디버깅하지 않고 시작” 또는 Ctrl+F5를 눌러, 웹 폼을 브라우저에서 보도록 하자. 다음과 같은 화면이 보이게 될 것이다.


<화면 6> RSS Viewer 화면

CommonUtility 클래스의 구성

위에서 생성한 웹 폼에서 데이터베이스의 데이터를 읽어오고, 저장하는 기능들과, 기타 다른 기능들을 제공하는 메소드들을 포함하는 CommonUtility 클래스를 만들어보도록 하겠다. 새 항목 추가 메뉴를 선택하여, 클래스 템플릿을 선택하고 클래스명을 <화면 7>과 같이 "CommonUtility.cs"라고 한다.


<화면 7> CommonUtility.cs 클래스의 생성

CommonUtility 클래스가 생성되었으면, using 선언부에 다음과 같은 네임스페이스를 추가한다.

---------------------------------------------------------------------------------------------------
using System.Data.SqlClient;
using System.Net;
using System.Xml;
---------------------------------------------------------------------------------------------------

다음으로, 데이터베이스에 연결하기 위한 연결 문자열에 대한 정보를 가지는 변수를 선언한다. (물론, 연결 문자열을 Web.Config의 <connectionStrings> 섹션에 정의하여도 상관은 없다.)

---------------------------------------------------------------------------------------------------
private static string strConnection="Server=localhost;DataBase=MASODataBase;UID=neostyx;PWD=;"
---------------------------------------------------------------------------------------------------

CommonUtility 클래스에는 다음과 같은 7개의 메소드가 추가되게 되며, 각각의 메소드의 설명은 다음과 같다.

- GetRssData() 메소드 : 입력받은 RSS 주소를 통해 반환되는 XML 정보를 XmlDocument로 반환한다.
- ConvertToFitDateTime() 메소드 : <Item>요소의 하위 요소인 <pubDate>의 날짜 정보를 변경한다.
- GetRssAddressCount() 메소드 : 등록된 RSS 주소의 카운트를 반환한다.
- GetRssAddressList() 메소드 : 등록된 RSS에 대한 기본 정보를 반환한다.
- GetRssItemList() 메소드 : 선택한 RSS에 대한 컨텐츠(Item) 정보를 반환한다.
- InsertRssAddress() 메소드 : 새로운 RSS 정보를 데이터베이스에 추가한다.
- InsertRssItems() 메소드 : 새로운 컨텐츠(Item) 정보를 반환한다.

CommonUtility 클래스의 전체 소스는 <리스트 9>와 같다.

---------------------------------------------------------------------------------------------------
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Net;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

public class CommonUtility
{
private static string strConnection
= "Server=localhost;DataBase=MASODataBase;UID=neostyx;PWD=;"

public CommonUtility()
{

}

public static XmlDocument GetRssData(string strURL)
{
HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(strURL);
httpReq.UserAgent
= HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"].ToString();
HttpWebResponse httpRes = (HttpWebResponse)httpReq.GetResponse();

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(httpRes.GetResponseStream());

return xmlDoc;
}

public static XmlNode ConvertToFitDateTime(XmlNode xChannel)
{
XmlNodeList xItems = xChannel.SelectNodes("item");

foreach (XmlNode xNode in xItems)
{
xNode.SelectSingleNode("pubDate").InnerText
= Convert.ToDateTime(xNode.SelectSingleNode("pubDate").InnerText).ToString("yyyy-MM-dd HH:mm:ss");
}

return xChannel;
}

public static string GetRssAddressCount()
{
string strReturn = string.Empty;

SqlConnection sqlCon = new SqlConnection(strConnection);
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "dbo.usp_GetRssAddressCount"
sqlCom.CommandType = CommandType.StoredProcedure;

sqlCon.Open();
strReturn = sqlCom.ExecuteScalar().ToString();
sqlCon.Close();

return strReturn;
}

public static DataTable GetRssAddressList()
{
DataTable dtReturn = new DataTable();

SqlConnection sqlCon = new SqlConnection(strConnection);
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "dbo.usp_GetRssAddressList"
sqlCom.CommandType = CommandType.StoredProcedure;

SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCom);
sqlDa.Fill(dtReturn);

return dtReturn;
}

public static DataTable GetRssItemList(string strLink)
{
DataTable dtReturn = new DataTable();

SqlConnection sqlCon = new SqlConnection(strConnection);
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "dbo.usp_GetRssItemList"
sqlCom.CommandType = CommandType.StoredProcedure;

sqlCom.Parameters.Add("@link", SqlDbType.VarChar, 200);
sqlCom.Parameters["@link"].Value = strLink;

SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCom);
sqlDa.Fill(dtReturn);

return dtReturn;
}

public static string InsertRssAddress(string strTitle, string strLink, string strDesc)
{
string strReturn = string.Empty;

SqlConnection sqlCon = new SqlConnection(strConnection);
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "dbo.usp_InsertRssChannel"
sqlCom.CommandType = CommandType.StoredProcedure;

sqlCom.Parameters.Add("@title", SqlDbType.NVarChar, 200);
sqlCom.Parameters["@title"].Value = strTitle;

sqlCom.Parameters.Add("@link", SqlDbType.VarChar, 200);
sqlCom.Parameters["@link"].Value = strLink;

sqlCom.Parameters.Add("@description", SqlDbType.NVarChar, 2000);
sqlCom.Parameters["@description"].Value = strDesc;

sqlCom.Parameters.Add("@result", SqlDbType.NVarChar, 5);
sqlCom.Parameters["@result"].Direction = ParameterDirection.Output;

sqlCon.Open();
sqlCom.ExecuteNonQuery();
sqlCon.Close();

strReturn = sqlCom.Parameters["@result"].Value.ToString();

return strReturn;
}

public static string InsertRssItems(string strLink, XmlNode xChannel)
{
string strReturn = string.Empty;

SqlConnection sqlCon = new SqlConnection(strConnection);
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "dbo.usp_InsertRssItem"
sqlCom.CommandType = CommandType.StoredProcedure;

sqlCom.Parameters.Add("@link", SqlDbType.VarChar, 200);
sqlCom.Parameters["@link"].Value = strLink;

sqlCom.Parameters.Add("@iteminfo", SqlDbType.NText);
sqlCom.Parameters["@iteminfo"].Value = xChannel.OuterXml;

sqlCom.Parameters.Add("@result", SqlDbType.NVarChar, 5);
sqlCom.Parameters["@result"].Direction = ParameterDirection.Output;

sqlCon.Open();
sqlCom.ExecuteNonQuery();
sqlCon.Close();

strReturn = sqlCom.Parameters["@result"].Value.ToString();

return strReturn;
}
}
---------------------------------------------------------------------------------------------------
<리스트 9> CommonUtility 클래스의 전체 소스 코드


Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형

이 글은 월간 마이크로소프트웨어(일명 마소) 2008년 01월호 실전 강의실에 기고한 글입니다. 요즘 도통 포스팅을 할 수 없는 관계로 인해 대체합니다. ㅡ_ㅡ;; (하는 거 없이 바빠요~~~)



ASP.NET을 이용하여, 사용자에게 친숙한 인터페이스 프로그래밍을 제공할 수 있는 확장 도구인 ASP.NET AJAX와 개발의 편의성을 제공되는 ASP.NET AJAX 컨트롤 툴킷이 나온지도 거의 1년이 넘었다. 이러한 장점을 바탕으로 한 ASP.NET AJAX에서 제공하는 확장 컨트롤과 ASP.NET AJAX 컨트롤 툴킷에서 제공하는 컨트롤을 이용하여 간단하게나마 RSS Viewer를 만들어보도록 하겠다.

필자가 ASP.NET을 접한 지 4년이라는 시간이 흘렀다. 이 기간 동안 ASP.NET을 가지고 프로젝트를 진행하는 사이트가 상당히 증가되었다는 점은 ASP.NET이 그만큼 사용자들에게 효율적이며, 개발자들에게 개발에 필요한 용이성을 제공해준다는 것을 인정받은 셈이다. 더더욱, 요즘 추세에 맞추어서 ASP.NET AJAX라는 ASP.NET과 궁합이 잘 들어맞는 프레임워크를 사용함으로써, ASP.NET의 단점이라 할 수 있는 불필요한 화면의 깜빡임을 없애고, 사용자에게 동적이고 파워풀한 기능을 보여줄 수 있게 되었다. 이번 호에서는 이 ASP.NET과 ASP.NET AJAX를 사용하여, 간단하게나마 사용자 자신이 등록한 RSS의 정보를 볼 수 있는 프로그램을 만들어보도록 하겠다.

RSS는 무엇인가?

웹 2.0의 시대에 들어서면서, 대다수의 사용자는 자신만의 인터넷 공간인 블로그를 가지고 있을 것이다. 사용자 자신의 자유로운 생각과 다른 인터넷 사용자들에게 필요한 정보를 포스트의 형태로 블로그에 등록하게 된다. 그래서, 인터넷 사용자가 자신에게 필요한 정보가 등록되어 있는 블로그를 찾게 되었을 때, 이를 즐겨찾기에 등록하거나 자신의 블로그로 해당 포스트를 등록하게 된다, 하지만 이러한 목록이 많아지게 되면, 정작 필요할 때 즐겨찾기에 등록한 블로그 목록을 선택해가며, 찾고자 하는 정보가 나와 있는 블로그를 다시 찾아야 하는 번거로움이 생길 수 있다. 이러한 불편함을 해소하기 위해 나온 것이 RSS이며, 이러한 RSS를 관리해 줄 수 있는 사이트 또는 프로그램을 이용하여 간편하게 정보를 찾을 수 있겠다. 필자의 경우는 한RSS를 통하여 이러한 정보를 제공하는 블로그 또는 사이트들을 관리하고 있다.


<화면 1> 한RSS 사이트

RSS의 구조는 이미 많은 사이트에서 내용을 알려주고 있고, 이 글을 읽고 있는 독자들도 어느 정도의 지식이 있다고 생각하므로, 간단하게RSS에 대한 설명을 하도록 하겠다.
RSS를 제공하고 있는 ““ASP.NET News””(http://www.asp.net/news/rss.ashx) 의 RSS 소스를 보면 다음과 같다.


<화면 2> Xml 형태로 구성되어 있는 RSS 정보

RSS는 Xml의 형태로 제공되고 있으며, 구조는 크게 요소와 요소의 하위에 속하는 으로 구분질 수 있다. <표 1>은, 요소에필요한 요소의 목록을 보여준다.


기타, 요소에 들어갈 수 있는 요소들이 더 있으나, 여기에서는 이 요소들에 대한 설명은 하지 않도록 하겠다. <표 2>는, 요소의 하위 항목들의 정의에 쓰이는 요소에 사용되는 요소의 목록을 보여준다.


대부분의 웹 사이트 또는 블로그에서 RSS에 대한 정보를 제공해줌으로, 사이트나 블로그를 사용하는 사용자들은 크게 신경을 쓰지 않아도 된다. 다만, 이러한 요소들로 RSS에 대한 정보가 제공된다는 것을 아는 것도 나쁘지는 않을 듯 하다.

데이터베이스의 생성 및 구성

먼저, ASP.NET 웹 사이트를 만들기 전에 RSS 주소를 등록, 삭제하고 RSS 주소에 들어있는 정보를 저장하기 위한 데이터베이스 및 테이블을 만들도록 하겠다. 먼저, SQL Server 2005를 실행시킨 후, 새 데이터베이스 생성 메뉴를 통해, 새로운 데이터베이스를 만들도록 한다. 데이터베이스의 명은 MASODataBase라고 한다.


<화면 3> MASO 데이터베이스의 생성

확인 버튼을 눌러 MASODataBase를 생성한다. 이제RSS 정보를 저장할 테이블을 만들도록 하겠다. 정보를 저장할RSS_CHANNEL 테이블과 정보를 저장할 RSS_ITEMS라는 2개의 테이블을 만든다. 각 테이블의 필드들은 다음과 같다.



이들 테이블의 관계는 <화면 4>와 같다.


<화면 4> RSS_CHANNEL 테이블과 RSS_ITEM 테이블의 관계

저장 프로시저의 생성 및 구성

지금 만들려고 하는 RSS Viewer 프로그램은, RSS 정보를 저장하고 읽어오는 과정을 저장 프로시저를 사용하여 처리할 것이다. 그러므로 웹 사이트를 만들기 전에 사용하는 저장 프로시저를 미리 만들어놓도록 한다. RSS Viewer 프로그램에 사용되는 저장 프로시저는 총 5개이며, 각 저장프로시저의 이름은 다음과 같다.

- dbo.usp_GetRssAddressCount
- dbo.usp_GetRssAddressList
- dbo.usp_GetRssItemList
- dbo.usp_InsertRssChannel
- dbo.usp_InsertRssItem

이제부터, 위에 나열한 저장 프로시저에 대한 설명을 하도록 하겠다. 우선, 첫 번째 저장 프로시저인 dbo.usp_GetRssAddressCount는 RSS_CHANNEL 테이블에 등록되어 있는 RSS 주소의 카운트를 가지고 오는 저장 프로시저로 <리스트 1>과 같이 구성되어 있다.

---------------------------------------------------------------------------------------------------
CREATE PROCEDURE [dbo].[usp_GetRssAddressCount]
AS
BEGIN
SELECT ISNULL(COUNT(channelid), 0) AS CNT
FROM dbo.RSS_CHANNEL WITH(NOLOCK)
END
---------------------------------------------------------------------------------------------------
<리스트 1> dbo.usp_GetRssAddressCount 저장 프로시저

두 번째 저장 프로시저인 dbo.usp_GetRssAddressList는 RSS_CHANNEL 테이블에 등록되어 있는 정보들을 반환하는 역할을 하며, <리스트 2>와 같이 구성되어 있다.

---------------------------------------------------------------------------------------------------
CREATE PROCEDURE [dbo].[usp_GetRssAddressList]
AS
BEGIN
SELECT channelid, title, link
FROM dbo.RSS_CHANNEL WITH(NOLOCK)
END
---------------------------------------------------------------------------------------------------
<리스트 2> dbo.usp_GetRssAddressList 저장 프로시저

세 번째 저장 프로시저인 dbo.usp_GetRssItemList는 @link 파라미터를 통해, RSS_CHANNEL 테이블에 등록되어 있는 link 필드에서 @link 파라미터와 동일한 channelid를 찾은 후, RSS_ITEM 테이블의 channelid 필드의 값과 동일한 channelid 값을 가지는 행들의 정보를 반환하는 역할을 하며, <리스트 3>과 같이 구성되어 있다.

---------------------------------------------------------------------------------------------------
CREATE PROCEDURE [dbo].[usp_GetRssItemList]
(
@link VARCHAR(200)
)
AS
BEGIN
DECLARE @channelid INT

IF @link = ''
BEGIN
SELECT @channelid = (SELECT TOP 1 ISNULL(channelid, 0)
FROM dbo.RSS_CHANNEL WITH(NOLOCK) ORDER BY channelid ASC)
END
ELSE
BEGIN
SELECT @channelid = (SELECT ISNULL(channelid, 0)
FROM dbo.RSS_CHANNEL WITH(NOLOCK) WHERE link = @link)
END

IF @channelid <> 0
BEGIN
SELECT title, link, description, pubdate
FROM dbo.RSS_ITEM WITH(NOLOCK)
WHERE channelid = @channelid
ORDER BY itemid ASC
END
END
---------------------------------------------------------------------------------------------------
<리스트 3> dbo.usp_GetRssItemList 저장 프로시저

네 번째 저장 프로시저인 dbo.usp_InsertRssChannel 저장 프로시저는 새로운 RSS 주소를 추가할 때의 RSS 주소의 기본 정보를 저장하는 저장 프로시저로, <리스트 4>와 같이 구성되어 있다.

---------------------------------------------------------------------------------------------------
CREATE PROCEDURE [dbo].[usp_InsertRssChannel]
(
@title NVARCHAR(200)
, @link VARCHAR(200)
, @description NVARCHAR(2000)
, @result VARCHAR(5) OUTPUT
)
AS
BEGIN
IF EXISTS ( SELECT link FROM dbo.RSS_CHANNEL WITH(NOLOCK) WHERE link = @link )
BEGIN
SET @result = 'EXIST'
END
ELSE
BEGIN
INSERT INTO dbo.RSS_CHANNEL WITH(ROWLOCK) (title, link, description)
VALUES (@title, @link, @description)

SET @result = 'OK'
END
END
---------------------------------------------------------------------------------------------------
<리스트 4> dbo.usp_InsertRssChannel 저장 프로시저

마지막 저장 프로시저인 dbo.usp_InsertRssItem는 dbo.usp_InsertRssChannel 저장 프로시저와 마찬가지로, 새롭게 추가된 RSS 주소에 속한 Item의 기본 정보를 저장하는 저장 프로시저로, <리스트 5>와 같이 구성되어 있다.

---------------------------------------------------------------------------------------------------
CREATE PROCEDURE [dbo].[usp_InsertRssItem]
(
@link VARCHAR(200)
, @iteminfo NTEXT
, @result VARCHAR(5) OUTPUT
)
AS
BEGIN
DECLARE @channelid INT
DECLARE @pDoc INT

SELECT @channelid = (SELECT channelid FROM dbo.RSS_CHANNEL WITH(NOLOCK)
WHERE link = @link)

EXEC sp_xml_preparedocument @pDoc OUTPUT, @iteminfo

INSERT INTO dbo.RSS_ITEM WITH(ROWLOCK)
(channelid, title, link, description, pubdate)
SELECT @channelid, title, link, description, pubdate
FROM OPENXML (@pDoc, '//channel/item', 2)
WITH (
title NVARCHAR(200) 'title'
, link VARCHAR(200) 'link'
, description NTEXT 'description'
, pubdate DATETIME 'pubDate' )

EXEC sp_xml_removedocument @pDoc

SET @result = 'OK'
END
---------------------------------------------------------------------------------------------------
<리스트 5> dbo.usp_InsertRssItem 저장 프로시저

저장 프로시저를 만들었다면, 이제 RSS Viewer를 만들기 위한 ASP.NET AJAX 웹 사이트를 만들어보도록 하자.


Creative Commons License
저작물크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
반응형
반응형
CREATE TRIGGER 트리거 이름
ON { 테이블이름 | 뷰이름}
[ WITH ENCRYPTION ]
{ FOR | AFTER | INSTEAD OF }
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
AS
    실행할 SQL 문들

* WITH ENCRYPTION : 트리거의 내용을 암호화시켜서 추후에 내용을 확인할 수 없도록 한다.
* FOR | AFTER | INSTEAD OF : AFTER를 지정하면 해당 테이블에 작업이 수행되고 작업이 정상적으로
 끝난 후에 트리거의 내용이 실행된다. AFTER는 테이블에 대해서만 지정할 수 있으며, 뷰에 대해서는
 지정할 수 없다.
 INSTEAD OF는 테이블 및 뷰에 지정할 수 있지만 뷰에 많이 사용된다. INSTEAD OF를 지정하고 해당
 테이블이나 뷰에 지정한 SQL(INSERT, UPDATE, DELETE)이 작동하면 시도된 SQL은 무시되고
 트리거에 지정된 SQL문이 대신 작동하게 된다. FOR는 AFTER와 동일한 것으로 생각하면 된다.
* INSERT | UPDATE | DELETE : 트리거가 실행되는 이벤트를 지정한다. 하나 이상으로 조합해서
 작동시킬 수 있다.
반응형
반응형
DECLARE cursorTbl_cursor CURSOR
    FOR SELECT LineTotal FROM cursorTbl;

DECLARE @result CURSOR
EXEC sp_describe_cursor @cursor_return = @result OUTPUT,
        @cursor_source = N'GLOBAL',  -- 커서임을 지정
    @cursor_identity = N'cursorTbl_cursor'  -- 커서 이름 지정

FETCH NEXT from @result
WHILE (@@FETCH_STATUS <> -1)
        FETCH NEXT FROM @result



결과중 model :
1 - STATIC(정적)
2 - KEYSET(키 집합)
3 - DYNAMIC(동적)
4 - FAST_FORWARD(빠른 전진)

concurrency :
1 - READ_ONLY(읽기전용)
2 - SCROLL_LOCKS(스크롤 잠금)
3 - OPTIMISTIC(낙관적)

status :
-1 - 커서가 아직 열리지 않은 상태

cursor_scope :
1 - 지역커서
2 - 전역커서

반응형

+ Recent posts

반응형