스프링 부트 CKEditor

스프링 부트 CKEditor 14 - 게시글 삭제 코드

https://youtu.be/-OV1zGW61mA?si=ggcy2erQ0wVSGnFz

스프링 부트 CKEditor 14 - 게시글 삭제 코드


Spring Boot + CKEditor 5 : 게시글 삭제 기능 구현하기

이번 글에서는 CKEditor로 작성하여 DB에 저장한 게시글을 삭제하는 기능을 구현한다.

CRUD 기준으로 보면:

  • Create → 생성 ✅
  • Read → 조회 ✅
  • Update → 수정 (다음 단계)
  • Delete → 삭제 ✅

이번 단계는 바로 마지막 D(Delete) 기능이다.

핵심은 한 줄이다.

URL로 전달받은 게시글 ID를 기반으로 DB에서 데이터를 삭제한다


1. 전체 삭제 흐름 이해

게시글 삭제는 다음 흐름으로 동작한다.

사용자 클릭
   ↓
/delete/{id} 요청
   ↓
Controller
   ↓
Service
   ↓
Repository
   ↓
DB delete
   ↓
목록 페이지 리다이렉트

2. 삭제 URL 설계

삭제 요청 URL은 다음 형태로 구성한다.

/delete/1
/delete/2
/delete/3

여기서 마지막 숫자는 게시글의 고유 ID다.


왜 ID가 필요할까?

DB에는 여러 게시글이 존재한다.

1 | 제목1
2 | 제목2
3 | 제목3

👉 어떤 게시글을 삭제할지 특정해야 한다.

즉:

/delete/2

의 의미는:

“2번 게시글 삭제”


3. DeleteController 생성

이제 삭제 요청을 처리할 Controller를 만든다.

@Controller
public class DeleteController {

    private final ContentsService contentsService;

    public DeleteController(ContentsService contentsService) {
        this.contentsService = contentsService;
    }

    @GetMapping("/delete/{id}")
    public String delete(@PathVariable Long id) {

        contentsService.deleteOneContent(id);

        return "redirect:/list";
    }
}

4. 핵심 포인트 설명

1) @PathVariable

@PathVariable Long id

URL의 {id} 값을 변수로 받는다.

예:

/delete/5

👉 id = 5


2) redirect:/list

return "redirect:/list";

삭제 후 다시 목록 페이지로 이동한다.


5. Service 삭제 로직 구현

이제 실제 삭제를 수행한다.

@Service
public class ContentsService {

    private final ContentRepository contentRepository;

    public ContentsService(ContentRepository contentRepository) {
        this.contentRepository = contentRepository;
    }

    public void deleteOneContent(Long id) {

        contentRepository.deleteById(id);
    }
}

6. deleteById() 내부 동작

contentRepository.deleteById(id);

Spring Data JPA가 자동으로 다음 SQL을 생성한다.

DELETE FROM content_entity
WHERE id = ?

👉 직접 SQL 작성 필요 없음


7. View에서 삭제 버튼 추가

이제 사용자가 삭제를 요청할 수 있도록 링크를 만든다.


content.html

<a th:href="@{/delete/{id}(id=${content.id})}">
    게시글 삭제
</a>

실제 렌더링 결과

<a href="/delete/3">
    게시글 삭제
</a>

👉 클릭 시:

/delete/3

요청 발생


8. 실행 테스트


1) 게시글 작성

제목: 테스트
내용: 삭제 테스트

2) 상세 페이지 이동

/content/1

3) 삭제 버튼 클릭


4) 결과

  • DB 데이터 삭제
  • /list 페이지 이동
  • 목록에서 게시글 사라짐

👉 성공


9. 현재 구조의 문제점 (중요)

현재는:

@GetMapping("/delete/{id}")

👉 즉 GET 요청으로 삭제 수행 중


왜 문제일까?

GET은 원칙적으로:

조회 전용

이어야 한다.


실무 권장 방식

@DeleteMapping

또는

@PostMapping

사용


이유

  • 브라우저 자동 요청 위험
  • 보안 문제
  • RESTful 설계 위반

👉 지금 구조는 학습용으로는 괜찮지만 실무에서는 수정 필요


10. 실무 관점에서 중요한 포인트

1. 삭제 전 권한 검증 필요

현재:

누구나 삭제 가능

👉 실제 서비스에서는:

  • 로그인 사용자 확인
  • 작성자 검증

필수


2. Soft Delete 고려

현재는 물리 삭제:

DELETE FROM ...

실무에서는 종종:

deleted = true

형태의 논리 삭제 사용


3. 존재하지 않는 ID 처리

deleteById(9999)

예외 처리 필요


11. 지금 단계에서 중요한 것

이 단계는 단순 삭제가 아니다.


핵심 이해 포인트

  • URL 기반 리소스 식별
  • Controller → Service → Repository 흐름
  • JPA delete 메소드 사용

12. 다음 단계

이제 CRUD 거의 완성이다.


다음 작업

  1. 게시글 수정 기능
  2. 기존 데이터 불러오기
  3. CKEditor 재렌더링
  4. Update 처리

정리

이번 글의 핵심은 한 줄이다.

삭제 기능은 “ID 기반 리소스를 찾아 제거하는 과정”이다


핵심 요약

  • /delete/{id} 구조 사용
  • @PathVariable로 ID 수신
  • Service에서 deleteById() 호출
  • 삭제 후 목록 페이지 리다이렉트


© 2020. All rights reserved.

SIKSIK