단계별 로드맵
1단계 — “작은 클라우드” 만들기 (MVP 단계)
- 회원가입/로그인 | 이미지·동영상 업로드 | 업로드된 파일 목록 조회
- 개별 파일 다운로드/삭제 | 로컬 저장소에 파일 저장
기술 스택 추천
- 백엔드: Django / Django REST Framework
- 스토리지: 로컬 MEDIA_ROOT | DB: SQLite 또는 PostgreSQL
- 프런트: 템플릿 or React 생략하고 DRF Browsable API로 먼저 테스트 가능
업로드 기능 알고리즘
- 로그인한 유저인지 확인 | form-data 로 파일 받기 | 파일 확장자·용량 검사
- 파일을 MEDIA_ROOT/user_id/ 폴더에 저장 | DB에 File 레코드 생성 (파일명, 경로, 크기 등)
- 저장된 파일 정보 반환
2단계 — S3(또는 Cloudflare R2)로 스토리지 확장
- 로컬 스토리지는 금방 용량 문제 + 백업 문제 생김.
- 그래서 중간 단계에서 S3 기반 스토리지로 변경하는 것이 좋음
추천 스토리지
- Cloudflare R2 (가성비 좋음, 트래픽 무료) | AWS S3 | Naver Object Storage (한국에서 빠름)
구현 방식
- Django → django-storages 사용
- 업로드된 파일들은 직접 서버에 저장되지 않고 바로 S3에 전송
- URL 은 프리사인(pre-signed URL)로 접근
3단계 — 동영상 최적화 / 썸네일 / 변환
- 동영상 클라우드의 핵심은 여기
- 이미지 썸네일 생성 | Pillow 사용 or Django Signals로 업로드 후 자동 생성
동영상 처리
- FFmpeg 필수
- 서버에서 직접 돌려도 되고
Celery + Redis 로 비동기 처리 가능
- 업로드 → DB 등록
- Celery worker가
- 해상도 변경 | 썸네일 추출 | MP4 변환 -> 진행
4단계 — 공유 기능 / 폴더 구조 / 태그
- 실제 클라우드 서비스 기능 들어감 | 폴더 생성 | 폴더 안에 파일 업로드
- 태그/검색 기능 | 파일 공유 링크 생성 | 공유 링크 → 만료 시간 설정
5단계 — 모바일 UI / 웹 UI 만들기
- 이제 React / Vue / Flutter 로 프런트 시작 가능.
- DRF API 완성된 상태이면 프런트만 붙이면 됨.
6단계 — 백업 / 중복 제거 / 용량 제한 (고급 기능)
- 사용자별 용량 제한 | 파일 중복 제거(hash 기반)
- 자동 백업 | 파일 암호화(옵션)
- 여기까지 완성하면 개인용 미니 Google Photos / iCloud 수준
가상환경 설정
# 1. python 설치 (이미 했으면 pass)
pyenv install 3.13.1
# 2. 프로젝트에서 해당 버전 사용
pyenv local 3.13.1
# 3. poetry 설정 (딱 1번만)
## Poetry 가상환경을 프로젝트 폴더 내부에 생성하도록 설정
poetry config virtualenvs.in-project true
# 4. 프로젝트 생성
mkdir myproject
cd myproject
poetry init
# 5. 가상환경 생성
poetry env use 3.13.1
# 6. 가상환경 활성화
poetry env activate
# 6-1. 나온거 그대로 복사 붙여넣기
# 7. 패키지 설치
poetry add django
# 8. django 기본 설정
django-admin startproject config.


시작
1일차(25.12.01)
-
poetry add djangorestframework -> DRF 설치
-
python manage.py startapp files
-
리스트 / 업로드 / 삭제 / 다운로드 구현
- settings.py
- files - urls.py / views.py / serializers.py / models.py
- core - urls.py
-
추가해야 할 내용
- 각 사진 확대
- 폴더생성(디테일 페이지로 만들면 될 듯)
2일차(25.12.02)
설치
poetry add djangorestframework
poetry add djangorestframework-simplejwt
poetry add djangorestframework-simplejwt[token_blacklist]
- 형태는 맞는데
[] 넣으면 쉘에서 해석 에러
poetry add "djangorestframework-simplejwt[token_blacklist]"
poetry add djangorestframework-simplejwt\[token_blacklist\]
INSTALLED_APPS = [
"rest_framework",
"rest_framework_simplejwt",
"rest_framework_simplejwt.token_blacklist",
"users",
]
AUTH_USER_MODEL = "users.User"
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
from datetime import timedelta
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=60),
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
"BLACKLIST_AFTER_ROTATION": True,
}
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication",
"rest_framework_simplejwt.authentication.JWTAuthentication",
]
}
LOGIN_URL = '/users/login/'
LOGIN_REDIRECT_URL = '/files/list/'
LOGOUT_REDIRECT_URL = '/users/login/'
현재까지 흐름
- API 로그인 = JWT
- → /api/users/login/
- → 모바일 앱, React 등 클라이언트용
- HTML 로그인 = Django 세션
- → /users/login/html/
- → 파일 관리 페이지에서 사용
- 세션 로그인하면
- → /files/list/, /files/upload/ 모두 정상 동작
3일차(2025.12.04)
문제
- 세션 로그인 로그아웃 회원가입 / JWT 로그인 로그아웃 회원가입 2개 존재 → 충돌 위험
로그인
- /users/login/html/ → Django 기본 LoginView 사용 (세션 로그인)
- /api/users/login/ → JWT 로그인 API (TokenObtainPairView)
- 템플릿: users/login.html → 세션 로그인 방식
로그아웃
- HTML 로그아웃: Django 기본 LogoutView (세션 기반, 쿠키로 로그아웃)
- API 로그아웃: Refresh Token을 블랙리스트에 넣음(JWT 기반)
- 템플릿: users/logout.html → JWT 기반 로그아웃
- 로그인은 세션 로그인이기 때문에 로그아웃도 세션으로 하는게 좋음
회원가입
- 회원가입 템플릿도 JWT 형태 / 세션 방식 혼합되어 있음
- 작동은 하지만 웹 세션 로그인과는 어울리지 않는 구조
개선방안
- 웹 로그인 → Django LoginView(세션)
- 웹 로그아웃 → Django LogoutView(세션)
- 웹 회원가입 → DRF API 호출 (OK)