2026-04-03 20:45:51 +09:00
2026-04-03 20:45:51 +09:00
2026-04-03 20:45:51 +09:00
2026-04-03 20:53:29 +09:00

Web Platform (학습센터)

유튜브 링크와 PowerPoint(.pptx) 강의를 등록하고, 목록에서 클릭해 바로 시청할 수 있는 사내 학습센터 예제입니다.


접속 방법

브라우저에서 열기 전에 반드시 터미널에서 서버를 실행해야 합니다. (npm start 미실행 상태에서는 http://localhost:8030에 연결되지 않습니다.)

서버 실행 후 아래 주소로 접속합니다.

환경 URL
로컬 기본 http://localhost:8030
포트 변경 시 http://localhost:{PORT} (예: PORT=4000 npm starthttp://localhost:4000)
  • 메인 페이지 (/): 학습센터 뷰어 (강의 목록)
  • 학습센터 뷰어 (/learning): 강의 검색/필터 + 카드 목록 (일반 사용자)
  • 관리자 (/admin): 강의 등록(YouTube/PPT/웹 링크 등), 썸네일·AI 추가 등 통합 관리
  • 강의 상세: 카드 클릭 시 유튜브 재생 또는 PPT 뷰어
  • 기타 메뉴: 채팅(/chat), AI(/ai-explore), 프롬프트 라이브러리(/ai-explore/prompts), AI 성공 사례(/ai-cases), AX 과제 신청(/ax-apply)
  • 관리자 이벤트 로그: http://localhost:8030/admin/thumbnail-events?token={ADMIN_TOKEN}

접속이 안 될 때 (트러블슈팅)

  1. 서버가 떠 있는지 확인
    프로젝트 루트에서 npm start를 실행하고, 터미널에 Server started: http://localhost:8030 같은 로그가 나오는지 확인합니다.
  2. 포트 번호 확인
    .envPORT=...가 있으면 그 포트로 접속합니다. (기본값은 8030)
  3. 부팅 실패
    터미널에 Failed to bootstrap:이 나오면 프로세스가 종료되며 HTTP 서버가 뜨지 않습니다. 메시지를 확인한 뒤 data/ 쓰기 권한, 디스크 여유, DB 설정 등을 점검합니다.
  4. 포트 충돌
    다른 프로그램이 8030을 쓰는 경우 PORT=8031 npm start처럼 바꿔 실행하거나, 이미 떠 있는 Node 서버 프로세스를 종료합니다. 구체적인 명령은 아래 실행 방법 절의 기존 서버 프로세스 종료 항목을 참고하세요.
  5. 바인드 주소
    기본은 모든 네트워크 인터페이스(0.0.0.0)에서 수신합니다. 로컬 루프백만 쓰려면 HOST=127.0.0.1 npm start를 사용할 수 있습니다.

핵심 기능

  • 학습센터 UI (좌측 메뉴 + 상단 헤더 + 강의 카드 레이아웃)
  • AI 탐색 (/ai-explore): 전체 너비 레이아웃, AI 서비스 카드(프롬프트·회의록 등). 검색창에 **「프롬프트」**가 포함된 채 검색(Enter) 시 프롬프트 라이브러리로 이동
  • 프롬프트 라이브러리 (/ai-explore/prompts): 업무별 기본 프롬프트 카드 선택·미리보기·클립보드 복사 (data/company-prompts.json). 좌측 메뉴(채팅·AI·AI 성공 사례·학습센터·AX 과제 신청)는 관리자 여부와 관계없이 접근 가능(강의 삭제·관리자 대시보드 등 일부 기능은 관리자 모드에서만)
  • 검색/필터/페이지네이션
    • 검색어(q) 기반 제목/설명/태그 필터
    • 타입(YouTube, PPT) 필터
    • 태그 필터 + 페이지네이션
  • 유튜브 강의 등록/시청
    • 유튜브 URL 입력 후 목록에 추가
    • 강의 상세에서 iframe 임베드로 재생
  • PPT 강의 등록/시청
    • .pptx 파일 업로드
    • 상세에서 슬라이드 텍스트 기반 뷰어 제공
    • 목록 카드에 PPT 프리뷰(첫 슬라이드 제목 + 장수) 표시
    • macOS 환경에서는 qlmanage 기반 실제 썸네일(첫 장 이미지) 자동 생성
  • 썸네일 백그라운드 큐
    • 썸네일 생성은 비동기 큐에서 처리
    • 상태값: pending / processing / ready / failed
    • 실패 시 자동 재시도 정책 적용(최대 횟수 이후 failed 고정)
    • 큐 스냅샷을 data/thumbnail-jobs.json에 저장해 재시작 후 복구
    • 작업 이벤트를 data/thumbnail-events.json에 기록
  • 관리자 삭제
    • 관리자 토큰으로 강의 삭제 가능
  • 초기 샘플 데이터 시드
    • resources/lecture에 있는 .pptx를 최초 실행 시 자동 등록

프로젝트 구조

ai_platform/
├─ server.js                  # Express 서버 진입점 (라우팅, 업로드, 썸네일 큐, DB 연동)
├─ package.json               # 의존성 및 npm 스크립트
├─ .env                       # 환경 변수 (실제 값, .gitignore 대상)
├─ .env.example               # 환경 변수 예시 템플릿
├─ db/
│  └─ schema.sql              # PostgreSQL lectures 테이블 스키마 (서버 기동 시 자동 적용)
├─ scripts/
│  └─ apply-schema.js         # 수동 스키마 적용 스크립트 (npm run db:schema)
├─ public/
│  └─ styles.css              # 전역 스타일
├─ views/
│  ├─ partials/
│  │  └─ nav.ejs              # 좌측 공통 네비게이션
│  ├─ learning-viewer.ejs     # 학습센터 뷰어 (일반 사용자)
│  ├─ learning-admin.ejs      # 학습센터 관리 (업로드·삭제·썸네일)
│  ├─ chat.ejs                # 채팅
│  ├─ ai-explore.ejs          # AI 탐색 (전체 너비, 프롬프트 카드·검색)
│  ├─ ai-prompts.ejs          # 프롬프트 라이브러리 (카드·미리보기·복사)
│  ├─ ai-cases.ejs            # AI 성공 사례 목록(카드)
│  ├─ ai-case-detail.ejs       # AI 성공 사례 상세(마크다운)
│  ├─ ai-cases-write.ejs      # AI 성공 사례 관리자 등록·편집
│  ├─ ax-apply.ejs            # AX 과제 신청
│  ├─ lecture-youtube.ejs     # 유튜브 강의 상세 (iframe 임베드)
│  ├─ lecture-ppt.ejs         # PPT 강의 상세 (슬라이드 텍스트 뷰어)
│  └─ admin-thumbnail-events.ejs  # 썸네일 이벤트 로그 관리자 페이지
├─ data/
│  ├─ lectures.json           # 강의 메타데이터 (ENABLE_POSTGRES=0 또는 DB 폴백 시)
│  ├─ company-prompts.json    # AI 프롬프트 라이브러리 템플릿 (제목·설명·본문)
│  ├─ thumbnail-jobs.json     # 썸네일 큐 스냅샷 (재시작 후 복구용)
│  └─ thumbnail-events.json   # 썸네일 작업 이벤트 로그
├─ uploads/                   # 업로드된 .pptx 파일 저장
│  └─ thumbnails/             # 생성된 썸네일 이미지
└─ resources/
   └─ lecture/                # 초기 시드용 샘플 PPT (최초 실행 시 자동 등록)

구조 설명

구분 설명
서버 server.js가 Express 앱, 라우트, Multer 업로드, 썸네일 백그라운드 워커, PostgreSQL 연동을 모두 담당
데이터 저장소 ENABLE_POSTGRES=1이면 PostgreSQL lectures 테이블이 단일 소스, 0이면 data/lectures.json 사용
썸네일 비동기 큐 처리, data/thumbnail-jobs.json으로 영속화, data/thumbnail-events.json에 이벤트 기록
EJS 템플릿으로 메인/유튜브/PPT/관리자 페이지 렌더링

서버 배포 (새 머신·처음부터)

아래는 저장소를 처음 받아 운영 서버에 올리는 경우를 가정한 절차입니다. macOS(개발용·소규모 호스팅)와 Linux(일반적인 VPS·온프레미스 서버)를 구분했습니다.

공통 사전 요구사항

항목 설명
Node.js v18 이상 권장 (node -v로 확인)
npm Node와 함께 설치
Git 저장소 클론용
PostgreSQL ENABLE_POSTGRES=1 사용 시 접속 가능한 DB(로컬 설치 또는 원격)
환경 변수 .env.example을 복사해 .env 작성(비밀번호·토큰은 반드시 변경)

PPT 썸네일·슬라이드 이미지는 macOS에서는 qlmanage가 우선 사용되고, 그 외에는 LibreOffice·poppler(pdftoppm) 조합이 필요합니다. 도구가 없으면 텍스트 프리뷰로 동작합니다.


macOS에서 배포 (새 머신)

  1. 도구 설치

    • Node.js: nodejs.org LTS 설치, 또는 brew install node@20
    • Git: Xcode Command Line Tools(xcode-select --install) 또는 brew install git
    • PostgreSQL(로컬 DB를 쓸 때): brew install postgresql@16 후 서비스 기동, 또는 원격 DB만 사용
    • PPT 변환 강화(선택): brew install --cask libreoffice, brew install poppler
  2. 코드 받기

    mkdir -p ~/workspace && cd ~/workspace
    git clone <저장소 URL> ai_platform
    cd ai_platform
    

    (이미 클론한 경우 예: cd /Users/dsyoon/workspace/ai_platform)

  3. 의존성·환경

    npm install
    cp .env.example .env
    # 편집기로 .env 수정: PORT, ADMIN_TOKEN, DB_*, ENABLE_POSTGRES 등
    
  4. DB 스키마 (ENABLE_POSTGRES=1일 때)

    npm run db:schema
    
  5. 실행 방식 선택

    • 포그라운드(테스트): npm start → 터미널에 Server started: http://localhost:8030 확인 후 브라우저 접속
    • 백그라운드(PM2): 아래 「PM2로 실행」 절 참고 (pm2 start … --name ai_platform)
  6. 접속
    같은 Mac에서: http://127.0.0.1:8030 (또는 .envPORT). 다른 기기에서 접속하려면 HOST=0.0.0.0이 기본이므로, macOS 방화벽에서 Node 허용 여부를 확인합니다.


Linux에서 배포 (새 서버)

배포 경로는 예시로 /var/www/ai_platform을 둡니다. 배포 사용자·그룹(www-data 등)은 배포 정책에 맞게 조정하세요.

  1. 시스템 패키지 (Ubuntu/Debian 예시)

    sudo apt update
    sudo apt install -y git build-essential
    
    • Node.js: 배포판 기본 패키지가 오래된 경우가 많으므로 NodeSource 또는 nvm으로 v18+ 설치를 권장합니다.
    • PostgreSQL 클라이언트/서버: 원격 DB만 쓰면 클라이언트 라이브러리만으로도 되고, 로컬 DB면 postgresql 패키지 설치 후 DB·사용자 생성.
    • PPT 변환(선택): sudo apt install -y libreoffice poppler-utils
  2. 코드 배치

    sudo mkdir -p /var/www
    cd /var/www
    sudo git clone <저장소 URL> ai_platform
    cd ai_platform
    sudo chown -R "$USER:$USER" /var/www/ai_platform   # 이후 작업 사용자에 맞게 조정
    
  3. 의존성·환경

    npm install --production
    cp .env.example .env
    nano .env   # 또는 vim — PORT, ADMIN_TOKEN, DB_*, ENABLE_POSTGRES 등
    
  4. DB 스키마 (ENABLE_POSTGRES=1일 때)

    npm run db:schema
    
  5. 프로세스 관리 (PM2 권장)

    sudo npm install -g pm2
    cd /var/www/ai_platform
    pm2 start server.js --name ai_platform
    pm2 save
    pm2 startup    # 부팅 시 자동 기동(출력되는 sudo 명령 실행)
    
  6. 방화벽·리버스 프록시

    • 외부에 직접 8030을 열지 않고 Nginx/Apache로 TLS·프록시하는 구성이 일반적입니다.
    • Apache2 예시(모듈·VirtualHost)는 docs/DEPLOYMENT-xavis.ncue.net.md를 참고하세요.
    • ufw 사용 시: sudo ufw allow 80,443/tcp 후 앱은 로컬에서만 듣게 하거나, 프록시 뒤에 둡니다.
  7. 데이터 디렉터리 권한
    data/, uploads/ 등에 앱 실행 사용자(예: pm2로 띄운 사용자, 또는 www-data)가 쓰기 가능해야 합니다. 실패 시 로그에 Failed to bootstrap 또는 권한 오류가 납니다.


배포 후 확인

  • 터미널 또는 pm2 logs ai_platform에서 에러 없이 Server started 로그 확인
  • 브라우저로 메인·/learning·관리자(토큰)까지 동작 확인
  • PostgreSQL 사용 시 npm run db:schema최초 1회(또는 스키마 변경 시); 백업·마이그레이션 정책은 운영 환경에 맞게 별도 수립

실행 방법

로컬에서 빠르게 띄우기는 아래 순서면 됩니다. 새 서버에 맞춰 처음부터 배포할 때는 위 「서버 배포 (새 머신·처음부터)」의 macOS 또는 Linux 절을 따르세요.

1) 의존성 설치

