2025/12/09 MainProject - 2

김기훈·2025년 12월 9일

TIL

목록 보기
78/191

오늘 학습 내용 ✅

  • 모델 설계 및 모델 관련 코드 정리


내 파트

기능메서드URL
질문 등록POST/api/v1/qna/questions
질문 목록 조회GET/api/v1/qna/questions
질문 상세 조회GET/api/v1/qna/questions/{question_id}
질문 수정PUT/api/v1/qna/questions/{question_id}

파트 변경

  • 질문 등록("/api/v1/qna/questions")

    • 웹사이트 이용자 중 수강생 권한을 가진 로그인 유저는 질의응답 메뉴로 접속하여 질문 등록 가능
    • 질문 등록 시 입력 항목
      • 제목
      • 질문 내용 ( 마크다운 문법 사용 가능, 이미지 첨부 가능 )
      • 카테고리 (대분류 > 중분류 > 소분류)
      • 내용에 첨부된 이미지들

  • 질의응답 목록 조회("/api/v1/qna/questions")

    • 모든 웹사이트 이용자는 질의응답 메뉴로 접속하여 등록된 질의응답 목록을 조회 가능
    • 질의응답 목록 조회 시 상단의 탭을 이용하여 답변 작성 여부에 따라 목록을 조회할 수 있음
      • 추가로 질문 카테고리별로 필터링을 적용 가능
    • 질의응답 목록 조회 시 검색 기능을 활용하여 원하는 질의응답 항목을 찾기 가능
    • 조회된 질의응답 목록은 최신순으로 정렬되어야하며 페이지네이션이 적용
    • 목록에서 각 항목은 카드 형태로 노출
    • 질의응답 목록에서 조회가능한 항목 ( 각 카드에 포함되어야 하는 항목 )

      • 질의응답 카테고리 ( 대분류 > 중분류 > 소분류 형태 )
      • 작성자 정보
        • 프로필 이미지
        • 닉네임
      • 질의응답 제목
      • 질문 내용
      • 답변 수
      • 조회수
      • 질문 작성일시
      • 질문 내용에 포함된 이미지의 썸네일 이미지"

  • 질의응답 상세 조회("/api/v1/qna/questions/{question_id}")

    • 모든 웹사이트 이용자는 조회된 질의응답 목록 중에서 특정 항목을 클릭하여 상세 조회 가능
    • 특정 항목을 클릭 시 상세조회 페이지로 이동
    • 상세 조회 페이지에서 확인 가능한 항목

      • 질문 제목
      • 질문 내용
      • 질문 내용에 첨부된 이미지
      • 질문 작성자 정보
        • 프로필 썸네일 이미지
        • 닉네임
      • 질문 카테고리 정보
        • 대, 중, 소분류 카테고리 이름
      • 질문 조회수
      • 질문 작성일시
      • 답변 목록
        • 답변 작성자 정보
          • 프로필 썸네일 이미지
          • 닉네임
        • 답변 내용
        • 답변 작성일시
        • 답변 채택 여부
        • 답변에 대한 댓글 목록
          • 댓글 작성자 정보
            • 프로필 썸네일 이미지
            • 유저 닉네임
          • 댓글 내용
          • 댓글 작성일시

  • 질문 수정("/api/v1/qna/questions/{question_id}")

    • 웹사이트 이용자 중 수강생 권한을 가진 로그인 유저는 질의응답 메뉴로 접속하여
      • 자신이 작성한 질문 내용을 수정 가능
    • 질의응답 상세 페이지 내에 위치한 수정하기 버튼을 클릭하여 해당 질문 내용을 수정 가능
    • 수정하기 버튼은 작성자 본인외에 노출되지 않아야 함
    • 수정 가능한 항목

      • 제목
      • 질문 내용 ( 마크다운 문법 사용 가능, 이미지 첨부 가능 )
      • 카테고리
      • 내용에 첨부된 이미지들"

