feat: TK 안전관리 플랫폼 초기 구현
위험성평가, 안전 RAG Q&A, 안전점검 체크리스트를 통합한 안전관리자 전용 웹 플랫폼 전체 구현. - Next.js 15 (App Router) + TypeScript + Tailwind + shadcn/ui - Drizzle ORM + PostgreSQL 16 (12개 테이블) - 위험성평가 CRUD + 5x5 위험성 매트릭스 + 인쇄 내보내기 - 체크리스트 템플릿/점검/NCR 추적 - RAG 문서 파이프라인 (Tika + bge-m3 + Qdrant) - SSE 스트리밍 RAG 채팅 (qwen3.5:35b-a3b) - AI 어시스트 (위험요인 추천, 감소대책, 점검항목 생성) - 대시보드 통계/차트 (recharts) - 단일 사용자 인증 (HMAC 쿠키 세션) - 다크모드 지원 - Docker 멀티스테이지 빌드 (standalone) - 프로젝트 가이드 문서 (docs/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
107
docs/architecture.md
Normal file
107
docs/architecture.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# TK 안전관리 플랫폼 - 아키텍처 가이드
|
||||
|
||||
## 기술 스택
|
||||
|
||||
| 분류 | 기술 |
|
||||
|------|------|
|
||||
| 프레임워크 | Next.js 15 (App Router, TypeScript, Server Actions) |
|
||||
| UI | Tailwind CSS + shadcn/ui + Lucide icons + recharts |
|
||||
| ORM | Drizzle ORM |
|
||||
| DB | PostgreSQL 16 (컨테이너 `tk-safety-db`) |
|
||||
| AI 생성 | 맥미니 Ollama qwen3.5:35b-a3b |
|
||||
| AI 임베딩 | 조립컴 Ollama bge-m3 (1024d) |
|
||||
| 벡터DB | Qdrant (컬렉션 `safety-docs`) |
|
||||
| OCR | Apache Tika (port 9998) |
|
||||
| 인증 | 단일 사용자 (환경변수 비밀번호 + HMAC 쿠키 세션) |
|
||||
|
||||
## 포트 매핑
|
||||
|
||||
| 서비스 | 호스트:컨테이너 |
|
||||
|--------|------------------|
|
||||
| tk-safety (Next.js) | 3100:3000 |
|
||||
| tk-safety-db (PostgreSQL) | 127.0.0.1:5433:5432 |
|
||||
|
||||
## 프로젝트 구조
|
||||
|
||||
```
|
||||
tk-safety/
|
||||
├── docker-compose.yml # 서비스 정의
|
||||
├── Dockerfile # multi-stage 빌드 (standalone)
|
||||
├── .env / .env.example # 환경변수
|
||||
├── drizzle.config.ts # Drizzle ORM 설정
|
||||
├── drizzle/migrations/ # DB 마이그레이션 (자동 생성)
|
||||
├── uploads/ # 업로드 파일 (documents, photos)
|
||||
├── docs/ # 프로젝트 가이드 문서
|
||||
└── src/
|
||||
├── app/
|
||||
│ ├── layout.tsx # 루트 레이아웃 (다크모드 초기화)
|
||||
│ ├── page.tsx # 인증 리다이렉트
|
||||
│ ├── login/page.tsx # 로그인 페이지
|
||||
│ ├── middleware.ts # 인증 미들웨어
|
||||
│ ├── (authenticated)/ # 인증 필요 라우트 그룹
|
||||
│ │ ├── layout.tsx # 사이드바 + 헤더
|
||||
│ │ ├── dashboard/ # 대시보드
|
||||
│ │ ├── risk-assessment/ # 위험성평가
|
||||
│ │ ├── rag/ # 안전 Q&A
|
||||
│ │ ├── checklists/ # 점검 체크리스트
|
||||
│ │ └── settings/ # 설정
|
||||
│ └── api/
|
||||
│ ├── auth/ # 로그인/로그아웃 API
|
||||
│ ├── ai/ # AI 엔드포인트 (SSE 스트리밍)
|
||||
│ └── health/ # 서비스 헬스체크
|
||||
├── actions/ # Server Actions (CRUD)
|
||||
├── components/
|
||||
│ ├── ui/ # shadcn/ui 컴포넌트
|
||||
│ ├── layout/ # 사이드바, 헤더, 모바일 내비
|
||||
│ ├── dashboard/ # 통계, 차트, 퀵액션
|
||||
│ ├── risk-assessment/ # 평가 폼, 매트릭스, AI 패널
|
||||
│ ├── rag/ # 채팅, 문서 관리
|
||||
│ └── checklists/ # 템플릿, 점검, NCR
|
||||
├── lib/
|
||||
│ ├── db/ # schema.ts, index.ts
|
||||
│ ├── ai/ # ollama, qdrant, tika, embeddings, prompts
|
||||
│ ├── auth.ts # 인증 유틸
|
||||
│ ├── constants.ts # 상수 정의
|
||||
│ └── utils.ts # shadcn 유틸
|
||||
├── hooks/ # use-streaming.ts (SSE)
|
||||
└── types/ # 타입 정의
|
||||
```
|
||||
|
||||
## DB 스키마 (12개 테이블)
|
||||
|
||||
### 위험성평가
|
||||
- `risk_assessments` — 평가 마스터 (제목, 상태, 버전)
|
||||
- `risk_assessment_hazards` — 유해위험요인 (S×L=위험성)
|
||||
|
||||
### RAG 문서
|
||||
- `rag_documents` — 업로드 문서 (처리 상태 포함)
|
||||
- `rag_chunks` — 문서 청크 (Qdrant pointId 매핑)
|
||||
- `rag_conversations` — 대화 세션
|
||||
- `rag_messages` — 메시지 (질문/답변 + 출처)
|
||||
|
||||
### 체크리스트
|
||||
- `checklist_templates` — 점검 템플릿
|
||||
- `checklist_template_items` — 템플릿 항목
|
||||
- `inspections` — 점검 실행 기록
|
||||
- `inspection_results` — 항목별 결과
|
||||
- `non_conformances` — 부적합 사항 (NCR)
|
||||
|
||||
### 기타
|
||||
- `app_settings` — 앱 설정 (key-value)
|
||||
|
||||
## AI 연동 흐름
|
||||
|
||||
### RAG Q&A
|
||||
```
|
||||
질문 → bge-m3 임베딩(조립컴) → Qdrant 검색(top-5) → 컨텍스트 + 질문 → qwen3.5 생성(맥미니) → SSE 스트리밍
|
||||
```
|
||||
|
||||
### AI 위험요인 추천
|
||||
```
|
||||
작업 설명 → bge-m3 임베딩 → Qdrant 검색(top-3) → 컨텍스트 + 프롬프트 → qwen3.5 JSON 생성 → 구조화 응답
|
||||
```
|
||||
|
||||
### 문서 처리 파이프라인
|
||||
```
|
||||
파일 업로드 → Tika 텍스트 추출 → 1500자/200 overlap 청킹 → bge-m3 배치 임베딩(10개씩) → Qdrant 저장
|
||||
```
|
||||
107
docs/deployment.md
Normal file
107
docs/deployment.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# TK 안전관리 - 배포 가이드
|
||||
|
||||
## 사전 요구사항
|
||||
|
||||
맥미니 서버 (192.168.1.122)에 다음 서비스가 실행 중이어야 합니다:
|
||||
- Ollama (qwen3.5:35b-a3b) — port 11434
|
||||
- Qdrant — port 6333
|
||||
- Apache Tika — port 9998
|
||||
- Docker Desktop
|
||||
|
||||
조립컴 (192.168.1.186 / Tailscale 100.111.160.84):
|
||||
- Ollama (bge-m3) — port 11434
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
### 1. 환경변수 설정
|
||||
```bash
|
||||
cd ~/docker/tk-safety
|
||||
cp .env.example .env
|
||||
# .env 파일에서 ADMIN_PASSWORD, SESSION_SECRET 변경
|
||||
```
|
||||
|
||||
### 2. Docker 빌드 및 실행
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 3. DB 마이그레이션
|
||||
```bash
|
||||
# 로컬에서 마이그레이션 생성
|
||||
npx drizzle-kit generate
|
||||
|
||||
# 마이그레이션 적용
|
||||
npx drizzle-kit push
|
||||
```
|
||||
|
||||
또는 DB URL을 직접 지정:
|
||||
```bash
|
||||
DATABASE_URL=postgres://tksafety:tksafety_password@localhost:5433/tksafety npx drizzle-kit push
|
||||
```
|
||||
|
||||
### 4. 접속 확인
|
||||
- http://192.168.1.122:3100
|
||||
- 설정한 비밀번호로 로그인
|
||||
|
||||
## 환경변수
|
||||
|
||||
| 변수 | 설명 | 기본값 |
|
||||
|------|------|--------|
|
||||
| DATABASE_URL | PostgreSQL 연결 문자열 | (필수) |
|
||||
| ADMIN_PASSWORD | 로그인 비밀번호 | changeme |
|
||||
| SESSION_SECRET | 세션 서명 키 (32자 이상) | (필수) |
|
||||
| OLLAMA_BASE_URL | Ollama 생성 AI URL | http://host.docker.internal:11434 |
|
||||
| OLLAMA_MODEL | 생성 모델명 | qwen3.5:35b-a3b |
|
||||
| EMBEDDING_BASE_URL | 임베딩 서버 URL | http://100.111.160.84:11434 |
|
||||
| EMBEDDING_MODEL | 임베딩 모델명 | bge-m3 |
|
||||
| QDRANT_URL | Qdrant URL | http://host.docker.internal:6333 |
|
||||
| QDRANT_COLLECTION | Qdrant 컬렉션명 | safety-docs |
|
||||
| TIKA_URL | Tika URL | http://host.docker.internal:9998 |
|
||||
|
||||
## 업데이트
|
||||
|
||||
```bash
|
||||
cd ~/docker/tk-safety
|
||||
git pull
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
## 데이터 백업
|
||||
|
||||
### PostgreSQL
|
||||
```bash
|
||||
docker exec tk-safety-db pg_dump -U tksafety tksafety > backup.sql
|
||||
```
|
||||
|
||||
### 복원
|
||||
```bash
|
||||
docker exec -i tk-safety-db psql -U tksafety tksafety < backup.sql
|
||||
```
|
||||
|
||||
### 업로드 파일
|
||||
`~/docker/tk-safety/uploads/` 디렉토리를 백업하세요.
|
||||
|
||||
## 트러블슈팅
|
||||
|
||||
### DB 연결 실패
|
||||
```bash
|
||||
# DB 컨테이너 상태 확인
|
||||
docker logs tk-safety-db
|
||||
|
||||
# DB 직접 접속
|
||||
docker exec -it tk-safety-db psql -U tksafety tksafety
|
||||
```
|
||||
|
||||
### AI 서비스 연결 실패
|
||||
설정 페이지 (Settings)에서 서비스 연결 상태를 확인하세요.
|
||||
- Ollama: `curl http://localhost:11434/api/tags`
|
||||
- Qdrant: `curl http://localhost:6333/collections`
|
||||
- Tika: `curl http://localhost:9998/tika`
|
||||
|
||||
### 빌드 실패
|
||||
```bash
|
||||
# 캐시 정리 후 재빌드
|
||||
docker-compose down
|
||||
docker-compose build --no-cache
|
||||
docker-compose up -d
|
||||
```
|
||||
80
docs/development.md
Normal file
80
docs/development.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# TK 안전관리 - 개발 가이드
|
||||
|
||||
## 로컬 개발 환경 설정
|
||||
|
||||
### 1. 의존성 설치
|
||||
```bash
|
||||
cd ~/docker/tk-safety
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. DB 실행 (Docker)
|
||||
```bash
|
||||
docker-compose up db -d
|
||||
```
|
||||
|
||||
### 3. DB 마이그레이션
|
||||
```bash
|
||||
npx drizzle-kit push
|
||||
```
|
||||
|
||||
### 4. 개발 서버 실행
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
→ http://localhost:3000
|
||||
|
||||
## 주요 패턴
|
||||
|
||||
### Server Actions
|
||||
모든 CRUD 작업은 `src/actions/` 디렉토리의 Server Actions로 구현됩니다.
|
||||
- `risk-assessment.ts` — 위험성평가 + 유해위험요인
|
||||
- `checklists.ts` — 템플릿 + 점검 + NCR
|
||||
- `rag.ts` — 문서 업로드/처리 + 대화
|
||||
|
||||
### AI API 라우트
|
||||
SSE 스트리밍이 필요한 AI 기능은 `src/app/api/ai/` 라우트로 구현됩니다.
|
||||
- `chat/route.ts` — RAG Q&A (SSE)
|
||||
- `suggest-hazards/route.ts` — 위험요인 추천 (JSON)
|
||||
- `suggest-controls/route.ts` — 감소대책 제안 (SSE)
|
||||
- `suggest-checklist/route.ts` — 점검항목 생성 (JSON)
|
||||
|
||||
### SSE 스트리밍
|
||||
클라이언트에서는 `src/hooks/use-streaming.ts` 훅을 사용합니다.
|
||||
```tsx
|
||||
const { isStreaming, content, sources, error, streamChat, reset } = useStreaming();
|
||||
await streamChat("/api/ai/chat", { question, conversationId });
|
||||
```
|
||||
|
||||
### 인증 시스템
|
||||
- HMAC 기반 쿠키 세션 (7일 유효)
|
||||
- `src/lib/auth.ts` — 세션 생성/검증
|
||||
- `src/middleware.ts` — 라우트 보호
|
||||
- `src/app/(authenticated)/layout.tsx` — 서버사이드 인증 확인
|
||||
|
||||
## DB 스키마 수정
|
||||
|
||||
1. `src/lib/db/schema.ts` 수정
|
||||
2. 마이그레이션 생성: `npx drizzle-kit generate`
|
||||
3. 마이그레이션 적용: `npx drizzle-kit push`
|
||||
|
||||
## 새 컴포넌트 추가
|
||||
|
||||
### shadcn/ui 컴포넌트
|
||||
```bash
|
||||
npx shadcn@latest add [component-name]
|
||||
```
|
||||
|
||||
### 커스텀 컴포넌트
|
||||
기능별 디렉토리에 배치:
|
||||
- `src/components/risk-assessment/` — 위험성평가 관련
|
||||
- `src/components/rag/` — RAG/채팅 관련
|
||||
- `src/components/checklists/` — 체크리스트 관련
|
||||
- `src/components/dashboard/` — 대시보드 관련
|
||||
|
||||
## 코드 컨벤션
|
||||
|
||||
- TypeScript strict 모드
|
||||
- Drizzle ORM 타입 추론 (`InferSelectModel<typeof table>`)
|
||||
- Server Actions에서 `revalidatePath()` 호출
|
||||
- 한국어 UI 텍스트 (상수는 `src/lib/constants.ts`에 정의)
|
||||
71
docs/features.md
Normal file
71
docs/features.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# TK 안전관리 - 기능 가이드
|
||||
|
||||
## 1. 위험성평가 (Risk Assessment)
|
||||
|
||||
### 평가 작성
|
||||
1. 대시보드 또는 위험성평가 페이지에서 "새 평가" 클릭
|
||||
2. 기본 정보 입력 (제목, 부서, 장소, 평가자)
|
||||
3. 평가 생성 후 유해위험요인 추가
|
||||
|
||||
### 유해위험요인 등록
|
||||
- **수동 입력**: "위험요인 추가" 버튼 → 분류, 작업, 위험요인, 중대성(1-5) × 가능성(1-5)
|
||||
- **AI 추천**: "AI 추천" 버튼 → 작업 설명 입력 → AI가 위험요인 분석 → "추가" 클릭
|
||||
|
||||
### 위험성 매트릭스
|
||||
- 5×5 매트릭스 자동 시각화
|
||||
- 위험등급: 저위험(1-4), 보통(5-9), 고위험(10-16), 매우위험(17-25)
|
||||
|
||||
### AI 감소대책 제안
|
||||
- 각 위험요인 행의 "대책 제안" 클릭
|
||||
- 제거 → 대체 → 공학적 → 관리적 → PPE 계층별 제안
|
||||
|
||||
### 상태 워크플로
|
||||
초안 → 검토 → 승인 → 보관
|
||||
|
||||
### 인쇄/내보내기
|
||||
- "인쇄" 버튼으로 고용노동부 양식 기반 인쇄 페이지 열기
|
||||
- 브라우저 인쇄(Ctrl+P)로 PDF 저장 가능
|
||||
|
||||
## 2. 안전 Q&A (RAG)
|
||||
|
||||
### 문서 업로드
|
||||
1. "문서 관리" 탭 선택
|
||||
2. 카테고리 선택 (산업안전보건법, KOSHA 가이드, 사내규정, 안전작업절차서, 기타)
|
||||
3. 파일 선택 (PDF, HWP, DOCX 등)
|
||||
4. 자동 처리: Tika 추출 → 청킹 → 임베딩 → Qdrant 저장
|
||||
|
||||
### 채팅
|
||||
1. "채팅" 탭에서 "새 대화" 클릭
|
||||
2. 질문 입력 (Enter 전송, Shift+Enter 줄바꿈)
|
||||
3. AI가 업로드된 문서 기반으로 답변 (SSE 스트리밍)
|
||||
4. 출처 배지로 참고 문서 확인
|
||||
|
||||
## 3. 점검 체크리스트
|
||||
|
||||
### 템플릿 관리
|
||||
1. "새 템플릿" 클릭 → 이름, 유형(일상/정기/특별/장비), 설명 입력
|
||||
2. 점검 항목 추가 (수동 또는 AI 생성)
|
||||
3. **AI 항목 생성**: "AI 항목 생성" → 작업환경 설명 → AI가 항목 제안 → 개별 또는 전체 추가
|
||||
|
||||
### 점검 실행
|
||||
1. "점검 실행" → 템플릿 선택, 점검자, 장소 입력
|
||||
2. 각 항목별 합격/불합격/해당없음 선택 + 메모
|
||||
3. 불합격 항목에서 NCR(부적합) 등록 가능
|
||||
4. "점검 완료" 클릭
|
||||
|
||||
### 부적합 사항 (NCR) 추적
|
||||
- 상태 흐름: 미조치 → 시정조치 중 → 확인 중 → 종결
|
||||
- "부적합" 탭에서 전체 NCR 현황 관리
|
||||
|
||||
## 4. 대시보드
|
||||
|
||||
- **통계 카드**: 총 평가 수, 점검 수, 미조치 NCR, RAG 문서 수
|
||||
- **위험등급 분포 차트**: 전체 위험요인의 등급별 분포 (막대 차트)
|
||||
- **부적합 현황 차트**: NCR 상태별 분포 (파이 차트)
|
||||
- **빠른 실행**: 새 위험성평가, 안전 Q&A, 점검 실행 바로가기
|
||||
|
||||
## 5. 설정
|
||||
|
||||
- **테마**: 라이트/다크 모드 전환
|
||||
- **서비스 연결 상태**: Ollama, Embedding, Qdrant, Tika 연결 확인
|
||||
- **시스템 정보**: 버전, 프레임워크, 모델 정보
|
||||
Reference in New Issue
Block a user