관리 메뉴

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

닷넷 게시판 만들기 Part 44 - 리스트 검색기능, 리스트 페이징(Page) 준비 본문

ⓟrogramming/asp.net 게시판

닷넷 게시판 만들기 Part 44 - 리스트 검색기능, 리스트 페이징(Page) 준비

가이브 2011. 6. 13. 16:17

2011/05/13 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 31
2011/05/16 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 32
2011/05/18 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 33
2011/05/19 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 34
2011/05/23 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 35
2011/05/25 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 36
2011/05/26 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 37
2011/05/27 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 38
2011/05/30 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 39
2011/05/31 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 40
2011/06/01 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 41
2011/06/08 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 42
2011/06/09 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 43



1. 닷넷 개발환경 준비, 테스트
2. 닷넷 알아보기 [7/7]
3. asp.net 컨트롤 [10/10]
4. 데이터베이스(DB) [7/7]
5. 닷넷 게시판을 만들어보기 전에.. [4/4]
6. 게시판 만들기 [14/..]


계속해서 게시판 리스트에 기능을 더 넣어보도록 하자. 이번에 넣을 기능은 검색기능이다.
게시판이든 어디든 검색 기능은 매우 편리하기 때문에 많이 사용한다. 게시판에서도 꼭 필요한 기능 중 하나이다.
사실 처음에 만들어서 넣어야 했지만 조금 덜 복잡하기 위해 지금 기능을 추가하려고 한다.

게시판 리스트에서의 검색 기능은 검색할 대상(제목,작성자,내용 등)에 대해 검색어를 입력받아 검색하면 해당하는 글의 리스트만 나오는 기능이다. 현재 Board.DLL 에 사용되는 리스트 쿼리문은 다음처럼 되어 있다.


"SELECT * FROM board WHERE category='" + category + "' ORDER BY board_id DESC"



예로 '제목'에 '안녕'이라는 단어가 포함되어 있는 글을 검색한다고 하면,


"SELECT * FROM board WHERE category='" + category + "' AND title LIKE '%안녕%'  ORDER BY board_id DESC "



이렇게 될 수 있을 것이다. 내용 검색은 내용 필드인 content 에서 검색하면 된다. 만약 [제목+내용] 검색, 그러니까 제목에도 '안녕'이 있거나(or) 내용에도 '안녕'이 있는 검색 쿼리는


"SELECT * FROM board WHERE category='" + category + "' AND ( title LIKE '%안녕%' OR content LIKE '%안녕%' ) ORDER BY board_id DESC "


이렇게 쿼리문을 작성할 수 있다. 무조건 category 에 해당하고 (AND) 검색어가 [제목] or [내용]에 '안녕'이 포함된 조건이기 때문에 괄호로 명확하게 구분해준다.

누차 말하지만 결국 쿼리문으로 어떻게 자료를 뽑아내는지, 그리고 프로그램에서 유도리 있게 잘 연동시키는지만 알아도 웬만한 기능은 구현이 가능하다. 현재 리스트 쿼리를 만들어놨기 때문에 검색버튼을 누르면 기존의 쿼리문이 아닌 검색용 쿼리문을 실행시키고 결과를 똑같이 받아서 처리하면 된다. 

이 프로그램이라는 것이 원하는 기능을 구현함에 있어서 여러가지 고려해야하는 것들이 많다. 같이 해보도록 하자. 구현을 위해 간단하게 검색조건은 제목/내용 2개만 넣고, 각각의 조건대로 검색하기로 한다. 먼저, 검색을 할 수 있는 UI(User Interface, 사용자 기능)를 board_list.aspx 하단 중간에 위치시켜보자.

