Coding 공부/IntelliJ

[IntelliJ_Springboot_MariaDB] Http 메소드, Reply 테이블 관계도, 게시글 삭제 코드, 댓글 관련 코드(RESTful 방식, JSON)

CBJH 2024. 5. 22.
728x90
반응형

1. list로 돌아가는 버튼 스크립트 예제 코드

const link = [[${pageRequestDTO.getLink()}]]; // 페이지 요청에 대한 링크 정보를 가져와 link 변수에 할당합니다.
const formObj = document.querySelector("#f1"); // id가 'f1'인 폼 요소를 찾아 formObj 변수에 할당합니다.

document.querySelector(".listBtn").addEventListener("click", function (e) { // .listBtn 클래스를 가진 요소에 클릭 이벤트 리스너를 추가합니다.
    e.preventDefault(); // 기본 동작을 방지합니다. (여기서는 a 태그의 클릭 이벤트를 막습니다.)
    e.stopPropagation(); // 이벤트의 전파를 중단합니다. (부모 요소로의 이벤트 전파를 막습니다.)
    formObj.reset(); // formObj의 내용을 초기화합니다. (폼 요소 내의 입력값들을 초기화합니다.)
    self.location = `/board/list?${link}`; // 현재 페이지를 새로운 URL로 이동합니다. (페이지 요청에 대한 링크를 포함한 새 URL로 이동합니다.)
}, false);
  • 이 부분은 .listBtn 클래스를 가진 요소를 클릭할 때 실행되는 이벤트 핸들러입니다. 여기서 e.preventDefault()와 e.stopPropagation()를 호출하여 클릭 이벤트의 기본 동작과 이벤트의 전파를 막습니다. 그 후, formObj.reset()을 호출하여 폼 요소 내의 입력값을 초기화합니다. 마지막으로, self.location을 이용하여 현재 페이지를 새로운 URL로 이동시킵니다. 새 URL은 /board/list로 시작하며, 해당 페이지로 이동할 때 link 변수에 저장된 페이지 요청에 대한 링크 정보가 쿼리 문자열로 전달됩니다.

2. Controller method 방식(Http 메소드)

  • 조회: GET 
  • 등록: POST
  • 수정: PUT
  • 삭제: DELETE

3. Board, Member, Reply 테이블 관계도

  1. Member
    • member_id (PK)
    • name
    • email
  2. Board
    • board_id (PK)
    • title
    • content
    • member_id (FK) -> Member(member_id)
  3. Reply
    • reply_id (PK)
    • content
    • member_id (FK) -> Member(member_id)
    • board_id (FK) -> Board(board_id)

관계

  • MemberBoard: 일대다 관계 (한 명의 멤버가 여러 개의 게시글을 작성할 수 있음)
  • MemberReply: 일대다 관계 (한 명의 멤버가 여러 개의 댓글을 작성할 수 있음)
  • BoardReply: 일대다 관계 (한 개의 게시글에 여러 개의 댓글이 달릴 수 있음)

4. 추가된 코드1(삭제, 리스트로 돌아가기)

//Delete 버튼을 눌렀을 때, 이벤트 처리
document.querySelector(".removeBtn").addEventListener("click", function (e){
    e.preventDefault()
    e.stopPropagation()
    formObj.action = `/board/remove`
    formObj.method = 'post'
    formObj.submit()
}, false)
  • 삭제버튼에 대한 스크립트 코드
@PostMapping("/remove")
public String remove(Long bno, RedirectAttributes redirectAttributes){
    boardService.remove(bno);
    redirectAttributes.addFlashAttribute("result", "removed success!");
    return "redirect:/board/list";
}
  • 삭제 boardController 코드
@Override
public void remove(Long bno){
    boardRepository.deleteById(bno);
}
  • 삭제 BoardServiceImpl 코드

 

5. 추가된 코드2(댓글)

@RestControllerAdvice  // @RestControllerAdvice 어노테이션은 전역적으로 컨트롤러에 적용되는 예외 처리기를 정의합니다.
@Log4j2  // @Log4j2 어노테이션은 로그 처리를 위해 Log4j2 라이브러리를 사용합니다.
public class CustomRestAdvice {
    
    @ExceptionHandler(BindException.class)  // @ExceptionHandler 어노테이션은 특정 예외 타입을 처리하는 메서드를 지정합니다. 여기서는 BindException을 처리합니다.
    public ResponseEntity<Map<String, String>> handleBindException(BindException e) {
        log.error(e);  // 예외가 발생했을 때 예외 정보를 로그에 기록합니다.
        
        Map<String, String> errorMap = new HashMap<>();  // 에러 메시지를 담을 Map 객체를 생성합니다.
        
        if(e.hasErrors()){  // BindException 객체에 에러가 있는지 확인합니다.
            BindingResult bindingResult = e.getBindingResult();  // 에러 정보를 가져옵니다.
            
            bindingResult.getFieldErrors().forEach(fieldError -> {  // 각 필드 에러에 대해 반복합니다.
                errorMap.put(fieldError.getField(), fieldError.getCode());  // 필드 이름과 에러 코드를 Map에 추가합니다.
            });
        }
        // 에러가 있을 때 CustomRestAdvice가 호출되므로 예외가 있는지 체크할 필요가 없다.
        return ResponseEntity.badRequest().body(errorMap);  // HTTP 상태 코드 400 (Bad Request)와 에러 메시지를 담은 Map 객체를 응답 본문에 포함하여 반환합니다.
    }
}

