lecture Home > ASP.NET > .NET Board

.NET 게시판 강좌 - 김연진님 제공

   강좌 최초 작성일 : 2001년 09월 10일
   강좌 최종 수정일 : 2001년 09월 20일

   작성자 : Cassatt(김 연진)
   편집자 : Taeyo(김 태영)

   강좌 제목 : 컴포넌트를 이용해보자

컴포넌트를 이용해보자

asp는 객체지향과는 거리가 멀었습니다. vbscript 5.0부터는 class 가 지원 되었지만, 퍼포먼스 문제로, 혹은 이런 저런 다른 문제로 잘 사용하지 못했습니다.

객체지향식으로 프로그래밍하면, 기본이 되는 객체를 하나 만들어두고, 거기서 원래 객체가 가지고 있는 모든 메서드와 속성을 "상속" 받은 객체를 만들 수 있습니다. 그런데 vbscript 5 에서 class를 사용하기 꺼려졌던 것은, 페이지가 로드될때마다 항상 그 모든 class 정의가 번역(interprete)되어야 한다는 것입니다. 세번 상속되고 각각의 class가 각각의 파일에 저장되어 있다면 include문을 세번써야 한다는 얘기가 됩니다. 그럼 그 각각을 매번 번역합니다. 이건 요새 컴퓨터가 아무리 빠르다지만 꺼려지는 일입니다다. 차라리 함수를 여러 파일에 나눠서 넣어두고, 필요한 함수를 가진 작은 파일만 include하는 것이 낫습니다. ( class는 그 안에 모든 메서드를 넣어야 하기 때문에, 나눌 수가 없습니다 )

* 그럼에도 class는 한번 써보시기 권합니다. class로 만들어진 소스는 vb로 금방 포팅해서 dll로 만들 수 있습니다. asp 소스는 약간만( New -> Server.CreateObject ) 변하면 됩니다. 현재의 com dll은 디버깅하기가 나쁘기 때문에, vbscript의 class로 만들고 테스트한 후 포팅하는 것이 나을수 있습니다.

COM은 객체지향에 가까왔지만, 상속이 없어서 완전한 객체지향이라 하기 어려 웠습니다. VB는 상속이 없고, C++은 물론 상속되지만, COM 개체를 만들면 거기서 상속은 끝입니다. 즉, 미리 정의되어 있는 개체에서 상속받아 새로운 개체를 만들 수는 있지만, 그 전체는 하나의 파일(dll이든, exe든)로 만들어지고, 더이상의 상속은 없습니다. ( 어느 dll에서 상속받은 다른 dll을 정의하거나 할 순 없다는 뜻입니다. )

상속은 객체지향에서 매우 중요한 부분중 하나입니다. 상속을 통해서, 코드 재사용성이 늘어납니다.
그런데, 여기 좋은 소식(?) 이 있습니다. 닷넷은 객체지향언어이기에 상속이 될 뿐만 아니라, dll 간에도 상속할 뿐더러, vb로 만든 dll을 c#에서 상속받아서 다른 dll 만들고, 그걸 JScript에서 사용할 수도 있습니다. 이건 ( 개인적으로 ) 매우 놀랍고 반가운 일이었습니다.

그리고

  • RegSvr32로 dll을 등록할 필요가 없습니다. 루트에 /bin 폴더를 만들고 몰아넣으면 됩니다.
  • dll에는 lock이 안걸립니다. 전에는 dll을 다시 컴파일해서 저장하려 하면 dll이 이미 사용중인경우 lock이 걸려있어서 저장이 안되었습니다. lock을 풀기 위해 웹사이트를 프로세스 격리상태에서 실행하거나, 혹은 IIS를 셧다운하거나, 심한경우 NT 자체를 부팅시켜야 했었습니다.