들어갈 컨트롤은 "어떤 항목을 검사"할지를 결정할 <select>..</select>태그에 해당하는 DropDownList (id=lstType) 컨트롤을 넣고 간단하게 [제목]과 [내용] 2개의 ListItem을 넣도록 하자. 그리고 검색어를 입력할 TextBox (id=txtSearch)  컨트롤, 검색을 수행할 Button (id=btnSearch) 컨트롤을 넣는다. 또 하나 더 필요한 기능은 검색중일 때 취소하고 전체 게시물로 다시 돌아가는 Button (id=btnCancel) 컨트롤을 하나 더 넣도록 하자. 그리고 속성 중 보여주거나 숨기는 기능인 Visible 의 값을 기본값인 true 를 false 로 바꾸어 처음에는 숨겨놓도록 한다. 후에 검색이 된다면 (btnSearch 클릭이벤트) btnCancel 컨트롤이 보여지면 되겠다. 두개의 버튼에 각각 클릭이벤트를 넣는 것도 잊지말자.

이렇게 서버컨트롤 4개를 <form runat="server" id="frm">..</form>으로 감싸자. 폼태그의 id는 'frm'으로 지정한다.





위의 그림은 해당 소스와 실행 결과이다.

이제 검색 결과를 처리할 메서드를 Board.cs 라이브러리에 넣도록하자.
앞서 예상 쿼리를 미리 만들어봤으므로 별 설명은 필요없을 듯 하다. 다만 같은 게시판 리스트 기능이기 때문에 메서드를 같은 이름인 List(..) 로 하자. 그리고 받는 인수는 기존 List(..)에서 "검색할 대상"과 "검색어" 두가지의 string 형을 추가하자.
이것이 MSDN에서 땡겨쓸 때 많이 봤던 오버로드(overload) 된 메서드를 만드는 것이다.


 




닷넷에서는 자신이 실행하는 쿼리가 쿼리문인지 뭔지 알리가 없다. 필자가 말하는 "ASP.NET과 DB와는 아~무 관련 없다"라는 말과 비슷하다. 여러분들이 DB뿐만 아니라 다른 외부 데이터나 네트워크와 연동함에 있어서 이렇게 사용자 입력 변수와 문자열 상수를 결합하여 만드는 문자열은 헷갈리지 말아야 한다. 강의엑서 여러번 사용한 String.Format(string, object[]) 을 사용하게 되면 문자열과 변수의 구분이 명확하기 때문에 좀 더 알아보고 쉬운 장점이 있다.

자세히 들여다보면 위에서 작성한 쿼리문은 DropDownList 의 값을 그대로 이용할 것이다. 작은따옴표와 큰따옴표 등을 헷갈리지 마시기 바란다. 제대로 동작이 안될 경우에는 먼저 테스트용으로 하나 메서드를 따로 만들어서 만든 쿼리문을 출력해보며 수정하는 방법도 괜찮을 것이다.


using System.Web;


  // 게시판 목록 (검색 테스트용)
  public void ListTest(string category, string search_target, string search_word)
  {
    HttpContext.Current.Response.Write("SELECT * FROM board WHERE category='" + category + "' AND " + search_target + " LIKE '%" + search_word + "%' ORDER BY board_id DESC");
    HttpContext.Current.Response.End();
  }



이제 검색 기능을 붙여보자. btnSearch_Click(..)  이벤트에서 검색이 일어나게 되면 검색결과를 뿌려주면 되는데, 하나 구민해야 할 것이 있다. 

예를 들어서 100개의 게시물이 있다고 치자. 그리고 검색을 수행하니 결과는 5개가 나왔다. 검색결과에서 첫번재 글을 읽었다. 그리고 다시 리스트로 돌아왔을 때, 그 리스트는 전체가 아닌 결과인 5개를 다시 보여줘야 할 것이다. 또한, 다음에 만들어볼 게시판 페이징(글이 많이 있을 때 길어지는 것을 특정 갯수를 페이지 단위로 잘라서 출력)기능에서도 결과가 2페이지 이상으로 나왔을 때, 2페이지 이동할 때도 역시 리스트 검색결과의 2페이지가 출력되어야 할 것이다.

이 말은 검색에 관련된 값들을 GET으로 계속 붙여서 가야된다는 말이다. 현재 지금 글의 카테고리인 "c"변수를 언제나 붙여서 페이지간에 전달하고 있다. 이유는 현재의 카테고리를 유지하기 위해서이다. 이처럼 검색도 마찬가지로 계속해서 유지를 시켜줘야만 글을 읽고 다시 돌아오거나 다음 페이지로 넘어가는 행위, 그러니까 검색 후에 board_list.aspx 페이지를 벗어나더라도 다시 돌아올 때를 대비해서(board_list.aspx 에서 board_list.aspx 를 다시 열더라도) 값을 계속해서 붙여가야되는 것이다.