npm install

2) PostgreSQL 스키마 적용

npm run db:schema

3) 서버 실행

프로젝트 루트에서:

npm start

정상 기동 시 터미널에 Server started: http://localhost:8030 (또는 설정한 PORT)가 출력됩니다. 이 상태에서만 브라우저로 접속할 수 있습니다.

PM2로 실행

프로젝트 루트에서 실행해야 server.js가 같은 디렉터리의 .env를 읽습니다( dotenv 기준).

1) PM2 설치 (전역, 한 번)

npm install -g pm2

2) 프로젝트 디렉터리로 이동 후 의존성

cd /Users/dsyoon/workspace/ai_platform
npm install
cp .env.example .env   # 최초 1회 — 값 편집

3) 앱 기동

pm2 start server.js --name ai_platform

npm start와 동일하게 server.js를 띄웁니다. 이름만 PM2에서 ai_platform으로 관리합니다.

4) 재부팅 후에도 유지 (선택)

pm2 save
pm2 startup

pm2 startup이 출력하는 sudo env PATH=... 한 줄을 그대로 실행한 뒤, 다시 pm2 save를 하면 부팅 시 자동 기동에 맞춰집니다.

5) 자주 쓰는 명령

목적 명령
상태 확인 pm2 list
로그(실시간) pm2 logs ai_platform
재시작 pm2 restart ai_platform
중지 pm2 stop ai_platform
목록에서 제거 pm2 delete ai_platform

