사진 아카이브 시스템
인증된 사용자 기반 사진 아카이브 시스템, EXIF 기반(구글 API) 메타데이터 추출 (촬영 시각, 위치) 분류하여 '저장 폴더 자동 생성' > 분류저장
NestJS
Next.js
PostgreSQL
TypeScript
Fastify
Drizzle ORM
On-premise (self-hosted physical server)
Outline
승인된 사용자만 사진을 업로드하고, 개인 갤러리 및 공유 데이터를 관리할 수 있는 사진 아카이브 애플리케이션입니다 공개형 SNS가 아니라, "인증된 사용자 기반으로 사진을 저장하고 관리하는 내부형 시스템"에 가깝습니다
What it solves
- 인증된 사용자만 접근 가능한 사진 저장소가 필요할 때
- 서버를 거치지 않고 파일을 직접 스토리지로 업로드하고 싶을 때
- 개인 사진과 공유 사진을 구분해서 관리하고 싶을 때
- 단순 업로드가 아니라 업로드시 자동 분류/운영 가능한 구조가 필요할 때
Core Features
- 승인 기반 인증 시스템 (activation / approved flow)
- 사진 업로드 (direct-to-storage presigned URL)
- 개인 갤러리 조회
- 공유 사진 조회
- 사진 visibility 전환 (private / shared)
- 사진 삭제
- EXIF 기반 메타데이터 추출 (촬영 시각, 위치)
- 슈퍼 관리자용 전체 데이터셋 관리
- 미완료 업로드 정리 (worker cleanup)
Tech Stack
- Language: TypeScript
- Frontend: Next.js (App Router, React)
- Backend: NestJS (Fastify, Node.js)
- Database: PostgreSQL (Drizzle ORM)
- Auth: Custom session (DB + cookie), email verification, password login
- Storage: MinIO object storage with presigned URL-based direct upload
- Worker: Node.js background worker
- Infra: On-premise (self-hosted physical server)
Architecture
- Web / API / Worker 분리 구조
- 클라이언트가 스토리지로 직접 업로드하는 direct-to-storage 방식
- 업로드 전 DB에 pending 상태 기록 후 완료 시 ready 전환
특징적인 흐름
업로드:
upload session 생성 → presigned URL 발급 → 직접 PUT → 완료 API 호출
완료 처리:
storage HeadObject로 객체 존재 확인 후 상태 변경
정리:
일정 시간 지난 pending 업로드를 abandoned로 전환
Design Decisions
- 파일은 서버를 거치지 않고 스토리지로 직접 업로드
- 업로드 상태는 DB 기반으로 관리 (pending → ready)
- 실패 복구 대신 cleanup 기반 단순 모델 선택
- 관리자 기능은 동일 API 레이어에서 확장
Security Notes
- 인증된 사용자만 업로드 및 조회 가능
- 세션 기반 인증 + 권한 체크 (approved / admin)
- presigned URL 기반 제한된 업로드 권한
Limitations
- multipart upload 미구현
- 업로드 resume / partial retry 없음
- 업로드 진행률 추적 없음
- 대용량 업로드에 최적화된 구조는 아님
- 상태 모델이 단순 (pending / ready / abandoned)
Why this structure
이 프로젝트는 확장성보다는 "단순하고 명확한 업로드 흐름"에 초점을 맞췄습니다.
- 서버 부하 최소화 (direct upload)
- 구현 복잡도 낮춤
- 기본적인 운영 기능 확보
Summary
direct-to-storage 업로드 구조를 기반으로 한 인증형 사진 아카이브 시스템입니다.
구조는 확장 방향을 갖고 있지만, 현재는 단일 PUT 기반의 간단한 업로드 모델로 구현되어 있습니다.
이 개발자의 다른 프로젝트
그누보드7 예약 모듈 - glitter-reservation
코어 수정 없이 붙여 사용하는 그누보드7 예약 모듈로, 신청·인증·조회·취소·관리까지 예약 흐름 전체를 모듈 단위로 제공합니다.
그누보드7 상담예약 템플릿 - Glitter Academy Core
GnuBoard7 Template 엔진 기반으로 상담예약 사이트 구성을 위한 초기 템플릿 예제로 설계되었습니다.
그누보드7 커뮤니티 템플릿 - SIRsoft Community
쇼핑몰(이커머스 의존)을 제거하고 커뮤니티 기능에 집중한 경량 사용자 템플릿, ID : sirsoft-comm
수정 이력 (1)
검증 흐름 개선
2026-04-16 (목) 01:33:57
- EXIF 기반 자동 분류 로직 안정화 - 업로드 완료 검증
멋진 프로젝트군요. 시롤로지 나스 사용하면서 늘 아쉬운 점이 행사 후 많은 사진 한꺼번에 올리면 썸레일 만드는 시간이 너무 많이 걸려서 더 바른 방법이 없을까, 고민했던 기억이 납니다. 아직도 해결 못한 과제이지만 ...
저도 사진을 취미로 하다 보니 몇몇 방안을 구현해 본 것들 중 하나입니다. 출사 한 번 다녀오면 수백~수천 장씩 쌓이는데, 실제로는 업로드보다 썸네일 생성과 정리가 더 오래 걸리는 것이 현실이더군요. 이 프로젝트는 단순 저장보다는 EXIF 기반으로 촬영일/위치 정보를 추출해서 자동 분류하는 쪽에 초점을 두었습니다. 전시회 등의 출품을 위해 특정 분류로 찾는 시간이 생각보다 많이 줄어들더군요. 썸네일 생성은 결국 CPU와 I/O를 많이 사용하는 작업이라 대량 업로드 환경에서는 비동기 워커나 사전 생성 전략 같은 방법을 검토하게 되는데, 말씀하신 '많은 사진을 한꺼번에 올리고 썸네일까지 생성하는 문제'는 고민해야 할 구현이군요. 수천 장을 EXIF-위치 기반으로 분류하는 것 자체는 큰 문제가 없었지만, 역시 처리 시간은 꽤 필요하더군요. https://glitter.im
저도 사진을 취미로 하다 보니 몇몇 방안을 구현해 본 것들 중 하나입니다. 출사 한 번 다녀오면 수백~수천 장씩 쌓이는데, 실제로는 업로드보다 썸네일 생성과 정리가 더 오래 걸리는 것이 현실이더군요. 이 프로젝트는 단순 저장보다는 EXIF 기반으로 촬영일/위치 정보를 추출해서 자동 분류하는 쪽에 초점을 두었습니다. 전시회 등의 출품을 위해 특정 분류로 찾는 시간이 생각보다 많이 줄어들더군요. 썸네일 생성은 결국 CPU와 I/O를 많이 사용하는 작업이라 대량 업로드 환경에서는 비동기 워커나 사전 생성 전략 같은 방법을 검토하게 되는데, 말씀하신 '많은 사진을 한꺼번에 올리고 썸네일까지 생성하는 문제'는 고민해야 할 구현이군요. 수천 장을 EXIF-위치 기반으로 분류하는 것 자체는 큰 문제가 없었지만, 역시 처리 시간은 꽤 필요하더군요. https://glitter.im