본문 바로가기
프로젝트/게시판 만들기

[Spring boot] 게시판 만들기 (4주차 : 페이징 처리, 페이지 블럭 출력하기, 게시판 검색 기능 추가)

by zzingni 2025. 5. 22.

 

※ [한코딩] 게시판 만들기 유튜브를 참고하여 진행하는 프로젝트입니다.

 

 

 

개발 환경


사용언어 : Java

프레임 워크 : Spring boot

통합 개발 환경 : IntelliJ

데이터베이스 : MariaDB

뷰 템플릿(템플릿 엔진) : Thymeleaf

 

 

프로젝트 진행 순서


 

 

 

[Spring boot] 게시판 만들기 (1주차 : 개발 환경 세팅, 프로젝트 생성)

※ [한코딩] 게시판 만들기 유튜브를 참고하여 진행하는 프로젝트입니다.   개발 환경사용언어 : Java프레임 워크 : Spring boot통합 개발 환경 : IntelliJ데이터베이스 : MariaDB뷰 템플릿(템플릿 엔진)

zprograming.tistory.com

 

 

1. 개발 환경 세팅

 - IntelliJ Community 다운로드

 - MariaDB 다운로드

 - MySQL Workbench 다운로드

 

2. 프로젝트 생성

 - IntelliJ Community에서 Spring Boot 프로젝트 생성 (https://start.spring.io/)

 - MariaDB Database(스키마) 생성 

 

 

 

 

[Spring boot] 게시판 만들기 (2주차 : DB 테이블 생성, 게시글 작성폼 생성, 글 작성 처리, 게시글 리

※ [한코딩] 게시판 만들기 유튜브를 참고하여 진행하는 프로젝트입니다.   개발 환경사용언어 : Java프레임 워크 : Spring boot통합 개발 환경 : IntelliJ데이터베이스 : MariaDB뷰 템플릿(템플릿 엔진)

zprograming.tistory.com

 

3. 게시물 작성

- db에 board 테이블 및 필드 생성

- 게시글 작성 폼 생성

 

4. 게시물 리스팅

 

 

 

[Spring boot] 게시판 만들기 (3주차 : 게시글 상세 페이지, 게시글 삭제 및 수정, 메시지 띄우기, 파

※ [한코딩] 게시판 만들기 유튜브를 참고하여 진행하는 프로젝트입니다. 개발 환경사용언어 : Java프레임 워크 : Spring boot통합 개발 환경 : IntelliJ데이터베이스 : MariaDB뷰 템플릿(템플릿 엔진) : Thy

zprograming.tistory.com

 

5. 게시물 삭제

- 게시글 상세 페이지 

 

6. 게시물 수정

- 게시글 수정

- 메시지 띄우기

 

7. 파일 업로드

 

8. 페이징 처리

 

@PageableDefault(page = 0, size = 10, sort = "id", direction = Sort.Direction.DESC) Pageable pageable

 

Controller의 boardList의 매개변수로 pageable을 추가해준다.

 

public Page<Board> boardList(Pageable pageable) {
    return boardRepository.findAll(pageable); // Board 라는 class가 담긴 LIst 반환
}

 

boardService로 pageable을 넘겨주고 Page<Board> 클래스로 리턴하는 코드로 수정한다.

 

 

역순으로 정렬된 리스트 화면으로 변경되었다.

 

 

list?page=2로 입력하면 3번째 페이지가 화면에 나타난다.

 

 

- 페이징 블럭 출력하기

필요한 변수
- nowPage : 현재 페이지
- startPage : 블럭에서 보여줄 시작 페이지
- endPage : 블럭에서 보여줄 마지막 페이지

 

타임리프 문법
- th:text : 태그 안에 데이터를 출력
- th:each : 반복문
- th:each = "${number:#number(시작 번호, 끝번호)}" 
                  >> 시작 번호에서 끝번호까지 반복

 

 

	int nowPage = list.getPageable().getPageNumber() + 1;
        int startPage = Math.max(nowPage -4, 1); // 1보다 작은 경우 1이 크기 때문에 1 반환
        int endPage = Math.min(nowPage + 5, list.getTotalPages());
        
        
        model.addAttribute("nowPage", nowPage);
        model.addAttribute("startPage", startPage);
        model.addAttribute("endPage", endPage);

 

boardService에 @GetMappeing("/board/list")에 위의 코드를 추가한다.

시작 페이지는 1페이지보다 작으면 안 되니까 Math.max로 비교해주고,

마지막 페이지는 총 페이지를 초과하면 안 되니까 getTotalPages() 를 사용한다.

 

model.addAttribute()로 thymeleaf로 변수를 다 넘겨준다.

 

 

 <th:block th:each="page: ${#numbers.sequence(startPage, endPage)}">
        <a th:if="${page != nowPage}" th:href="@{/board/list(page = ${page-1})}" th:text = "${page}"></a>
        <strong th:if="${page == nowPage}" th:text = "${page}" style = "color : red"></strong>
 </th:block>

 

boardlist.html 의 </table>태그 밑에 위의 코드를 작성하고 실행하면,

 

페이지버튼이 정상적으로 출력되며, 페이지 클릭시 빨간색으로 강조된다.

 

 

9. 게시판 검색 기능 

JPA Reposiory

findBy(컬럼 이름) : 컬럼에서 키워드를 넣어서 찾겠다.
* 정확하게 키워드가 일치하는 데이터만 검색

 

@Repository
public interface BoardRepository extends JpaRepository<Board, Integer> { // extends 상속받음. JpaRepository를 상속받아 타입지정.

    Page<Board> findByTitleContaining(String searchKeyword, Pageable pageable);
}

 

BoardRepository 인터페이스를 위와 같이 수정한다.

 

 

// 키워드 검색 기능
public Page<Board> boardSearchList(String searchKeyword, Pageable pageable) {
    return boardRepository.findByTitleContaining(searchKeyword, pageable);
}

 

BoardService에 키워드 검색 기능을 추가한다.

 

 

@GetMapping("/board/list")
public String boardList(Model model,
                        @PageableDefault(page = 0, size = 10, sort = "id", direction = Sort.Direction.DESC) Pageable pageable,
                        String searchKeyword) { // 데이터를 담아서 페이지로 보낼 때 Model 사용

    Page<Board> list = null;
    if(searchKeyword == null) {
        list = boardService.boardList(pageable);
    } else {
        list = boardService.boardSearchList(searchKeyword, pageable);
    }

    int nowPage = list.getPageable().getPageNumber() + 1;
    int startPage = Math.max(nowPage -4, 1); // 1보다 작은 경우 1이 크기 때문에 1 반환
    int endPage = Math.min(nowPage + 5, list.getTotalPages());

    model.addAttribute("list", boardService.boardList(pageable)); // list라는 이름으로 보낼 건데, boardService에 boardList() >> 반환된 리스트를 list 라는 이름으로 넘기겠다는 뜻.
    model.addAttribute("nowPage", nowPage);
    model.addAttribute("startPage", startPage);
    model.addAttribute("endPage", endPage);
    return "boardlist";
}

 

BoardController에 boardList 메서드에 searchKeyword 매개변수를 추가해준 후,

searchKeyword가 있을 경우와 없을 경우를 다르게 처리하기 위해 if문을 작성한다.

 

<th:block th:each="page: ${#numbers.sequence(startPage, endPage)}">
    <a th:if="${page != nowPage}" th:href="@{/board/list(page = ${page-1}, searchKeyword = ${param.searchKeyword})}" th:text = "${page}"></a>
    <strong th:if="${page == nowPage}" th:text = "${page}" style = "color : red"></strong>
</th:block>

 

list?searchKeyword=11 로 테스트 검색시 페이지 이동하면 검색한 Keyword가 사라짐

그 처리를 해주기 위해 boardlist.html의 a태그 안에 searchKeyword = ${param.searchKeyword} 를 추가했다.

 

<form th:action="@{/board/list}" method="get">
    <input type ="text" name="searchKeyword">
    <button type="submit">검색</button>
</form>

 

실제로 키워드를 검색하기 위한 form 을 html에 작성한다.

 

 

/board/list 에 접속하면 검색 박스와 버튼이 생긴 걸 확인할 수 있고,

 

 

11을 검색하면 키워드가 포함된 게시글이 정상적으로 검색된다!!

 

 

Trouble Shooting


1. /board/list?searchKeyword=11 테스트시 출력 오류

 

여기서 searchKeyword가 있는 경우에도 boardService.boardList(pageable)로 다시 전체 리스트를 넣고 있어서, 실제 검색 결과가 아닌 전체 목록이 화면에 나올 수 있음. 아래와 같이 코드 수정.

 model.addAttribute("list", list);

 

 

 

4주차 소감


게시판 만들기를 완료하였다!!!!!

간단한 기능들이지만, 각 파일들이 서로 어떤식으로 연관되어 동작하는지 처리과정을 알 수 있어서 매우 유익한 시간이었다.

다만... 아직 정확한 동작방법이나 메소드, 라이브러리 등 익숙하지 않은 것들이 많아서 배운 내용을 바탕으로 다른 개인 프로젝트를 진행하며 공부해봐야겠다는 생각을 했다! (특히 매개변수와 인수로 주고받는 부분들이 너무 헷갈린다 ㅠ)

 

시간이 된다면 게시판만들기 과정을 처음부터 끝까지 한번 더 복습하면 좋을 것 같다는 생각을 했다.

 

다 끝내서 뿌듯하다 ㅎ,ㅎ