환경 변수: 포트·DB 등은 프로젝트 루트의 .env에 두고, 변경 후 pm2 restart ai_platform으로 반영합니다. 별도 경로에 두었다면 해당 디렉터리에서 pm2 start 하거나, ecosystem 설정으로 cwd를 지정하세요.

운영/배포 환경에서 이미 PM2로 띄운 경우 재시작 예:

pm2 restart ai_platform

로컬에서 포그라운드로만 확인할 때:

node server.js

포트·수신 주소 변경

PORT=8030 npm start
# 로컬 루프백만 (외부 네트워크 인터페이스에 바인딩하지 않음)
HOST=127.0.0.1 npm start

서버는 기본적으로 HOST=0.0.0.0으로 바인딩합니다(동일 기기의 localhost 접속에 사용).

기존 서버 프로세스 종료

터미널을 닫았는데도 이전에 실행한 node server.js가 남아 있거나, **포트가 이미 사용 중(EADDRINUSE)**이라 새로 npm start가 실패할 때, 기존 프로세스를 먼저 종료합니다.

포트로 PID 확인 후 종료 (macOS / Linux, 기본 포트 8030 예시)

lsof -i :8030

출력의 PID 열 값을 확인한 뒤:

kill PID

응답이 없으면 kill -9 PID로 강제 종료할 수 있으나, 다른 Node 작업이 같은 포트를 쓰는지 확인한 뒤 사용하세요.

