콘텐츠로 이동

협업 포탈

GeoOmni 협업 포탈은 관리자(사용자)와 개발자 간 이슈 소통, 캡처/녹화 공유를 위한 독립 웹 앱입니다.

개요

항목
URL (로컬) http://localhost:3100
URL (외부) https://geoomni-cs.dahangis.co.kr
프레임워크 Next.js 16 (App Router, TypeScript)
UI shadcn/ui + Tailwind CSS v4
에디터 react-quill-new (React 19 호환)
인증 Firebase Auth (Google 로그인)
데이터베이스 Firebase Firestore (클라이언트 SDK 직접 연결)
미디어 Google Drive (Apps Script 프록시)
알림 Firestore 실시간 구독 + Gmail (Apps Script)

아키텍처

사용자 브라우저
  ├─→ Firebase Auth     (Google Cloud — 인증)
  ├─→ Firestore DB      (Google Cloud — 데이터)
  ├─→ Google Apps Script (Google Cloud — 이메일/드라이브)
  └─ 정적 파일 호스팅 (아래 중 택 1)
       ├─ Vercel                    (권장)
       ├─ Firebase Hosting          (firebase deploy)
       ├─ Cloudflare Pages          (wrangler)
       └─ 로컬 서버 (npm run dev)   (개발용)

핵심 특성: 서버 API 라우트 없음 — 100% 클라이언트 앱. 모든 데이터는 Firebase SDK가 브라우저에서 직접 접근합니다.

시작하기

설치 및 실행

cd portal
npm install          # 의존성 설치
npm run dev          # 개발 서버 시작 (http://localhost:3100)

환경 변수

.env 파일에 Firebase 키를 설정합니다. .env.example을 참조하세요.

cp .env.example .env
# Firebase Console > 프로젝트 설정에서 값 복사
변수 설명
NEXT_PUBLIC_FIREBASE_API_KEY Firebase API 키
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN Auth 도메인
NEXT_PUBLIC_FIREBASE_PROJECT_ID 프로젝트 ID
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET Storage 버킷
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID 메시징 ID
NEXT_PUBLIC_FIREBASE_APP_ID 앱 ID
NEXT_PUBLIC_APPS_SCRIPT_URL Apps Script 웹앱 URL

NEXT_PUBLIC_ 접두사

NEXT_PUBLIC_ 접두사 변수는 브라우저에 노출됩니다. Firebase 클라이언트 키는 공개 키이므로 보안 위험이 없습니다. Firestore 보안 규칙(firestore.rules)이 실제 접근을 제어합니다.

배포 방법

Portal은 100% 클라이언트 앱이므로 정적 호스팅에 배포 가능합니다. 서버(192.168.75.249 등)가 없어도 동작합니다.

옵션 1: Vercel (권장)

가장 간단한 방법입니다. Next.js 제작사 플랫폼으로 설정이 거의 불필요합니다.

  1. vercel.com에서 GitHub 저장소 연결
  2. Root Directory를 portal로 설정
  3. Environment Variables에 .env 값 입력
  4. Deploy — 이후 push마다 자동 배포
# 또는 CLI로 배포
npx vercel --cwd portal

옵션 2: Firebase Hosting

cd portal
npm run deploy:firebase    # 빌드 + 배포

사전 준비:

npm install -g firebase-tools
firebase login
firebase init hosting       # 이미 설정됨 (firebase.json)

firebase.jsonout/ 폴더를 서빙하도록 구성되어 있습니다. SPA rewrites로 동적 라우트(/issues/[id])도 정상 동작합니다.

옵션 3: 로컬 서버 (개발용)

로컬에서 개발 서버를 실행합니다.

cd portal
npm run dev                # 또는 npm run build && npm run start

옵션 4: 빌드 결과 미리보기

cd portal
npm run deploy:preview     # 빌드 + 로컬 서빙 (http://localhost:3100)

주요 기능

이슈 보드

이슈를 생성하고 상태/우선순위/카테고리로 관리합니다.

  • 상태: Open → In Progress → Resolved → Closed
  • 우선순위: Low / Normal / High / Critical
  • 카테고리: Bug / Feature / Question / Improvement

이슈 작성 시 react-quill-new 리치 텍스트 에디터를 사용합니다. 이미지는 Google Drive에 업로드됩니다.

실시간 코멘트

Firestore onSnapshot으로 실시간 갱신됩니다. 별도 새로고침 없이 코멘트가 즉시 표시됩니다.

미디어 갤러리

Google Drive에 저장된 이미지와 동영상을 확인할 수 있습니다.

