Initiation
## 프롬프트 목적
--Django 기반 영어 학습 웹서비스의 최적화된 모델과 매니저를 생성한다.
--영화 대사를 이용한 영어 발음 학습 시스템의 데이터 구조를 구현한다.
--성능 최적화, 보안 강화, 확장성을 고려한 모델 설계를 한다.
--커스텀 매니저를 통해 재사용 가능한 비즈니스 로직을 구현한다.
## 서비스 이름
--이름 : Endless Real Clips
## 서비스 목적
--다양한 실 환경에서 사용되는 영어문장 발음을 공부하기 위한 시스템이다.
--영어구문을 입력해 그 구문이 있는 있는 영상(영화, 드라마)을 찾아, 그 대사를 무한반복한다.
--쉽게 영어발음 및 억양을 배울 수 있는 시스템이다.
## 서비스 사용자
--유튜브 등으로 혼자 공부하는 사람
--스마트폰으로 어느 장소에서 건 영어공부하는 사람
--웹브라우저를 이용해 영어공부하는 사람
--영화정보를 입력하는 사람
--영화의 영화대사를 입력하는 사람
## 서비스 시나리오
--절차0. 이 서비스는 홈페이지(랜딩페이지)에서 로그인 해야 사용 가능하다.(로그인해야 'Movies' 버튼이 보임)
--절차1. 이 서비스는 사용자가 텍스트(단어 or 관용구 or 구문 or 문장)를 입력하면서 시작된다.
--절차2. 입력 텍스트가 포함된 영화 제목, 영화 대사와 그 영화 클립(mp4) 영상을 찾아 가져오고 저장한다.
--절차3. 가져온 영화 제목을 이용해 영화 포스터 등 영화정보를 찾아 가져오고 저장한다.
--절차4. 가져온 영화 포스트를 이용해 영화 포스터 카드를 만들고, 그 카드에 영화 제목과 영화 대사(영어, 한글)를 포스터 아래에 써넣는다.
--절차5. 포스터를 클릭하면 영화 클립 영상을 띄우고 플레이를 무한 반복한다.
## 서비스 시나리오 상세
--11. 사용자 텍스트 입력은 영어, 한글이 가능하다. 입력이 완료되면 입력한 내용이 맞는지 확인 절차를 거친다(오타로 인한 데이터 품질 훼손을 최소화하기 위해).
--12. 확인 완료 후, 영어로 입력된 경우 한글로 번역하고, 한글로 입력된 경우 영어로 번역해서 한글과 영어를 DB에 저장한다(영어: 필수, 한글: 선택)
--13. 영화 대사를 찾는 뒷 절차는 영어 텍스트를 사용한다.
--14. 영화 대사를 찾는 순서는 먼저 db 의 입력 텍스트 영어 필드와 영화 대사 영어 필드에서 입력된 텍스트를 찾아서 db에 있으면 db에서 영화 포스터를 찾아 포스터 카드를 만들고 db에서 영상을 찾아 플레이 한다.
--15. DB에 입력된 텍스트가 없는 경우 절차2 를 수행한다.
--21. 영화 대사와 영화 클립은 aaa 사이트를 크롤링해 확보하고 db 에 저장한다.
--211. aaa 사이트에서 획득하는 정보는 영화 대사, 영화 클립 영상, 영화 제목, 제작년도 이다.
--212. aaa 사이트에서 획득한 영화 대사는 영어 대사로 한글로 번역하고 영어, 한글 같이 저장한다.
--31. 영화 제목으로 bbb 사이트를 크롤링해 영화 정보를 확보하고 db 에 저장한다.
--311. bbb 사이트에서 획득하는 영화 정보는 영화 포스터 이미지, 영화 감독 이름 이다.
--41. 저장한 포스터 이미지와 영화제목, 영화제작년도, 영화대사 영어, 영화대사 한국어를 이용해 영화 포스터 카드를 만든다.
--411. 영화 포스터 이미지를 클릭하면 영상 플레이 화면이 뜬다.
--51. 영상 플레이 화면의 구성은 화면, 화면 전체 크기/원상 복구 토글버튼, 음성 크기 조정 바, 영화 포스터 카드 화면으로 돌아가기 버튼, 영어 대사, 한글 대사 로 구성된다.
--511. 플레이 초기 상태는 영상은 스톱 상태로 무한 루프 모드로 뜨며, 영상을 클릭하면 무한 루프로 영상이 플레이 된다.
## 단어 정의
--구문이란 자주 함께 쓰이는 단어들의 묶음으로, 특정한 의미나 문법 구조를 가진다.
--입력구문은 사용자가 영화대사를 찾기위해 입력하는 텍스트나 음성이다.
--입력구문은 특징별 영어텍스트, 영어음성, 한글텍스트, 한글음성 4종류로 나눈다.
--음성구문은 입력구문 중 스마트폰에서 음성으로 입력되 STT 처리한 텍스트이다.
--문자구문은 입력구문 중 키보드로 입력한 텍스트이다.
--영어구문은 입력구문 중 영어로 입력된 구문으로 영어음성구문, 영어문자구문으로 나눈다.
--한글구문은 입력구문 중 한글로 입력된 구문으로 한글음성구문, 한글문자구문으로 나눈다.
--영음구문은 영어구문 중 음성으로 입력되 STT 처리한 텍스트이다. 스마트폰 앱 입력
--영문구문은 영어구문 중 키보드로 입력된 텍스트이다. 웹브라우저 입력
--한음구문은 한글구문 중 음성으로 입려되 STT 처리한 텍스트이다. 스마트폰 앱 입력
--한문구문은 한글구문 중 키보드로 입력된 텍스트이다. 웹브라우저 입력
--번역구문은 한음구문과 한문구문을 영문구문으로 번역한 텍스트다.
--요청구문은 사용자의 확인을 마친 텍스트로 영화정보를 찾기 위해 요청하는 영어 텍스트이다. DB 저장
--요청한글은 요청구문을 한글로 번역한 텍스트이다. DB 저장
--대사구문은 영화정보의 하나로 요청구문이거나 요청구문이 포함된 영화대사다. DB 저장
## DB 스키마
--요청테이블은 요청구문을 저장하는 테이블이다.
--대사테이블은 요청구문이거나 요청구문이 포함된 문장을 저장하는 테이블이다.
--요청테이블과 대사테이블을 분리한다.
--요청테이블과 대사테이블은 마스터, 슬래이브 관계이다.
--요청테이블 레코드 1개당 대사테이블 레코드는 0개에서 다수개가 소속된다.
--요청테이블의 키 및 인덱스는 요청구문 필드이다.
--대사테이블의 키 및 인덱스는 ID 필드이다.
--영화테이블은 영화정보를 저장하는 테이블이다.
--영화테이블과 대사테이블은 마스터, 슬래이브 관계이다.
--영화테이블 레코드 1개당 대사테이블 레코드는 0개에서 다수개가 소속된다.
--영화테이블의 키 및 인덱스는 영화제목 컬럼 + 개봉연도 컬럼 + 제작국가 + 감독 컬럼 복합키이다.
--영화테이블의 개봉연도 컬럼 저장시 데이터가 없는 경우 default 값으로 '1004'을 사용한다.
--영화테이블의 제작국가 컬럼 저장시 데이터가 없는 경우 default 값으로 '지구'을 사용한다.
--영화테이블의 감독 컬럼 저장시 데이터가 없는 경우 default 값으로 'ahading'을 사용한다.
--모든테이블은 기본적으로 생성시간, 종료시간 필드를 갖는다.
--영화테이블의 컬럼은 영화제목, 개봉연도, 제작국가, 감독, IMDB_URL, 영화포스터_URL, 영화포스터_image, 영화포스터_image_path 이다.
--대사테이블의 컬럼은 영화테이블.id, 대사구문, 대사시작시간, 비디오_URL, 비디오_file, 비디오_file_path 이다.
--요청테이블의 컬럼은 요청구문, 요청한글 이다.
## DB 저장 시점 및 조건
--요청테이블의 요청구문은 요청구문 생성시 요청테이블에 요청구문을 저장한다.
--요청구문이 요청테이블에 존재하는 경우 저장하지 않는다.
--palyphraseme 에서 영화정보를 획득한 경우 요청구문을 저장한다.
--영화테이블은 요청구문을 저장하고, 영화정보를 이용해 imdb 에서 영화 포스터 및 상세 정보를 수집해 저장한다.
## 결과 조회 시점 및 조건
--요청구문과 요청한글 생성 후, 이것을 요청테이블의 요청구문이나 요청한글 필드에서 찾은 결과, 존재하는 경우는 DB에서 UI에 필요한 데이터를 조회한 결과를 웹브라우저에 전달하거나 rest api로 전달한다.
--요청구문과 요청한글 생성 후, 이것을 요청테이블의 요청구문이나 요청한글 필드에서 찾은 결과, 존재하지 않는 경우에는 playphraseme 와 imdb 에서 관련 데이터를 획득해 DB에 저장하고 그 결과를 웹브라우저에 전달하거나 rest api로 전달한다.
## 데이터 확보
--대사구문은 playphraseme 사이트를 크롤링해서 획득한다.
--영화정보는 playphraseme 사이트에서 획득한 정보를 바탕으로 imdb 사이트를 크롤링해서 획득한다.
## 스마트폰 앱
--웹 기능에 더해, 키보드 이외에 음성으로 입력이 가능하다.
## 기술 스택
--Python 3.13, Django 5.2
-- Flutter (스마트폰 앱 개발)
--SQLite (개발), MySQL 8.0 (운영)
--Ubuntu 24.04
--REST API 지원
코드 리버스 프롬프팅
## 모델 설계 원칙
--BaseModel 추상 클래스로 공통 필드 통합
--보안 강화된 URL 필드 사용
--다국어 지원 (영어, 한글)
--파일 업로드 보안 처리
--자동 번역 기능 통합
## 데이터베이스 테이블 구조
### 기본 모델 (BaseModel)
--id: BigAutoField, primary_key
--created_at: 생성시간, auto_now_add, 인덱스
--updated_at: 수정시간, auto_now, 인덱스
--is_active: 활성상태, Boolean, 기본값 True, 인덱스
--metadata: JSONField, 기본값 dict, 확장 가능
### 요청테이블 (RequestTable)
--request_phrase: 요청구문, CharField(500), unique, 인덱스
--request_korean: 요청한글, CharField(500), null 허용
--search_count: 검색횟수, PositiveIntegerField, 기본값 1
--last_searched_at: 마지막검색시간, auto_now
--result_count: 검색결과수, PositiveIntegerField, 기본값 0
--translation_quality: 번역품질, choices (excellent/good/fair/poor/unknown)
--ip_address: 요청IP, GenericIPAddressField, null 허용
--user_agent: 사용자에이전트, TextField(1000)
### 영화테이블 (MovieTable)
--movie_title: 영화제목, CharField(300), 필수
--original_title: 원제목, CharField(300), 선택
--release_year: 개봉연도, CharField(4), 기본값 '1004'
--production_country: 제작국가, CharField(100), 기본값 '지구'
--director: 감독, CharField(300), 기본값 'ahading'
--genre: 장르, CharField(200), 선택
--imdb_rating: IMDB평점, DecimalField(3,1), null 허용
--imdb_url: IMDB_URL, SecureURLField(600), null 허용
--poster_url: 포스터URL, SecureURLField(600), null 허용
--poster_image: 포스터이미지, ImageField, UUID 경로
--poster_image_path: 포스터경로, CharField(600)
--data_quality: 데이터품질, choices (verified/pending/incomplete/error)
--view_count: 조회수, PositiveIntegerField, 기본값 0
--like_count: 좋아요수, PositiveIntegerField, 기본값 0
### 대사테이블 (DialogueTable)
--movie: 영화FK, CASCADE, 인덱스
--dialogue_phrase: 영어대사, TextField, 필수
--dialogue_phrase_ko: 한글대사, TextField, null 허용
--dialogue_start_time: 시작시간, CharField(20)
--dialogue_end_time: 종료시간, CharField(20), 선택
--duration_seconds: 길이(초), PositiveIntegerField, null 허용
--video_url: 비디오URL, SecureURLField(600), 필수
--video_file: 비디오파일, FileField, UUID 경로
--video_file_path: 비디오파일경로, CharField(600)
--file_size_bytes: 파일크기, PositiveBigIntegerField, null 허용
--video_quality: 비디오품질, choices (720p/480p/360p/240p/unknown)
--translation_method: 번역방식, choices (manual/api_auto/ai_improved/user_submitted/unknown)
--translation_quality: 번역품질, choices (excellent/good/fair/poor/needs_review)
--play_count: 재생횟수, PositiveIntegerField, 기본값 0
--like_count: 좋아요수, PositiveIntegerField, 기본값 0
--search_vector: 검색벡터, TextField, 전문검색용
## 테이블 관계
--RequestTable - DialogueTable: 1:N (요청구문으로 검색)
--MovieTable - DialogueTable: 1:N (영화당 다수 대사)
--복합 유니크 키: (movie_title, release_year, director)
## 인덱스 전략
### RequestTable 인덱스
--request_phrase (단일)
--request_korean (단일)
--search_count, -last_searched_at (복합)
---last_searched_at (단일)
--translation_quality (단일)
--is_active, -search_count (복합)
--created_at, is_active (복합)
### MovieTable 인덱스
--movie_title (단일)
--release_year (단일)
--director (단일)
--genre (단일)
--imdb_rating (단일)
--data_quality (단일)
---view_count (단일)
--movie_title, release_year (복합)
--is_active, data_quality (복합)
---created_at, is_active (복합)
### DialogueTable 인덱스
--dialogue_phrase (단일)
--dialogue_phrase_ko (단일)
--video_url (단일)
--dialogue_start_time (단일)
--translation_method (단일)
--translation_quality (단일)
---play_count (단일)
--search_vector (단일)
--movie, dialogue_start_time (복합)
--movie, -created_at (복합)
--is_active, translation_quality (복합)
## 제약 조건
--모든 count 필드: 0 이상 체크
--imdb_rating: 0-10 범위 체크
--duration_seconds: 0 이상 체크
--unique_together: (movie_title, release_year, director)
## 커스텀 필드
### OptimizedCharField
--자동 인덱싱 (max_length <= 255)
--CharField 확장
### SecureURLField
--URL 스키마 검증 (http/https)
--악성 URL 패턴 차단 (javascript:, data:, vbscript:, file:)
--URLField 확장
## 파일 업로드
### 포스터 이미지 경로
--posters/{year}/{month}/{uuid}.{ext}
--UUID 기반 파일명 생성
--연도/월 디렉토리 구조
### 비디오 파일 경로
--videos/{year}/{month}/{uuid}.{ext}
--UUID 기반 파일명 생성
--연도/월 디렉토리 구조
## 매니저 구조
### ActiveManager
--활성 객체만 반환
--비활성 객체 조회
--활성 상태 토글
### RequestManager
--인기 검색어 조회
--최근 검색어 조회
--번역 품질별 조회
--구문 검색
--검색 횟수 증가 (F 표현식)
--통계 조회 (캐싱)
### MovieManager
--대사 포함 영화 조회
--데이터 품질별 조회
--인기 영화 조회
--연도/국가/감독별 조회
--평점 범위별 조회
--포스터 보유 영화 조회
--영화 검색
--조회수 증가 (F 표현식)
--통계 조회 (캐싱)
### DialogueManager
--한글 번역 유무별 조회
--번역 품질/방식별 조회
--영화별 대사 조회
--인기/최근 대사 조회
--비디오 보유 대사 조회
--길이 범위별 조회
--다국어 텍스트 검색
--영화 정보 포함 검색
--재생 횟수 증가 (F 표현식)
--번역 필요 대사 조회
--검색 벡터 일괄 업데이트
--통계 조회 (캐싱)
## 비즈니스 로직
### 자동 번역
--DialogueTable 저장 시 자동 실행
--LibreTranslator 사용
--번역 실패 시 로깅
--skip_translation 파라미터로 제어
### 검색 벡터 생성
--저장 시 자동 업데이트
--정규화 처리 (특수문자 제거, 공백 정리)
--다국어 텍스트 결합
--전문 검색 최적화
### 캐싱 전략
--통계 데이터: 5-10분 캐싱
--검색 결과: 해시 기반 키
--모델별 캐시 무효화
--신호 기반 자동 무효화
## 신호 처리
### post_save 신호
--RequestTable: 검색 관련 캐시 무효화
--DialogueTable: 대사/번역 캐시 무효화
--MovieTable: 영화 통계 캐시 무효화
### post_delete 신호
--MovieTable: 포스터 파일 삭제
--DialogueTable: 비디오 파일 삭제
## 사용자 활동 추적
### UserSearchQuery
--사용자별/세션별 검색 기록
--검색 성공/실패 추적
--응답 시간 측정
--IP/User-Agent 기록
### UserSearchResult
--검색 결과와 대사 연결
--관련성 점수 관리
--클릭 위치 추적
## 캐시 무효화
### CacheInvalidation
--캐시 키별 무효화 기록
--모델/인스턴스별 추적
--액션 타입 기록 (create/update/delete)
--오래된 기록 자동 정리
## 유틸리티 기능
### 통계 함수
--get_model_statistics(): 전체 통계 조회
--get_all_statistics(): 모든 모델 통계
### 데이터 정리
--cleanup_old_data(): 오래된 검색 기록 정리
--cleanup_old_records(): 캐시 기록 정리
### 캐시 관리
--clear_all_model_caches(): 전체 캐시 초기화
## 성능 최적화
--F 표현식으로 원자적 업데이트
--select_related/prefetch_related 활용
--배치 업데이트 지원
--인덱스 기반 빠른 검색
--캐싱으로 중복 쿼리 방지
## 보안 고려사항
--URL 검증 및 악성 패턴 차단
--파일 업로드 UUID 기반 보안
--XSS 방지를 위한 입력 정제
--SQL 인젝션 방지 (ORM 사용)
## 확장성 설계
--메타데이터 JSON 필드로 확장 가능
--다국어 필드 추가 지원
--번역 방식 확장 가능
--품질 등급 확장 가능
--새로운 매니저 메소드 추가 용이
## 호환성 유지
--Movie = MovieTable 별칭
--MovieQuote = DialogueTable 별칭
--기존 코드와의 하위 호환성 보장
'코딩' 카테고리의 다른 글
| The System Ideas' Methodology 11 (0) | 2025.07.28 |
|---|---|
| 프로그램 재생성 프롬프트 작성 가이드 (0) | 2025.07.28 |
| 웹서비스 개발을 위한 프롬프트 (0) | 2025.07.28 |
| GitHub 의 main, branch 개념 및 활용 (0) | 2025.07.24 |
| 나 만의 LLM 만들기 (0) | 2025.07.24 |