프로젝트 진입점만 대상으로 종료 (다른 node 작업에 영향을 줄 수 있으니 주의)

pkill -f "node server.js"

PM2로 띄운 경우

pm2 list
pm2 stop ai_platform
# 완전히 제거하려면
pm2 delete ai_platform

Windows에서는 작업 관리자에서 Node.js 프로세스를 종료하거나, PowerShell에서 Get-NetTCPConnection -LocalPort 8030 등으로 점유 프로세스를 확인한 뒤 해당 PID를 종료합니다.

관리자 토큰/페이지 크기 설정(선택)

ADMIN_TOKEN=my-secret PAGE_SIZE=12 npm start
  • ADMIN_TOKEN 미지정 시 기본값: xavis-admin
  • PAGE_SIZE 미지정 시 기본값: 8
  • .env 파일이 있으면 dotenv로 자동 로드

PostgreSQL 연결 설정

  • ENABLE_POSTGRES=1일 때: PostgreSQL이 단일 소스로 사용됩니다. data/lectures.json은 사용하지 않습니다.
  • ENABLE_POSTGRES=0일 때: data/lectures.json만 사용합니다.
  • DB 연결 실패 시 자동으로 data/lectures.json 기반 파일 저장소로 폴백합니다.
  • 필수 변수: DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD

