PROJECT/개발일지

[백엔드 야생 개발일지] 게시글 조회/수정/삭제 기능 만들어보기

Ray123 2023. 2. 28. 20:53

저번에 등록(create) 기능까지 만들었고, 이번엔 조회(Read), 수정(Update), 삭제(Delete) 기능을 만들어보려 한다. 우선 조회부터 시작쓰.

 

게시글의 상세내용을 보기 위해서 클라쪽에서 서버 쪽으로 게시글id를 넘기도록 할 건데, 이 때 url변수로 넘기든가(ex : /board/1) 아님 쿼리스트링 형태로 넘기든가(ex : /board?id=1) 해야 한다. (body에 적는 방법 등도 있지만..패쓰) 아무래도 대중적인 방법은 url변수로 하는 방법이라 어떻게 하는지 알아봤다.

 

방법은 간단했다. @PathVariable이라는 어노테이션을 사용하면 됐다! 방법은

 

  • GetMapping(Post든 뭐든 상관 X)의 url입력하는 부분에 {받을 변수명}
  • 메서드의 파라미터로 @PathVariable("받을 변수명")

 

이다. 다음과 같이 활용해줬다.

 

@GetMapping("/{id}")
    public BoardResponseDTO getBoard(@PathVariable("id") Long id) {
        Board board = boardService.findBoard(id).get();
        // ... 생략
    }

 

그리고 다음과 같이 BoardResponseDTO를 만들어줬다.

 

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class BoardResponseDTO {
    private Long boardId;
    private String writerNickname;
    private String title;
    private String content;
    private Long hits;
    private Long like;
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;
    private int categoryId;

    public static BoardResponseDTO from(Member writer, Board board) {
        return new BoardResponseDTO(
                board.getBoardId(),
                writer.getNickname(),
                board.getTitle(),
                board.getContent(),
                board.getHits(),
                board.getLike(),
                board.getCreatedDate(),
                board.getUpdatedDate(),
                board.getCategoryId()
        );
    }
}

 

요즘 이 토이플젝을 하면서 참고하는 분이 있는데, 그 분은 이런 식으로 from메서드를 만들어 활용하는 식으로 하는 것 같아 참고해봤다. AccessLevel지정해주는 건 Lombok으로 만들어주는 생성자의 접근지정자를 설정하는거다. private로 한 것은 외부에서 요 놈의 인스턴스를 만드는 것을 막아주므로, BoardResponseDTO를 만들려면 from메서드를 사용하는 수밖에 없다!

 

암튼! 그래서 결과는..

 

 

성공~! 저번에 인터셉터 통해서 응답값들을 통일시켜준 방식 그대로 뱉어지는 모습도 곁들여 볼 수 있었다.

 

그 다음으론 삭제기능을 만들어보기로 했다. 삭제 기능에서의 고민은 바로 "삭제 권한". 글의 작성자만이 본인의 글을 삭제할 수 있도록 해야 할 것이다. 저번 학기에 프론트를 했을 때는 따로 프론트 쪽에서 현재 로그인한 유저의 정보를 가지고 있었기 때문에, 내가 지금 보고 있는 글의 작성자와 내가 가진 유저의 정보가 같으면 그 글에 삭제버튼을 보이게 하는 식으로 이를 만들었다. 그러나 지금 드는 생각은 어차피 contextHolder?거기에 현재 로그인한 유저의 정보를 가진다 하니 걔를 통해서 비교해줄 수 있을 것 같다!

 

그래서 다음과 같이 일단 delete에 해당하는 메서드를 만들어줬다.

 

@DeleteMapping("/{id}")
public String deleteBoard(@AuthenticationPrincipal Member member, @PathVariable("id") Long id) {
    Board board = boardService.findBoard(id).get();
    Member writer = board.getWriter();
    if (writer.getEmail().equals(member.getEmail())) {
        return "same";
    }
    return "diff";
}

 

현재 유저와 게시글의 작성자 이메일이 같다면 same을 뱉고, 다르면 diff를 뱉을 거다. 우선 작성자로 로그인하고 request를 보내봤다! 결과는..

 

 

같다고 잘 나왔다. 이번엔 다른 사용자로 로그인하고 (즉 포스트맨 상에서는 헤더에 담는 토큰을 다른 걸로 설정) 보내봤다. 결과는..

 

 

다르다고 잘 나온다! 삭제코드 자체는 BoardRepository에 deleteById메서드를 만들어 다음과 같이 구현해줬다.

 

@Override
public void deleteById(Long id) {
    Board board = em.find(Board.class, id);
    em.remove(board);
}

 

암튼 그렇게 해서 만든 삭제기능은..

 

 

27번 게시물이 잘 삭제된 것을 볼 수 있었다.

 

마지막으로 수정 기능을 만들 차례. 제목이나 본문의 내용이 잘 바뀌는지도 중요하겠지만, 아무래도 관건은 

 

  1. 수정일이 알아서 업데이트되는지, 생성일자는 변함없는지
  2. 게시물의 id가 그대로 유지되는지

 

정도가 될 것 같다. 

컨트롤러에서 다음과 같이 코드를 작성했다.

 

@PutMapping("/{id}")
public BoardResponseDTO updateBoard(
        @AuthenticationPrincipal Member member,
        @PathVariable Long id,
        @RequestBody BoardDTO boardDTO) {
    Board oldBoard = boardService.findBoard(id).get();
    Member writer = oldBoard.getWriter();

    if (writer.getEmail().equals(member.getEmail())) {
        Board updatedBoard = boardService.updateBoard(id, boardDTO);
        return BoardResponseDTO.from(writer, updatedBoard);
    }
    
    return null;
}

 

역시나 요청을 보낸 사람의 정보와 게시글 작성자가 같을 때에만 수정이 이뤄지게 했다. 그리고 게시글 작성 때 사용했던 BoardDTO를 수정할 때도 그대로 재탕해줬다. 어차피 게시글 작성할 때 작성하는 부분이 수정할 때 작성하는 부분이랑 같으니까..

BoardRepository에서 다음과 같이 코드를 짜 수정이 이루어지게끔 했다.

 

@Override
public Board updateBoard(Long id, BoardDTO boardDTO) {
    Board board = em.find(Board.class, id);
    board.setTitle(boardDTO.getTitle());
    board.setContent(boardDTO.getContent());
    board.setCategoryId(boardDTO.getCategoryId());
    em.persist(board);
    return board;
}

 

세터 메서드들을 사용해 Board엔티티의 내용물들을 바꿔치기해주고 저장해주는 식. entitymanager의 save라는 메서드가 인자로 받는 entity의 id값이 있냐없냐에 따라 insert를 할지 update를 할지 결정해준다고 한다. 이 경우에선 이미 board는 id가 있는 상태이니 update가 될 것이다.

 

이제 한 번 시험해볼 차례! 우선 수정 전 db상황은 다음과 같았다. 여기서 28번 게시물을 바꿀 거다.

 

 

포스트맨을 사용해 수정 테스트하기. 결과는..!

 

 

우선 응답값 자체는 문제가 없어보인다! 과연 db에서는..?

 

 

수정한 부분들이 잘 바뀌었음을 확인했다. title, content, category_id 컬럼값이 바뀌었으며 board_id나 writer는 변함없는 걸 볼 수 있다. 또한 created_date는 변화가 없고 updated_date에만 변화가 생겼음을 잘 확인할 수 있었다.