요약 정리한 결론은, 이젠 dll을 집에서 컴파일해서, ftp로 서버에 업로드해도 된다는 것입니다. IDC센터에 있는 서버의 dll을 집에서 디버깅 해본 분은 그 차이를 아실 겁니다. ( 해봤는데, 할짓이 못됩니다 ^^; )
암튼,
  • com을 쓰자니 디버깅/유지보수가 힘들다.
  • vbscript class 사용하자니 interpreter라, 퍼포먼스가 맘에 걸린다.
이 상황이
  • 레지스트리에 등록할 필요가 없고, lock도 안걸리니 디버깅/유지보수가 asp 페이지 짜는 것보다 그리 나쁘지 않다.
  • 컴파일되므로 빠르다.

이렇게 바뀌게 됩니다. 전에는 asp를 중심으로, 꼭 필요한 부분만 COM 개체로 만들었다면, 이제는 아마도, cs(혹은 vb) 파일을 중심으로 하고, 화면처리 관련 로직만 aspx에 넣게 될 것입니다.


서론이 좀 길었습니다. 이제, 게시판에 쓰일 컴포넌트를 직접 만들면서 설명해 보겠습니다. 하나하나 설명하면서 진행하면 너무나 많은 분량이 될것 같아서, 우선 만들고 나서 간략히 설명하는 방식으로 진행하고자 합니다.

이번 강에서는 게시판의 틀이 될, 기본 컴포넌트 세개를 만들게 됩니다. 하나는 DB 연결 문자열(connection string)을 얻어오는 간단한 기능의 cstConnectionString이라는 개체이고, 두번째는 DB Connect와 close만 전담하는 DBConnectedObject라는 개체입니다. 그리고 세번째는 DBConnectedObject를 상속받은 OrderedTableReader 라는 개체로, 게시판/방명록/공지사항등의 뼈대가 될 개체입니다. ( 물론 지금은 게시판만 만들지만, 나중에 재사용을 위한 것입니다 )

컴포넌트를 만들게 되면 설계가 매우 중요해 집니다. 재사용성, 유지보수 용이 같은, 컴포넌트의 장점을 최대한 활용할 수 있어야 하기 때문입니다.

그런데, 앞으로 만들게 될 컴포넌트는 아마도, 좀 특이한 구조가 될것 같습니다. ^^; 이러한 형태의 설계가 좋다는 것은 전혀 아니며, 여러분도 여러분 나름의, 최적의 설계를 찾아내길 바랍니다. 설계엔 정답이 없다는 생각입니다. ( 좋은 설계는 물론 있겠지만요 )

첫번째로 만들어 볼것은 DB 연결 문자열(connection string)을 관리할 개체입니다. 이 개체를 만들면서, C#의 개체와 web.config라는 설정파일, 그리고 컴파일 방법을 한꺼번에 도매금으로 넘기렵니다. ^^;

참, 들어가기전에, c#은 vb와 달리 대/소문자를 구별한다는 점을 강조하겠습니다. c#으로 작성하다 에러가 나면, 1) 세미콜론을 보시고, 2) 대소문자를 보시기 바랍니다. 그럼 아마도 에러의 반은 잡으실 겁니다.

/bin/cstDB.cs :
using System;
using System.Configuration;

namespace cstDB {

   public class cstDBConnectionString {
      public static String connectionString {
        get {
          return ConfigurationSettings.AppSettings["connectionString"];
        }
      }
   }
}

위 파일을 루트폴더 밑 /bin 폴더에( 없으면 만듬) cstDB.cs 로 저장합니다. 그리고 컴파일하는데요,
시작버튼->실행에서 cmd(win98에선 command.com)를 실행시킨 후 [root]/bin 폴더로 이동합니다. 예를 들어 웹사이트의 root 폴더가 c:\wwwroot라면, 다음 처럼 csc를 이용하여 컴파일합니다.

c:\>cd wwwroot
c:\wwwroot>md bin <- 디렉터리 만듬.
c:\wwwroot>cd bin
c:\wwwroot\bin>csc /t:library /out:cstDB.dll /debug+ /optimize+ cstDB.cs