순서

    1. 모델 설계
    1. makemigrations / migrate
    1. Serializer 생성 (입력용 / 출력용)
    1. APIView 작성 (POST)
    1. URL 연결
    1. 실제 이미지 업로드 테스트
    1. 필요 시 GET/PUT/DELETE API도 확장

질문등록

질문등록 specapi

  • mock

    • 아직 서버가 구현되지 않은 상태에서 프론트엔드가 먼저 개발할 수 있도록
    • 임시(Mock) 데이터 + Mock API 구조를 만드는 것을 의미
      • SpecAPI → MockAPI → 실제 API 구현 순서로 가는 구조

모델 구현

  • Django는 기본적으로 id 필드를 자동 생성
    • 명시적으로 적는 것이 틀린 것은 아니고 오히려 특정한 상황에서는 더 선호되기도 함
      • Django 3.2 이후 프로젝트의 DEFAULT_AUTO_FIELD 설정에 따라
        • BigAutoField / AutoField 둘 중 하나로 생성 됨
      1. BigAutoField로 강제하고 싶을 때
      1. ERD 설계서·스키마 명세와 명확히 맞추기 위해
      1. PK 전략을 커스텀하고 싶을 때
      • 예: UUID 필드 사용, 또는 자연키 사용 등 이런 경우 명시적 선언이 필수
  • id를 넣은 이유

    • ERD 문서와 코드가 1:1로 매칭 → 유지보수의 이점 / 보기 좋음

모델 추가 사항

  • Category parent_id → SET_NULL
    • 부모 카테고리 삭제 시 자식이 고아가 되지만 데이터 유지 가능
  • Question의 category on_delete=PROTECT
    • 카테고리 삭제 시 질문이 같이 사라지면 안 됨 → 보호 필요
  • QuestionImage → CASCADE
    • 질문 삭제 → 이미지도 사라져야 자연스러움
  • QuestionAIAnswer → CASCADE
    • 질문 삭제되면 AI 자동응답도 함께 삭제되는 구조

api 기능 구현

  • 순서

    • ERD / 모델(Model) 먼저 확정
    • Serializer 설계
    • View(APIView) 설계
    • URL 등록

pre-signed

  • 이미지 업로드는 pre-signed 사용
    • 이미지를 API 서버(Django)로 직접 보내지 않고
    • AWS S3(스토리지)에 바로 업로드하도록 “임시로 허가된 URL”을 발급해주는 방식
      • 백엔드 서버는 이미지를 직접 저장하지 않음
      • 클라이언트(프론트)가 S3로 바로 업로드함
      • 백엔드는 “업로드 허가가 된 URL”만 발급해줌 → 그걸 프론트가 사용
  • 장점

    • 백엔드 서버 부하가 줄어듬 / 업로드 속도가 빠름 / 보안문제 해결 가능 / 서버는 url만 관리
      • 프론트 → S3로 바로 보내면 트래픽 비용과 CPU 리소스를 아낄 수 있음
      • 프론트가 S3에 직접 업로드하므로 중간 단계(백엔드)를 생략
      • S3 버킷을 전체 공개하면 위험함 → pre-signed URL은 몇 분만 유효한 임시 URL이라 안전
      • 이미지 실제 파일은 S3에 있고 Django DB에는 이미지 URL만 저장하면 됨

api 개발 순서

  • Spec API로 API 스펙 확정

    • 프론트와 “요청/응답은 이렇게 갈 거야”를 합의
    • URL, 필드, 응답형식 확정
    • Swagger 문서 생성됨
    • 프론트는 mock API 기반으로 화면 개발 시작 가능
  • 실제 API 구현 시작

    • ModelSerializer + create()로 DB 저장 구현
    • presigned URL 처리 구현
    • QuestionImage 저장 로직 구현
    • QuestionAIAnswer 생성 로직 구현
  • 기능 테스트(Unit Test / API Test)

    • 실제 기능이 동작하는지 검증
    • DB에 정상 저장되는지
    • 이미지 URL이 정상 저장되는지
    • 권한 체크 작동하는지