채팅 기능 (OpenAI API)

  • .envOPENAI_API_KEY를 넣은 뒤 서버를 재시작하면 채팅 메뉴(/chat)에서 OpenAI와 실제 대화가 이루어집니다.
  • API 키 발급: OpenAI Platform
  • 키 값 앞뒤 공백은 자동으로 제거합니다.
  • 화면의 모델 선택(gpt-5.4, gpt-5-mini)은 내부적으로 OpenAI에 전달할 실제 모델 ID로 매핑됩니다. 기본값은 각각 gpt-4o, gpt-4o-mini이며, 필요하면 .env에서 OPENAI_MODEL_DEFAULT, OPENAI_MODEL_MINI로 바꿀 수 있습니다.
  • 웹 검색(기본 활성): OPENAI_WEB_SEARCH0이 아니면 OpenAI Responses API와 내장 web_search 도구로 질의에 맞게 웹을 검색한 뒤 답변합니다. 끄려면 OPENAI_WEB_SEARCH=0으로 두면 이전과 같이 Chat Completions만 사용합니다. 선택적으로 OPENAI_WEB_SEARCH_COUNTRY(기본 KR), OPENAI_WEB_SEARCH_CITY, OPENAI_WEB_SEARCH_REGION, OPENAI_WEB_SEARCH_TIMEZONE(기본 Asia/Seoul)로 검색 맥락을 줄 수 있습니다.
  • GET /api/chat/config{ configured, webSearch }를 반환합니다(webSearch는 위 플래그와 동일).
  • 스트리밍(POST /api/chat/stream)은 SSE로 data: {JSON} 줄을 보냅니다. 타입 예: delta(본문 조각), status(예: phase: "web_search" — UI에서 «웹 검색 중…» 표시), sources(인용 URL·제목 목록), done, error. 비스트리밍 POST /api/chat은 필요 시 응답 JSON에 sources 배열을 포함할 수 있습니다.
  • 키가 비어 있으면 POST /api/chat·POST /api/chat/stream은 503을 반환하고, 채팅 화면 상단에 안내 배너가 표시됩니다.

