Role & Tech Stack
나의 역할: 기획, 백엔드, 프론트엔드, 데이터 모델링, 업로드·미디어 처리, 운영 구조 설계
기술 스택: Node.js 20, Fastify, TypeScript, Prisma, SQLite, React, Vite, Tailwind CSS, sharp, ffmpeg, Docker Compose, Caddy
1. 기획 배경
가족 여행을 다녀오면 각자 찍은 사진과 영상이 메신저, 휴대폰, 클라우드에 흩어지는 문제가 있었습니다. 이를 프로젝트 단위 앨범으로 모아 함께 보고, 원본 품질을 유지한 채 내려받을 수 있는 가족용 서버를 목표로 만들었습니다.
2. 핵심 기능
- 가입 / 로그인: 초대 코드와 관리자 승인 2단계 회원가입, argon2id 비밀번호 해시, HttpOnly 세션 쿠키
- 친구: 친구 ID 검색, 친구 요청, 수락·거절, 친구 끊기
- 프로젝트: 여행·일상 단위 사진첩 생성, 소유자·멤버 권한, 멤버 초대
- 업로드: 다중 파일 업로드, 드래그&드롭, 진행률 표시, 이미지·영상 자동 처리
- 미디어 처리: 원본 보존, SHA-256 중복 식별, 썸네일 생성, EXIF/ffprobe 메타데이터 추출
- 갤러리: 날짜별 그룹, 정렬, 업로더 필터, 라이트박스, 영상 range streaming
- 다운로드: 단일 원본 다운로드, 다중 선택 ZIP 스트리밍 다운로드
3. 시스템 구조
서버는 Fastify와 Prisma 기반으로 구성했고, SQLite WAL 모드를 사용해 셀프호스팅 환경에서 단순하면서도 관리하기 쉬운 저장 구조를 선택했습니다. 프론트엔드는 React, Vite, Tailwind CSS 기반으로 구현했으며, PWA 설치를 고려했습니다.
업로드된 원본은 변환하지 않고 보존하며, 서버의 비동기 처리 흐름에서 썸네일과 메타데이터를 생성합니다. 사진은 EXIF 정보를, 영상은 ffprobe 기반 정보를 추출해 추후 검색·정렬·정보 패널에 활용할 수 있도록 DB에 저장합니다.
4. 나의 핵심 기여
- 사용자, 친구, 프로젝트, 멤버, 미디어, 알림을 포함한 Prisma 데이터 모델 설계
- 초대 코드 기반 가입, 관리자 승인, 세션 인증 흐름 구현
- 앨범 생성, 멤버 관리, 친구 요청, 알림 흐름 구현
- 원본 업로드, 썸네일 생성, 메타데이터 추출, 중복 감지 처리 구현
- 갤러리, 라이트박스, 영상 스트리밍, 선택 다운로드 UI 구현
- Docker Compose와 Caddy 기반 LAN 배포 구조 정리
5. 문제 해결
사진첩 권한 구조
가족·친구가 함께 쓰는 서비스라 전체 공개가 아니라 프로젝트 멤버십 기반 접근 제어가 필요했습니다. 미디어 URL 요청 시에도 인증과 멤버십을 확인하도록 구조를 잡았습니다.
대용량 미디어 처리
원본을 보존하면서도 갤러리 탐색은 빠르게 해야 했습니다. 원본과 썸네일을 분리하고, 영상은 range request 스트리밍으로 재생할 수 있도록 구성했습니다.
앨범 단위 다운로드
여행 사진을 한 번에 내려받는 흐름이 필요해 다중 선택 후 ZIP 스트리밍 다운로드를 구현했습니다. 원본을 재압축하지 않고 묶어 내려받을 수 있도록 했습니다.
6. 진행 상황
- 스펙, 와이어프레임, 스택 문서 작성 완료
- 서버, 웹, 공유 타입, Docker, Caddy 모노레포 스캐폴딩 완료
- Prisma schema, admin seed, 인증 라우터, 관리자 페이지 구현
- 친구 라우터와 UI, 프로젝트·멤버 백엔드, 업로드·썸네일 워커 구현
- 갤러리, 라이트박스, 영상 스트리밍, 다운로드, 정렬·필터 UI 구현
- 프로젝트 설정 화면, 시스템 설정, 백업 UI, 통합 테스트는 추가 개선 예정