1.  REST 방식의 댓글 처리 준비

📌  REST 방식의 댓글 처리는 다음과 같은 단계로 진행

  • URL 설계와 데이터 포맷 결정
  • 컨트롤러의 JSON / XML 처리
  • 동작 확인
  • 자바스크립트를 통한 화면 처리


1)  URL 설계와 DTO 설계


  ⚡️  REST 방식은 주로 XML이나 JSON 형태의 문자열을 전송하고 이를 컨트롤러에서 처리하는 방식을 이용
  ⚡️  JSON을 이용해서 DTO에 맞는 데이터를 전송하고 스프링을 이용해서 이를 DTO 처리하도록 구성

 

댓글의 URL 설계
Method URL 설명 반환 데이터
POST /replies 특정한 게시물의 댓글 추가 {'rno':11} - 생성된 댓글의 번호
GET /replies/list/:bno 특정 게시물(bno)의 댓글 목록 '?'뒤에 페이지 번호를 추가해서 댓글 페이징 처리 PageResponseDTO를 JSON으로 처리
PUT /replies/:rno 특정한 번호의 댓글 수정 {'rno':11} - 수정된 댓글의 번호
DELETE /replies/:rno 특정한 번호의 댓글 삭제 {'rno':11} - 삭제된 댓글의 번호
GET /replies/:rno 특정한 번호의 댓글 조회 댓글 객체를 JSON으로 변환한 문자열

 

프로젝트 dto 패키지에 ReplyDTO를 추가
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReplyDTO {
    private Long rno; // 리플 고유번호
    private Long bno; // 게시판의 글 고유번호
    private String replyText; // 리플 내용
    private String replyWriter; // 리플 작성자
    private LocalDateTime regDate, modDate;
}

 

  ✓  ReplyDTO에는 고유한 rno외에도 특정한 게시물 번호 bno를 선언
  ✓  이를 통해서 현재 댓글이 특정한 게시물의 댓글임을 알 수 있음

 


 

2)  ReplyController 준비

 

  ⚡️  ReplyController는 기존과 달리 @RestController라는 어노테이션을 활용
  ⚡️ @RestController를 이용하게 되면 메서드의 모든 리턴 값은 JSP나 Thymeleaf로 전송되는 것이 아니라 바로 JSON이나 XML 등으로 처리
  ⚡️  본격적인 개발 전에 약간의 테스트를 진행 할 수 있도록 ReplyController에 POST 방식을 처리하는 메서드를 추가

@RestController
@RequestMapping("/api/replies")
@Log4j2
public class ReplyController {
    @Operation(summary = "Replies Post", description = "POST 방식으로 댓글 등록")
    @PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE)
    public Map<String, Long> register(@RequestBody ReplyDTO replyDTO) {
        log.info(replyDTO);
        Map<String, Long> map = new HashMap<>();
        map.put("rno", 111L);

        return map;
    }
}

 

  📍 register() 메서드의 파라미터에는 ReplyDTO를 이용해서 파라미터를 수집한다고 선언되어 있지만 앞에 @RequestBody라는 어노테이션이 존재. @RequestBody는 JSON 문자열을 ReplyDTO로 변환하기 위해 표시

  📍  @PostMapping에는 consumes 라는 속성을 사용. consumes는 해당 메서드를 받아서 소비(Consume)하는 데이터가 어떤 종류인지 명시할 수 있음. 이 경우 JSON 타입의 데이터를 처리하는 메서드임을 명시

  📍  Swagger UI에서는 필요한 JSON 데이터를 미리 구성해서 사용할 수 있도록 작성할 수 있음

  • Try it out 클릭 후 필요한 데이터만 입력해서 전송
  • register() 가 실행되고 리턴 값이 JSON으로 처리됨. @RestController는 리턴 값 자체가 JSON으로 처리
  • 서버에는 정상적으로 필요한 파라미터가 수집된 것을 확인

 

postman / Swagger 비교
  • boot 프로젝트의 경우 postman에 비해 Swagger가 작성한 애플리케이션의 특성에 맞게 테스트 할 수 있고, API 문서를 자동화 할 수 있는 장점이 존재
  • 프로젝트안에 Swagger가 들어가는 것을 기피하는 경우도 있음. 예를 들어 boot3 버전 부터는 Swagger 설정이 달라져서 프로젝트를 수정해야 함. 프로젝트와 독립된 방식으로 사용할 수 있는 postman을 선호하기도 함

 

