<개발일지> 4월 5일 연구일지 (게시판에서 새로운 글 작성 표시)

Posted by , April 22, 2018
TIL
Series ofTIL

주의

이 문건은 과거 Hexo 블로그 (2018-04-22) 에서 이동된 문서입니다.

시간이 지남에 따라 최신 기술과 다를 수 있으니 주의 바랍니다.


thumbnail


오늘의 주제는?

간만에 작성하는 연구일지입니다.
정말 많이 바빠서 포스팅도 주말에 시간을 내서 작성하게 되네요.

이번 주제는 게시판에서 새로운 글 작성 시 사이드 메뉴에 표시를 하는 것을 다루겠습니다.

img 01

위와 같이 새로운 글이 작성될 경우 옆에 new라는 버튼이 뜨게끔 하는 것이 목표입니다.

프로젝트 진행 환경은 Spring BootThymeleaf 에서 진행하고 있음을 알려드립니다.


어떻게 해야 새 글이라는 것을 알 수 있을까?

먼저 아래와 같은 순서로 구현을 생각해 보았습니다.

  1. 새 글이 작성된 기준은 조회 시점 정하기
  2. 각 게시판에서 새 글이 있는지 알기 위한 체크하는 로직이 필요하다.
  3. 새 글이 작성되었다는 것을 저장할 곳이 필요하다.
  4. 새 글이 있는 것을 어디서 조회할 것인가?
  5. 뷰 단에서 해당 값을 찾아서 있는 경우 표시를 해준다.

1번 구현법

프로젝트에서는 하루 전 작성된 글을 기준으로 하였습니다.
이것은 게시판을 저장하는 Repo에서 시간을 조회하는 메서드를 하나 만들었습니다.

List<Board> findByCreateDateAfter(LocalDateTime localDateTime);

그리고 조회할 때는 다음과 같이 사용하였습니다.

boardRepo.findByCreateDateAfter(LocalDateTime.now().minusDays(1))


2번 구현법

새 글을 알기 위해서는 DB를 조회하여 새로운 값이 있는지, 그리고 있다면 어떤 게시판에 새 글이 있는지를 알기 위한 메서드가 필요했습니다.

//구형 코드
public List<BoardCategory> getUpToDateContents() {
        List<BoardCategory> list = new ArrayList<>();
        List<Board> boardList = boardRepo.findByCreateDateAfter(LocalDateTime.now().minusDays(1)).stream()
                .filter(board -> !board.getCategory().equals(BoardCategory.TEMP_BOARD))
                .filter(board -> !board.getCategory().equals(BoardCategory.SYSTEM))
                .collect(Collectors.toList());
        for(Board board : boardList) { list.add(board.getCategory()); }
        return list.stream().distinct().collect(Collectors.toList());
}

게시판을 저장할 때 각 게시판을 위해 BoardCategory라는 Enum을 만들어서 저장하였습니다.
사실 저 코드는 옛날 코드고 지금은 코드 리펙토링을 통해 불필요한 연산을 줄인 코드를 만들었습니다. (Java8 만세!)

public List<BoardCategory> getUpToDateContents() {
        return boardRepo.findByCreateDateAfter(LocalDateTime.now().minusDays(1)).stream()
                .filter(board -> !board.getCategory().equals(BoardCategory.TEMP_BOARD))
                .filter(board -> !board.getCategory().equals(BoardCategory.SYSTEM))
                .map(Board::getCategory)
                .distinct()
                .collect(Collectors.toList());
}

3번 구현법

저장할 곳은 세션을 사용하였습니다.

public static void setSessionDataInNewContents(HttpSession session, List<BoardCategory> categoryList) {
        session.setAttribute(S_IN_NEW_CONTENTS, categoryList);
}

위와 같이 작성하여 세션에 저장하였습니다.


4번 구현법

조회를 하는 것은 Controller 단에 로그인 등에서 처음 로그인 시 저장하는 법도 생각하였지만, 만약 세션 타임 아웃 시간이 길 경우 갱신에 대한 문제도 있었습니다.

그래서 인터셉터에서 로그인 이후에 대한 호출하는 곳에서 세션에 저장하는 방법으로 구현을 하였습니다.

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(hasSessionInAccount(request.getSession())) {
            checkAnnotation4ClearSessionInTempData(request,handler);
            checkUpToDateContents(request);

            return true;
        }//세션에 계정 정보가 존재하는 경우
        else {
            try { response.sendRedirect("/users/login"); }
            catch (IOException ie ) {} //만약 리다이렉션 도중 에러가 난 경우
            return false;
        } //세션 정보가 존재하지 않는 경우
}

**
* 새로운 게시글이 있는지 체크하여 세션에 주입하는 메서드
* @param request
*/
private void checkUpToDateContents(HttpServletRequest request) {
        SessionHelper.setSessionDataInNewContents(request.getSession(), boardService.getUpToDateContents());
}

위 코드를 참고하면 되겠습니다.


5번 구현법

뷰 단에서는 메뉴를 구현한 Thymeleaf에서 th:eachth:if를 사용하여 구현을 하였습니다.

<i class="fa fa-flag"></i>
<span>공지사항</span>

<span
  class="pull-right-container"
  th:each="category : ${session.NewContents}"
  th:object="${category}"
  th:if="${category.toString()} == 'NOTICE'"
>
  <small class="label pull-right bg-green">new</small>
</span>

위의 thymeleaf의 반복문 내 if문 사용법에 대한 포스팅은 여기를 참고하세요.


결론

위와 같은 방법을 통해서 아래와 같이 기능을 구현하였습니다.

img 02

저와 비슷한 고민을 하셨던 분이 있다면 도움이 되셨으면 합니다.

감사합니다.