[데브코스] Spring Boot REST API 실습 (16강) - 글 삭제 API 구현, ForPostRsData 도입 배경

zuno·2025년 12월 21일

이번 강의에서는 글 삭제 API 구현을 진행하면서,
기존에 도입했던 RsData 구조의 한계를 직접 체감하게 된다.

결론적으로는
👉 글 관련 응답 전용 클래스인 ForPostRsData를 새로 도입하게 되었고,
이 과정 자체가 “왜 응답 구조를 처음부터 범용으로 설계해야 하는지”를 잘 보여주는 강의였다.


1️⃣ 글 삭제 API 구현

먼저 가장 기본적인 글 삭제 API부터 구현한다.

@GetMapping("/{id}/delete")
@Transactional
public PostDto delete(@PathVariable int id) {
    Post post = postService.findById(id).get();

    postService.delete(post);

    return new PostDto(post);
}
public void delete(Post post) {
    postRepository.delete(post);
}

🔎 여기서 중요한 포인트

  • 글(Post) 엔티티를 삭제하면
  • CascadeType.REMOVE 설정 덕분에
  • 해당 글에 달린 댓글들이 먼저 자동으로 삭제됨
@OneToMany(
    mappedBy = "post",
    cascade = {PERSIST, REMOVE},
    orphanRemoval = true
)
private List<PostComment> comments;

👉 즉, 별도의 댓글 삭제 로직 없이도 연관 데이터 정리가 자동으로 이루어진다.


2️⃣ RsData로 응답을 통일하고 싶었던 시도

이전 강의(15강)까지의 흐름상,
조회가 아닌 요청은 모두 RsData로 응답하는 구조를 만들고 있었다.

그래서 글 삭제도 이렇게 처리해보려 했다.

@GetMapping("/{id}/delete")
@Transactional
public RsData delete(@PathVariable int id) {
    Post post = postService.findById(id).get();

    postService.delete(post);

    return new RsData(
            "200-1",
            "%d번 글이 삭제되었습니다.".formatted(id),
            new PostDto(post)
    );
}

하지만 여기서 문제가 발생한다.


3️⃣ RsData 구조의 한계

현재 RsData는 다음과 같은 형태였다.

public record RsData(
        String resultCode,
        String msg,
        PostCommentDto data
) {
}

즉,

  • 댓글 관련 응답에는 잘 맞지만
  • 글(PostDto) 응답에는 사용할 수 없음

👉 RsData가 댓글 DTO에 강하게 결합되어 있는 상태였다.

이 시점에서 강사님도 명확하게 말씀하셨다.

“RsData만으로 처리하기엔 지금 구조가 만족스럽지 않다.”


4️⃣ 임시 해결책: ForPostRsData 도입

그래서 이번 강의에서는
글 관련 응답 전용 RsData를 하나 더 만든다.

package com.back.global.rsData;

import com.back.domain.post.post.dto.PostDto;

public record ForPostRsData(
        String resultCode,
        String msg,
        PostDto data
) {
}

그리고 글 삭제 API는 이렇게 변경된다.

@GetMapping("/{id}/delete")
@Transactional
public ForPostRsData delete(@PathVariable int id) {
    Post post = postService.findById(id).get();

    postService.delete(post);

    return new ForPostRsData(
            "200-1",
            "%d번 글이 삭제되었습니다.".formatted(id),
            new PostDto(post)
    );
}

5️⃣ 왜 이 방식이 아쉬운가?

이 방식은 당장은 동작하지만, 구조적으로 아쉬운 점이 분명하다.

  • 댓글용 RsData
  • 글용 ForPostRsData
  • 주문용?
  • 장바구니용?

👉 도메인마다 RsData가 하나씩 늘어나는 구조가 된다.

이는 결국:

  • 코드 중복 증가
  • 응답 구조 관리 복잡도 증가
  • 유지보수 비용 증가

로 이어진다.


6️⃣ 이 강의의 핵심 메시지

이번 강의의 핵심은 “글 삭제 구현” 자체보다도 이것이다.

응답 객체는 처음부터 범용적으로 설계하는 것이 중요하다

앞선 15강에서 살짝 언급되었던 것처럼,
결국 가장 이상적인 형태는 제네릭 RsData다.

public record RsData<T>(
        String resultCode,
        String msg,
        T data
) {
}

이렇게 되면:

  • 댓글
  • 주문
  • 장바구니

모든 응답을 하나의 구조로 처리할 수 있다.


7️⃣ 정리

  • 글 삭제 시 CascadeType.REMOVE로 댓글이 자동 삭제된다
  • 삭제된 엔티티는 트랜잭션 내에서 DTO로 응답 가능하다
  • RsData를 사용해 응답을 통일하려 했지만
  • 현재 구조에서는 댓글 전용이라 한계가 드러났다
  • 임시로 ForPostRsData를 도입했지만
  • 궁극적인 해결책은 제네릭 RsData

💡 한 줄 요약

16강은 “글 삭제”보다
응답 구조 설계의 중요성을 몸으로 느끼게 해준 강의였다.

0개의 댓글