3) @Valid와 @RestControllerAdvice

 

  ⚡️  REST 방식의 컨트롤러는 대부분 Ajax와 같이 눈에 보이지 않는 방식으로 서버를 호출하고 결과를 전송하므로 에러가 발생하면 어디에서 어떤 에러가 발생했는지 알아보기 힘든 경우가 많음 * Ajax 개발의 힘든 점 중 하나가 디버깅
  ⚡️ 이런 이유로 @Vaild 과정에서 문제가 발생하면 처리할 수 있도록 @RestControllerAdvice를 작성

 

controller 패키지에 advice 패키지를 추가하고 CustomRestAdvice 클래스를 추가
@Log4j2
@RestControllerAdvice
public class CustomRestAdvice {
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity<Map<String, String>> handleBindException(BindException e) {
        log.error(ex);

        Map<String, String> errorsMap = new HashMap<>();

        if (e.hasErrors()) {
            BindingResult bindingResult = e.getBindingResult();

            bindingResult.getFieldErrors().forEach(fieldError -> {
                errorsMap.put(fieldError.getField(), fieldError.getCode());
            });
        }
        return ResponseEntity.badRequest().body(errorsMap);
    }
}

 

  ✓  @RestControllerAdvice을 이용하면 컨트롤러에서 발생하는 예외에 대해 JSON과 같은 응답 메시지를 생성해서 보낼 수 있음
  ✓  작성한 handleBindException() 메서드는 컨트롤러에서 BindException이 던져지는 경우 이를 이용해서 JSON 메시지와 400에러 (Bad Request)를 전송

 


4)  댓글 등록 @Valid


  ⚡️  @RestControllerAdvice를 이용해서 ReplyDTO를 검증해서 register()를 처리하도록 변경

 

ReplyDTO에 검증과 관련된 어노테이션을 추가
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReplyDTO {
    private Long rno; // 리플 고유번호

    @NotNull
    private Long bno; // 게시판의 글 고유번호
    
    @NotEmpty
    private String replyText; // 리플 내용

    @NotEmpty
    private String replyWriter; // 리플 작성자
    private LocalDateTime regDate, modDate;
}

 

실제 동작 여부를 확인하기 위해 ReplyController의 register()를 수정
public class ReplyController {

    @Operation(summary = "Replies Post", description = "POST 방식으로 댓글 등록")
    @PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE)
    public Map<String, Long> register(@Valid @RequestBody ReplyDTO replyDTO,
            BindingResult bindingResult) throws BindException {

            log.info(replyDTO);

            if (bindingResult.hasErrors()) {
                throw new BindException(bindingResult);
            }

            Map<String, Long> map = new HashMap<>();
            map.put("rno", 111L);

            return map;
    }
}

 

  📍 register()는 다음과 같은 점들이 수정

  • ReplyDTO를 수집할 때 @Valid를 적용
  • BindingResult를 파라미터로 추가하고 문제가 있을 때는 BindException을 throw하도록 수정
  • 메서드 선언부에 BindException을 throws하도록 수정
  • 메서드 리턴값에 문제가 있다면 @RestControllerAdvice가 처리할 것이므로 정상적인 결과만 리턴

 

프로젝트를 실행하고 ReplyDTO가 체크할 내용이 없는 데이터를 Swagger UI로 전송 테스트

 

  ⚡️  ReplyDTO는 bno나 replyText 등의 값이 반드시 있어야하므로 실행 결과는 다음과 같이 문제가 있는 부분만 에러 메시지를 전송받을 수 있음

 

 

✓  결과 메시지를 보면 @Valid 과정에 문제가 있는 필드들과 메시지를 JSON 문자열로 전송
✓Ajax를 이용하는 개발에는 에러의 발생 소지가 서버인 경우도 있고, 브라우저나 자바 스크립트일 때도 있기 때문에 서버에서 먼저 확실하게 문제가 없는 것을 확인하고 화면을 개발하는 것이 좋음

 

 

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

+ Recent posts