btnSearch_Click(..) 에서 할 일은, 그저 board_list.aspx 에 GET 값으로 사용자가 검색한 값들을 붙여주는 것이다. 물론 카테고리인 "c"값과 함께 말이다. 그 전에 "검색어의 입력여부"정도는 체크해줘야 할 것이다. (이 과정은 이미 회원가입이나 글쓰기에서 해봤으므로 생략)






String.Format(..) 은 길어지는 현상을 방지하기 위해, 그리고 알아보기 쉽게 여러줄로 표현했으니 형식에 헷갈려 하지마시기 바란다.


이제 버튼을 클릭하면 Response.Redirect() 를 이용해서 검색 GET 값을 붙여 board_list.aspx 를 다시 열게된다. 버튼 이벤트가 일어날 찰나에는 IsPostBack 이 true 이겠지만 Response.Redirect() 로 다시 열었으니 IsPostback 은 false 이다.

아무렇게나 검색하고 실행한 후 주소창에 GET 으로 잘 붙었는지 확인하자. 필자는 [제목]검색으로 [방금]이라고 검색하였다.


board_list.aspx?c=test&stype=title&svalue=%eb%b0%a9%ea%b8%88


한글이나 특수문자는 저렇게 %XX 형식으로 변환된다고 생각하자. 어쨌든 제목에 해당되는 값인 stype의 값은 title, 검색어에 해당하는 svalue 값은 입력한 값이 잘 넘어가는 것을 볼 수 있다. 게시물 검색을 수행했다는 의미가 위의 주소처럼 "stype", "svalue"값이 모두 다 값을 가지고 있을 때라고 할 수 있다.

이렇게 열리게 되면 Page_Load() 에서는 stype, svalue 값이 모두 존재하는 것을 확인하면 되겠다. 단, stype 값은 무조건 title 또는 content 값일 수 밖에 없다. 이 것까지 체크하도록 하자. 모두 만족한다면 검색버튼이 눌러진 것이며, 좀 전에 라이브러리에 만든 오버르도 된 검색용 List(..) 메서드를 실행하면 된다.

여러번 사용할 일이 많을 것 같으므로, 클래스 변수로 string 형 STYPE, SVALUE 두가지를 지정하고 넣어주자. 그리고 현재 검색중인지를 파악할 수 있는 bool 형 변수 IsSearch 도 하나 넣자.




이제 이 변수들은 board_list.aspx 에서 어디서든 사용가능하다.





Page_Load() 에서 하는 일은 STYPE, SVALUE 에 무조건 값을 담아둔다. 그리고 이 값이 모두가 비어있지 않을시에 검색중이므로 IsSearch 를 true 로 할당한다. 뒤에서 IsSearch 가 true 일 때 검색 메서드를, 아니라면 그냥 리스트 메서드를 호출해주면 되겠다.

이제 검색을 해보자.




[제목]으로 'dd' 를 넣어 검색한 결과가 잘 출력되는 것을 볼 수 있다.
잠깐 빠진 기능이 있다. 검색일 때는 "검색취소"버튼이 보여져야 한다. 그리고 검색중임을 명확하게 표시하기 위해 검색 대상과 검색어 값을 컨트롤에 매치를 시켜주도록 하자.





반전된 부분이 추가된 코드이다. 그리고 '검색취소'버튼 이벤트를 처리하는 코드를 넣자. 검색취소는 stype, svalue 값이 없음을 말하는 것이므로, 간단하게 board_list.aspx 를 처음에 클릭했듯이 열어준다고 생각하면 되겠다.



 




이렇게 해서 검색기능은 구현이 된 것 같다. 하나 더 시각적인 옵션으로 '제목으로 검색시 검색이 된 단어가 진하게 표시(<b> 태그처리)'되게 해보자. 각자가 어떻게 구현할지 고민해보도록 한다.