알림 시스템

  • 실시간 알림: Firestore 구독으로 브라우저 내 즉시 표시
  • 이메일 알림: Google Apps Script를 통해 Gmail 발송

앱 연동

GeoOmni 앱의 타이틀바에서 포탈에 직접 접속할 수 있습니다:

  • 포탈 버튼: 포탈 웹 페이지 열기 (커스텀 도메인 우선, 없으면 localhost 폴백)
  • 이슈 보고 버튼: 이슈 작성 페이지 열기 (로그인 시만 활성)
  • 설정 > 계정: Google OAuth 로그인 (로그인하면 이슈 보고 버튼 활성화)
  • 프로필 사진: 로그인 시 Google 프로필 사진이 네비게이션 하단, 설정 좌측 패널, 계정 개요에 원형으로 표시

Google OAuth 로그인

앱 설정 > 계정 > 포탈 로그인에서 Google OAuth 2.0 (PKCE 흐름)으로 로그인합니다. 로그인하면 Firebase Auth 토큰이 앱에 저장되어 이슈 보고 기능이 활성화됩니다.

앱 매뉴얼

/manual 경로에서 GeoOmni 사용자 매뉴얼(MkDocs)을 iframe으로 확인할 수 있습니다.

Firestore 컬렉션 구조

/authors/{uid}              — 작성자 (Firebase Auth UID)
/issues/{autoId}            — 이슈 (HTML content, 상태, 우선순위)
  /comments/{autoId}        — 코멘트 (이슈별 서브컬렉션)
  /media/{autoId}           — 미디어 (이슈별 서브컬렉션)
/notifications/{autoId}     — 알림 (실시간 구독, 이메일 트리거)

페이지 구조

경로 설명
/ 대시보드 (통계 카드 + 최근 이슈)
/issues 이슈 목록 (필터/검색/정렬)
/issues/new 이슈 작성 (리치 텍스트 에디터)
/issues/[id] 이슈 상세 + 코멘트 (실시간 갱신)
/media 미디어 갤러리 (Google Drive 임베드)
/manual 앱 매뉴얼 (MkDocs iframe)
/settings Firebase 계정 프로필

설정

/settings 페이지에서 다음을 설정할 수 있습니다:

  • 작성자 프로필: 이름, 역할(admin/developer/guest)
  • 테마: 라이트/다크 모드 전환

서버 의존성 분석

서버(192.168.75.249)가 다운되면?

구성 요소 영향
Firestore 데이터 (이슈/알림/코멘트) 안전 — Google Cloud
Firebase Auth (로그인 정보) 안전 — Google Cloud
Google Drive 미디어 안전 — Google Cloud
Portal 웹 UI (로컬 배포 시) 접속 불가 — 서버 프로세스 중단

해결: Vercel/Firebase Hosting에 배포하면 서버 없이 완전 독립 동작합니다.

긴급 복구: 아무 PC에서 npm install && npm run dev만 실행하면 즉시 복구됩니다 (데이터는 Firebase에 있으므로 손실 없음).

커스텀 도메인 설정

외부 접속용 커스텀 도메인 geoomni-cs.dahangis.co.kr은 DNS 레벨에서 설정합니다.

방법 1: Firebase Hosting 커스텀 도메인

Firebase Hosting에서 커스텀 도메인을 연결합니다.

  1. Firebase Console > Hosting > 커스텀 도메인 추가
  2. geoomni-cs.dahangis.co.kr 입력
  3. DNS 소유권 확인 (TXT 레코드 추가)
  4. A 레코드를 Firebase에서 제공하는 IP로 설정
  5. SSL 인증서 자동 발급 (최대 24시간)

방법 2: Vercel 커스텀 도메인

Vercel에서 커스텀 도메인을 연결합니다.

  1. Vercel Dashboard > 프로젝트 > Settings > Domains
  2. geoomni-cs.dahangis.co.kr 추가
  3. CNAME 레코드를 cname.vercel-dns.com으로 설정
  4. SSL 자동 발급

방법 3: Cloudflare DNS

도메인 DNS를 Cloudflare에서 관리하는 경우:

  1. Cloudflare Dashboard > DNS
  2. CNAME 레코드 추가: geoomni-cs → 배포 호스트(Vercel/Firebase)
  3. Proxied(주황색 구름) 활성화 → CDN + DDoS 보호

Firebase Auth 승인 도메인

Firebase Auth 승인 도메인에 geoomni-cs.dahangis.co.kr을 추가해야 합니다. Firebase Console > Authentication > Settings > Authorized domains