요약 설명

  • @RestControllerAdvice와 @Log4j2 어노테이션을 사용하여, 이 클래스가 전역 예외 처리와 로그 기록을 담당하도록 합니다.
  • handleBindException 메서드는 BindException이 발생할 때 호출됩니다.
  • 발생한 예외를 로그에 기록한 후, 에러 메시지를 담은 Map 객체를 생성합니다.
  • BindException에 포함된 모든 필드 에러를 Map 객체에 추가합니다.
  • 최종적으로, HTTP 400 상태 코드와 에러 메시지를 클라이언트에게 반환합니다.
@RestController  // @RestController 어노테이션은 이 클래스가 RESTful 웹 서비스의 컨트롤러임을 나타냅니다.
@RequestMapping("/replies")  // @RequestMapping 어노테이션은 이 컨트롤러의 기본 URL 경로를 "/replies"로 설정합니다.
@Log4j2  // @Log4j2 어노테이션은 로그 처리를 위해 Log4j2 라이브러리를 사용합니다.
public class ReplyController {

    @PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE)  // @PostMapping 어노테이션은 HTTP POST 요청을 처리합니다. 요청 경로는 기본 경로 "/replies"에 "/"를 더한 "/replies/"이며, 요청 본문은 JSON 형식이어야 합니다.
    public Map<String, Long> register(@Valid @RequestBody ReplyDTO replyDTO,  // @Valid 어노테이션은 ReplyDTO 객체를 유효성 검사합니다. @RequestBody 어노테이션은 요청 본문을 ReplyDTO 객체로 변환합니다.
                                      BindingResult bindingResult) throws BindException {  // BindingResult 객체는 유효성 검사 결과를 저장합니다. BindException을 던질 수 있습니다.
        log.info(replyDTO);  // replyDTO 객체의 정보를 로그에 기록합니다.
        
        if (bindingResult.hasErrors()) {  // 유효성 검사에서 에러가 발생했는지 확인합니다.
            throw new BindException(bindingResult);  // 에러가 발생한 경우 BindException을 던집니다.
        }

        Map<String, Long> resultMap = new HashMap<>();  // 결과를 담을 Map 객체를 생성합니다.
        resultMap.put("rno", 10L);  // "rno"라는 키로 10L 값을 Map에 추가합니다. (실제 구현에서는 등록된 댓글의 ID 값을 반환하도록 해야 합니다)

        return resultMap;  // 결과 Map을 반환합니다.
    }
}

요약 설명

  • @RestController, @RequestMapping, @Log4j2 어노테이션을 사용하여, 이 클래스가 RESTful 웹 서비스의 컨트롤러임을 나타내고, 기본 경로를 /replies로 설정하며, 로그 기록을 위해 Log4j2를 사용합니다.
  • register 메서드는 HTTP POST 요청을 처리합니다.
    • 요청 경로는 /replies/이고, 요청 본문은 JSON 형식이어야 합니다.
    • @Valid 어노테이션으로 ReplyDTO 객체를 유효성 검사합니다.
    • 유효성 검사 결과는 BindingResult 객체에 저장됩니다.
    • 유효성 검사에서 에러가 발생하면 BindException을 던집니다.
    • 유효성 검사를 통과하면, 결과를 담은 Map 객체를 생성하여 반환합니다. 여기서는 임시로 "rno" 키에 10L 값을 반환합니다.
@Entity  // @Entity 어노테이션은 이 클래스가 JPA 엔티티임을 나타냅니다.
@Getter  // @Getter 어노테이션은 Lombok 라이브러리를 사용하여 모든 필드에 대한 getter 메서드를 자동으로 생성합니다.
@Builder  // @Builder 어노테이션은 Lombok 라이브러리를 사용하여 빌더 패턴을 적용합니다.
@AllArgsConstructor  // @AllArgsConstructor 어노테이션은 Lombok 라이브러리를 사용하여 모든 필드를 인자로 받는 생성자를 자동으로 생성합니다.
@NoArgsConstructor  // @NoArgsConstructor 어노테이션은 Lombok 라이브러리를 사용하여 인자가 없는 기본 생성자를 자동으로 생성합니다.
@ToString(exclude = "board")  // @ToString 어노테이션은 Lombok 라이브러리를 사용하여 toString 메서드를 자동으로 생성합니다. "board" 필드는 toString 출력에서 제외됩니다.
public class Reply extends BaseEntity {  // Reply 클래스는 BaseEntity를 상속받아 공통 엔티티 속성을 가집니다.