필자 생각에는 실제 화면에 뿌려지는 컬럼인 title 에서 현재 제목 검색중이라면, 제목 값에 들어있는 검색어를 '<b>'태그로 감싸주면 될 것 같다. Repeater 에서 돌고 있는 자료를 처리해야 하므로, board_list.aspx 에 임의로 메서드를 하나 만들도록 하자. 이 메서드가 하는 기능은 "현재 검색일 시, 들어오는 문자열에 검색어가 있다면 <b>태그를 감싸주는 기능"이다.
리턴은 string 으로 하자. 인수는 들어오는 문자열 1개. 이 메서드는 검색취소버튼 이벤트 메서드 하단에 위치시키겠다.




이제 Repeater에 있는 제목에 이 메서드를 적용해보자.




Eval("title")은 object 형이므로 (string) 키워드를 앞에 붙여 string 형으로 변환하기로 한다. 변환시 제목은 null 값이 될 수가 없으니 (글쓰기 페이지에서 체크한 후 저장하므로) 오류가 발생할 일은 없을 것 같다. 그런 후 이 값을 방금 만든 메서드 CheckSearch(string src) 에 던져주도록 한다.




이렇게 원하는 결과로 잘 나오는 것을 확인할 수 있다.

이제 글을 읽을 때 board_view.aspx 로 넘어갈 때 현재 검색중인 값을 넘겨줘야한다. 앞서 STYPE, SVALUE 변수를 클래스선에서 선언했기 때문에 링크하는 <a href="board_view.aspx?....."> 의 끝에 함께 붙여서 넘기도록하자.  이 값은 현재 검색중이든 아니든 별 상관이 없다. board_read.aspx 에서는 검색 여부에 관련없이 값을 가지고만 있다가 [리스트] 링크를 누를 때 다시 이전에 검색된 결과를 보여주기 위해 받은 값을 그대로 또 넘겨주는 역할만 하기 때문이다.





이렇게 추가한 후 실행하자. 테스트를 위해 검색결과가 나올 수 있게 검색하고 제목(링크)에 마우스를 갖다 댄 후 , 웹브라우저 하단에 링크되는 페이지를 확인하자.



이처럼 board_view.aspx 에서는 stype 과 svalue 가 잘 붙어서 전달될 것이다. 이제 board_view.aspx 페이지를 열어서, 맨 하단에 있는 "리스트"링크에 이 값을 그대로 넘겨주는 수정작업을 하자.


<a href="board_list.aspx?c=<%= CATEGORY_ID %>>리스트</a>

수정후

<a href="board_list.aspx?c=<%= CATEGORY_ID %>&stype=<%= Request["stype"] %>&svalue=<%= Request["svalue"] %>">리스트</a>




이제 다음 그림처럼 리스트로 링크를 통해 다시 리스트로 돌아가더라도 이전의 검색된 결과가 그대로 나올 것이다.





다음 시간에는 글이 많이 늘어났을시에 페이지 단위로 잘라주는 게시판 페이징 기능을 구현할 예정이다.
구현하기에 앞서, 글이 많이 있어야지 눈에 띄므로 일단 게시판의 게시물을 강제로 늘여주자.

board_write.aspx 에 글을 작성하는 메서드가 있으므로, 여기에서 for(;;) 로 루프를 한번 돌려주자. 그러면 1회 작성시 여러개의 글이 for(;;) 를 돌면서 지정한 갯수대로 올라갈 것이다. 100 개 이상으로 강제로 넣어주도록 하자.

board_write.aspx 

    // 새글쓰기
    for (int i=0; i<123 ; i++)
    {
     BOARD_LIB.Write(category, user_id, user_name, "[ " + i + " ]" + title, content, upload_file);
    }




제목이 똑같으면 밋밋하니(?) 제목에 순번을 붙여준다.




이렇게 100여개가 넘더라도 페이지의 길이가 많이 길어졌다. ^_^
일단 이렇게 준비를 하고 다음 시간에 리스트 페이징을 구현해보도록 하자. 다음 소스는 이번 Part 에서 수정된 것들이다.

board_list.aspx

Board.cs

board_view.aspx




 

반응형
Comments