PPT 썸네일 및 슬라이드 이미지 생성 제어(선택)

ENABLE_PPT_THUMBNAIL=1 npm start
  • 기본값: 1 (활성)
  • ENABLE_PPT_THUMBNAIL=0이면 썸네일·슬라이드 이미지 생성 비활성화
  • 우선순위: macOS qlmanage → LibreOffice(soffice/libreoffice) + pdftoppm
  • 도구 미설치 또는 변환 실패 시 텍스트 프리뷰로 자동 폴백

PPT 슬라이드 이미지(뷰어용): PPTX 파일은 LibreOffice로 PDF 변환 후 pdftoppm으로 이미지 생성.

  • PPTX: LibreOffice 필수. macOS: brew install --cask libreoffice
  • PDF: pdftoppm만 있으면 동작 (poppler 패키지)

.env 예시

PORT=8030
HOST=0.0.0.0
ADMIN_TOKEN=xavis-admin
PAGE_SIZE=8
ENABLE_POSTGRES=1
DB_HOST=your-db-host
DB_PORT=5432
DB_DATABASE=your_database
DB_USERNAME=your_user
DB_PASSWORD=your_password
ENABLE_PPT_THUMBNAIL=1
THUMBNAIL_WIDTH=1000
THUMBNAIL_MAX_RETRY=2
THUMBNAIL_RETRY_DELAY_MS=5000
THUMBNAIL_EVENT_KEEP=200
THUMBNAIL_EVENT_PAGE_SIZE=50

# 채팅 기능 (OpenAI API 키)
OPENAI_API_KEY=
# OPENAI_MODEL_DEFAULT=gpt-4o
# OPENAI_MODEL_MINI=gpt-4o-mini

사용 방법

  1. 메인 페이지에서 강의 등록
    • 유튜브 강의 등록: 제목 + 유튜브 링크 (+설명)
    • PowerPoint 강의 등록: 제목 + .pptx 파일 (+설명)
    • 두 등록 폼 모두 태그(쉼표 구분) 입력 가능
  2. 하단 등록된 강의 카드에서 항목 클릭
  3. 강의 상세 화면에서 시청
    • 유튜브: 동영상 재생
    • PPT: 슬라이드 텍스트 목록 확인

검색/필터

  • 검색어, 타입, 태그를 조합해서 목록을 조회할 수 있습니다.
  • 결과 목록은 페이지 단위로 분할되어 이동 가능합니다.

관리자 삭제

  1. 화면의 관리자 모드에서 토큰 입력 후 활성화
  2. 강의 카드의 삭제 버튼으로 즉시 삭제
  3. PPT 강의 삭제 시 업로드 파일도 함께 제거 시도

썸네일 재생성(관리자)

  • 관리자 모드에서 PPT 카드의 썸네일 재생성 버튼으로 수동 재생성 가능
  • 실패 썸네일 일괄 재시도 버튼으로 실패 건을 큐에 일괄 재등록 가능
  • 이벤트 로그 페이지에서 기간/유형/강의ID/사유 필터 조회 가능
  • 이벤트 로그는 CSV 다운로드 지원

주요 라우트

메뉴별 화면

