240629 Springboot 게시판만들기

PangE·2024년 6월 29일

교안 15~20

Entity와 DTO 분리하기

Entity 클래스는 요청과 응답을 처리하는 과정에서 계층 간에 값으로 전달되는 DTO로 사용하는 것을 권장하지 않는다. 그래서 Entity와 DTO를 분리해서 이전에는 Service 계층에서 뷰로 전달되는 객체를 Entity 클래스인 Board 타입으로 바환했는데 지금부터는 BoardDTO 클래스를 새로 작성해서 BoardDTO 타입으로 변환해 반환할 것이다.

BoardDTO 클래스 추가

  • com.springbootstudy.bbs.domain.BoardDTO
@Data
@Builder
@NoArgsConsttructor
@AllArgsConstuctor
pubclic class BoardDTO{
	private int no;
    private String title;
    private String writer;
    private String content;
    private Timestamp regDate;
    private int readCount;
    private String pass;
    private String file1;
    
    public BoardDTO(Board board){
    	this.no = board.getNo();
        this.title= board.getTitle();
        this.writer = board.getWriter();
        this.content = board.getContent();
        this.regDate = board.getRegDate();
        this.readCount = board.getReadCount();
        this.pass = board.getPass();
        this.file1 = board.getFile1();
    }
    
    public static Board toEntity(final BoardDTO dto){
    	return Board.builder()
        		.no(dto.getNo())
                .title(dto.getTitle())
                .writer(dto.getWriter())
                .content(dto.getContent())
                .readCount(dto.getReadCount())
                .pass(dto.getPass())
                .file1(dto.getFile1())
                .build();
         
    }

}

BoardService 클래스 수정

  • com.springbootstudy.bbs.service.BoardService
@Service
@Slf4j
public class BoardService{
	@Autowried
    private BoardRepository boardRepsitory;
    
    public List<BoardDTO> boardList(){
    	return boardRepository.findAll(Sort.by(Sort.Direction.DESC,"no"))
        						.stream()
                                .map(BoardDTO::new)
                                .toList()
    }
}

게시 글상세보기

스프링 부트와 JAP를 활용해 웹 애플리케이션을 구현하기 위한 설정과 Rrepository를 이용한 게시판 테이블로부터 게시 글 리스트를 읽어와 출력하는 과정에 대해서 알아보았다. 지금부터는 앞에서 설정한 정보를 그대로 사용하면서 구현하는 기능에 맞춰서 Repository, Service, Controller, View 페이지를 구현해 추가하면 된다.

  • src/main/resources/templates/views/boardList.html에 링크 추가
<div class="row">
  <div class="col text-end">
      <a th:href="@{addBoard}" class="btn btn-outline-success">글쓰기</a>
  </div>
</div>

DAO 계층 구현

BoardRepository 인터페이스가 상속 받은 상위 인터페이스에 이미 기본적인 CRUD 기능이 정의 되어 있기 때문에 아직까지 메서드를 추가할 필요가 없다.

Service 계층 구현

  • com.springbootstudy.bbs.service.BoardService
public BoardDTO getBoard(int no){
	return new BoardDTO(boardRepository.findById(no).get());
}

Controller 클래스

  • com.springbootstudy.bbs.controller.BoardController
@GetMapping("/boardDetail")
public String getBOard(Model model, @RequestParam("no") int no){
	nodel.addAttribute("board", boarService.getBOard(no));
    return "views/boardDetail";
}

@GetMapping("/boardDetail"): "/boardDetail" 경로로 들어오는 HTTP GET 요청을 처리하는 메서드를 정의한다.
@RequestParam("no") int boardNo: no라는 요청 파라미터의 값을 boardNo 변수에 바인딩한다. @RequestParam 애노테이션을 사용하여 요청 파라미터의 이름을 지정하고, 필요에 따라 기본값(defaultValue)이나 필수 여부(required)를 설정할 수 있다.
Model model: Spring MVC에서 제공하는 Model 객체를 사용하여 뷰에 데이터를 전달한다.
boardService.findBoardById(boardNo): 예시로 사용한 메서드로, 해당 게시글 번호에 해당하는 게시글을 조회하는 로직을 수행한다. 실제 서비스 클래스의 메서드 이름과 구현은 상황에 따라 달라질 수 있다.
model.addAttribute("board", board): 조회한 게시글 정보를 board라는 이름으로 모델에 추가하여, 뷰에서 사용할 수 있도록 준비한다.
return "boardDetail": 최종적으로 보여줄 뷰의 이름을 반환한다. 예를 들어, Thymeleaf를 사용한다면 "boardDetail.html"과 같은 뷰를 찾아서 클라이언트에게 반환할 것이다.
이와 같은 방식으로 @RequestParam 애노테이션을 활용하여 HTTP 요청의 파라미터를 처리하고, 그에 따른 비즈니스 로직을 수행하며, 결과를 뷰로 전달하는 것이 Spring MVC의 기본적인 동작 방식입니다.

게시글 상세보기 View

  • src/main/resources/templates/views/boardDetail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/main_layout}">

<!-- content -->
<th:block layout:fragment="content">
    <div class="row my-5" id="global-content">
        <div class="col-10 offset-1">
            <form name="checkForm" id="checkForm">
                <input type="hidden" name="no" id="no" th:value="${board.no}"/>
                <input type="hidden" name="pass" id="rPass" />
            </form>
            <div class="row text-center">
                <div class="col">
                    <h2 class="fs-3 fw-bold">게시 글 상세보기</h2>
                </div>
            </div>
            <div class="row my-3">
                <div class="col">
                    <table class="table table-bordered">
                        <tbody>
                            <tr>
                                <th class="table-secondary">제 목</th>
                                <td colspan="3" th:text="${board.title}"></td>
                            </tr>
                            <tr>
                                <th>글쓴이</th>
                                <td th:text="${board.writer}"></td>
                                <th>작성일</th>
                                <td th:text="${#dates.format(board.regDate, 'yyyy-MM-dd HH:mm:ss')}"></td>
                            </tr>
                            <tr>
                                <th>비밀번호</th>
                                <td>
                                    <div class="col-sm-8">
                                        <input class="form-control" type="password" name="pass" id="pass">
                                    </div>
                                </td>
                                <th>조회수</th>
                                <td th:text="${board.readCount}"></td>
                            </tr>
                            <tr>
                                <th>파일</th>
                                <td colspan="3">
                                    <th:block th:if="${not #strings.isEmpty(board.file1)}">
                                        <a th:href="@{|upload/${board.file1}|}">다운로드</a>
                                    </th:block>
                                    <th:block th:unless="${not #strings.isEmpty(board.file1)}">
                                        첨부파일 없음
                                    </th:block>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="4" style="white-space: pre" th:text="${board.content}"></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
            <div class="row my-3">
                <div class="col text-center">
                    <input class="btn btn-warning" type="button" id="detailUpdate" value="수정하기"/>
                    &nbsp;&nbsp;<input class="btn btn-danger" type="button" id="detailDelete" value="삭제하기" />
                    &nbsp;&nbsp;<input class="btn btn-primary" type="button" value="목록보기" onclick="location.href='boardList'"/>
                </div>
            </div>
        </div>
    </div>
</th:block>
</html>

0개의 댓글