    @Id  // @Id 어노테이션은 이 필드가 엔티티의 기본 키임을 나타냅니다.
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // @GeneratedValue 어노테이션은 기본 키 생성을 데이터베이스에 위임합니다. (자동 증가)
    private Long rno;  // rno 필드는 댓글의 고유 식별자입니다.

    @ManyToOne(fetch = FetchType.LAZY)  // @ManyToOne 어노테이션은 이 필드가 Board 엔티티와 다대일 관계임을 나타냅니다. fetch 속성은 지연 로딩을 사용합니다.
    private Board board;  // board 필드는 이 댓글이 속한 게시글을 나타냅니다.

    private String replyText;  // replyText 필드는 댓글의 내용을 나타냅니다.
    private String replyer;  // replyer 필드는 댓글 작성자를 나타냅니다.
}

요약 설명

  • @Entity, @Getter, @Builder, @AllArgsConstructor, @NoArgsConstructor, @ToString 어노테이션을 사용하여 댓글(Reply) 엔티티를 정의합니다.
    • @Entity: 이 클래스가 JPA 엔티티임을 나타냅니다.
    • @Getter: 모든 필드에 대한 getter 메서드를 생성합니다.
    • @Builder: 빌더 패턴을 적용합니다.
    • @AllArgsConstructor: 모든 필드를 인자로 받는 생성자를 생성합니다.
    • @NoArgsConstructor: 기본 생성자를 생성합니다.
    • @ToString(exclude = "board"): toString 메서드를 생성하지만, board 필드는 제외합니다.
  • Reply 클래스는 BaseEntity를 상속받아 공통 엔티티 속성을 가집니다.
  • rno 필드는 댓글의 고유 식별자로, 기본 키로 설정되며 자동 증가합니다.
  • board 필드는 이 댓글이 속한 게시글과의 다대일 관계를 나타내며, 지연 로딩을 사용합니다.
  • replyText 필드는 댓글의 내용입니다.
  • replyer 필드는 댓글 작성자입니다.
@Data  // @Data 어노테이션은 Lombok 라이브러리를 사용하여 getter, setter, toString, equals, hashCode 메서드를 자동으로 생성합니다.
@Builder  // @Builder 어노테이션은 Lombok 라이브러리를 사용하여 빌더 패턴을 적용합니다.
@AllArgsConstructor  // @AllArgsConstructor 어노테이션은 Lombok 라이브러리를 사용하여 모든 필드를 인자로 받는 생성자를 자동으로 생성합니다.
@NoArgsConstructor  // @NoArgsConstructor 어노테이션은 Lombok 라이브러리를 사용하여 인자가 없는 기본 생성자를 자동으로 생성합니다.
public class ReplyDTO {
    private Long rno;  // 댓글의 고유 식별자

    @NotNull  // @NotNull 어노테이션은 이 필드가 null이 아니어야 함을 나타냅니다.
    private Long bno;  // 댓글이 속한 게시글의 고유 식별자

    @NotEmpty  // @NotEmpty 어노테이션은 이 필드가 비어 있지 않아야 함을 나타냅니다.
    private String replyText;  // 댓글의 내용

    @NotEmpty  // @NotEmpty 어노테이션은 이 필드가 비어 있지 않아야 함을 나타냅니다.
    private String replyer;  // 댓글 작성자

    private LocalDateTime regDate, modDate;  // 댓글의 생성 시간과 수정 시간
}

요약 설명

  • @Data, @Builder, @AllArgsConstructor, @NoArgsConstructor 어노테이션을 사용하여 댓글(Reply)의 데이터 전송 객체를 정의합니다.
    • @Data: Lombok 라이브러리를 사용하여 getter, setter, toString, equals, hashCode 메서드를 자동으로 생성합니다.
    • @Builder: 빌더 패턴을 적용합니다.
    • @AllArgsConstructor: 모든 필드를 인자로 받는 생성자를 생성합니다.
    • @NoArgsConstructor: 기본 생성자를 생성합니다.
  • rno 필드는 댓글의 고유 식별자입니다.
  • bno 필드는 댓글이 속한 게시글의 고유 식별자입니다. @NotNull 어노테이션으로 null이 아닌 값만 허용합니다.
  • replyText 필드는 댓글의 내용입니다. @NotEmpty 어노테이션으로 빈 값이 허용되지 않습니다.
  • replyer 필드는 댓글 작성자입니다. @NotEmpty 어노테이션으로 빈 값이 허용되지 않습니다.
  • regDate와 modDate 필드는 댓글의 생성 시간과 수정 시간을 나타냅니다.

생성된 Reply 테이블

 

댓글