2025/12/25 PR Riview

김기훈·2025년 12월 24일

TIL

목록 보기
94/194

오늘 학습 내용 ✅

PR Riview

1. is_editable 제거

  • 문제

    • 클라이언트에서 가지고 있는 작성자 정보와 비교해서 수정 버튼의 활성화여부를 결정할 것이기 때문에
    • is_editable = serializers.SerializerMethodField() 이 값을 없애라
  • 해석

    • 수정 버튼을 보여줄지 말지의 판단 책임은 백엔드(API)가 아니라 프론트엔드(클라이언트)
  • 나의 구현 현황

    • 현재 로그인 유저가 누구인지 확인하고 질문 작성자인지 비교해서
      • is_editable: true / false 를 응답으로 내려줌
      • 이 값으로 프론트에게 이 질문이 수정이 가/불가능 을 알리려 했음
    • 이미 질문 상세 조회에 author.id가 내려가고 있기 때문에
      • 프론트는 로그인한 유저 id / question.author.id를 비교하여 같으면 "수정" 버튼을 보여준다.
      • 그렇기 때문에 굳이 is_editable같은 UI용 bool값을 내려줄 필요가 없다.
    • 그렇기 때문에 지금 is_editable 값은 지우고 나는 실제 수정 가능 여부만 엄격하게 검사한다.
is_editable = serializers.SerializerMethodField()

    def get_is_editable(self, obj: Question) -> bool:
        request = self.context.get("request")

        if not isinstance(request, Request):
            return False

        user = request.user
        if not user.is_authenticated:
            return False

        return obj.author_id == user.id
  • 해결

    • QuestionDetailSerializer 에서 필드 제거
    • Meta.fields 에서 제거
    • 메서드 제거

이미지 관리 방식

[1] FE: 이미지 업로드 요청
        ↓
[2] BE: Presigned URL 발급
        ↓
[3] FE: S3에 직접 PUT 업로드
        ↓
[4] FE: S3 URL을 content에 삽입
        ↓
[5] FE: 질문 등록/수정 요청
        ↓
[6] BE: content 파싱 → 이미지 URL 추출
        ↓
[7] BE: QuestionImage 생성/삭제
  • FE 과정

[1] 이미지 선택: 사용자가 에디터에서 이미지 선택

[2] BE에게 Presigned URL 요청 
	POST /images/presigned

[3] BE 응답
{
  "upload_url": "https://s3....(PUT용)",
  "file_url": "https://bucket.s3/.../uuid.png"
}

[4] FE가 S3에 직접 업로드
	BE 서버는 관여 안함
    S3에 바로 저장됨

[5]	FE가 content를 만든다(이 시점 이미지는 content 일부)
  <p>질문 설명</p>
  <img src="https://bucket.s3/.../uuid.png" />

[6] 질문 등록 / 수정 요청
{
  "title": "...",
  "content": "<p>...</p><img src='https://...'>",
  "category": 1
}
  • BE 과정

[1] BE는 content를 그대로 믿지 않는다
	content = validated_data["content"]

[2] content에서 이미지 URL 파싱
	content_images = extract_image_urls_from_content(content)

[3] 결과(이 질문에서 실제로 사용 중인 이미지)
{
  "https://bucket.s3/.../uuid.png"
}

[4] QuestionImage 테이블과 동기화

[5] 질문 생성
for url in content_images:
    QuestionImage.objects.create(
        question=question,
        img_url=url,
    )

[6] 질문 수정
삭제 대상 = DB 이미지 - content 이미지
추가 대상 = content 이미지 - DB 이미지

  • 이미지 삭제

[1] 사용자가 에디터에서 이미지 삭제
	<img ...> ← 제거됨

[2] FE는 그냥 content만 보냄
{
  "content": "<p>이미지 없음</p>"
}

[3] BE가 파싱
	content_images = set()  # 비어 있음

[4] DB 동기화
기존: 이미지 있음
content 이미지: 없음
→ QuestionImage 삭제

[1] 

[2] 

[3] 

[4] 

[5] 

[6] 
[1] 

[2] 

[3] 

[4] 

[5] 

[6] 

새롭게 알게된 내용 ✅

오늘 발생한 문제(발생 했다면) ✅

profile
안녕하세요.

0개의 댓글