이러면 폴더에 cstDB.dll 이란 파일이 생길것입니다. 에러가 난다면, 대소문자등을 주의해서 다시 소스를 살펴봅니다.

csc는 c-sharp-compiler의 약자로, c# 프로그램을 컴파일 할때 쓰입니다. 항상 위처럼 키보드로 치기는 불편하니까, .bat 배치 파일을 만들어 사용하면 편합니다. ( 소스에는 mkcstboard.bat로 되어 있습니다 )
여러 옵션이 있는데, 위에 쓰인 옵션만 설명하면 다음과 같습니다.

  • /t:library : 파일을 dll로( exe가 아닌) 컴파일합니다
  • /out:cstDB.dll : 컴파일된 파일은 cstDB.dll로 저장될 것입니다.
  • /debug+ : 디버그 모드로 컴파일합니다. 이 옵션을 주면, 런타임 에러가 났을때 에러가 난 줄번호도 알려주기 때문에 편리합니다. 디버깅이 끝난 후 이 옵션을 빼고 다시 컴파일하면 됩니다.
  • /optimize+ : 최적화 시켜서 컴파일합니다.
cstDB.cs 이후에는 해당 dll에 포함될 소스파일 이름을 적어줍니다. 여러 파일이면 한칸씩 띄면서 모두 적어주시면 됩니다.

설정파일: /cstBoard/web.config
<configuration> 
    <appSettings>
          <add key="connectionString" 
                 value="server=localhost;uid=yourID;pwd=yourPassword;database=yourDB" />
    </appSettings>
</configuration>

이 파일을 /cstBoard/web.config 파일에 저장합니다. 물론 connectionString 값은, 자신의 DB userid, password, db로 설정하면 됩니다. web.config에는 여러 설정값이 들어갑니다. dot.net 설치가 잘 되었다면, root 폴더에 web.config라는 파일이 있을 것입니다. 이 파일을 변경해서, 웹사이트의 세부사항을 조정할 수 있습니다.

web.config는 웹사이트에 대한 설정사항을 저장해 두는 파일입니다. 여기서는 다만, connectionString을 저장하기 위해서만 사용하였지만, 많은 내용이 있습니다. 다른 분의 강좌에 의해 채워지리라 기대합니다.

* text 파일에 DB 암호를 저장한다는 것이 보안상 마음에 걸릴 수 있으리라 생각합니다. 우선 web.config는 url로 직접 보려하면, "This type of page is not served"라는 에러가 나고 말기 때문에 어느정도는 안전하지만, 그럼에도 예전의 ::$data나 %cc 경우처럼 완전히 믿을 수는 없습니다. 이에 대해서 많은 논의가 있었으면 합니다.
* 이파일이 완전한 xml 파일이기 때문에, 대소문자도 엄격히 따진다는 점도 주의합니다.

테스트: /cstBoard/dsnTest.aspx

<%@ Import Namespace="cstDB" %>

<script language="c#" runat="server">
  string ConnStr;

  void Page_Load( Object o, EventArgs e )
  {
     ConnStr = cstDBConnectionString.connectionString;
     DataBind();
  }
</script>

연결 문자열 : <%# ConnStr %>

이 페이지를 실행해서, web.config 파일에 저장한 connectionString 값이 나오면 성공입니다.

지금 만든 것은, DB 연결 문자열 ( connection string )을 제공하는 class입니다. 이 개체는 connectionString 이라는 static 프로퍼티 하나만 제공합니다. static 메서드는, 해당 개체에 대한 참조 없이도 실행될 수 있는 메서드입니다. 지금 쓰이는 개체가 어느 개체인지 몰라도 실행가능할때, static으로 하게 됩니다. ( 쉽게 설명을 못해 죄송 ) 그냥, 전에 쓰였던 전역 변수, 전역 함수를 c#에서 쓰고 싶으면 아무 개체에나 몰아넣고 앞에 static을 붙여주면 된다고 이해하시면 됩니다.