경로 설명
GET / 학습센터 뷰어 (강의 목록)
GET /learning 학습센터 뷰어 (검색/필터/페이지네이션)
GET /admin 관리자 대시보드 (강의·썸네일·AI 등)
GET /chat 채팅
GET /ai-explore AI 탐색 (프롬프트·회의록 등 카드, 전체 너비 레이아웃)
GET /ai-explore/prompts 프롬프트 라이브러리 (업무 시나리오별 기본 프롬프트)
GET /ai-cases AI 성공 사례 목록(검색·태그 필터, 카드)
GET /ai-cases/:slug AI 성공 사례 상세
GET /ai-cases/write AI 성공 사례 관리(관리자 토큰 필요)
POST/PUT/DELETE /api/ai-success-stories 사례 CRUD(관리자) · 본문은 data/ai-success-stories/*.md
GET /ax-apply AX 과제 신청
GET /lectures/:id 강의 상세 뷰어 (유튜브/PPT)

API

  • GET /api/chat/config
    채팅용 OpenAI 키 설정 여부 { configured: boolean } (키 문자열은 노출하지 않음)

  • POST /api/chat
    JSON { model, messages } — OpenAI Chat Completions 연동(비스트리밍). OPENAI_API_KEY 필수.

  • POST /api/chat/stream
    동일 본문으로 SSE(text/event-stream) 스트리밍 응답. 이벤트: data: {"type":"delta","text":"..."} 조각, 마지막 {"type":"done"}. 오류 시 {"type":"error","error":"..."}. 채팅 UI는 이 엔드포인트를 사용합니다.

  • POST /lectures/youtube
    유튜브 강의 등록

  • POST /lectures/ppt
    PPT 강의 등록 (multipart/form-data)

  • POST /lectures/:id/delete
    관리자 토큰 기반 강의 삭제

  • POST /lectures/:id/thumbnail/regenerate
    관리자 토큰 기반 PPT 썸네일 재생성

  • POST /thumbnails/retry-failed
    관리자 토큰 기반 실패 썸네일 일괄 재시도 큐 등록

  • GET /api/queue/metrics?token=...
    관리자 토큰 기반 큐/상태 메트릭 JSON 조회

  • GET /api/queue/events-summary?token=...&hours=24
    최근 시간대 요약 KPI/시간대별 처리량 JSON 조회

  • GET /admin/thumbnail-events?token=...
    관리자 이벤트 로그 페이지 (필터/페이지네이션)

  • GET /admin/thumbnail-events.csv?token=...
    필터 기준 이벤트 로그 CSV 다운로드


최근 업데이트 (요약)

  • AI 탐색 (/ai-explore): 메인 콘텐츠를 뷰포트 전체 너비로 사용, 프롬프트 서비스 카드를 첫 번째에 배치, 검색어에 **「프롬프트」**가 포함된 채 검색(Enter) 시 프롬프트 라이브러리로 이동. 좌측 전체 메뉴는 관리자 여부와 관계없이 동일하게 표시·접근 가능
  • 프롬프트 라이브러리 (/ai-explore/prompts): 시나리오 카드·미리보기·복사 UI, 템플릿 데이터는 data/company-prompts.json에서 로드
  • 서버 수신 주소: 기본 HOST=0.0.0.0(로컬 localhost 접속에 사용). 필요 시 HOST=127.0.0.1로 제한 가능
  • 문서: localhost 접속 불가 시 확인할 항목을 아래 「접속이 안 될 때 (트러블슈팅)」 절에 정리

기술 스택

  • Node.js
  • Express
  • EJS
  • PostgreSQL (pg)
  • Multer (파일 업로드)
  • JSZip (.pptx 내부 XML 파싱)
  • UUID

구현 참고/제약

  • PPT 뷰어는 원본 슬라이드 디자인 렌더링이 아닌, .pptx 내부 텍스트를 추출해 보여주는 방식입니다.
  • PPT 썸네일은 시스템 도구 상태에 따라 생성 실패할 수 있으며, 이 경우 이미지 없이 텍스트 프리뷰만 표시됩니다.
  • 썸네일 큐는 단일 프로세스 워커 기준으로 동작합니다(다중 인스턴스 분산 락은 미구현).
  • 폰트/도형/애니메이션까지 완전 동일 렌더링이 필요하면 별도 문서 렌더러(예: LibreOffice/PDF 변환 파이프라인) 연동이 필요합니다.
  • 이벤트 로그 페이지의 실시간 그래프는 클라이언트 폴링 기반이며, 다수 접속 시 폴링 주기 조정이 필요할 수 있습니다.
Description
No description provided
Readme 3.1 MiB
Languages
JavaScript 48.2%
EJS 39.2%
CSS 9.2%
HTML 1.7%
PLpgSQL 1.7%