Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

히콩쓰 개발 일지

@ReqestBody String 사용 시 Json이 그대로 입력되는 이유 본문

Spring

@ReqestBody String 사용 시 Json이 그대로 입력되는 이유

용히콩 2023. 11. 14. 20:27

게시판 CRUD를 개발하던 중, 아래와 같은 요구사항을 구현하다 문제에 직면했다.

선택한 게시글 삭제 기능

  • 선택한 게시글을 삭제할 수 있습니다.
  • 서버에 게시글 삭제를 요청할 때 비밀번호를 함께 전달합니다.
  • 선택한 게시글의 비밀번호와 요청할 때 함께 보낸 비밀번호가 일치할 경우에만 삭제가 가능합니다.

password를 매개변수로 전달해주고 이를 비교하는 로직을 작성하면 된다고 생각해 아래와 같이 Controller를 구현했다.

    @DeleteMapping("/board/{id}")
    public void removeBoard(@PathVariable Long id, @RequestBody String password){
        boardService.removeBoard(id, password);
    }

Postman에서 body에 json 형식으로 password를 전달했고,

http://localhost:8080/board/6
{
    "password" : "1234"
}

비밀번호가 일치함에도, 일치하지 않는다는 오류를 출력해 디버깅으로 돌려봤다. (⭐은 중단점을 의미함)

    ⭐ public void removeBoard(Long id, String password) {
        Board findBoard = boardRepository.findById(id);
    ⭐   if (findBoard.getPassword().equals(password)) {
            boardRepository.deleteById(id);
        } else {
            System.out.println("비밀번호가 일치하지 않습니다.");
        }
    }

디버깅 결과,

password 가 기대값인 1234 로 입력되지 않고 json 형식 그대로 입력된 것을 확인할 수 있다.
이렇게 되면, DB에 저장된 값과 ✖️ 당연히 일치하지 않을 것이다 ✖️


@RequestBody의 역할은 HTTP의 Header와 Body 중에 Body로 들어온 데이터를 @RequestBody가 달린 Parameter에 넣어주는 역할이다.

이 때, Parameter가 String이면 그대로 넣어주지만,
Class라면 Jackson을 이용해 직렬화해서 매핑해준다.

이 경우는 String을 사용해 Jackson이 json을 직렬화 하지 않아 발생한 문제이다.


이 문제를 해결하기 위해, passwordDTO로 변경하는 방법을 고안했다.

  • password를 매개변수로 전달하는 것이 좋은 방법이 아니다.
    같은 맥락으로 url에 password가 노출되어서도 안 된다.

BoardDeleteRequestDto

import lombok.Getter;

@Getter
public class BoardDeleteRequestDto {
    private Long id;
    private String password;
}

Controller

    @DeleteMapping("/board")
    public void removeBoard(@RequestBody BoardDeleteRequestDto boardDeleteRequestDto){
        boardService.removeBoard(boardDeleteRequestDto);
    }

BoardService

    public void removeBoard(BoardDeleteRequestDto boardDeleteRequestDto) {
        Board findBoard = boardRepository.findById(boardDeleteRequestDto.getId());
        if (findBoard.getPassword().equals(boardDeleteRequestDto.getPassword())) {
            boardRepository.deleteById(boardDeleteRequestDto.getId());
        } else {
            System.out.println("비밀번호가 일치하지 않습니다.");
        }
    }

위와 같이 코드를 수정했다.

그 결과,

DTO로 전달된 password와 기존에 DB에 저장된 password의 값이 일치하는 것을 확인할 수 있다.
DB에서도 잘 삭제 되었다❗

해결 끝 ! 😚