오늘은 게시판 게시글을 조회수와 댓글수, 최신순으로 정렬기능을 구현하고,
게시글을 10개, 20개, 30개씩 볼 수 있는 기능도 같이 만들어봤다.
이 기능을 어떻게 구현해야할지 생각하던 중,
OKKY 사이트의 구현되있는 버튼을 눌러보다가 방법을 찾았다.
이런식으로 게시글 정렬이 url에 따라 변경되고,
이렇게 url이 바뀌면서, 결국 검색,페이징기능과 비슷한 로직이라는 것을 알았다.
먼저 게시글목록을 select하는 쿼리의 정렬부분을 바꿔줘야 한다.
전에 게시글의 댓글수를 목록페이지에서 출력하고, 조회수를 출력하는 부분을 구현할때
댓글수와 조회수를 count하는 로직은 이미 만들어뒀기 때문에 그 부분은 넘어가도록 하겠다.
<select id="listPage" resultType="kr.co.vo.BoardVO"
parameterType="kr.co.vo.SearchCriteria">
SELECT BNO,
TITLE,
CONTENT,
WRITER,
REGDATE,
HIT,
REPLYHIT
FROM (
SELECT BNO,
TITLE,
CONTENT,
WRITER,
REGDATE,
HIT ,
REPLYHIT,
ROW_NUMBER() OVER(
<include refid="sort" />) AS RNUM
FROM MP_BOARD
WHERE 1=1
<include refid="search" />
and BGNO=#{bgno}
) MP
WHERE RNUM BETWEEN #{rowStart} AND #{rowEnd}
<include refid="sort" />
</select>
<sql id="sort">
<if test="sort == null">
ORDER BY BNO DESC
</if>
<if test="sort == 'bno'">
ORDER BY BNO DESC
</if>
<if test="sort == 'viewCount'">
ORDER BY HIT DESC
</if>
<if test="sort == 'replyCount'">
ORDER BY REPLYHIT DESC
</if>
<if test="sort == 'likeCount'">
</if>
</sql>
일단 설명을 하자면
이번에 주목해야할 것은 inclue refid="sort" 두 부분이다
원래 최신순으로만 게시글을 출력했는데, 저 부분은 ORDER BY BNO(게시글PR) 이였다
select할 MP_BOARD테이블의 where문에 해당하는 속성들을
ROW_NUMBER() OVER(<include refid="sort" />) AS RNUM
row_number로 over() 안의 속성을 기준으로 내림차순 정렬을 하고
다시 페이징 기준에따라 1페이지 안의 1~10개의 게시글을 내림차순으로 정렬한다.
ORDER 부분만 동적쿼리로 바꿔주면 되는것이다.
sort 라는 값을 기준으로 구분할 예정이다.
SearchCriteria의 일부분
private int page;
private int perPageNum;
private int rowStart;
private int rowEnd;
private int bgno;
private String sort;
목록쿼리가 파라미터타입으로 받는 VO에 sort라는 String문을 추가해줬다.(getter&setter 생성)
pageMaker의 일부분
// 검색기능
public String makeSearch(int page) {
UriComponents uriComponents = UriComponentsBuilder.newInstance().queryParam("page", page)
.queryParam("perPageNum", cri.getPerPageNum())
.queryParam("searchType", ((SearchCriteria) cri).getSearchType())
.queryParam("keyword", encoding(((SearchCriteria) cri).getKeyword()))
.queryParam("bgno", cri.getBgno())
.queryParam("sort",cri.getSort()).build()
;
return uriComponents.toUriString();
}
검색,페이징,게시판 카테고리를 나누는데 사용하는 url을 만들어주는 클래스에 sort값도 추가해준다.
목록뷰에 버튼을 추가해줬다.
<button type="button" onclick="location.href='/board/list?bgno=${scri.bgno}&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=viewCount'" class="btn btn-outline-dark float-right " >조회순</button>
<button type="button" onclick="location.href='/board/list?bgno=${scri.bgno}&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=replyCount'" class="btn btn-outline-dark float-right" data-bs-toggle="button" >댓글순</button>
<button type="button" onclick="location.href='/board/list?bgno=${scri.bgno}&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=bno'" class="btn btn-outline-dark float-right ">최신순</button>
<button type="button" onclick="location.href=
'/board/list?bgno=${scri.bgno}&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=viewCount'" class="btn btn-outline-dark float-right " >조회순</button>
이렇게 onclick으로, 클릭시 해당 url로 sort의 String값을 Mapper의 if test문에 맞게 버튼마다 넣어줬다.
다른 정렬방법을 클릭해도 당연히 게시판의 구분을 위해 bgno(게시판구분속성)를 가져오고
검색시에도 검색어가 유지된 상태로 정렬방법이 바뀌도록 검색어도 유지되게 해놓았다.
@RequestMapping(value = "board/list", method = RequestMethod.GET)
public String list(Model model, @ModelAttribute("scri") SearchCriteria scri) throws Exception{
logger.info("list");
model.addAttribute("list", service.list(scri));
PageMaker pageMaker = new PageMaker();
pageMaker.setCri(scri);
pageMaker.setTotalCount(service.listCount(scri));
model.addAttribute("pageMaker", pageMaker);
return "board/list";
}
목록부분을 구현하는 컨트롤러인데, @ModelAttribute로 아까 sort를 추가한 VO의 객체를 생성해서 뷰에서 값을 받고 , 넘길 수 있도록 구현해놨다.
setCri(scri)로 목록뷰가 로딩될때마다(검색이나 페이징등) url값이 넘어오면 페이지가 바뀌어도 그 값이 계속 유지될 수 있다.
결과
최신순과 댓글순을 클릭했다.
최신은 게시글번호순(BNO),
제목옆의 () 가 댓글수(replyHIT)인데 내림차순으로 잘 적용되었다.
url부분이 변경되는 것을 잘 확인하자.
그 다음은 원래 10개씩 출력되던 게시글을 20개, 30개씩 출력을 하려고 한다.
위의 PageMaker의
.queryParam("perPageNum", cri.getPerPageNum())
이 부분이다.
페이징에서 표시할 게시글수를 설정하는 부분인데, 이 부분도 위의 과정과 동일한 과정으로 간단하게 처리가 가능하다.
게시글수를 정하는 값은 이미 VO에 페이징을 구현 할 때 넣어놨기 때문에, 따로 설명하진 않겠다.(perPageNum)
<button class="btn btn-dark dropdown-toggle float-right" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Content Count
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="/board/list?bgno=${scri.bgno}&page=${scri.page}&perPageNum=10&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=${scri.sort}">10개씩</a>
<a class="dropdown-item" href="/board/list?bgno=${scri.bgno}&page=${scri.page}&perPageNum=20&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=${scri.sort}">20개씩</a>
<a class="dropdown-item" href="/board/list?bgno=${scri.bgno}&page=${scri.page}&perPageNum=30&searchType=${scri.searchType}&keyword=${scri.keyword}&sort=${scri.sort}">30개씩</a>
</div>
목록뷰에 부트스트랩 드롭다운버튼을 활용해서 만들었다.
먼저 설명한 정렬과 다른점은 sort는 set되있는 sort값을 가져오고,perPageNum의 부분만 바꿔주면 된다.
게시글 수를 변경할때는
페이징에 필요한 모든 값이 필요하기 때문에 모든값을 페이지수만 빼고 다 scri의 값에서 가져와준다.
(그렇지 않으면 검색 가서 20개씩 보기로 변경했을때, 검색어가 초기화되는 빡침을 사용자에게 선물 할 수 있겠다.)
결과
++++문제
Mapper에서 srot==null이 아닌, string값이기 때문에 srot== '' 을 해줘야 값이 없을때 제대로 BNO가 들어감
'SPRING > IceWater Community' 카테고리의 다른 글
[스프링]인터셉터를 활용한 로그인구현 (세션부여) - 로그인2 (0) | 2021.09.15 |
---|---|
[스프링]회원가입(ajax 유효성 검사,비밀번호 암호화) - 로그인1 (0) | 2021.09.10 |
[스프링] 다중 게시판 구현 (CRUD) (1) | 2021.09.06 |
[스프링]게시판 이전글 다음글 구현 (5) | 2021.09.03 |
[스프링] ajax 댓글 에디터 및 이미지 삽입 구현 (0) | 2021.09.02 |