게시판의 CRUD를 위해 End Point를 개발해보자.
클라이언트가 서버와 통신하고자 하는 URL 경로로 해당 포스트에서는 CRUD 기능을 제공하기 위해 응답 요청을 구현하는 것으로 한다.
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class BoardRequest {
@NotBlank
private String boardName;
}
board 테이블에 추가할 것은 게시판 이름 뿐이므로 request는 boardName만 작성한다.
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardRepository boardRepository;
public BoardEntity create(
BoardRequest boardRequest
) {
var entity = BoardEntity.builder()
.boardName(boardRequest.getBoardName())
.status("REGISTERED").build();
return boardRepository.save(entity);
}
}
service에서 status를 REGISTERED 리터럴로 지정해준다. 그럼 ID는 Auto-Increament를 통해 자동으로 등록된다.
@RestController
@RequestMapping("/api/board")
@RequiredArgsConstructor
public class BoardController {
private final BoardService boardService;
@PostMapping("")
public BoardEntity create(
@Valid
@RequestBody
BoardRequest boardRequest
){
return boardService.create(boardRequest);
}
}
위와 같은 방법으로 post, reply도 작성할 수 있다.
단, column의 수가 더 많으므로 빠지지 않도록 유의하며 작성한다.
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class PostRequest {
@NotBlank
private String userName;
@NotBlank
@Size(min = 4, max = 4)
private String password;
@NotBlank
@Email
private String email;
@NotBlank
private String title;
@NotBlank
private String content;
}
단편적으로 post 테이블의 request 필드는 5개인데, 각각 NotNull을 달고 있으며 필드마다 조건을 달아줄 수 있다ㅏ.
public class PostEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long boardId;
private String userName;
private String password;
private String email;
private String status;
private String title;
@Column(columnDefinition = "TEXT")
private String content;
private LocalDateTime postedAt;
}
post의 엔터티 필드인데, Service에서 엔터티를 만들 때 각 내용이 입력돼야한다.

QNA 게시판이라는 board를 생성한다.
위에서 boardEntity의 Status가 "REGISTERED"로 입력돼있기 때문에 자동으로 입력된다.

POST 요청을 하게되면 200 OK가 떨어진 것을 볼 수 있다.

데이터베이스에도 잘 적용이 됐다.
reply도 마찬가지로 동작한다.
public class ReplyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long postId;
private String userName;
private String password;
private String status;
private String title;
@Column(columnDefinition = "TEXT")
private String content;
private LocalDateTime repliedAt;
}
post entity와 유사한 엔터티를 가지고 있고,
ublic class ReplyService {
private final ReplyRepository replyRepository;
private final PostRepository postRepository;
public ReplyEntity create(
ReplyRequest replyRequest
) {
var optionalPostEntity = postRepository.findById(replyRequest.getPostId());
if(optionalPostEntity.isEmpty()){
throw new RuntimeException("게시물이 존재하지 않습니다. : " + replyRequest.getPostId());
}
var entity = ReplyEntity.builder()
.post(optionalPostEntity.get())
.userName(replyRequest.getUserName())
.password(replyRequest.getPassword())
.status("REGISTERED")
.title(replyRequest.getTitle())
.content(replyRequest.getContent())
.repliedAt(LocalDateTime.now())
.build();
return replyRepository.save(entity);
}
public List<ReplyEntity> findAllByPostId(Long postId) {
return replyRepository.findAllByPostIdAndStatusOrderByIdDesc(postId, "REGISTERED");
}
}
같은 내용의 create 메소드이지만, 없을 수 있는 reply에 대한 처리는 optionalPostEntity로 처리한다.
물론 get으로 postId를 가져오는 것은 바람직하지는 않다.
위 내용을 적절하게 개선시킨 내용을 다음 포스팅에서 작성하도록 한다.