새롭게 알게된 내용 ✅

  • git branch -vv
    • 현재 브랜치의 추적 상태 보기
  • git config pull.rebase true

  • git checkout develop

  • git pull origin develop

  • git checkout feature/~

  • git rebase develop

    • 내 현재 브랜치의 변경사항을 대상브랜치의 변경사항 위에 새롭게 쌓아올림
    • 내 브린치의 변경사항(커밋들) / 커밋들의 커밋 해시가 변경됨

  • git commit --amend : 방금 만든 커밋 내용 수정
  • git log --oneline : 한줄로 깔끔하게 커밋 이력 보기 (푸시 전도 보임)
    • 나가기: q
  • git log origin/develop..HEAD --oneline : 푸시 안 된 커밋만 따로 보기
  • git log --oneline --graph --all : 그래프 형태로 보기

  • poetry run black .

  • poetry run isort .

  • poetry run dmypy run -- .

  • poetry run coverage run manage.py test

어려운 내용(추가 학습 필요) ✅

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

  • git pull 오류
    • 원인

      • 현재 작업 중인 브랜치(develop)가 원격(origin)의
      • 어떤 브랜치를 추적해야 하는지 설정이 안 되어 있어서 git pull을 못함
    • 해결 1

      • develop 브랜치를 사용하는 거라면 원격의 origin/develop을 추적하도록 설정
      • git branch --set-upstream-to=origin/develop develop
      • 결과: develop 브랜치에서 그냥 git pull만 입력해도 자동으로 origin/develop에서 가져옴
    • 해결 2

      • git pull -u origin develop
      • -u 옵션: 이제 앞으로 이 브랜치는 origin/develop을 기본으로 사용하겠다.
  • 결과

    • 내가 develop 브랜치에 있을 경우 git pull 하면 origin/develop 에서 가져옴
    • 주의 ⚠️: 다른 브랜치(feature/login, main 등)에 있을 때는 develop이 pull 불가

  • 문제:
    • develop브랜치 내용 pull하고 새로운 브랜치 파고나니 로컬에서는 코드의 변화가 없고
    • 레포에는 develop 내용 푸시되어 있음
  • 해결:
    • 아직 코드 작성이 많이 진행된것도 아니기 때문에 그냥 develop상태로 강제 리셋
    • develop 최신 코드 가져오기
      • git fetch origin
    • 현재 브랜치를 origin/develop 기준으로 강제 리셋
      • git reset --hard origin/develop

  • 스웨거 질문 등록 specapi 테스트중 401 뜸
  • 이유: permission_classes가 설정되지 않아서
    • settings.py 에서 기본 권한을 지정하지 않았다면 대부분의 프로젝트에서는 “인증 필요” 함
    • 즉, 로그인하지 않으면 → 모든 API가 401 Unauthorized 를 발생시키는 상태가 되는 것.
  • 해결: Spec API에 명시적으로 AllowAny 추가
    • permission_classes = [AllowAny]

  • 이번에는 500에러 발생
    • 이유
      • specapi에서 category는 ForeignKeyField이기 때문에 category가 실제로 DB에 존재하는지 검증
      • 하지만 Spec API에서는 DB 테이블을 만들지 않았음
      • ModelSerializer는 모델 기반으로 자동 필드를 만들기 때문에
        • ForeignKeyField도 자동으로 "queryset 기반 검증"을 만듬
        • 즉, ModelSerializer는 무조건 ForeignKey를 DB에서 검증하려고 한다.
    • 해결 방법
      • category를 IntegerField로 override 해서 DB 조회를 막는다
      • Spec API에서는 category를 FK로 검증할 필요가 없음
      • 그냥 “번호(integer)”만 받게 함
        • 즉, ModelSerializer에서 category 필드를 재정의
profile
안녕하세요.

0개의 댓글