어쨌건, 그럼 결론은?

ConnStr = cstDBConnectionString.connectionString;

어느 페이지에서건, <%@ Import Namespace="cstDB" %> 처럼 해서(혹은 c# 소스 파일이라면 using cstDB; ) 해당 namespace를 사용할 수 있도록 하고, 소스 중간에 cstDBConnectionString.connectionString 로 연결문자열을 알아낼 수 있다는 것입니다.

이것은 ibuyspy.com의 beta1 버젼 소스에서 사용된 방식을 약간 바꾼 것입니다. 이렇게 연결 문자열을 하나의 방식으로 관리를 하면, 나중에 암호가 변경되던가 할때 편해집니다. 위에서는 web.config 설정 파일을 이용하였습니다. DB 암호가 바뀐다면, web.config 파일을 바꾸면 됩니다. 보안이 마음에 걸린다면, connectionString 프로퍼티 의 코드를 원하는 방식으로 변경하고 재 컴파일하면 됩니다.

여기서 말하고자 하는 요점은, 하나의 방식으로 통일하는 것이 좋다는 것입니다. 전에 asp 초보일때, 각각의 페이지 마다 연결 id/암호를 넣어서 open 했었는데, %cc 로 소스가 뚫리는 바람에 암호를 바꾸느라 고생한 적이 있습니다. 그때 회사 웹서버 소스의 DB컨넥션 부분만 빼서 모두 <!--#include virtual="/include/dbopen.asp"--> 식으로 include 문으로 바꾸었습니다. 이 방식으로 보안 문제가 완전히 해결된 것은 아니었지만, 적어도 다음부터는 암호를 바꾸거나, ODBC 연결을 OLE-DB 연결로 바꾸는 것 같은 작업이 수월해졌습니다.

소스를 잠깐 설명하고 넘어갑니다.

using System.Configuration;

aspx 에서 DB 관련 개체를 사용하기 위해 <%@ Import Namespace="System.Data.SqlClient" %>를 썼던 것 처럼, 어떤 개체를 사용하려면 그 개체가 속한 namespace를 Import 해와야 합니다. 이후 ConfigurationSettings 개체를 사용하기위해 System.Configuration을 사용한다고 선언하였습니다.

namespace cstDB {
...
}

이것은 using과 반대로, 다음 부터 만들어질 개체가 어떤 namespace에 속할지 알려주는 부분입니다. 여기서는 cstDB에 속한다고 하였으므로 중괄호( { } ) 안의 모든 개체는 cstDB라는 namespace에 속하게 됩니다. 이렇게 하고 컴파일해서 [root]/bin 디렉터리에 넣어두면 그 웹사이트의 모든 페이지에서는 <%@ Import Namespace="cstDB" %> 를 추가하고, cstDB 내의 개체를 사용할 수 있게 됩니다.

   public class cstDBConnectionString {
      public static String connectionString {
        get {
          return ConfigurationSettings.AppSettings["connectionString"];
        }
      }
   }

여기서 cstDBConnectionString이라는 개체를 정의해 주었는데, connectionString이라는 static 프로퍼티 하나만 정의해 주고 있습니다. 이 프로퍼티의 코드는 , 조회(get)할 경우 설정 파일(web.config)에서 appSettings 태그에 connectionString라는 키key로 정의된 값을 가져오는 것입니다. 실제로 쓰일때는 connectionString은 다른 속성값 처럼 (메서드와 달리) 괄호 없이 쓰이지만, 블럭 내에서 정의 해준 get, set에 의해 동적으로 값을 주고 받게됩니다. 위에서는 set은 쓰이지 않았는데, 만약 변동도 가능한 속성이면 대략 다음처럼 하게 됩니다.

    public String aProperty {
      get { // 이것은 a = 개체.aProperty 형태의 문장일때 실행된다.
        ... 값을 구한 후,
        return 값;
      }
      set { // 이것은 개체.aProperty = a 형태의 문장일때 실행된다.
        .. value 값을 이용해서 처리한다.
        xx = value;
      }
    }

이제 두번째로 여기에, 앞으로 여러 개체를 파생할 예정인 기본 개체 두개를 추가시킵니다. cstDB.cs를 다시 편집하여, 다음처럼 만듭니다.

( * 이 파일에서 OrderedTableReader 부분은 앞으로도 계속 첨삭됩니다 )

/bin/cstDB.cs
using System;
using System.Web;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace cstDB {

   public class cstDBConnectionString {
      public static String connectionString {
        get {
          return ConfigurationSettings.AppSettings["connectionString"];
        }
      }
   }

   public class DBConnectedObject : IDisposable {
       
       protected SqlConnection dbConnection;

       public DBConnectedObject()
       {
           dbConnection = 
              new SqlConnection( cstDBConnectionString.connectionString );
           dbConnection.Open();
       }

       public void Dispose()
       {
          dbConnection.Close();
       }

   }

   public class OrderedTableReader : DBConnectedObject {
       
       protected String tableName;
       protected String orderedFieldName;

       public OrderedTableReader( String _tableName, 
                                  String _orderedFieldName ) : base()
       {
         tableName = _tableName;
         orderedFieldName = _orderedFieldName;
       }

       // ... 앞으로 여러 메서드가 추가된다.

    }
}

이제 두개의 개체가 추가 되었습니다.

1. DBConnectedObject

이 개체는 DB 연결 개체인 dbConnection 이란 프로퍼티 하나만 갖고 있고, 그 개체를 열고 닫는 역할만 합니다.

   public class DBConnectedObject : IDisposable {

       protected SqlConnection dbConnection;

우선 DBConnectedObject는 IDisposable이란 인터페이스( 개체가 아님 )를 이용합니다. IDisposable 인터페이스를 상속하는 개체는 잠시후 설명합니다. DBConnectedObject는 SqlConnection 개체인, dbConnection 이라는 프로퍼티 하나만 가집니다.

       public DBConnectedObject()
       {
           dbConnection = new SqlConnection( cstDBConnectionString.connectionString );
           dbConnection.Open();
       }

개체 이름과 같은 이름의 메서드는 생성자라 불리우는데, 개체가 만들어질때 실행됩니다. 코드에 의하면 개체가 new에 의해 만들어질때, DB에 연결하게 됩니다

       public void Dispose()
       {
          dbConnection.Dispose();
       }

Dispose는, IDiposable 인터페이스, 나중에 설명할 using과 함께 사용되어서, 개체가 더이상 필요없게 될때 호출되는 메서드입니다. 앞의 class 정의에서 이 개체가 IDisposable 인터페이스를 사용하는 것을 보았는데, IDisposable을 사용하게 되면 Dispose를 구현해야 합니다. 위에선 SqlConnection의 Dispose()를 호출하는데요, SqlConnection.Dispose()는 컨넥션을 닫는것 포함해서, 메모리에서 개체를 제거하는 일을 합니다.

java나 C# 에서, garbage collector를 사용한다는 들어보셨을 것입니다. garbage collector란, cpu가 하는 일이 없거나 메모리가 부족할때 실행되어서, 메모리에 할당된 것들 중 필요없는 것들(쓰레기, garbage)을 수집해서(collect) 없애는 역할을 하는 스레드입니다. 이것이 있기 때문에, java나 c#에선 메모리가 필요하면 할당만 할 뿐, 지우진 않습니다. 즉, new 는 있어도 delete 는 없습니다. ( c나 c++에선 할당했으면 꼭 지워야 합니다. 코딩에 약간이라도 실수가 있거나하면 모르는 새에 메모리 누수가 일어나고, 컴퓨터를 죽일(?) 수 있습니다 ) garbage collector가 있기 때문에, 메모리에 신경쓰지 않고 맘편히 작업할 수 있게 되었습니다.

그런데 garbage collector는 앞서 썼듯, cpu가 한가하거나 메모리가 부족할때 실행됩니다. 그 말은 바꿔말하면 cpu가 한가하지 않는한 메모리가 부족해 질때가 되어서야 실행된다는 뜻입니다. 이것은 db connection인 경우엔 좋지 않습니다. 예전 ASP때 그랬지만, 사용할 필요가 없을땐 빨리 닫아버리는 것이 낫습니다. 굳이 메모리가 부족해질 때까지 기다릴 필요가 없으니까요.

* DB 사용이 끝났으면 빨리 Close() 하는것이 좋다는 건 닷넷도 마찬가집니다. Close() 해야 Connection Pool로 들어가고, 컨넥션 풀에 컨넥션이 있어야 다른 사용자 연결때 즉시 제공될 수 있습니다.

얘기가 좀 길어졌는데, DBConnectedObject 개체 만든 것이, 이런 작업을 좀 편하게 하려는 것입니다.

IDisposable 인터페이스 쓰는 개체를 사용할때는, 다음 예처럼 using을 쓰게 됩니다.

using( DBConnectedObject aObject = new DBConnectedObject() ) {
   .... 이런 저런 작업
}

using 블럭을 빠져나갈때면, using에서 사용한다고 한 개체(위에서 aObject)의 Dispose() 메서드를 호출해줍니다. ( 즉, DBConnectionObject 경우 컨넥션을 닫아줍니다 ) 이렇게 되면 일일히 Close() 문으로 DB를 닫지 않아도 됩니다. 일일히 닫아줘도 되지만, ... ^^; 전에 ASP 코딩할때 이게 매우 귀찮았었습니다. open 후 에러 검사로 중간에 빠져나가는 경우에도 일일히 close를 넣어줘야 하다 보니,... 코드가 너무 지저분해져서 그냥 안하고 만 경우가 좀 있었습니다.

아무튼, 내용이야 어떻건, 중요한 것은 결론이 뭐냐는 것이고, 다음에 사용할 사람은 결론만 알면 됩니다. 결론은 - DBConnectedObject 를 상속한 모든 개체는, using 문을 쓰는 한, dbConnection 열고 닫는건 신경꺼도 된다는 것입니다. 생성될때 연결되고, 필요없어질때 Dispose()되는 것이 보장되므로, 그냥 컨넥션은 언제나 열려있다고 가정하고 작업하면 됩니다. 그리고 그 개체를 사용할때 using() { } 블럭을 쓰는 것만 잊지 않으면 됩니다.

* 여기엔 몇가지 고려할 점이 있습니다. 우선, SqlConnection 자체가 앞서 보았듯, IDisposable 인터페이스를 구현하기 때문에 using 쓰면 되고요, SqlCommand.ExecuteReader 경우 CommandBehavior.CloseConnection 를 인수로 주어서 호출하면, 모두 읽고나면 자동으로 컨넥션이 닫히죠. ibuyspy.com 소스경우 이것을 이용하는데요, 이 편이 SqlConnection.Close()의 귀찮음을 줄이는데(?) 더 나을 수 있습니다. 설계엔 여러 방법이 있고, 이게 꼭 좋다는건 아니라는 점을 말씀드리고 싶습니다.

 

2. OrderedTableReader 개체

이 개체는 순서대로 정렬되어 출력되는 것들을 위해 만든 개체입니다. 게시판, 방명록, 공지사항등, asp에서 많은 부분을 차지하는 것들이 보통 역순으로 ( 최근글이 앞에 오도록 ) 정렬되어 출력됩니다. select 문으로 치면

select * from tableName order by fieldName desc

형태로 정렬되는 것들입니다. 그러한 개체들은 모두 이 OrderedTableReader를 상속받게 됩니다. 이번에 다루진 않지만, 답변형 게시판 경우도, 제 경우 순서를 필드 하나만으로 하고, 이 개체에서 상속받아서 만들 수 있었습니다. 방명록, 공지사항, 자료실 등등, 거의 모든 게시판 형태에 적용하려고 만든 개체입니다.

   public class OrderedTableReader : DBConnectedObject {
       
       protected String tableName;
       protected String orderedFieldName;

       public OrderedTableReader( String _tableName, 
                                  String _orderedFieldName ) : base()
       {
         tableName = _tableName;
         orderedFieldName = _orderedFieldName;
       }

       // ... 앞으로 여러 메서드가 추가된다.
    }

DBConnectionObject에서 상속받고, 생성자에서 테이블이름과 순서의 기준이될 필드의 이름을 받습니다. ( 즉, 만약 OrderedTableReader를 사용하게 되면 OrderedTableReader otr = new OrderedTableReader("cstBoard", "seq") 식으로 생성합니다 )

순서대로 정렬된 테이블에서 일부 의 레코드를 뽑아오는 것 ( 예를 들어, 30 번째 부터 50 번째까지 ) 은 게시판, 공지사항, 방명록 모두 중복됩니다. 나중에 구현하겠지만, 어느 테이블 몇번째서 부터 몇 번째까지의 레코드만 뽑아내는 것, 레코드의 총 갯수를 세는 것, 어느 글의 이전글과 다음글을 구하는 것 등 여러 곳에서 중복되는 것들을 이 OrderedTableReader에 넣을 생각입니다.


순서가 잘못된것 같다는 생각도 드네요( asp 하기도 전에 com dll먼저 만드는 것 같은 ^^ ). 좀 복잡하더라도, 컴포넌트 중심인 asp.net을 강조하려다 보니, 개체 정의 부터 들어가게 되었습니다. 이번 강좌에선 컴파일하는 방법만 익히시고, 다음 강좌를 위한 준비로 생각하시기 바랍니다. 자세한 사항은 글쓰기/글보기/글목록 등 각각의 페이지를 만들때 다시 설명드리겠습니다.

제가 만들려고, 머리속에 그려보는 개체의 구성도는 다음과 같습니다.

  • cstDBConnectionString : 연결 문자열 관리
  • DBConnectedObject
    • OrderedTableReader
      • MessageBoard : 게시판 개체.
      • GuestBook : 방명록 개체.
      • NoticeBoard : 공지사항 개체
      • ThreadedBoard : 답변형 게시판 개체
    • Poll : 여론조사 개체
  • cstUtil : 문자열 치환, IP 변환등 여러 함수 모음
강좌에서 NoticeBoard, ThreadedBoard, Poll 같은 것을 만드는 것은 아니고요, 미리, 앞으로 어떤 개체를 어디서 파생해서, 어떻게 만들면 효율적일지 그려보는 것입니다. 강좌에선 DBConnectedObject 를 상속해서 OrderedTableReader를 만들고, 다시 그것을 상속해서 MessageBoard로 만드는데요, 게시판 만 만들자면 그럴 필요가 없습니다. 그러나 위처럼 공지사항이나, 여론조사 같은 다른 것도 만들게 되면, 기반이 되는 클래스를 하나 만들고, 거기서 파생해 나가면서 Tree 형태를 만들면 효율적으로 구성할 수 있습니다.

저는 이렇게 구성할 생각입니다만, 개체를 설계에는 여러 방법, 여러 그림이 있을 수 있겠습니다. 좋은 설계, 나쁜 설계는 있을 수 있지만, 정답은 없는 것 같습니다. 여기서 제가 생각하는 그림을 설명해 드리는 것은, 제 설계가 괜찮아서가 아니고요, 개체 지향형 프로그래밍이라는 것과 '상속'이란 것을 조금이나마 보여주려는 것이었습니다.

게시판 만들고, 강좌를 쓰면서 생각해 보니, 다른 방법이 더 좋겠다는 생각이 자꾸 드네요 ^^ 좀 경험이 생기면 괜찮은 설계가 나오지 않을까 합니다.

 

Back