_이 글은 Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass에 제출하는 글입니다.
제가 만든 것 (What I Built)
Parallel은 실제 장소와 연결된 이야기를 발견하고 공유하기 위한 지도 중심의 스토리텔링 플랫폼입니다. 하나의 위치는 역사, 개인적인 기억, 지역 전설, 소설, 편집 기사 등 여러 독립적인 이야기 챕터를 담을 수 있습니다.
피드를 스크롤하는 대신, 지도를 열고 근처 장소를 선택한 후 사람들이 그 장소에 대해 무엇을 말했는지 읽게 됩니다. 방문 기록은 사용자가 직접 보고하므로, 앱이 어딘가에 다녀왔다고 기록할 뿐 이를 검증한다고 주장하지는 않습니다. 목표는 사람들을 자신이 서 있는 거리로 이끄는 것입니다.
이는 도시를 걸어 다니며 지나치는 것들에 대한 더 많은 맥락을 원하는 사람들, 그리고 특정 장소에 대한 출처가 명시된 이야기를 게시하려는 작가와 지역 역사가를 위한 것입니다.
데모 (Demo)
parallel-flame.vercel.app
코드 (Code)
Parallel
모든 장소에는 여러 이야기가 있다.
Parallel은 실제 장소와 연결된 이야기를 발견하고 공유하기 위한 지도 중심의 스토리텔링 플랫폼입니다. 하나의 위치는 많은 독립적인 이야기 챕터를 담을 수 있습니다.
프로젝트 구조 (Project structure)
parallel/
├── apps/
│ ├── backend/ # FastAPI API (Python)
...
빠른 시작 (Quick start)
필수 조건: Node.js 22+, npm, Python 3.12+, uv, 그리고 Git. 로컬 PostGIS 컨테이너를 실행할 때만 Docker Desktop이 필요합니다.
.env.example을 .env로 복사하고 apps/frontend/.env.local.example을 apps/frontend/.env.local로 복사합니다.
- API 시작:
apps/backend에서 uv sync --extra dev, uv run alembic upgrade head를 실행한 다음, uv run uvicorn app.main:app --reload를 실행합니다.
- 웹 앱 시작:
apps/frontend에서 npm install을 실행한 다음, npm run dev를 실행합니다.
- http://localhost:3000을 엽니다. API 상태는…
GitHub에서 보기
제가 만든 방법 (How I Built It)
- 프론트엔드: Next.js App Router, React, TypeScript, Tailwind CSS, MapLibre GL JS, 그리고 TanStack Query.
- API: FastAPI, Pydantic, 그리고 SQLAlchemy 2 (async).
- 데이터베이스: 지리 정보를 위한 PostGIS가 포함된 Neon PostgreSQL.
- 미디어: Neon Object Storage (S3 호환). Postgres는 객체 키와 메타데이터만 저장하며, 이미지나 오디오 바이트 자체는 절대 저장하지 않습니다.
- 인증: Neon Auth (관리형 Better Auth). API는 브랜치 JWKS 엔드포인트에서 JWT를 검증합니다.
디자인 규칙은 AI, 오디오 또는 스토리지에 접근할 수 없어도 핵심 탐색 기능이 작동하도록 유지하는 것입니다. '컨시어지' 기능의 AI 지원 발견(discovery)에는 모델 키가 필요 없는 결정론적이고 근거 기반의 폴백(fallback) 메커니즘이 있습니다. 내레이션과 지도 타일은 선택 사항이며 환경 변수를 통해 구성됩니다.
AI 모델: Gemma4 32B
Open Innovation이 중요한 이유?
오픈 소스는 이 플랫폼이 누구나 검사할 수 있는 도구로 실행될 수 있게 합니다. 코드베이스, 스키마, 마이그레이션, 그리고 API 계약 모두 공개되어 있어 지역 역사 협회나 지역 작가도 벤더 관계 없이 자체 호스팅(self-host) 할 수 있습니다. 지도는 키나 가입이 필요 없는 OpenFreeMap 타일을 사용하므로, 새로운 기여자도 전체 스택을 로컬에서 실행할 수 있습니다.
AI를 선택 사항으로 유지하는 것도 중요합니다. 결정론적 순위 지정(deterministic ranking)은 모델 없이 작동하기 때문에, 제품이 특정 폐쇄형 API에 묶이지 않으며, 장소에 대한 이야기가 모델의 가용성에 의존하지 않습니다.
수상 부문
- Render 활용 최우수작
- Render Gemma 활용 최우수작
- Eleven Labs 활용 최우수작
- Sentry 활용 최우수작