네이버 클라우드 캠프/Spring

[Spring Boot] 게시판 제작하기(4)

graph-dev 2023. 6. 22. 19:56
728x90

컨트롤러

이번에는 게시판에서 CRUD 기능을 구현하기 위한 컨트롤러(BoardController)를 제작해보겠습니다.

여기서는 두가지 방식이 있습니다. RepositoryEntity를 선언하는 방식과 ModelAndView를 사용하는 방법으로 나누어 진행해보겠습니다.

 

RepositoryEntity

RepositoryEntity를 사용하고 타입은 와일드카드로 정의해서 데이터베이스에 저장된 값을 한번에 조회할 수 있습니다. 

 

READ

@GetMapping("/board-list")
    public ResponseEntity<?> getBoardList() {
        ResponseDTO<BoardDTO> responseDTO = new ResponseDTO<BoardDTO>();
        try {
            List<Board> boardList = boardService.getBoardList();
            List<BoardDTO> boardDTOList = new ArrayList<BoardDTO>();
            ...
        } catch (Exception e) {
			...
        }
    }

먼저 ResponseDTO 객체를 생성하고, boardService.getBoardList를 통해 리스트 객체를 만듭니다. 그리고 빈 리스트를 BoardDTO 타입에 맞게 boardDTOList라고 생성합니다.

 

boardList에서 Board 엔티티 객체인 b를 설정해서 하나씩 요소를 꺼냅니다. 한 행에 해당하는 값들이 담기게 되고, 이를 향상된 for문을 통해 boardDTOList에 추가하면서 저장합니다.

 for(Board b : boardList) {
                BoardDTO returnBoardDTO = 
                	  BoardDTO.builder()
                              .boardNo(b.getBoardNo())
                              .boardTitle(b.getBoardTitle())
                              .boardWriter(b.getBoardWriter())
                              .boardRegDate(b.getBoardRegdate().toString())
                              .boardCnt(b.getBoardCnt())
                              .build();
                boardDTOList.add(returnBoardDTO);
            }

 

그 다음으로 setItems를 통해 boardDTOList 값을 responseDTO에 저장하고 이를 반환하는 형태로 진행됩니다.

try~catch 문으로 혹시 잘못된 요청이 왔을 경우 예외처리를 해줍니다.

...
			responseDTO.setItems(boardDTOList);
            return ResponseEntity.ok().body(responseDTO);
        } catch (Exception e) {
            responseDTO.setStatusCode(HttpStatus.BAD_REQUEST.value());
            responseDTO.setErrorMessage(e.getMessage());
            return ResponseEntity.badRequest().body(responseDTO);
        }
    }

 

유사한 방식으로 insert, update, delete 등을 수행하면 다음과 같습니다.

 

CREATE

다음은 insert를 수행하는 코드입니다. 대부분 동일하지만, builder 메서드를 사용해서 구성요소를 담을 수 있게 만든 점이 다릅니다. 여기서는 제목, 내용, 작성자 세가지 구성요소를 정하고 생성날짜를 추가로 명시합니다. 이는 BoardEntity에 지정한 boardRegdate의 기본값은 기본생성자 호출할 때만 기본값으로 지정되는데, builder 메서드는 모든 매개변수를 갖는 생성자를 호출하기 때문에 boardRegdate의 값이 null값으로 들어가기 때문입니다. 즉, 생성날짜처럼 별도로 디폴트 값이 정의된 컬럼이라도 builder 방식에서는 null값으로 초기화합니다. 따라서 디폴트값에 해당하는 현재 시간을 명시적으로 넣어 null이 입력되는 것을 방지합니다.

//insert
    @PostMapping("/board")
    public ResponseEntity<?> insertBoard(BoardDTO boardDTO) {
        ResponseDTO<Map<String, String>> responseDTO =
        			new ResponseDTO<Map<String, String>>();
        try {

            Board board = Board.builder()
                            .boardTitle(boardDTO.getBoardTitle())
                            .boardContent(boardDTO.getBoardContent())
                            .boardWriter(boardDTO.getBoardWriter())
                            .boardRegdate(LocalDateTime.now())
                            .build();

            boardService.insertBoard(board);
            Map<String, String> returnMap = new HashMap<String, String>();
            returnMap.put("msg", "정상적으로 저장되었습니다.");
            responseDTO.setItem(returnMap);
            return ResponseEntity.ok().body(responseDTO);
        } catch (Exception e) {
            responseDTO.setStatusCode(HttpStatus.BAD_REQUEST.value());
            responseDTO.setErrorMessage(e.getMessage());
            return ResponseEntity.badRequest().body(responseDTO);
        }
    }

 

UPDATE

이번에는 데이터를 업데이트하겠습니다. 아래와 같이 코드를 작성합니다. update를 수행할 때 필요한 파라미터는 boardNo, boardTitle, boardContent 세가지입니다. 그러나 builder 메서드에서 boardWriter는 쿼리에서는 수정하지 않지만 언급되지 않으면 null로 처리되는 문제점이 발생하므로 boardWriter에서 이전 값을 다시 적어줘야 하는 번거로움이 있습니다.

 

  //update
    @PutMapping("/board")
    public ResponseEntity<?> updateBoard(BoardDTO boardDTO) {
        ResponseDTO<Map<String, String>> responseDTO =
                new ResponseDTO<Map<String, String>>();
        try {
            Board board = Board.builder()
                    .boardNo(boardDTO.getBoardNo())
                    .boardTitle(boardDTO.getBoardTitle())
                    .boardContent(boardDTO.getBoardContent())
                    .boardWriter(boardDTO.getBoardWriter())
                    .build();
            boardService.updateBoard(board);
            Map<String, String> returnMap = new HashMap<String, String>();
            returnMap.put("msg", "정상적으로 수정되었습니다.");
            responseDTO.setItem(returnMap);
            return ResponseEntity.ok().body(responseDTO);
            }
            returnMap.put("msg", "정상적으로 수정되었습니다.");
            responseDTO.setItem(returnMap);
            responseDTO.setStatusCode(HttpStatus.OK.value());
            return ResponseEntity.ok().body(responseDTO);*/
        } catch(Exception e) {
            responseDTO.setStatusCode(HttpStatus.BAD_REQUEST.value());
            responseDTO.setErrorMessage(e.getMessage());
            return ResponseEntity.badRequest().body(responseDTO);
        }
    }

 

DELETE

마지막으로 삭제를 수행합니다. 별도로 엔티티를 생성하지 않고, 바로 boardService의 deleteBoard 메서드를 호출하면 끝입니다. 아주 간단합니다.

 @DeleteMapping("/board")
    public ResponseEntity<?> deleteBoard(BoardDTO boardDTO) {
        ResponseDTO<Map<String, String>> responseDTO =
                new ResponseDTO<Map<String, String>>();
        try {
            boardService.deleteBoard(boardDTO.getBoardNo());
            Map<String, String> returnMap = new HashMap<String, String>();
            returnMap.put("msg", "정상적으로 삭제되었습니다.");
            responseDTO.setItem(returnMap);
            return ResponseEntity.ok().body(responseDTO);
        } catch(Exception e) {
            responseDTO.setStatusCode(HttpStatus.BAD_REQUEST.value());
            responseDTO.setErrorMessage(e.getMessage());
            return ResponseEntity.badRequest().body(responseDTO);
        }
    }