Skip to content

fix: 탈퇴자 삭제 시 채팅 첨부와 게시글 이미지의 S3 객체가 고아로 남음 #850

Open

Description

@whqtker

어떤 버그인가요

탈퇴자 삭제 시 DB 행만 지워지고 S3 객체는 그대로 남아 영구 누적됩니다. 탈퇴자가 올린 파일이 계속 보관되므로 파기 관점에서도 문제입니다.

채팅 첨부 (#848 에서 새로 발생)

UserRemovalScheduler가 채팅 메시지를 삭제하면 ChatAttachment 행이 캐스케이드로 함께 삭제되는데, ChatAttachment.url이 가리키는 S3 객체는 지우지 않습니다. 행이 사라진 뒤에는 key를 다시 찾을 방법이 없어 영구 고아가 됩니다.

채팅 파일은 POST /s3/chat 으로 UploadPath.CHAT(chat/files)에 업로드됩니다. UploadPath.isResizable이 CHAT 에 대해 항상 false를 반환해 리사이즈를 거치지 않으므로, 반환되는 fileUrl이 곧 S3 key(chat/files/<uuid>.<ext>)이고 그 값이 ChatAttachment.url에 저장됩니다. 즉 저장된 값을 그대로 삭제 key 로 쓸 수 있습니다.

ChatAttachment.thumbnailUrl이 별도 S3 객체인지도 확인이 필요합니다. 별도 객체라면 함께 정리해야 합니다.

게시글 이미지 (기존 문제)

postRepository.deleteAllBySiteUserId가 Post 캐스케이드로 post_image 행을 지우지만, S3 객체는 남습니다. S3Service.deletePostImage는 PostCommandService:147, NewsCommandService:104 에서만 호출되고 탈퇴 배치 경로에는 없습니다. 채팅만 고치면 반쪽이 됩니다.

함께 해결해야 하는 것

1. S3 호출을 트랜잭션 밖으로

현재 scheduledUserRemoval은 삭제 대상 전원을 트랜잭션 하나로 처리합니다. 여기에 첨부 삭제를 넣으면 사용자당 S3 호출이 1회에서 N회로 늘어, 네트워크 실패 하나로 그날 삭제 전체가 롤백될 확률이 올라갑니다. #844 에서 범위 밖으로 남긴 "사용자 단위 트랜잭션 분리"와 함께 다루는 것이 맞습니다.

S3 삭제는 커밋 이후에 수행하고, 실패 시 재시도하거나 별도 정리 작업에 맡기는 구조가 필요합니다.

2. 삭제 key 검증

ChatService:250 은 chatImageSendRequest.imageUrls() 를 검증 없이 ChatAttachment.url 에 저장합니다. 서버가 업로드 결과와 대조하지 않으므로 임의 문자열이 들어올 수 있습니다. 이 값을 그대로 삭제 key 로 쓰면, 다른 경로의 객체(profile/... 등)를 가리키는 값을 넣어둔 뒤 탈퇴해 타인의 파일을 지우는 것이 가능합니다.

최소한 삭제 전에 chat/files/ 접두사를 검증해야 하고, 업로드 시점에 서버가 발급한 key 만 저장하도록 막는 쪽이 근본적입니다.

작업 상세 내용

  • ChatAttachment.thumbnailUrl 이 별도 S3 객체인지 확인
  • 삭제 대상 key 접두사 검증 (또는 업로드 시점 검증 강화)
  • S3 삭제를 트랜잭션 커밋 이후로 분리
  • 채팅 첨부 S3 객체 삭제
  • 게시글 이미지 S3 객체 삭제
  • 이미 누적된 고아 객체 정리 방안 검토

참고할만한 자료

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    버그Something isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions