Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
翻訳待ち
No updates detected yet. GitHub releases will appear here.
Loading the full README. The saved excerpt is shown below.
AI 개발 도구 사용량을 살펴보는 Next.js 관리자 콘솔입니다. Node.js와 npm을 설치한 뒤 실행합니다. 의존성 버전은 package-lock.json을 따릅니다. http://localhost:3000 에서 확인할 수 있습니다. 로컬 API 포트는 Enrollment 8080 / Dashboard 8081를 사용합니다. 백엔드도 이 포트로 실행하고 루트 .env.local에 아래 주소를 설정합니다. 브라우저용 Enrollment 주소와 Next 서버용 주소는 같은 백엔드를 가리킵니다. 로컬 시드 로그인에는 .env.example의 DEV_SEED_AUTH_ENABLED와 DEV_SEED_AUTH_PASSWORD도 설정합니다. 주소를 바꾼 후 개발 서버는 재시작하고, 배포 빌드는 다시 생성해야 합니다. 로그인·개요·온보딩·설정은 실제 백엔드 API를 사용합니다. 팀 분석·구성원 화면에는 아직 목 데이터와 로컬 상태가 남아 있습니다. 초대 메일 발송과 벤더 좌석 회수는 연결하지 않았습니다.Read the full README ↗
AI 개발 도구 사용량을 살펴보는 Next.js 관리자 콘솔입니다.
Node.js와 npm을 설치한 뒤 실행합니다. 의존성 버전은 package-lock.json을 따릅니다.
npm ci
npm run dev
http://localhost:3000 에서 확인할 수 있습니다.
운영 빌드는 npm run build 후 PORT=3107 npm start로 실행합니다(비어 있는 포트 사용).
start는 standalone 서버를 실행하기 전에 public과 정적 JS/CSS를 빌드 폴더에 복사하며, 빌드는 수행하지 않습니다.
루트 .env.production.local, .env.local, .env.production, .env를 Next.js의 운영 환경 우선순위로 읽습니다. 명령행에서 전달한 환경변수가 우선하며, 환경 파일을 standalone 폴더에 복사할 필요는 없습니다.
로컬 관측을 켜려면 npm run observability:up 후 PORT=3107 npm run start:otel을 실행합니다.
start:otel은 환경 이름 local, Alloy 주소 http://127.0.0.1:14318을 사용합니다.
다른 수집기를 사용하려면 OTel 환경변수 세 개를 직접 지정하고 npm start를 실행합니다.
개발 서버와 빌드 폴더도 분리하려면 빌드와 실행 양쪽에 같은 NEXT_DIST_DIR=.next-production을 지정합니다.
포트는 --port 인자 대신 PORT 환경변수로 지정하고, 인증에 사용하는 BFF_ORIGIN과 콜백 주소도 실행 주소에 맞춥니다.
로컬 API 포트는 Enrollment 8080 / Dashboard 8081를 사용합니다.
백엔드도 이 포트로 실행하고 루트 .env.local에 아래 주소를 설정합니다.
NEXT_PUBLIC_ENROLLMENT_API_URL=http://localhost:8080
ENROLLMENT_API_URL=http://localhost:8080
DASHBOARD_API_URL=http://localhost:8081
BFF_ORIGIN=http://localhost:3000
BFF_SESSION_KEYS=<openssl rand -hex 32로 생성한 값>
회사 이메일로 소속 회사를 찾고 회사에 설정된 OIDC 제공자(개발은 Cognito)의 로그인 페이지로 이동합니다. 프론트 앱 설정에는 비밀번호·OIDC client secret을 넣지 않습니다. 업무 API는 BFF를 거치며, 조회할 조직은 로그인 세션에서만 가져옵니다. Storybook과 브라우저 테스트도 명시적인 세션 fixture를 사용합니다. 서비스 AT/RT는 암호화 HttpOnly 쿠키로 관리하고, 브라우저는 같은 출처의 BFF만 호출합니다. Node.js 프로세스 하나로 운영합니다. 다중 worker·replica·serverless에서는 갱신 공유를 재설계해야 합니다. 키 교체·보안·재시작 시 제약은 BFF 운영 안내를 따릅니다. 백엔드/Cognito 연결과 정확한 callback 설정은 OIDC 실행·계약 안내를 따릅니다. 주소를 바꾼 후 개발 서버는 재시작하고, 배포 빌드는 다시 생성해야 합니다.
| 화면 | 경로 | 범위 |
|---|---|---|
| 개요 | /overview | 기간별 KPI, 추이, 모델 구성, 상위 3팀과 미배분 요약 |
| 팀 분석 | /teams | 팀 비교, 모델 분석, 사용자 사용량, 팀 상세 드로어 |
| 구성원 | /members | 명단·검색, 초대, 팀 배정, 좌석 회수 UI |
| 설정 | /settings | 벤더 계약, 수집·보존 정책, 알림 규칙 UI |
| 로그인 | /login | 이메일 회사 탐색·복수 회사 선택 후 실제 OIDC 로그인 |
| 인증 복귀 | /auth/callback | state 검증·단회 코드 교환·관리자/온보딩 확인 |
| 로그인 | /login | 시드 이메일로 실제 백엔드에 인증하는 개발용 어댑터(시드 관리자만). 회사 로그인(SSO)은 별도 작업(PROJ-186) |
| 온보딩 | /onboarding | 수집 정책, 서버 벤더·플랜 카탈로그, 계약과 팀 등록 |
| 초대 수락 | /invite | 초대 메일의 링크가 가리키는 화면. 링크의 코드(#code=…)로 계정을 만든다 |
| 도입 문의 | /contact | 로그인 전 문의 폼. 입력 확인 뒤 서버에 접수하고 접수 번호·시각을 표시 |
| 성과 | /ops | 생산성·지출·도입 효용성 요약과 고른 지표의 8주 추이, 팀 범위의 전체 평균 비교. 백엔드 API가 없어 예시 데이터(src/mocks/performance.ts)를 보여준다 |
| 보안 | /security | 보안 범주 알림(미등록 제품 사용과 과거 이력)의 목록·상세·확인과 CSV. 세션 조회·감사 로그는 범위 밖 |
로그인·개요·온보딩·설정·구성원은 실제 백엔드 API를 사용합니다. 구성원 화면은 명단·요약·미배정·초대 대기·팀 목록을
조회하고, 팀·역할 편집, 미배정 구성원의 팀 배정, 팀 만들기·이름 변경·삭제, 초대 코드 발급·재발급·취소, 활성 구성원의 설치 코드 발급(새 PC 설치용 — 가입에는 쓸 수 없음)을 서버 명령으로 저장합니다.
초대는 코드 발급이고 메일 발송은 서버가 따로 합니다. 화면은 서버가 준 발송 상태(delivery)로만 말합니다 — 발급 직후는 "발송 대기"이고,
"발송됨"은 서버가 그렇게 답했을 때만 씁니다. 메일을 보내지 않는 서버에서는 코드를 직접 전달하라고 안내합니다. 발급된 코드는 발급 직후 화면에서만 볼 수 있습니다.
"다시 보내기"는 기존 코드를 폐기하고 새 코드를 발급하는 일이라 먼저 확인받습니다. 온보딩의 초대 폼도 같은 명령을 씁니다.
도입 문의는 세션 없이 POST /api/v1/inquiries로 접수합니다. 서버가 201을 준 뒤에만 접수 완료를 보여 주며, 접수는 조직·계정을 만들지 않습니다.
이전 초대 수락 링크는 fragment를 지우고 회사 SSO 로그인을 안내합니다. 초대 코드는 CLI 설치에만 사용합니다.
팀 분석·보안도 실제 API를 씁니다(성과는 예시 데이터). 좌석 회수·복원은 서버의 회수 작업으로 연결돼 있습니다 — 연결된 커넥터가 회수하는 제품은 벤더 제어,
그 밖은 관리자가 벤더 콘솔에서 하고 확인하는 관리자 조치입니다(복원을 구현한 커넥터는 없습니다).
실제 렌더링 화면과 소스 코드를 대조한 현재 구현 범위는 현재 구현 화면 명세에 정리되어 있습니다.
백엔드 담당자에게는 화면별 API 구현 요청서를 전달하면 됩니다. 공통 날짜·금액·권한·페이지네이션 규칙과 화면별 요청/응답 타입, JSON 예시, 저장·초대·회수의 처리 기준이 들어 있습니다.
조회·저장 상태 UI를 구현할 때는 조회·요청 상태 UI 규칙을 따른다. 로딩·오류·빈 상태·성공 Toast의 표시 범위와 현재 적용 현황, Storybook 사례를 정리한다.
브라우저 LCP·INP·CLS 수집·실행 설정은 브라우저 RUM 안내를 참고합니다.
Next.js 서버의 요청 추적, Node.js 메모리와 서버 로그를 OTel SDK → Alloy → Prometheus·Tempo·Loki → Grafana 경로로 확인할 수 있습니다. 로컬 메트릭 저장소는 Prometheus이며, Grafana의 Prometheus 데이터 소스에서 조회합니다. AWS 인프라 변경 없이 실행하며, 설정과 수집 범위는 로컬 관측성 안내를 따릅니다.
npm run observability:up
npm run dev:otel
프론트는 http://localhost:3000, Grafana는 http://localhost:3300/d/pulsemetry-frontend-local 입니다.
기존 npm run dev가 3000번에서 실행 중이면 해당 터미널에서 종료한 뒤 dev:otel로 다시 실행합니다.
일반 npm run dev는 명시적으로 계측을 활성화하지 않는 한 데이터를 전송하지 않습니다.
npm run dev로 실행하면 화면 하단의 TanStack Query 버튼에서 쿼리 키, 캐시,
조회 상태를 확인할 수 있습니다. 루트 QueryProvider에 연결되어 있으며 프로덕션에서는 표시하지 않습니다.
백엔드 없이 공통 UI 컴포넌트를 개별 확인합니다.
npm run storybook
# http://localhost:6006
npm run build-storybook
# storybook-static/에 정적 빌드 생성
상단 테마 메뉴에서 라이트·다크를 바꾸고 Controls에서 props를 조절할 수 있습니다.
버튼, 지표 카드(0과 미확정 값 포함), 상세 드로어(열기·닫기와 긴 내용) 스토리를 제공합니다.
대시보드는 Pages / 개요·팀 분석·구성원·보안·설정 아래 각각 일반 / 로딩 / 에러로, 예시 데이터만 쓰는 Pages / 성과는 일반 / 팀 범위로 확인합니다.
에러의 Controls → 에러 상황에서 최초 조회 실패와 마지막 데이터를 유지하는 갱신 실패를 전환합니다.
실제 페이지·공통 헤더·API 클라이언트를 사용하며 스토리 또는 Controls를 전환하면 캐시를 새로 만듭니다.
지표의 특수 값과 설정의 상세 동작은 각 페이지의 세부 사례에 있습니다.
바로 열기: http://localhost:6006/?path=/story/pages-overview--normal
온보딩은 Pages / Onboarding에서 수집 정책, 벤더·플랜 등록, 팀 구성, 로딩, 조회 실패, 등록 실패를 확인합니다.
바로 열기: http://localhost:6006/?path=/story/pages-onboarding--collection
MSW가 Storybook 전용 API 응답을 제공하므로 백엔드 실행이나 시드 로그인 환경변수가 필요하지 않습니다.
등록·삭제 결과는 스토리 안에서만 유지되며, 스토리를 다시 실행하면 초기화됩니다.
완료·로그아웃의 페이지 이동은 Storybook Actions에서 확인합니다.
새 스토리는 컴포넌트 옆에 *.stories.tsx로 추가합니다. 설정은 .storybook/에 있습니다.
npm run lint에는 Storybook 권장 규칙도 적용됩니다.
실제 백엔드 연동 검증은 기존 Playwright E2E로 실행합니다. 기존 목 API 테스트의 Storybook 이관은 포함하지 않습니다.
포맷은 프로젝트에 고정된 Prettier와 .prettierrc.json을 사용합니다.
VS Code에서는 추천된 Prettier 확장을 설치하면 저장 시 같은 설정으로 포맷합니다.
전체 파일을 정리하려면 npm run format, 변경한 파일만 정리하려면
npx --no-install prettier --write <파일 경로>를 실행합니다.
자동 생성 파일과 빌드 결과물은 .prettierignore로 제외합니다.
This is the beginning of the README. Read the rest at the original. Read the full README ↗