docs: [종합정비] 구조 재편 — Phase 0+2+4 통합
- Phase 0: INDEX.md 전면 재작성, CLAUDE.md→INDEX.md 통합 삭제 - Phase 0: front/→guides/ 이관(5개 파일), changes/ D7 포맷 통일(3개) - Phase 0: guides/ai-config-설정.md→ai-config-settings.md D3 통일 - Phase 2: architecture/+specs/→system/ 이관(6개 이동, 4개 폐기) - Phase 2: 13개 파일 경로 참조 수정 (specs/→system/, architecture/→system/) - Phase 4: 7개 파일 11개 교차참조 깨진 링크 수정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
729
CLAUDE.md
729
CLAUDE.md
@@ -1,729 +0,0 @@
|
|||||||
# Claude Code 전역 설정
|
|
||||||
|
|
||||||
> 이 파일은 모든 프로젝트에 적용되는 전역 규칙입니다.
|
|
||||||
|
|
||||||
## 메모리
|
|
||||||
|
|
||||||
### sam설명
|
|
||||||
SAM 프로젝트의 기술적 개요 문서입니다. 이 문서를 참조하면 SAM 프로젝트가 무엇인지 이해할 수 있습니다.
|
|
||||||
|
|
||||||
**파일 경로**: `/home/aweso/sam/docs/SAM_PROJECT_OVERVIEW_FOR_AI.md`
|
|
||||||
|
|
||||||
**핵심 요약**:
|
|
||||||
- **회사**: 주일/경동 (블라인드/스크린 제조업체)
|
|
||||||
- **프로젝트**: SAM (Smart Automation Management) - 차세대 ERP/MES 통합 시스템
|
|
||||||
- **기술 스택**: Laravel 11 + HTMX + Tailwind CSS + MySQL 8.0
|
|
||||||
- **아키텍처**: Multi-tenant (tenant_id 기반 데이터 격리)
|
|
||||||
- **레거시**: 5130.co.kr (PHP 기반) → SAM으로 마이그레이션 중
|
|
||||||
|
|
||||||
**사용자가 'sam설명'이라고 말하면**:
|
|
||||||
1. 위 경로의 `SAM_PROJECT_OVERVIEW_FOR_AI.md` 파일을 읽어서 전체 내용을 파악하세요
|
|
||||||
2. SAM 프로젝트의 비즈니스 도메인, 기술 스택, 현재 작업 현황을 이해한 상태로 작업하세요
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Git 커밋 규칙 (최우선 필수 규칙)
|
|
||||||
|
|
||||||
> **경고: 이 규칙은 절대 누락되어서는 안 됩니다!**
|
|
||||||
> **기준 문서**: `sam/docs/standards/git-conventions.md`
|
|
||||||
|
|
||||||
### 필수 수행 절차
|
|
||||||
|
|
||||||
**모든 코드 작업 완료 후 반드시 다음을 수행:**
|
|
||||||
|
|
||||||
1. 변경된 파일이 있는 Git 저장소로 이동
|
|
||||||
2. `git status`로 변경사항 확인
|
|
||||||
3. `git add <파일들>` 로 스테이징
|
|
||||||
4. `git commit -m "type: [scope] 작업내용"` 로 커밋
|
|
||||||
|
|
||||||
### 커밋 메시지 형식 (필수)
|
|
||||||
|
|
||||||
```
|
|
||||||
type: [scope] 작업내용
|
|
||||||
|
|
||||||
- 세부항목 (생략가능)
|
|
||||||
- 세부항목 2
|
|
||||||
|
|
||||||
Issue: URL (생략가능)
|
|
||||||
```
|
|
||||||
|
|
||||||
**예시:**
|
|
||||||
```bash
|
|
||||||
feat: [calendar] 달력 기능 개선
|
|
||||||
|
|
||||||
- 클릭시 오류 기능 개선
|
|
||||||
- 색상 변경
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
fix: [auth] 로그인 시 세션 만료 오류 수정
|
|
||||||
```
|
|
||||||
|
|
||||||
### Commit Types
|
|
||||||
|
|
||||||
| Type | 설명 | 예시 |
|
|
||||||
|------|------|------|
|
|
||||||
| `feat` | 새로운 기능 추가 | `feat: [file] 파일 업로드 기능 추가` |
|
|
||||||
| `fix` | 버그 수정 | `fix: [auth] 세션 만료 오류 수정` |
|
|
||||||
| `chore` | 설정, 빌드 등 변경 | `chore: composer 패키지 업데이트` |
|
|
||||||
| `refactor` | 프로덕션 코드 리팩토링 | `refactor: [user] 서비스 메서드 분리` |
|
|
||||||
| `style` | 포맷/코딩 스타일 수정 | `style: Pint 포맷팅 적용` |
|
|
||||||
| `test` | 테스트 추가/수정 | `test: Product API 테스트 추가` |
|
|
||||||
| `docs` | 문서 변경 | `docs: API 문서 업데이트` |
|
|
||||||
|
|
||||||
### Claude 서명 제외 (필수)
|
|
||||||
|
|
||||||
```
|
|
||||||
❌ Co-Authored-By: Claude <noreply@anthropic.com> — 포함 금지
|
|
||||||
❌ 🤖 Generated with Claude Code — 포함 금지
|
|
||||||
```
|
|
||||||
|
|
||||||
- Git hooks로 자동 제거됨
|
|
||||||
- 간결하고 명확한 한글 커밋 메시지만 유지
|
|
||||||
|
|
||||||
### 푸시 정책
|
|
||||||
|
|
||||||
- **사용자가 수동으로 푸시 진행**
|
|
||||||
- 자동 푸시 하지 않음
|
|
||||||
- 커밋 후 푸시 여부를 묻지 않음
|
|
||||||
|
|
||||||
### Claude Code 설정 파일도 커밋 대상
|
|
||||||
|
|
||||||
다음 파일들이 변경되면 반드시 커밋:
|
|
||||||
|
|
||||||
| 파일/폴더 | 설명 | 커밋 예시 |
|
|
||||||
|-----------|------|----------|
|
|
||||||
| `CLAUDE.md` | 프로젝트 설정 | `docs: CLAUDE.md 규칙 업데이트` |
|
|
||||||
| `claudedocs/` | Claude 관련 문서 | `docs: 기능 분석 문서 추가` |
|
|
||||||
| `.claude/settings.json` | Claude 설정 | `chore: Claude 설정 변경` |
|
|
||||||
| `agents/`, `skills/` | 커스텀 에이전트/스킬 | `feat: [claude] 새 스킬 추가` |
|
|
||||||
|
|
||||||
### 커밋 전 체크리스트
|
|
||||||
|
|
||||||
- [ ] `./vendor/bin/pint` 실행 (코드 포맷팅, 해당 시)
|
|
||||||
- [ ] `git diff`로 변경사항 검토
|
|
||||||
- [ ] 불필요한 파일 제외 (.env, node_modules 등)
|
|
||||||
- [ ] 변경된 파일이 있는 저장소에서 git add → git commit
|
|
||||||
- [ ] CLAUDE.md, claudedocs/, agents/, skills/ 변경 확인 → git commit
|
|
||||||
- [ ] 커밋 메시지: `type: [scope] 한글 작업내용` 형식 준수
|
|
||||||
- [ ] Co-Authored-By 서명 미포함 확인
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 주요 프로젝트 경로
|
|
||||||
|
|
||||||
| 경로 | 설명 | Git 저장소 |
|
|
||||||
|------|------|-----------|
|
|
||||||
| `/home/aweso/sam/mng` | 관리자 웹 (Laravel) | 독립 저장소 |
|
|
||||||
| `/home/aweso/sam/api` | API 서버 (Laravel) | 독립 저장소 |
|
|
||||||
| `/home/aweso/sam/react` | 프론트엔드 (Next.js) | 독립 저장소 |
|
|
||||||
|
|
||||||
**각 폴더는 독립적인 Git 저장소입니다. 해당 폴더에서 git 명령을 실행해야 합니다.**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 서버 직접 접근 금지 (최우선 필수 규칙)
|
|
||||||
|
|
||||||
> **경고: 운영/개발 서버에 SSH로 직접 접속하여 파일을 수정하거나 명령을 실행하지 마세요!**
|
|
||||||
> **2026-02-21 사고**: Claude가 서버에 SSH로 직접 접속하여 설정을 변경한 결과 502 Bad Gateway 발생. 개발팀장이 복구함.
|
|
||||||
|
|
||||||
### 핵심 원칙
|
|
||||||
|
|
||||||
서버는 **개발팀장이 관리**한다. Claude는 서버에 절대 직접 접근하지 않는다.
|
|
||||||
|
|
||||||
### 금지 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
❌ ssh pro@114.203.209.83 ... 로 서버 접속 금지
|
|
||||||
❌ ssh hskwon@114.203.209.83 ... 로 서버 접속 금지
|
|
||||||
❌ 서버에서 파일 수정, 프로세스 종료/시작, 설정 변경 금지
|
|
||||||
❌ 서버에서 npm run build, npm start, node server.js 등 실행 금지
|
|
||||||
❌ 서버에서 git pull, composer install, php artisan 등 실행 금지
|
|
||||||
❌ scp, rsync로 서버에 파일 직접 전송 금지
|
|
||||||
```
|
|
||||||
|
|
||||||
### 허용 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
✅ 로컬에서 코드 작성 및 수정
|
|
||||||
✅ 로컬에서 git add → git commit
|
|
||||||
✅ 사용자에게 git push 안내 (사용자가 수동으로 실행)
|
|
||||||
✅ 사용자에게 서버 배포 절차 안내 (사용자가 수동으로 실행)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 배포 흐름
|
|
||||||
|
|
||||||
```
|
|
||||||
Claude 역할 사용자/팀장 역할
|
|
||||||
┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ 코드 작성/수정 │ │ │
|
|
||||||
│ git add │ │ │
|
|
||||||
│ git commit │──push──→ │ git pull │
|
|
||||||
│ │ │ 서버 배포 │
|
|
||||||
│ │ │ 서비스 재시작 │
|
|
||||||
└─────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 서버 작업이 필요한 경우
|
|
||||||
|
|
||||||
사용자에게 명령어를 안내만 한다:
|
|
||||||
|
|
||||||
```
|
|
||||||
서버에서 다음 명령을 실행해주세요:
|
|
||||||
cd /home/webservice/api && git pull && composer install && php artisan migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
### 체크리스트 (모든 작업 시)
|
|
||||||
|
|
||||||
- [ ] SSH 명령 사용하지 않음
|
|
||||||
- [ ] 서버 파일 직접 수정하지 않음
|
|
||||||
- [ ] 배포가 필요하면 사용자에게 안내만 제공
|
|
||||||
- [ ] git push까지만 Claude 역할
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## React 빌드/배포 정책 (필수 규칙)
|
|
||||||
|
|
||||||
> **경고: React(Next.js) 빌드는 반드시 로컬에서 실행합니다. 서버에서 빌드 절대 금지!**
|
|
||||||
|
|
||||||
### 배경
|
|
||||||
|
|
||||||
서버 스펙(2코어, 3.8GB RAM, Swap 없음)으로는 Next.js 빌드 시 메모리 부족으로 20분 이상 소요되거나 실패한다.
|
|
||||||
로컬(WSL)에서 빌드 후 결과물만 서버에 배포한다.
|
|
||||||
|
|
||||||
### 금지 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
❌ 서버에서 npm run build 실행 금지
|
|
||||||
❌ 서버 SSH 접속 후 빌드 명령 실행 금지
|
|
||||||
❌ Claude가 직접 npm run build 실행 금지 (로컬 포함)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 빌드/배포 방법
|
|
||||||
|
|
||||||
```
|
|
||||||
Claude 역할 사용자/팀장 역할
|
|
||||||
┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ 코드 작성/수정 │ │ │
|
|
||||||
│ git commit │──push──→ │ git pull │
|
|
||||||
│ │ │ npm run build │
|
|
||||||
│ │ │ 서비스 재시작 │
|
|
||||||
└─────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 빌드가 필요한 상황
|
|
||||||
|
|
||||||
사용자에게 다음과 같이 안내한다:
|
|
||||||
|
|
||||||
```
|
|
||||||
React 코드가 변경되었습니다. git push 후 서버에서 배포해주세요.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터베이스 아키텍처 (필수 규칙)
|
|
||||||
|
|
||||||
> **경고: 이 규칙을 반드시 준수하세요!**
|
|
||||||
|
|
||||||
### 핵심 원칙
|
|
||||||
|
|
||||||
**모든 데이터베이스 관련 파일은 API 프로젝트에서만 관리합니다.**
|
|
||||||
|
|
||||||
| 항목 | API (`/home/aweso/sam/api`) | MNG (`/home/aweso/sam/mng`) |
|
|
||||||
|------|----------------------------|----------------------------|
|
|
||||||
| 마이그레이션 | ✅ 여기에 생성 | ❌ 생성 금지 |
|
|
||||||
| 시더 | ✅ 여기에 생성 | ⚠️ MNG 전용만 허용 |
|
|
||||||
| 팩토리 | ✅ 여기에 생성 | ❌ 생성 금지 |
|
|
||||||
|
|
||||||
### 금지 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
❌ /home/aweso/sam/mng/database/migrations/ 에 파일 생성 금지
|
|
||||||
❌ MNG에서 테이블 생성/수정 마이그레이션 작성 금지
|
|
||||||
```
|
|
||||||
|
|
||||||
### 허용 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
✅ /home/aweso/sam/api/database/migrations/ 에 모든 마이그레이션 생성
|
|
||||||
✅ MNG에서는 MngMenuSeeder 같은 MNG 전용 시더만 허용
|
|
||||||
```
|
|
||||||
|
|
||||||
### 마이그레이션 실행
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 마이그레이션은 반드시 API 컨테이너에서 실행
|
|
||||||
docker exec sam-api-1 php artisan migrate
|
|
||||||
|
|
||||||
# MNG 컨테이너에서 마이그레이션 실행 금지
|
|
||||||
# docker exec sam-mng-1 php artisan migrate ← 사용하지 않음
|
|
||||||
```
|
|
||||||
|
|
||||||
### 이유
|
|
||||||
|
|
||||||
- MNG: 프론트엔드/관리자 화면 담당 (컨트롤러, 뷰, 라우트)
|
|
||||||
- API: 백엔드/데이터베이스 담당 (마이그레이션, 모델 정의, API)
|
|
||||||
- 단일 DB를 두 프로젝트가 공유하므로 마이그레이션은 한 곳에서만 관리
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 메뉴 관리 규칙 (필수)
|
|
||||||
|
|
||||||
> **경고: 메뉴 시더(Seeder)를 절대 실행하지 마세요!**
|
|
||||||
|
|
||||||
### 배경
|
|
||||||
|
|
||||||
메뉴 시더 실행 시 부서별 권한 설정(permission_overrides)이 초기화되는 문제가 반복 발생합니다.
|
|
||||||
메뉴 ID가 변경되면 기존 부서-메뉴 권한 매핑이 깨지기 때문입니다.
|
|
||||||
|
|
||||||
### 금지 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
❌ php artisan db:seed --class=MngMenuSeeder 실행 금지
|
|
||||||
❌ php artisan db:seed --class=*MenuSeeder 실행 금지
|
|
||||||
❌ 메뉴 시더 파일 생성 금지
|
|
||||||
❌ 메뉴 데이터를 일괄 삭제 후 재생성하는 방식 금지
|
|
||||||
```
|
|
||||||
|
|
||||||
### 메뉴 변경 시 올바른 절차
|
|
||||||
|
|
||||||
메뉴 추가/수정/삭제/이동이 필요할 때는 **사용자에게 수동 실행 안내**를 제공합니다:
|
|
||||||
|
|
||||||
1. **tinker 명령어를 안내** (사용자가 직접 실행)
|
|
||||||
2. **또는 SQL 쿼리를 안내** (사용자가 phpMyAdmin 등에서 직접 실행)
|
|
||||||
3. **절대 시더를 만들어 실행하지 않음**
|
|
||||||
|
|
||||||
### 안내 예시
|
|
||||||
|
|
||||||
```
|
|
||||||
메뉴를 추가하려면 아래 명령을 서버에서 실행해 주세요:
|
|
||||||
|
|
||||||
ssh sam-server "cd /home/webservice/mng && php artisan tinker --execute=\"
|
|
||||||
App\\Models\\Commons\\Menu::create([
|
|
||||||
'tenant_id' => 1,
|
|
||||||
'parent_id' => <부모ID>,
|
|
||||||
'name' => '새 메뉴',
|
|
||||||
'url' => '/new-menu',
|
|
||||||
'icon' => 'icon-name',
|
|
||||||
'sort_order' => 1,
|
|
||||||
'is_active' => true,
|
|
||||||
]);
|
|
||||||
\""
|
|
||||||
```
|
|
||||||
|
|
||||||
### 체크리스트 (메뉴 변경 요청 시)
|
|
||||||
|
|
||||||
- [ ] 시더 파일 생성하지 않음
|
|
||||||
- [ ] 시더 실행하지 않음
|
|
||||||
- [ ] tinker 또는 SQL로 개별 레코드만 수정
|
|
||||||
- [ ] 변경 후 부서 권한 설정이 유지되는지 확인
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Docker 환경 (필수 인지)
|
|
||||||
|
|
||||||
> **중요: 로컬 개발 환경은 Docker 기반입니다!**
|
|
||||||
|
|
||||||
### 왜 Docker를 통해 실행하나?
|
|
||||||
|
|
||||||
PHP, Laravel, Node.js 등이 **Docker 컨테이너 안에** 설치되어 있습니다.
|
|
||||||
로컬 PC(WSL)에는 이런 도구들이 없으므로, 반드시 Docker 컨테이너를 통해 실행해야 합니다.
|
|
||||||
|
|
||||||
```
|
|
||||||
로컬 PC (WSL)
|
|
||||||
└── Docker
|
|
||||||
├── sam-mng-1 ← PHP + Laravel (MNG 앱)
|
|
||||||
├── sam-api-1 ← PHP + Laravel (API 앱)
|
|
||||||
├── sam-mysql-1 ← MySQL DB
|
|
||||||
└── sam-nginx-1 ← Nginx 웹서버
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker 명령어 패턴
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# MNG 앱에서 artisan 명령 실행
|
|
||||||
docker exec sam-mng-1 php artisan <명령어>
|
|
||||||
|
|
||||||
# API 앱에서 artisan 명령 실행
|
|
||||||
docker exec sam-api-1 php artisan <명령어>
|
|
||||||
|
|
||||||
# 예시: 시더 실행
|
|
||||||
docker exec sam-mng-1 php artisan db:seed --class=MngMenuSeeder
|
|
||||||
|
|
||||||
# 예시: 마이그레이션 실행 (API에서만!)
|
|
||||||
docker exec sam-api-1 php artisan migrate
|
|
||||||
|
|
||||||
# 예시: 캐시 클리어
|
|
||||||
docker exec sam-mng-1 php artisan cache:clear
|
|
||||||
```
|
|
||||||
|
|
||||||
### 체크리스트 (명령 실행 시)
|
|
||||||
|
|
||||||
- [ ] `php artisan` 명령 → `docker exec sam-mng-1 php artisan` 또는 `sam-api-1` 사용
|
|
||||||
- [ ] `composer` 명령 → `docker exec sam-mng-1 composer` 또는 `sam-api-1` 사용
|
|
||||||
- [ ] DB 시더 실행 필요 시 → Docker를 통해 실행
|
|
||||||
- [ ] **마이그레이션은 반드시 API에서 실행** → `docker exec sam-api-1 php artisan migrate`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 공동 개발 워크플로우 (필수)
|
|
||||||
|
|
||||||
> **중요: 코드를 pull 받은 후 반드시 필요한 명령을 실행하세요!**
|
|
||||||
|
|
||||||
### 로컬 환경 (Docker) 업데이트
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 코드 받기 (WSL에서 실행)
|
|
||||||
cd /home/aweso/sam/api
|
|
||||||
git pull
|
|
||||||
|
|
||||||
cd /home/aweso/sam/mng
|
|
||||||
git pull
|
|
||||||
|
|
||||||
# 2. 의존성 업데이트 (composer.json 변경 시)
|
|
||||||
docker exec sam-api-1 composer install
|
|
||||||
docker exec sam-mng-1 composer install
|
|
||||||
|
|
||||||
# 3. DB 마이그레이션 (API에서만!)
|
|
||||||
docker exec sam-api-1 php artisan migrate
|
|
||||||
|
|
||||||
# 4. 캐시 클리어 (설정 변경 시)
|
|
||||||
docker exec sam-api-1 php artisan config:clear
|
|
||||||
docker exec sam-mng-1 php artisan config:clear
|
|
||||||
```
|
|
||||||
|
|
||||||
### 서버 환경 업데이트
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# API 프로젝트
|
|
||||||
cd /home/webservice/api
|
|
||||||
git pull
|
|
||||||
composer install
|
|
||||||
php artisan migrate
|
|
||||||
php artisan config:clear
|
|
||||||
|
|
||||||
# MNG 프로젝트 (마이그레이션 없음)
|
|
||||||
cd /home/webservice/mng
|
|
||||||
git pull
|
|
||||||
composer install
|
|
||||||
php artisan config:clear
|
|
||||||
```
|
|
||||||
|
|
||||||
### 요약 표
|
|
||||||
|
|
||||||
| 작업 | 로컬 (Docker) | 서버 |
|
|
||||||
|------|--------------|------|
|
|
||||||
| git pull | WSL에서 직접 | 서버에서 직접 |
|
|
||||||
| composer install | `docker exec sam-api-1 composer install` | `composer install` |
|
|
||||||
| migrate | `docker exec sam-api-1 php artisan migrate` | `php artisan migrate` |
|
|
||||||
| config:clear | `docker exec sam-api-1 php artisan config:clear` | `php artisan config:clear` |
|
|
||||||
|
|
||||||
### 체크리스트 (pull 후)
|
|
||||||
|
|
||||||
- [ ] API: `git pull` → `composer install` → `php artisan migrate` → `config:clear`
|
|
||||||
- [ ] MNG: `git pull` → `composer install` → `config:clear` (마이그레이션 없음)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 사용 가능한 Agents
|
|
||||||
|
|
||||||
`~/.claude/agents/` 폴더에 있는 에이전트들:
|
|
||||||
|
|
||||||
### 코드 품질 & 개발
|
|
||||||
|
|
||||||
| Agent | 모델 | 설명 | 출처 |
|
|
||||||
|-------|------|------|------|
|
|
||||||
| `code-reviewer` | sonnet | 코드 리뷰 (품질/보안/유지보수성), 메모리 학습 지원 | 공식 문서 패턴 |
|
|
||||||
| `debugger` | sonnet | 에러/테스트 실패 근본 원인 분석 및 수정 | 공식 문서 패턴 |
|
|
||||||
| `test-runner` | haiku | 테스트 실행 및 결과 분석/요약 | 커뮤니티 인기 |
|
|
||||||
| `security-auditor` | sonnet | OWASP Top 10 기반 보안 취약점 감사 | 커뮤니티 인기 |
|
|
||||||
| `performance-optimizer` | sonnet | N+1 쿼리, 알고리즘, 캐싱 최적화 | 커뮤니티 인기 |
|
|
||||||
| `refactoring-agent` | sonnet | 코드 구조 개선, SOLID 원칙, DRY 위반 제거 | 커뮤니티 인기 |
|
|
||||||
| `laravel-expert` | sonnet | Laravel 전문가 (SAM 프로젝트 환경 인지) | 커스텀 |
|
|
||||||
|
|
||||||
### 워크플로우 & 문서
|
|
||||||
|
|
||||||
| Agent | 모델 | 설명 | 출처 |
|
|
||||||
|-------|------|------|------|
|
|
||||||
| `git-manager` | haiku | Git 브랜치/커밋/머지/PR 관리 | 커뮤니티 인기 |
|
|
||||||
| `doc-writer` | haiku | API 문서, README, 기술 가이드 작성 | 커뮤니티 인기 |
|
|
||||||
| `research-agent` | sonnet | 웹 리서치 및 자료 조사 | 기존 |
|
|
||||||
| `organizer-agent` | - | 프로젝트 구조화 및 정리 | 기존 |
|
|
||||||
| `proposal-agent` | - | 제안서 작성 | 기존 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 사용 가능한 Skills
|
|
||||||
|
|
||||||
`~/.claude/skills/` 폴더에 있는 스킬들 (슬래시 명령어로 사용):
|
|
||||||
|
|
||||||
### 문서/프레젠테이션
|
|
||||||
|
|
||||||
| Skill | 설명 |
|
|
||||||
|-------|------|
|
|
||||||
| `pptx-skill` | PowerPoint 생성 |
|
|
||||||
| `ppt-auto-generator` | 마크다운/텍스트에서 PPT 생성 |
|
|
||||||
| `pdf-template-skill` | PDF 템플릿 분석/생성 |
|
|
||||||
| `text-analyzer-skill` | 텍스트 분석 및 PDF 구조 매핑 |
|
|
||||||
| `proposal-skill` | 제안서 생성 |
|
|
||||||
| `storyboard-generator` | 스토리보드 생성 |
|
|
||||||
| `design-skill` | 프레젠테이션 HTML 디자인 |
|
|
||||||
|
|
||||||
### 코드 분석/시각화
|
|
||||||
|
|
||||||
| Skill | 설명 |
|
|
||||||
|-------|------|
|
|
||||||
| `code-flow-web-report` | 웹 앱 런타임 흐름 시각화 리포트 |
|
|
||||||
| `code-flow-web-doc-generator` | 소스 코드 호출/데이터 흐름 다이어그램 HTML 생성 |
|
|
||||||
| `codebase-analysis-web-report` | 코드베이스 아키텍처 인터랙티브 HTML 리포트 |
|
|
||||||
| `uml-generator` | UML 다이어그램 생성 |
|
|
||||||
|
|
||||||
### 코드 품질 (levnikolaevich/claude-code-skills)
|
|
||||||
|
|
||||||
| Skill | 설명 | 출처 |
|
|
||||||
|-------|------|------|
|
|
||||||
| `code-bug-finder` | 버그 자동 탐지 및 보고서 생성 | 기존 |
|
|
||||||
| `code-refactoring` | 리팩토링 권장사항/성능 분석/코드 패치 | 기존 |
|
|
||||||
| `code-commenter` | 소스 코드에 이해하기 쉬운 주석 추가 | 기존 |
|
|
||||||
| `async-await-keyword-fixer` | JS/TS 누락된 async/await 수정 | 기존 |
|
|
||||||
| `code-quality-checker` | DRY/KISS/YAGNI 위반 탐지 | levnikolaevich |
|
|
||||||
| `code-quality-auditor` | 코드 복잡도, 매직넘버 분석 | levnikolaevich |
|
|
||||||
| `code-principles-auditor` | DRY/KISS/YAGNI, TODO, DI 패턴 검사 | levnikolaevich |
|
|
||||||
| `dead-code-auditor` | 미사용 코드 탐지 | levnikolaevich |
|
|
||||||
| `build-auditor` | 컴파일러/타입 에러 검사 | levnikolaevich |
|
|
||||||
| `concurrency-auditor` | 레이스 컨디션 탐지 | levnikolaevich |
|
|
||||||
| `layer-boundary-auditor` | 레이어 위반, I/O 격리 검사 | levnikolaevich |
|
|
||||||
| `observability-auditor` | 로깅, 메트릭 적절성 검사 | levnikolaevich |
|
|
||||||
| `query-efficiency-auditor` | DB 쿼리 효율성 분석 | levnikolaevich |
|
|
||||||
| `dependencies-auditor` | 오래된 패키지, CVE 취약점 검사 | levnikolaevich |
|
|
||||||
| `regression-checker` | 기존 테스트 실행으로 사이드이펙트 탐지 | levnikolaevich |
|
|
||||||
| `story-quality-gate` | 코드리뷰 + 테스트 2단계 품질 검증 | levnikolaevich |
|
|
||||||
|
|
||||||
### 테스트/커버리지
|
|
||||||
|
|
||||||
| Skill | 설명 | 출처 |
|
|
||||||
|-------|------|------|
|
|
||||||
| `app-comprehensive-test-generator` | 테스트 시나리오 생성/실행, QA 리포트 | 기존 |
|
|
||||||
| `coverage-improvement-planner` | 테스트 커버리지 분석 및 개선 계획 | 기존 |
|
|
||||||
| `test-coverage-auditor` | 테스트 커버리지 측정/분석 | levnikolaevich |
|
|
||||||
| `test-isolation-auditor` | 테스트 독립성/격리 검사 | levnikolaevich |
|
|
||||||
| `webapp-testing` | Playwright 기반 웹 앱 UI 테스트 | anthropics 공식 |
|
|
||||||
|
|
||||||
### 보안 (Trail of Bits)
|
|
||||||
|
|
||||||
| Skill | 설명 | 출처 |
|
|
||||||
|-------|------|------|
|
|
||||||
| `security-auditor` | 시크릿 노출, Injection, XSS 탐지 | levnikolaevich |
|
|
||||||
| `static-analysis` | CodeQL/Semgrep/SARIF 정적 분석 (3개 하위 스킬) | Trail of Bits |
|
|
||||||
| `insecure-defaults` | 위험한 기본 설정, 하드코딩 자격증명 탐지 | Trail of Bits |
|
|
||||||
| `sharp-edges` | 에러 유발 API, 위험한 디자인 패턴 탐지 | Trail of Bits |
|
|
||||||
| `differential-review` | 보안 중심 코드 변경 리뷰 | Trail of Bits |
|
|
||||||
|
|
||||||
### 디버깅/로깅
|
|
||||||
|
|
||||||
| Skill | 설명 |
|
|
||||||
|-------|------|
|
|
||||||
| `system-debug-logger` | 에러/예외 자동 캡처 디버그 로깅 |
|
|
||||||
| `node-debug-logging-middleware` | Node.js Express/Koa 디버깅 로그 미들웨어 |
|
|
||||||
|
|
||||||
### 프론트엔드/UI
|
|
||||||
|
|
||||||
| Skill | 설명 | 출처 |
|
|
||||||
|-------|------|------|
|
|
||||||
| `frontend-design` | 프론트엔드 디자인 품질 향상 (AI slop 방지) | anthropics 공식 |
|
|
||||||
| `flutter-ux-hardening` | Flutter 앱 UI/UX 강화 | 기존 |
|
|
||||||
| `웹문서` | SAM 프로젝트 웹문서 디자인 표준 | 기존 |
|
|
||||||
|
|
||||||
### 유틸리티
|
|
||||||
|
|
||||||
| Skill | 설명 |
|
|
||||||
|-------|------|
|
|
||||||
| `duplicate-file-cleaner` | 중복 이미지/미디어 파일 정리 |
|
|
||||||
| `npm-release-manager` | NPM 패키지 배포 자동화 |
|
|
||||||
|
|
||||||
**사용 방법**: `/skill-name` 형식으로 호출 (예: `/code-quality-checker`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 문서 작성 규칙 (개발팀 협약 - 필수 준수)
|
|
||||||
|
|
||||||
> **경고: 개발자들이 `sam/docs`의 문서 작성 기법을 준용하기로 협약했습니다. 모든 문서 작성 시 반드시 따르세요!**
|
|
||||||
|
|
||||||
### 참조 경로
|
|
||||||
|
|
||||||
- **인덱스**: `/home/aweso/sam/docs/INDEX.md` (전체 문서 목록 및 폴더 구조)
|
|
||||||
- **작업 전 확인**: 작업 유형에 맞는 문서를 `INDEX.md`에서 찾아 먼저 읽고 시작
|
|
||||||
|
|
||||||
### 폴더 선택 기준 (의미 기반 분류)
|
|
||||||
|
|
||||||
| 폴더 | 질문 | 설명 |
|
|
||||||
|------|------|------|
|
|
||||||
| `plans/` | "무슨 작업을 할 것인가?" | 임시 개발 계획 (완료 후 삭제) |
|
|
||||||
| `standards/` | "어떻게 코드를 작성할 것인가?" | 코딩 컨벤션, 스타일 가이드 |
|
|
||||||
| `architecture/` | "왜 이렇게 설계하는가?" | 시스템 설계, 아키텍처 결정 |
|
|
||||||
| `rules/` | "무엇이 유효한 데이터인가?" | 비즈니스 규칙, 검증 규칙 |
|
|
||||||
| `specs/` | "무엇을 구현할 것인가?" | 기술 스펙, DB 스키마 |
|
|
||||||
| `guides/` | "어떻게 구현할 것인가?" | 단계별 구현 매뉴얼 |
|
|
||||||
| `features/` | 기능별 상세 | 기능 단위 심층 문서 |
|
|
||||||
| `changes/` | "무엇이 변경되었는가?" | 완료된 변경 이력 |
|
|
||||||
|
|
||||||
### 파일명 규칙
|
|
||||||
|
|
||||||
- **일반 문서**: `kebab-case.md` (소문자 + 하이픈) 예: `api-rules.md`, `item-policy.md`
|
|
||||||
- **변경 이력**: `YYYYMMDD_short_description.md` 예: `20260109_handover_report_api.md`
|
|
||||||
- **폴더 인덱스**: `README.md` (대문자)
|
|
||||||
- **크기 목표**: 10KB 이하
|
|
||||||
- **새 문서 작성 시**: 반드시 `docs/INDEX.md`에 추가
|
|
||||||
|
|
||||||
### 문서 구조 템플릿
|
|
||||||
|
|
||||||
#### 정책/규칙 문서 (`rules/`, `standards/`)
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# 제목
|
|
||||||
|
|
||||||
> **작성일**: YYYY-MM-DD
|
|
||||||
> **상태**: 설계 확정
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
### 1.1 목적
|
|
||||||
### 1.2 핵심 원칙
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 테이블 구조 (해당 시)
|
|
||||||
### 2.1 ERD 개요
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## N. 비즈니스 규칙
|
|
||||||
### N.1 검증 규칙
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## N. API 엔드포인트
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 관련 문서
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**최종 업데이트**: YYYY-MM-DD
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 변경 이력 문서 (`changes/`)
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# 변경 내용 요약
|
|
||||||
|
|
||||||
**날짜:** YYYY-MM-DD
|
|
||||||
**작업자:** Claude Code
|
|
||||||
|
|
||||||
## 변경 개요
|
|
||||||
|
|
||||||
## 수정된 파일
|
|
||||||
| 파일 | 변경 내용 |
|
|
||||||
|------|----------|
|
|
||||||
|
|
||||||
## 상세 변경 사항
|
|
||||||
|
|
||||||
## 테스트 체크리스트
|
|
||||||
- [x] 완료 항목
|
|
||||||
- [ ] 미완료 항목
|
|
||||||
|
|
||||||
## 관련 문서
|
|
||||||
```
|
|
||||||
|
|
||||||
### 작성 스타일 규칙
|
|
||||||
|
|
||||||
| 항목 | 규칙 |
|
|
||||||
|------|------|
|
|
||||||
| **언어** | 한글 기본, 코드/경로/기술 식별자만 영어 |
|
|
||||||
| **어조** | 서술형 ("X를 해야 한다" 아닌 "X 한다") |
|
|
||||||
| **경고** | `> **경고: ...**` 블록인용 형식 |
|
|
||||||
| **금지/필수** | `❌` 금지, `✅` 필수 접두사 |
|
|
||||||
| **우선순위** | `🔴 필수`, `🟡 중요`, `🟢 권장` |
|
|
||||||
| **섹션 번호** | `## 1.`, `### 1.1` 번호 매기기 |
|
|
||||||
| **규칙 번호** | R1, R2, R3... 순차 라벨 |
|
|
||||||
| **코드 블록** | 반드시 언어 지정 (```php, ```bash, ```json, ```sql) |
|
|
||||||
| **인라인 코드** | 파일 경로, 메서드명, 변수명, 컬럼명에 백틱 |
|
|
||||||
| **다이어그램** | `┌─┐│└─┘` 박스 문자, `→` 화살표 사용 |
|
|
||||||
| **구분선** | `---` 주요 섹션 사이마다 |
|
|
||||||
| **테이블** | API: `| Method | Path | 설명 |`, 필드: `| 필드 | 타입 | 설명 |` |
|
|
||||||
|
|
||||||
### plans/ 워크플로우
|
|
||||||
|
|
||||||
1. 개발 계획 문서를 `plans/`에 작성
|
|
||||||
2. 작업 진행
|
|
||||||
3. 완료 후 결과물을 해당 폴더(`features/`, `changes/` 등)에 정리
|
|
||||||
4. plan 문서 삭제
|
|
||||||
|
|
||||||
### 체크리스트 (문서 작성 시)
|
|
||||||
|
|
||||||
- [ ] 적절한 폴더에 배치 (위 폴더 선택 기준 참고)
|
|
||||||
- [ ] `kebab-case.md` 파일명 사용
|
|
||||||
- [ ] 문서 구조 템플릿 준수
|
|
||||||
- [ ] 한글 기본, 기술 용어만 영어
|
|
||||||
- [ ] 코드 블록에 언어 지정
|
|
||||||
- [ ] `docs/INDEX.md`에 새 문서 등록
|
|
||||||
- [ ] 10KB 이하 크기 유지
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PPT / 프레젠테이션 제작 규칙 (필수 준수)
|
|
||||||
|
|
||||||
> **경고: 모든 프레젠테이션 및 문서 제작 시 반드시 따르세요!**
|
|
||||||
|
|
||||||
### 회사 정보
|
|
||||||
|
|
||||||
| 항목 | 값 |
|
|
||||||
|------|------|
|
|
||||||
| **공식 회사명** | **(주)코드브릿지엑스** |
|
|
||||||
| **서비스명** | **SAM** (Smart Automation Management) |
|
|
||||||
| **푸터 표기 예시** | `SAM 서비스 요금 안내 | (주)코드브릿지엑스` |
|
|
||||||
|
|
||||||
### 금지 사항
|
|
||||||
|
|
||||||
```
|
|
||||||
❌ "주일/경동" — 문서, 슬라이드, 푸터 어디에도 사용 금지
|
|
||||||
❌ "주일", "경동" 단독 사용 금지
|
|
||||||
❌ 내부 제조사(주일/경동) 이름을 외부 문서에 노출 금지
|
|
||||||
```
|
|
||||||
|
|
||||||
> **배경**: 주일/경동은 SAM을 기반으로 만든 내부 제조업체 이름이며, 대외 문서에 노출되어서는 안 된다.
|
|
||||||
> 모든 대외 문서의 회사명은 **(주)코드브릿지엑스**를 사용한다.
|
|
||||||
|
|
||||||
### SAM BI (Brand Identity) 이미지
|
|
||||||
|
|
||||||
**프로젝트 내 경로**: `/home/aweso/sam/docs/assets/bi/`
|
|
||||||
|
|
||||||
| 파일 | 용도 | 배경 |
|
|
||||||
|------|------|------|
|
|
||||||
| `sam_bi_black.png` | 밝은 배경 슬라이드 | 투명 배경, 검정 로고 |
|
|
||||||
| `sam_bi_white.png` | 다크 배경 슬라이드 | 투명 배경, 흰색 로고 |
|
|
||||||
| `sam_bi_blue.png` | 청색 테마 슬라이드 | 투명 배경, 파란 로고 |
|
|
||||||
| `sam_bi_green.png` | 녹색 테마 슬라이드 | 녹색 배경, 흰색 로고 |
|
|
||||||
| `sam_bi_red.png` | 적색/대외비 슬라이드 | 적색 배경, 흰색 로고 |
|
|
||||||
| `sam_bi_orange.png` | 주황 포인트 슬라이드 | 주황 배경, 흰색 로고 |
|
|
||||||
| `sam_bi_purple.png` | 보라 테마 슬라이드 | 보라 배경, 흰색 로고 |
|
|
||||||
|
|
||||||
### PPT 슬라이드 제작 시 적용 규칙
|
|
||||||
|
|
||||||
1. **표지(slide-01)에 BI 로고 필수** — 배경색에 맞는 BI 이미지 사용
|
|
||||||
2. **푸터에 회사명**: `(주)코드브릿지엑스` (주일/경동 절대 금지)
|
|
||||||
3. **BI 로고 + "SAM" 텍스트** 조합 사용 권장
|
|
||||||
4. **배경색별 BI 선택**:
|
|
||||||
- 다크 배경 → `sam_bi_white.png`
|
|
||||||
- 밝은 배경 → `sam_bi_black.png`
|
|
||||||
- 테마 컬러 배경 → 해당 색상 BI (green, blue, red 등)
|
|
||||||
|
|
||||||
### 체크리스트 (PPT 제작 시)
|
|
||||||
|
|
||||||
- [ ] 회사명: (주)코드브릿지엑스 사용
|
|
||||||
- [ ] "주일/경동" 미포함 확인
|
|
||||||
- [ ] 표지에 SAM BI 로고 포함
|
|
||||||
- [ ] 푸터에 (주)코드브릿지엑스 표기
|
|
||||||
- [ ] 배경색에 맞는 BI 색상 선택
|
|
||||||
430
INDEX.md
430
INDEX.md
@@ -1,30 +1,26 @@
|
|||||||
# SAM 프로젝트 문서 인덱스
|
# SAM 프로젝트 문서 인덱스
|
||||||
|
|
||||||
> **Claude Code 작업 전 필수 확인** - 작업 유형에 맞는 문서를 먼저 읽고 시작하세요.
|
> **Claude Code 작업 전 필수 확인** — 작업 유형에 맞는 문서를 먼저 읽고 시작하세요.
|
||||||
|
> **최종 갱신**: 2026-02-27
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 작업별 필수 문서 (반드시 먼저 확인)
|
## 🎯 작업별 필수 문서
|
||||||
|
|
||||||
| 작업 유형 | 필수 문서 | 용도 |
|
| 작업 유형 | 필수 문서 | 용도 |
|
||||||
|----------|----------|------|
|
|----------|----------|------|
|
||||||
| **TODO 확인** | `TODO.md` | 긴급/중요 이슈 및 개선사항 추적 |
|
|
||||||
| **API 개발** | `standards/api-rules.md` | Service-First, FormRequest, i18n 규칙 |
|
| **API 개발** | `standards/api-rules.md` | Service-First, FormRequest, i18n 규칙 |
|
||||||
| **DB 변경** | `specs/database-schema.md` | 테이블 구조, 관계, 컬럼 규칙 |
|
| **DB 변경** | `system/database/README.md` | 테이블 구조, 관계, 컬럼 규칙 |
|
||||||
| **새 기능 구현** | `architecture/system-overview.md` | 전체 아키텍처 이해 |
|
| **새 기능 구현** | `system/overview.md` | 전체 아키텍처 이해 |
|
||||||
| **보안 관련** | `architecture/security-policy.md` | 인증/인가, 보안 규칙 |
|
| **보안 관련** | `system/security-policy.md` | 인증/인가, 보안 규칙 |
|
||||||
| **Git 커밋** | `standards/git-conventions.md` | 커밋 메시지, 브랜치 전략 |
|
| **Git 커밋** | `standards/git-conventions.md` | 커밋 메시지, 브랜치 전략 |
|
||||||
| **품질 검증** | `standards/quality-checklist.md` | 코드 품질 체크리스트 |
|
| **품질 검증** | `standards/quality-checklist.md` | 코드 품질 체크리스트 |
|
||||||
| **Swagger 작성** | `guides/swagger-guide.md` | API 문서 작성 방법 |
|
| **Swagger 작성** | `guides/swagger-guide.md` | API 문서 작성 방법 |
|
||||||
| **품목관리** | `rules/item-policy.md` | 품목 정책 (유형, 예약어, API 규칙) |
|
| **품목관리** | `rules/item-policy.md` | 품목 정책 (유형, 예약어, API 규칙) |
|
||||||
| **게시판** | `specs/board-system-spec.md` | 게시판 시스템 설계 |
|
|
||||||
| **단가관리** | `rules/pricing-policy.md` | 원가/판매가 계산, 리비전 관리 |
|
| **단가관리** | `rules/pricing-policy.md` | 원가/판매가 계산, 리비전 관리 |
|
||||||
| **운영 배포** | `plans/production-deployment-plan.md` | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) |
|
|
||||||
| **서버 동작 원리** | `guides/server-how-it-works.md` | 요청 흐름, 배포 원리 이해 |
|
|
||||||
| **과금정책 (고객용)** | `rules/customer-pricing.md` | 고객 안내용 서비스 요금표 |
|
|
||||||
| **과금정책 (파트너)** | `rules/partner-commission.md` | 영업파트너 수당 체계 및 정산 |
|
|
||||||
| **과금정책 (내부용)** | `rules/billing-policy.md` | 내부용 원가/마진/코드참조 (CONFIDENTIAL) |
|
|
||||||
| **견적관리** | `features/quotes/README.md` | 견적 시스템, BOM 계산, 10단계 로직 |
|
| **견적관리** | `features/quotes/README.md` | 견적 시스템, BOM 계산, 10단계 로직 |
|
||||||
|
| **운영 배포** | `plans/production-deployment-plan.md` | 운영 환경 배포 계획 |
|
||||||
|
| **서버 운영** | `deploys/ops-manual/README.md` | 서버 운영 매뉴얼 |
|
||||||
| **MES 개발** | `projects/mes/README.md` | MES 프로젝트 개요 |
|
| **MES 개발** | `projects/mes/README.md` | MES 프로젝트 개요 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -33,27 +29,67 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
docs/
|
docs/
|
||||||
├── plans/ # 🆕 개발 계획 - 임시 (작업 완료 후 정리 → 삭제)
|
├── system/ # 시스템 현황 — 아키텍처, DB 스키마, 인프라 (architecture/ + specs/ 통합)
|
||||||
├── standards/ # 개발 표준 - "어떻게 코드를 작성할 것인가"
|
├── standards/ # 개발 표준 — "어떻게 코드를 작성할 것인가"
|
||||||
├── architecture/ # 아키텍처 - "왜 이렇게 설계하는가"
|
├── rules/ # 비즈니스 규칙 — "무엇이 유효한 데이터인가"
|
||||||
├── rules/ # 비즈니스 규칙 - "무엇이 유효한 데이터인가"
|
├── features/ # 기능별 상세 — 도메인별 기능 문서
|
||||||
├── specs/ # 기술 스펙 - "무엇을 구현할 것인가"
|
├── guides/ # 구현 가이드 — "어떻게 구현할 것인가"
|
||||||
├── guides/ # 구현 가이드 - "어떻게 구현할 것인가"
|
├── quickstart/ # 빠른 시작 — 핵심 요약, 명령어
|
||||||
├── quickstart/ # 빠른 시작 - 핵심 요약
|
├── plans/ # 작업 추적 — 예정 → 진행 → 완료 → archive/
|
||||||
├── front/ # 프론트엔드 공유 문서
|
├── projects/ # 프로젝트 자료 — 프로젝트성 분석, 설계, 참고
|
||||||
├── features/ # 기능별 상세 문서
|
├── deploys/ # 운영 매뉴얼 — 서버 운영, 배포
|
||||||
├── projects/ # 프로젝트별 문서 (MES, Legacy)
|
├── changes/ # 변경 이력
|
||||||
├── history/ # 히스토리 및 로드맵
|
├── data/ # 데이터 분석
|
||||||
├── contracts/ # 전자계약서 버전 관리
|
├── history/ # 히스토리 기록
|
||||||
├── changes/ # 변경 이력
|
├── api/ # API 통합 문서
|
||||||
└── data/ # 데이터 분석
|
├── requests/ # 요청/기획 문서
|
||||||
|
└── assets/ # BI 등 정적 자산
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📚 폴더별 문서 목록
|
## 📚 폴더별 문서 목록
|
||||||
|
|
||||||
### standards/ - 개발 표준
|
### system/ — 시스템 현황
|
||||||
|
> 아키텍처, DB 스키마, 기술 스펙, 인프라 (기존 architecture/ + specs/ 통합)
|
||||||
|
|
||||||
|
| 문서 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| [overview.md](system/overview.md) | 전체 시스템 아키텍처 (api/react/mng 구조, 기술 스택) |
|
||||||
|
| [api-structure.md](system/api-structure.md) | API 서버 구조 (~1,027 엔드포인트, 18 도메인) |
|
||||||
|
| [react-structure.md](system/react-structure.md) | React 프론트엔드 구조 (249 페이지, 612 컴포넌트) |
|
||||||
|
| [mng-structure.md](system/mng-structure.md) | MNG 관리자 패널 구조 (171 컨트롤러, 436 뷰) |
|
||||||
|
| [docker-setup.md](system/docker-setup.md) | Docker 환경 + CI/CD (7 서비스, Jenkins) |
|
||||||
|
| [database/README.md](system/database/README.md) | DB 스키마 인덱스 (220 모델, 32 도메인, 459 마이그레이션) |
|
||||||
|
|
||||||
|
**DB 도메인별 스키마:**
|
||||||
|
|
||||||
|
| 문서 | 포함 도메인 |
|
||||||
|
|------|-----------|
|
||||||
|
| [database/tenants.md](system/database/tenants.md) | 테넌트, 사용자, 권한 (63 모델) |
|
||||||
|
| [database/products.md](system/database/products.md) | 제품, 품목, 설계 (21 모델) |
|
||||||
|
| [database/sales.md](system/database/sales.md) | 영업, 수주, 견적 (18 모델) |
|
||||||
|
| [database/production.md](system/database/production.md) | 생산, 시공, 자재, 품질 (20 모델) |
|
||||||
|
| [database/finance.md](system/database/finance.md) | 재무, 회계 |
|
||||||
|
| [database/hr.md](system/database/hr.md) | 인사, 면접 |
|
||||||
|
| [database/documents.md](system/database/documents.md) | 문서, 전자서명 (19 모델) |
|
||||||
|
| [database/commons.md](system/database/commons.md) | 공통, 게시판, 감사 (17 모델) |
|
||||||
|
| [database/stats.md](system/database/stats.md) | 통계 (21 모델, sam_stat DB) |
|
||||||
|
|
||||||
|
**이관 완료 (architecture/ + specs/ → system/):**
|
||||||
|
|
||||||
|
| 문서 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| [security-policy.md](system/security-policy.md) | 보안 정책 (다층 방어, Sanctum, RBAC) |
|
||||||
|
| [scaling-roadmap.md](system/scaling-roadmap.md) | 10K 테넌트 스케일링 로드맵 |
|
||||||
|
| [board-system-spec.md](system/board-system-spec.md) | 게시판 시스템 설계 스펙 |
|
||||||
|
| [item-master-integration.md](system/item-master-integration.md) | 품목 마스터 통합 설계 |
|
||||||
|
| [remote-work-setup.md](system/remote-work-setup.md) | 원격 개발 설정 (DEPRECATED) |
|
||||||
|
| [erp-analysis/](system/erp-analysis/) | ERP 스토리보드 분석 (9개 파일) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### standards/ — 개발 표준
|
||||||
> 코딩 컨벤션, 스타일 가이드, 품질 기준
|
> 코딩 컨벤션, 스타일 가이드, 품질 기준
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
| 문서 | 설명 | 필수 확인 시점 |
|
||||||
@@ -61,40 +97,54 @@ docs/
|
|||||||
| [api-rules.md](standards/api-rules.md) | API 개발 규칙 (Service-First, FormRequest, i18n) | API 개발 전 |
|
| [api-rules.md](standards/api-rules.md) | API 개발 규칙 (Service-First, FormRequest, i18n) | API 개발 전 |
|
||||||
| [git-conventions.md](standards/git-conventions.md) | Git 커밋 메시지, 브랜치 전략 | 커밋 전 |
|
| [git-conventions.md](standards/git-conventions.md) | Git 커밋 메시지, 브랜치 전략 | 커밋 전 |
|
||||||
| [quality-checklist.md](standards/quality-checklist.md) | 코드 품질 체크리스트 | PR 전 |
|
| [quality-checklist.md](standards/quality-checklist.md) | 코드 품질 체크리스트 | PR 전 |
|
||||||
|
| [pagination-policy.md](standards/pagination-policy.md) | 페이지네이션 표준 | 목록 API 구현 시 |
|
||||||
|
|
||||||
### architecture/ - 아키텍처 & 설계 원칙
|
---
|
||||||
> 시스템 설계, 보안 정책, 아키텍처 결정
|
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
### rules/ — 비즈니스 규칙
|
||||||
|------|------|--------------|
|
> 도메인 로직, 검증 규칙, 정책
|
||||||
| [system-overview.md](architecture/system-overview.md) | 전체 시스템 아키텍처 | 새 기능 설계 전 |
|
|
||||||
| [security-policy.md](architecture/security-policy.md) | 인증/인가, 보안 규칙 | 보안 관련 작업 전 |
|
|
||||||
| [scaling-roadmap-10k-tenants.md](architecture/scaling-roadmap-10k-tenants.md) | 10,000 테넌트 스케일링 로드맵 | 확장 전략 검토 시 |
|
|
||||||
|
|
||||||
### rules/ - 비즈니스 규칙
|
|
||||||
> 도메인 로직, 검증 규칙, 상태 전이
|
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
| 문서 | 설명 | 필수 확인 시점 |
|
||||||
|------|------|--------------|
|
|------|------|--------------|
|
||||||
| [README.md](rules/README.md) | 비즈니스 규칙 개요 | 도메인 로직 구현 전 |
|
| [README.md](rules/README.md) | 비즈니스 규칙 개요 | 도메인 로직 구현 전 |
|
||||||
| [item-policy.md](rules/item-policy.md) | 품목 정책 (유형 체계, 예약어, API 규칙) | 품목 관련 작업 전 |
|
| [item-policy.md](rules/item-policy.md) | 품목 정책 (유형, 예약어, API 규칙) | 품목 관련 작업 전 |
|
||||||
| [pricing-policy.md](rules/pricing-policy.md) | 단가 정책 (원가/판매가 계산, 리비전 관리) | 단가 관련 작업 전 |
|
| [pricing-policy.md](rules/pricing-policy.md) | 단가 정책 (원가/판매가, 리비전) | 단가 관련 작업 전 |
|
||||||
| [customer-pricing.md](rules/customer-pricing.md) | 고객 안내용 서비스 요금표 | 고객 요금 안내 시 |
|
| [customer-pricing.md](rules/customer-pricing.md) | 고객 안내용 서비스 요금표 | 고객 요금 안내 시 |
|
||||||
| [partner-commission.md](rules/partner-commission.md) | 영업파트너 수당 체계 및 정산 | 수당/정산 관련 작업 전 |
|
| [partner-commission.md](rules/partner-commission.md) | 영업파트너 수당 체계 및 정산 | 수당/정산 관련 작업 전 |
|
||||||
| [billing-policy.md](rules/billing-policy.md) | 내부용 원가/마진/코드참조 (CONFIDENTIAL) | 과금 코드 개발 전 |
|
| [billing-policy.md](rules/billing-policy.md) | 내부용 원가/마진/코드참조 (CONFIDENTIAL) | 과금 코드 개발 전 |
|
||||||
|
| [client-policy.md](rules/client-policy.md) | 고객사 관리 정책 | 고객 관련 작업 전 |
|
||||||
|
| [attendance-api.md](rules/attendance-api.md) | 근태 API 규칙 | 근태 관련 작업 전 |
|
||||||
|
| [department-tree-api.md](rules/department-tree-api.md) | 부서 트리 API 규칙 | 부서 관련 작업 전 |
|
||||||
|
| [employee-api.md](rules/employee-api.md) | 직원 API 규칙 | 직원 관련 작업 전 |
|
||||||
|
| [numbering-rules.md](rules/numbering-rules.md) | 채번규칙 (패턴 기반 자동 번호 생성) | 채번 로직 수정 전 |
|
||||||
|
|
||||||
### specs/ - 기술 스펙
|
---
|
||||||
> 구현 명세, DB 스키마, 시스템 설정
|
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
### features/ — 기능별 문서
|
||||||
|------|------|--------------|
|
> 도메인별 기능 상세 (기능 설명 + 엔드포인트 경로 + Swagger 참조)
|
||||||
| [database-schema.md](specs/database-schema.md) | DB 구조 및 관계도 | DB 변경 전 |
|
|
||||||
| [board-system-spec.md](specs/board-system-spec.md) | 게시판 시스템 설계 | 게시판 작업 전 |
|
|
||||||
| [item-master-integration.md](specs/item-master-integration.md) | 품목관리 연동 설계 | 품목 연동 구현 시 |
|
|
||||||
| [docker-setup.md](specs/docker-setup.md) | Docker 환경 구성 | 환경 설정 시 |
|
|
||||||
| [remote-work-setup.md](specs/remote-work-setup.md) | 원격 개발 설정 | 원격 작업 시 |
|
|
||||||
|
|
||||||
### guides/ - 구현 가이드
|
| 문서 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| [quotes/README.md](features/quotes/README.md) | 견적 시스템 (BOM 계산, 10단계 로직) |
|
||||||
|
| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 |
|
||||||
|
| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 |
|
||||||
|
| [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 |
|
||||||
|
| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) |
|
||||||
|
| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 + 세금계산서 연동 |
|
||||||
|
| ~~business-card-request.md~~ | 명함신청 관리 (DB 마이그레이션만 존재, 문서 미작성) |
|
||||||
|
| [sales/README.md](features/sales/README.md) | 영업 관리 (면접 시나리오 포함) |
|
||||||
|
| [crm/README.md](features/crm/README.md) | CRM (거래처, 미수금, 미지급금) |
|
||||||
|
| [finance/README.md](features/finance/README.md) | 재무 관리 (14개 하위 문서) |
|
||||||
|
| [card-vehicle/README.md](features/card-vehicle/README.md) | 법인카드·차량 관리 |
|
||||||
|
| [settlement/README.md](features/settlement/README.md) | 정산 관리 |
|
||||||
|
| [esign/README.md](features/esign/README.md) | 전자서명 (계약·OTP·PDF 합성) |
|
||||||
|
| [documents/README.md](features/documents/README.md) | 문서관리 (EAV 기반 서식·결재) |
|
||||||
|
| [ai/README.md](features/ai/README.md) | AI 분석 리포트 (Gemini 연동) |
|
||||||
|
| [equipment/README.md](features/equipment/README.md) | 설비관리 (MNG 전용) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### guides/ — 구현 가이드
|
||||||
> 특정 기능 구현을 위한 단계별 매뉴얼
|
> 특정 기능 구현을 위한 단계별 매뉴얼
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
| 문서 | 설명 | 필수 확인 시점 |
|
||||||
@@ -103,180 +153,184 @@ docs/
|
|||||||
| [file-storage-guide.md](guides/file-storage-guide.md) | 파일 업로드/다운로드 구현 | 파일 기능 구현 전 |
|
| [file-storage-guide.md](guides/file-storage-guide.md) | 파일 업로드/다운로드 구현 | 파일 기능 구현 전 |
|
||||||
| [item-management-migration.md](guides/item-management-migration.md) | Item 시스템 전환 가이드 | 마이그레이션 작업 전 |
|
| [item-management-migration.md](guides/item-management-migration.md) | Item 시스템 전환 가이드 | 마이그레이션 작업 전 |
|
||||||
| [project-launch-roadmap.md](guides/project-launch-roadmap.md) | 런칭 준비 현황 | 런칭 관련 작업 시 |
|
| [project-launch-roadmap.md](guides/project-launch-roadmap.md) | 런칭 준비 현황 | 런칭 관련 작업 시 |
|
||||||
| [production-env-sync.md](guides/production-env-sync.md) | 운영 전환 시 .env 동기화 절차 | 테스트→운영 전환 시 |
|
| [production-env-sync.md](guides/production-env-sync.md) | 운영 전환 시 .env 동기화 | 테스트→운영 전환 시 |
|
||||||
| [server-how-it-works.md](guides/server-how-it-works.md) | 서버 인프라 시리즈 ① 서버 동작 원리 | 신규 합류 시 |
|
| [server-how-it-works.md](guides/server-how-it-works.md) | 서버 동작 원리 | 신규 합류 시 |
|
||||||
| [nginx-fastcgi-guide.md](guides/nginx-fastcgi-guide.md) | 서버 인프라 시리즈 ② Nginx & FastCGI | Nginx/FastCGI 개념 이해 시 |
|
| [nginx-fastcgi-guide.md](guides/nginx-fastcgi-guide.md) | Nginx & FastCGI 가이드 | 서버 이해 시 |
|
||||||
| [php-fpm-guide.md](guides/php-fpm-guide.md) | 서버 인프라 시리즈 ③ PHP-FPM | PHP-FPM 개념 이해 시 |
|
| [php-fpm-guide.md](guides/php-fpm-guide.md) | PHP-FPM 가이드 | 서버 이해 시 |
|
||||||
| [jenkins-setup-guide.md](guides/jenkins-setup-guide.md) | Jenkins CI/CD 셋업 가이드 | Jenkins 설치/설정 시 |
|
| [jenkins-setup-guide.md](guides/jenkins-setup-guide.md) | Jenkins CI/CD 셋업 | Jenkins 설치/설정 시 |
|
||||||
|
| [auto-login-guide.md](guides/auto-login-guide.md) | MNG→DEV 자동 로그인 | 자동 로그인 구현 시 |
|
||||||
|
| [erp-api-list.md](guides/erp-api-list.md) | ERP API 목록 (List vs Detail 구분) | 프론트 API 연동 시 |
|
||||||
|
| [erp-api-detail.md](guides/erp-api-detail.md) | ERP API 상세 스펙 | 프론트 API 연동 시 |
|
||||||
|
| [item-master-guide.md](guides/item-master-guide.md) | 품목기준관리 페이지-섹션-필드 구조 | 품목 UI 구현 시 |
|
||||||
|
| [item-master-items-api.md](guides/item-master-items-api.md) | ItemMaster & Items API 문서 | 품목 API 연동 시 |
|
||||||
|
|
||||||
### quickstart/ - 빠른 시작
|
---
|
||||||
|
|
||||||
|
### quickstart/ — 빠른 시작
|
||||||
> 핵심 규칙 요약, 자주 쓰는 명령어
|
> 핵심 규칙 요약, 자주 쓰는 명령어
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
|
||||||
|------|------|--------------|
|
|
||||||
| [quick-start.md](quickstart/quick-start.md) | 프로젝트 핵심 규칙 요약 | 세션 시작 시 |
|
|
||||||
| [dev-commands.md](quickstart/dev-commands.md) | 일상 개발 명령어 모음 | 명령어 확인 시 |
|
|
||||||
|
|
||||||
### front/ - 프론트엔드 공유 문서
|
|
||||||
> API 연동 가이드, 프론트엔드 스펙
|
|
||||||
|
|
||||||
| 문서 | 설명 |
|
| 문서 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [item-master-guide.md](front/item-master-guide.md) | 품목기준관리 페이지-섹션-필드 구조 |
|
| [quick-start.md](quickstart/quick-start.md) | 프로젝트 핵심 규칙 요약 |
|
||||||
|
| [dev-commands.md](quickstart/dev-commands.md) | 일상 개발 명령어 모음 |
|
||||||
|
|
||||||
> 날짜별 API 요청 문서는 `history/2025-11/front-requests/`로 이동됨
|
---
|
||||||
|
|
||||||
### data/ - 데이터 분석
|
### plans/ — 작업 추적
|
||||||
> 시스템 분석, 데이터 모델링
|
> 예정 → 진행 → 완료 → archive/ (이미 정리 완료, 현행 유지)
|
||||||
|
|
||||||
|
| 문서 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| [index_plans.md](plans/index_plans.md) | 계획 인덱스 (ACTIVE + PLANNED) |
|
||||||
|
| [GUIDE.md](plans/GUIDE.md) | 계획 문서 작성 가이드 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### projects/ — 프로젝트 자료
|
||||||
|
> 프로젝트성 분석, 설계, 참고 자료 (지속 보관)
|
||||||
|
|
||||||
|
| 프로젝트 | 문서 | 설명 |
|
||||||
|
|---------|------|------|
|
||||||
|
| [index_projects.md](projects/index_projects.md) | 프로젝트 인덱스 | |
|
||||||
|
| **MES** | [README.md](projects/mes/README.md) | MES 프로젝트 개요 |
|
||||||
|
| **MES** | [MES_PROJECT_ROADMAP.md](projects/mes/MES_PROJECT_ROADMAP.md) | 개발 로드맵 |
|
||||||
|
| **5130 이관** | [MASTER_PLAN.md](projects/5130-migration/MASTER_PLAN.md) | 레거시 이관 마스터 플랜 |
|
||||||
|
| **API 연동** | [MASTER_PLAN.md](projects/api-integration/MASTER_PLAN.md) | React↔API 연동 |
|
||||||
|
| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 |
|
||||||
|
| **견적** | [quotation/](projects/quotation/) | 견적 프로젝트 자료 |
|
||||||
|
| **전자서명** | [e-sign/](projects/e-sign/) | 전자서명 프로젝트 자료 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### deploys/ — 운영 매뉴얼
|
||||||
|
> 서버 운영, 배포 (현행 유지)
|
||||||
|
|
||||||
|
| 문서 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| [ops-manual/README.md](deploys/ops-manual/README.md) | 서버 운영 매뉴얼 (11부 구성) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### changes/ — 변경 이력
|
||||||
|
> 파일명 형식: `YYYYMMDD_description.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### data/ — 데이터 분석
|
||||||
|
|
||||||
| 문서 | 설명 |
|
| 문서 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [analysis/item-db-analysis.md](data/analysis/item-db-analysis.md) | Item DB/API 분석 최종본 |
|
| [analysis/item-db-analysis.md](data/analysis/item-db-analysis.md) | Item DB/API 분석 최종본 |
|
||||||
|
| [analysis/bom-item-mapping-analysis.md](data/analysis/bom-item-mapping-analysis.md) | BOM-품목 매핑 분석 |
|
||||||
### contracts/ - 전자계약서 버전 관리
|
|
||||||
> DOCX 배포본 + Markdown 추적본 + 자동화 스크립트
|
|
||||||
|
|
||||||
| 문서 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| [CHANGELOG.md](contracts/CHANGELOG.md) | 전체 개정이력 |
|
|
||||||
| [revisions.json](contracts/revisions.json) | 개정 데이터 |
|
|
||||||
| [docx/](contracts/docx/) | DOCX 배포본 (전자서명용 4종, 바로 사용 가능) |
|
|
||||||
| [markdown/](contracts/markdown/) | Markdown 추적본 (Git diff용 4종) |
|
|
||||||
| [scripts/extract_to_markdown.py](contracts/scripts/extract_to_markdown.py) | DOCX → Markdown 추출 |
|
|
||||||
| [scripts/sync_check.py](contracts/scripts/sync_check.py) | DOCX ↔ Markdown 동기화 검증 |
|
|
||||||
|
|
||||||
### plans/ - 개발 계획
|
|
||||||
> 임시 개발 계획 문서 (작업 완료 후 정리 → 삭제)
|
|
||||||
|
|
||||||
| 문서 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| [SAM_ERP_Storyboard_D1.4_260116.md](plans/SAM_ERP_Storyboard_D1.4_260116.md) | ERP 전체 스토리보드 D1.4 (167p PDF → 마크다운 변환, 14개 섹션 146개 화면) |
|
|
||||||
| [SAM_ERP_Storyboard_D1.4.md](plans/SAM_ERP_Storyboard_D1.4.md) | ERP 스토리보드 D1.4 AI 최적화 버전 (구조화된 한글 마크다운, 15개 섹션) |
|
|
||||||
| [SAM_ERP_회계관리_Storyboard_D1.6.md](plans/SAM_ERP_회계관리_Storyboard_D1.6.md) | ERP 회계관리 스토리보드 D1.6 (65p PDF → 마크다운 변환) |
|
|
||||||
| [SAM_General_Rule_Storyboard_D1.0.md](plans/SAM_General_Rule_Storyboard_D1.0.md) | General Rule 스토리보드 D1.0 (43p PDF → 마크다운 변환, UIUX 공통 규칙) |
|
|
||||||
| [production-deployment-plan.md](plans/production-deployment-plan.md) | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) |
|
|
||||||
| **[integrated-master-plan.md](plans/integrated-master-plan.md)** | **통합 개선 계획 — 제품코드 추적성 + 검사 단위 구조 (마스터)** |
|
|
||||||
| [integrated-phase-0-1.md](plans/integrated-phase-0-1.md) | 통합 Phase 0-1: 사전 조사 + product_code 전파 수정 |
|
|
||||||
| [integrated-phase-2.md](plans/integrated-phase-2.md) | 통합 Phase 2: 절곡 검사 분석/설계 + 견적/품질 개선 |
|
|
||||||
| [integrated-phase-3.md](plans/integrated-phase-3.md) | 통합 Phase 3: 절곡 검사 동적 구현 |
|
|
||||||
| [integrated-test-scenarios.md](plans/integrated-test-scenarios.md) | 통합 계획 기능 단위 테스트 시나리오 (11개 FU) |
|
|
||||||
| [product-code-traceability-plan.md](plans/product-code-traceability-plan.md) | 제품코드 추적성 계획 (아카이브 — 통합 계획 참조) |
|
|
||||||
| [document-system-improvement-plan.md](plans/document-system-improvement-plan.md) | 검사 단위 구조 정비 계획 (아카이브 — 통합 계획 참조) |
|
|
||||||
|
|
||||||
### features/ - 기능별 문서
|
|
||||||
|
|
||||||
| 문서 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 |
|
|
||||||
| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 |
|
|
||||||
| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 |
|
|
||||||
| [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 (화면/데이터/비즈니스규칙/API) |
|
|
||||||
| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) |
|
|
||||||
| [quotes/README.md](features/quotes/README.md) | 견적 시스템 분석 (BOM 계산, 10단계 로직) |
|
|
||||||
| [business-card-request.md](features/business-card-request.md) | 명함신청 관리 (3단계 워크플로우: 요청→제작의뢰→처리완료) |
|
|
||||||
| [academy/fire-shutter-image-prompts.md](features/academy/fire-shutter-image-prompts.md) | 방화셔터 백과사전 이미지 생성 프롬프트 (Gemini용) |
|
|
||||||
|
|
||||||
### projects/ - 프로젝트별 문서
|
|
||||||
|
|
||||||
| 프로젝트 | 문서 | 설명 |
|
|
||||||
|---------|------|------|
|
|
||||||
| **MES** | [README.md](projects/mes/README.md) | MES 프로젝트 개요 |
|
|
||||||
| **MES** | [MES_PROJECT_ROADMAP.md](projects/mes/MES_PROJECT_ROADMAP.md) | 개발 로드맵 |
|
|
||||||
| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 |
|
|
||||||
|
|
||||||
### history/ - 히스토리
|
|
||||||
|
|
||||||
| 기간 | 문서 |
|
|
||||||
|------|------|
|
|
||||||
| **2025-11** | [item-master-gap-analysis.md](history/2025-11/item-master-gap-analysis.md), [item-master-spec.md](history/2025-11/item-master-spec.md), [front-requests/](history/2025-11/front-requests/), [item-master-archived/](history/2025-11/item-master-archived/) |
|
|
||||||
| **2025-09** | [checkpoint.md](history/2025-09/checkpoint.md), [database-schema.md](history/2025-09/database-schema.md) |
|
|
||||||
| **Roadmaps** | [december-2025.md](history/roadmaps/december-2025.md) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🏗️ 서브프로젝트 문서
|
### 서브프로젝트 문서
|
||||||
|
|
||||||
각 서브프로젝트는 독립적인 `docs/` 디렉토리를 가집니다.
|
각 서브프로젝트는 독립적인 `docs/` 디렉토리를 가집니다.
|
||||||
|
|
||||||
| 프로젝트 | 문서 경로 | 설명 |
|
| 프로젝트 | 문서 경로 | 설명 |
|
||||||
|---------|----------|------|
|
|---------|----------|------|
|
||||||
| **API** | [api/docs/INDEX.md](../api/docs/INDEX.md) | REST API 프로젝트 |
|
| **API** | [api/docs/](../api/docs/) | REST API 프로젝트 |
|
||||||
| **MNG** | [mng/docs/INDEX.md](../mng/docs/INDEX.md) | Plain Laravel 관리자 (운영 주력) |
|
| **MNG** | [mng/docs/](../mng/docs/) | Plain Laravel 관리자 |
|
||||||
| **React** | [react/docs/](../react/docs/) | Next.js 프론트엔드 |
|
| **React** | [react/docs/](../react/docs/) | Next.js 프론트엔드 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📝 문서 작성 가이드
|
## 📝 문서 작성 규칙
|
||||||
|
|
||||||
### 새 문서 작성 시
|
|
||||||
1. **적절한 폴더 선택**: 위 폴더 구조 참고
|
|
||||||
2. **파일명**: 소문자 + 하이픈 (kebab-case)
|
|
||||||
3. **크기 목표**: 10KB 이하
|
|
||||||
4. **INDEX 업데이트**: 새 문서는 반드시 이 파일에 추가
|
|
||||||
|
|
||||||
### 폴더 선택 기준
|
### 폴더 선택 기준
|
||||||
- **"개발 계획/작업 예정"** → `plans/` (임시, 완료 후 삭제)
|
|
||||||
- **"어떻게 코드 작성?"** → `standards/`
|
|
||||||
- **"왜 이렇게 설계?"** → `architecture/`
|
|
||||||
- **"무엇이 유효한 데이터?"** → `rules/`
|
|
||||||
- **"무엇을 구현?"** → `specs/`
|
|
||||||
- **"어떻게 구현?"** → `guides/`
|
|
||||||
|
|
||||||
### plans/ 워크플로우
|
| 질문 | 폴더 |
|
||||||
1. 개발 계획 문서를 `plans/`에 작성
|
|------|------|
|
||||||
2. 작업 진행
|
| "시스템이 현재 어떤 상태인가?" | `system/` |
|
||||||
3. 완료 후 결과물을 해당 프로젝트 docs에 정리
|
| "어떻게 코드를 작성할 것인가?" | `standards/` |
|
||||||
4. plan 문서 삭제
|
| "무엇이 유효한 데이터인가?" | `rules/` |
|
||||||
|
| "이 기능은 어떻게 동작하는가?" | `features/` |
|
||||||
|
| "어떻게 구현할 것인가?" | `guides/` |
|
||||||
|
| "무슨 작업을 할 것인가?" | `plans/` |
|
||||||
|
| "프로젝트 자료를 보관하고 싶다" | `projects/` |
|
||||||
|
| "무엇이 변경되었는가?" | `changes/` |
|
||||||
|
|
||||||
### plans/flow-tests/
|
### 파일명 규칙
|
||||||
API Flow Tester에서 생성되는 JSON 파일 저장 경로
|
|
||||||
- 경로: `plans/flow-tests/*.json`
|
| 유형 | 규칙 | 예시 |
|
||||||
- 용도: MNG API Flow Tester 테스트 시나리오
|
|------|------|------|
|
||||||
- 예시: `item-master-page-api-flow.json`, `client-api-flow.json`
|
| 기술 문서 (코드 참조) | 영문 kebab-case | `api-rules.md`, `database-schema.md` |
|
||||||
|
| 업무/비즈니스 문서 | 한글 허용 | `영업파트너가이드북.md`, `수당지급.md` |
|
||||||
|
| 변경 이력 | `YYYYMMDD_description.md` | `20260205_sus_inspection_template.md` |
|
||||||
|
| 폴더 인덱스 | `README.md` (대문자) | `features/finance/README.md` |
|
||||||
|
| **혼용 금지** | 한글+영문 섞지 않음 | ❌ `영업partner가이드.md` |
|
||||||
|
|
||||||
|
### 크기 제한
|
||||||
|
- **목표**: 10KB 이하
|
||||||
|
- 초과 시 도메인별로 분할
|
||||||
|
|
||||||
|
### 문서 구조 템플릿
|
||||||
|
|
||||||
|
#### 정책/규칙 문서 (`rules/`, `standards/`)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# 제목
|
||||||
|
|
||||||
|
> **작성일**: YYYY-MM-DD
|
||||||
|
> **상태**: 설계 확정
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔄 문서 구조 변경 이력
|
## 1. 개요
|
||||||
|
## 2. 핵심 원칙
|
||||||
|
## 3. 상세 규칙
|
||||||
|
## 4. API 엔드포인트 (해당 시)
|
||||||
|
## 관련 문서
|
||||||
|
|
||||||
- **2026-01-28**: API 라우터 분리 및 버전 폴백 시스템 구현
|
---
|
||||||
- `routes/api.php` → 13개 도메인별 파일로 분리 (1,479줄 → 61줄)
|
|
||||||
- `ApiVersionMiddleware` 추가 (헤더/쿼리 기반 버전 선택, v2→v1 폴백)
|
|
||||||
- `standards/api-rules.md` 라우팅 섹션 업데이트
|
|
||||||
- `architecture/system-overview.md` 라우팅 구조 업데이트
|
|
||||||
|
|
||||||
- **2025-12-09**: 품목 정책 통합 문서 생성
|
**최종 업데이트**: YYYY-MM-DD
|
||||||
- `rules/item-policy.md` 생성 (4개 문서 통합)
|
```
|
||||||
- 삭제: `specs/ITEM-MASTER-INDEX.md`, `specs/item-master-field-key-validation.md`, `specs/item-master-field-integration.md`, `plans/items-api-unified-plan.md`
|
|
||||||
- 품목 관련 정책을 rules/ 디렉토리로 이동
|
|
||||||
|
|
||||||
- **2025-12-09**: Item Master 문서 정리 및 인덱스 생성
|
#### 변경 이력 문서 (`changes/`)
|
||||||
- `specs/ITEM-MASTER-INDEX.md` 생성 (개발 현황/필요 항목 정리)
|
|
||||||
- `history/2025-11/item-master-archived/` 생성 (구버전 문서 아카이브)
|
|
||||||
- 중복 문서 정리 (front-requests → history 이동)
|
|
||||||
|
|
||||||
- **2025-12-09**: 문서 정리 및 통합
|
```markdown
|
||||||
- 중복 분석 문서 삭제 (v2, DB_Modeling)
|
# 변경 내용 요약
|
||||||
- `SAM_Item_DB_API_Analysis_v3_FINAL.md` → `item-db-analysis.md` 리네임
|
|
||||||
- `ITEM_MASTER_FIELD_INTEGRATION_PLAN.md` → `item-master-field-integration.md` 리네임
|
|
||||||
- `HR_API_ANALYSIS.md` → `features/hr/hr-api-analysis.md` 이동
|
|
||||||
- 날짜 접두사 front 문서 → `history/2025-11/front-requests/` 이동
|
|
||||||
- api/docs에서 프로젝트 문서 분리 (swagger, api-flows만 유지)
|
|
||||||
|
|
||||||
- **2025-12-09**: api/docs 문서 통합
|
**날짜:** YYYY-MM-DD
|
||||||
- `api/docs/analysis/` → `docs/data/analysis/` 이동
|
|
||||||
- `api/docs/front/` → `docs/front/` 병합
|
|
||||||
- `api/docs/specs/` → `docs/specs/` 병합
|
|
||||||
- api/docs에는 API 구성/설정 문서만 유지 (swagger, api-flows)
|
|
||||||
|
|
||||||
- **2025-12-09**: `plans/` 폴더 추가
|
## 변경 개요
|
||||||
- 개발 계획 문서용 임시 폴더
|
## 수정된 파일
|
||||||
- 작업 완료 후 정리 → 삭제 워크플로우
|
## 상세 변경 사항
|
||||||
|
## 테스트 체크리스트
|
||||||
|
```
|
||||||
|
|
||||||
- **2025-12-05**: 폴더 구조 대폭 재정리
|
### 작성 스타일
|
||||||
- `reference/` → `standards/`, `architecture/`, `quickstart/`로 분리
|
|
||||||
- `principles/` → `architecture/`로 통합
|
|
||||||
- 작업별 필수 문서 가이드 추가
|
|
||||||
|
|
||||||
- **2025-11-20**: 문서 구조 대규모 재정리
|
| 항목 | 규칙 |
|
||||||
- claudedocs → docs/ 체계화
|
|------|------|
|
||||||
- 각 서브프로젝트별 docs/ 디렉토리 생성
|
| **언어** | 한글 기본, 코드/경로/기술 식별자만 영어 |
|
||||||
|
| **어조** | 서술형 ("X 한다") |
|
||||||
|
| **경고** | `> **경고: ...**` 블록인용 |
|
||||||
|
| **금지/필수** | `❌` 금지, `✅` 필수 |
|
||||||
|
| **우선순위** | `🔴 필수`, `🟡 중요`, `🟢 권장` |
|
||||||
|
| **코드 블록** | 반드시 언어 지정 (```php, ```bash 등) |
|
||||||
|
| **인라인 코드** | 파일 경로, 메서드명, 변수명에 백틱 |
|
||||||
|
| **구분선** | `---` 주요 섹션 사이 |
|
||||||
|
|
||||||
|
### 새 문서 작성 시 체크리스트
|
||||||
|
- [ ] 적절한 폴더에 배치
|
||||||
|
- [ ] 파일명 규칙 준수
|
||||||
|
- [ ] 문서 구조 템플릿 준수
|
||||||
|
- [ ] 이 INDEX.md에 등록
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 문서 정비 진행 현황
|
||||||
|
|
||||||
|
> 참조: [docs-comprehensive-update-plan.md](plans/docs-comprehensive-update-plan.md)
|
||||||
|
|
||||||
|
| Phase | 작업 | 상태 |
|
||||||
|
|-------|------|------|
|
||||||
|
| **Phase 0** | 문서 정책 재정립 | ✅ 완료 |
|
||||||
|
| **Phase 1** | 시스템 현황 문서화 (DB, API, React, MNG, Docker) | ✅ 완료 (14개 문서) |
|
||||||
|
| **Phase 2** | 기존 문서 정비 (architecture/+specs/ → system/ 이관) | ⏳ 대기 |
|
||||||
|
| **Phase 3** | 신규 도메인 기능 문서 작성 | ⏳ 대기 |
|
||||||
|
| **Phase 4** | 최종 검증 및 INDEX 갱신 | ⏳ 대기 |
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Architecture (아키텍처 & 설계 원칙)
|
|
||||||
|
|
||||||
> 시스템 설계와 아키텍처 결정의 근간 - **"왜 이렇게 설계하는가"**
|
|
||||||
|
|
||||||
## 목적
|
|
||||||
- 일관된 아키텍처 결정 기준 제공
|
|
||||||
- 기술 부채 방지
|
|
||||||
- 확장성과 유지보수성 확보
|
|
||||||
|
|
||||||
## 문서 목록
|
|
||||||
|
|
||||||
| 문서 | 설명 | 필수 확인 시점 |
|
|
||||||
|------|------|--------------|
|
|
||||||
| [system-overview.md](system-overview.md) | 전체 시스템 아키텍처 | 새 기능 설계 전 |
|
|
||||||
| [security-policy.md](security-policy.md) | 인증/인가, 보안 규칙 | 보안 관련 작업 전 |
|
|
||||||
|
|
||||||
## 관련 폴더
|
|
||||||
- [standards/](../standards/) - 개발 표준 (어떻게 코드를 작성할 것인가)
|
|
||||||
- [rules/](../rules/) - 비즈니스 규칙 (무엇이 유효한 데이터인가)
|
|
||||||
- [specs/](../specs/) - 기술 스펙 (무엇을 구현할 것인가)
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
# SAM 10,000 테넌트 스케일링 로드맵
|
|
||||||
|
|
||||||
> **작성일**: 2026-02-22
|
|
||||||
> **성격**: 가상 시나리오 — 세계 최고 수준 엔지니어링 팀이 설계한다는 가정
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 현재 상태 진단
|
|
||||||
|
|
||||||
### 1.1 현재 아키텍처 요약
|
|
||||||
|
|
||||||
```
|
|
||||||
브라우저 → Nginx → PHP-FPM(20 workers) → Laravel → MySQL 8.0 (단일)
|
|
||||||
서버: 2코어/3.8GB RAM | 배포: 수동 git pull | 모니터링: 없음 | 캐시: 없음
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 핵심 병목 지점
|
|
||||||
|
|
||||||
| 영역 | 현재 | 10,000 테넌트 시 문제 | 심각도 |
|
|
||||||
|------|------|---------------------|--------|
|
|
||||||
| DB | MySQL 단일 | 커넥션 폭발, 슬로우 쿼리 | 치명적 |
|
|
||||||
| 컴퓨팅 | FPM 20워커 | 동시 요청 20개 제한 | 치명적 |
|
|
||||||
| 캐시 | 없음 | 모든 요청이 DB 직행 | 치명적 |
|
|
||||||
| 큐 | DB 드라이버 | 큐 자체가 DB 압박 | 심각 |
|
|
||||||
| 검색 | SQL LIKE | 219개 테이블 풀스캔 | 심각 |
|
|
||||||
| 배포 | 수동 git pull | 다운타임, 롤백 불가 | 높음 |
|
|
||||||
| 모니터링 | 없음 | 장애 인지 불가 | 높음 |
|
|
||||||
|
|
||||||
### 1.3 가장 먼저 죽는 곳
|
|
||||||
|
|
||||||
- 동시 사용자 **20명** → FPM 워커 전부 점유 → 504 Timeout
|
|
||||||
- 동시 사용자 **200명** → MySQL `max_connections`(151) 고갈
|
|
||||||
- 테넌트 **1,000개** → 권한 UNION 3개 쿼리가 매 요청마다 실행
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 5단계 로드맵 개요
|
|
||||||
|
|
||||||
```
|
|
||||||
Phase 1 (0~3개월) 캐시 + 모니터링 + 서버 업그레이드 → 100 테넌트
|
|
||||||
Phase 2 (3~6개월) DB 복제 + K8s + S3 + 검색 엔진 → 1,000 테넌트
|
|
||||||
Phase 3 (6~9개월) 마이크로서비스 + 이벤트 아키텍처 → 3,000 테넌트
|
|
||||||
Phase 4 (9~12개월) DB 샤딩 + 테넌트 티어링 + 멀티리전 → 10,000 테넌트
|
|
||||||
Phase 5 (12~18개월) 관측성 고도화 + 카오스 엔지니어링 → 10,000+ 테넌트
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Phase 1: 기초 체력 (0~3개월) → 100 테넌트
|
|
||||||
|
|
||||||
### 3.1 Redis 도입 (최우선)
|
|
||||||
|
|
||||||
| 대상 | 캐시 TTL | 효과 |
|
|
||||||
|------|---------|------|
|
|
||||||
| 세션 저장소 | 2시간 | DB 세션 테이블 부하 제거 |
|
|
||||||
| 권한 캐시 | 5분 | UNION 3개 쿼리 제거 (매 요청) |
|
|
||||||
| 메뉴 트리 | 10분 | 중첩 쿼리 제거 |
|
|
||||||
| 공통 코드 | 1시간 | `common_codes` 반복 조회 제거 |
|
|
||||||
| Laravel 큐 | - | `database` → `redis` 드라이버 전환 |
|
|
||||||
|
|
||||||
**예상 효과**: DB 쿼리 **60~70% 감소**, 응답 시간 **3~5배 개선**.
|
|
||||||
|
|
||||||
### 3.2 모니터링 구축
|
|
||||||
|
|
||||||
Grafana + Prometheus + Laravel Telescope + MySQL slow_log.
|
|
||||||
|
|
||||||
**핵심 알림**: FPM 워커 사용률 >80%, MySQL 커넥션 >100, 응답 시간 >2초, 큐 적체 >1000건 → Slack 알림.
|
|
||||||
|
|
||||||
### 3.3 서버 업그레이드 + CI/CD
|
|
||||||
|
|
||||||
| 항목 | 현재 | Phase 1 |
|
|
||||||
|------|------|---------|
|
|
||||||
| CPU/RAM | 2코어/3.8GB | 8코어/32GB |
|
|
||||||
| 스토리지 | HDD | NVMe SSD |
|
|
||||||
| FPM | 20 워커 | 100 워커 |
|
|
||||||
| 배포 | 수동 git pull | Jenkins CI/CD (무중단 rolling) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Phase 2: 수평 확장 (3~6개월) → 1,000 테넌트
|
|
||||||
|
|
||||||
### 4.1 아키텍처
|
|
||||||
|
|
||||||
```
|
|
||||||
브라우저 → LB(L7) → App Server ×N → Redis Cluster
|
|
||||||
→ MySQL Primary + Replica ×2
|
|
||||||
→ S3 + CDN (정적/업로드 파일)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 핵심 변경
|
|
||||||
|
|
||||||
| 영역 | 변경 | 효과 |
|
|
||||||
|------|------|------|
|
|
||||||
| **K8s** | HPA 기반 오토스케일링 (API 3~10 pods) | 트래픽에 따라 자동 확장 |
|
|
||||||
| **DB R/W 분리** | `config/database.php`에 read/write 설정 | 읽기 부하 80% Replica로 분산 |
|
|
||||||
| **파일 → S3** | Laravel Filesystem → S3 + CloudFront | 서버 간 파일 공유, CDN 가속 |
|
|
||||||
| **검색 엔진** | SQL LIKE → Meilisearch | 밀리초 응답, 형태소 분석, 오타 허용 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Phase 3: 마이크로서비스 (6~9개월) → 3,000 테넌트
|
|
||||||
|
|
||||||
### 5.1 서비스 분리
|
|
||||||
|
|
||||||
```
|
|
||||||
모놀리스(sam-api) → Auth | Product | Order | MES | Finance | Notification
|
|
||||||
```
|
|
||||||
|
|
||||||
**분리 순서**: ① 알림 (독립적, 비동기) → ② MES (변경 빈도 높음) → ③ 인증 (가용성 최우선)
|
|
||||||
|
|
||||||
### 5.2 이벤트 기반 전환
|
|
||||||
|
|
||||||
동기 호출 체인을 이벤트 발행으로 전환한다. 주문 생성 시 재고 차감/알림/회계를 비동기 처리.
|
|
||||||
|
|
||||||
**메시지 브로커**: Redis Streams 또는 RabbitMQ. 응답 시간 2초 → 200ms.
|
|
||||||
|
|
||||||
### 5.3 API Gateway
|
|
||||||
|
|
||||||
Kong/Traefik으로 테넌트별 Rate Limiting, 인증 검증, 요청 라우팅, 응답 캐싱 통합.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Phase 4: 대규모 멀티테넌시 (9~12개월) → 10,000 테넌트
|
|
||||||
|
|
||||||
### 6.1 DB 샤딩
|
|
||||||
|
|
||||||
```
|
|
||||||
Shard Router (tenant_id 기반) → Shard 0 | Shard 1 | Shard 2 ...
|
|
||||||
각 Shard = Primary + Replica
|
|
||||||
```
|
|
||||||
|
|
||||||
`tenant_id`가 파티션 키이므로 크로스 샤드 조인 불필요 — SAM의 강점.
|
|
||||||
|
|
||||||
### 6.2 테넌트 티어링
|
|
||||||
|
|
||||||
| Tier | 자원 | SLA | Rate Limit |
|
|
||||||
|------|------|-----|-----------|
|
|
||||||
| Enterprise | 전용 DB/Redis/Pod | 99.99% | 1000/분 |
|
|
||||||
| Business | 공유 (높은 우선순위) | 99.9% | 300/분 |
|
|
||||||
| Standard | 공유 | 99.5% | 60/분 |
|
|
||||||
|
|
||||||
### 6.3 멀티리전
|
|
||||||
|
|
||||||
한국(Primary) + 일본/동남아(Secondary) 리전. DB 복제 + Global Load Balancer로 지리적 라우팅.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Phase 5: 엔터프라이즈 성숙 (12~18개월) → 10,000+
|
|
||||||
|
|
||||||
| 영역 | 도입 | 목적 |
|
|
||||||
|------|------|------|
|
|
||||||
| **관측성** | Jaeger(분산추적) + Loki(중앙로그) + PagerDuty | 전체 서비스 체인 추적 |
|
|
||||||
| **카오스 엔지니어링** | DB 다운, Pod Kill, 네트워크 지연 주입 | 복원력 검증 |
|
|
||||||
| **데이터 파이프라인** | CDC(Debezium) → 데이터 웨어하우스 | 운영 DB에서 분석 쿼리 분리 |
|
|
||||||
| **배포** | Blue-Green + Canary (5% → 100%) | 30초 이내 롤백 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. 기술 스택 진화 요약
|
|
||||||
|
|
||||||
| 영역 | 현재 | Phase 1 | Phase 2 | Phase 4 |
|
|
||||||
|------|------|---------|---------|---------|
|
|
||||||
| 서버 | 단일 2코어 | 단일 8코어 | K8s 3+ 노드 | 멀티리전 |
|
|
||||||
| DB | MySQL 단일 | + 쿼리 최적화 | Primary + Replica ×2 | Shard ×N |
|
|
||||||
| 캐시 | 없음 | Redis 단일 | Redis Cluster | 테넌트별 격리 |
|
|
||||||
| 큐 | DB | Redis | Redis | 티어별 큐 |
|
|
||||||
| 배포 | 수동 | Jenkins CI/CD | K8s Rolling | Canary |
|
|
||||||
| 모니터링 | 없음 | Grafana | + Telescope | + 카오스 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. 가장 중요한 3가지
|
|
||||||
|
|
||||||
**1. Redis (=산소)**: 캐시 없이 10,000 테넌트는 **절대 불가능**. 권한 UNION 쿼리 3개 + 메뉴 + 세션이 매 요청마다 실행된다. Redis 하나로 DB 부하 60% 감소.
|
|
||||||
|
|
||||||
**2. DB R/W 분리 (=심장)**: ERP 읽기:쓰기 = 8:2. Replica 2대 추가로 DB 부하 1/3 분산. Laravel `config/database.php` 변경만으로 적용.
|
|
||||||
|
|
||||||
**3. 관측성 (=눈)**: 모니터링 없이 스케일링은 눈 감고 운전하는 것. 슬로우 쿼리 + 응답 시간 + 알림부터 시작.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. SAM 특수 고려사항
|
|
||||||
|
|
||||||
### 10.1 tenant_id 기반 격리
|
|
||||||
|
|
||||||
- **강점**: `BelongsToTenant` 스코프 일관 적용, 크로스 테넌트 조인 불필요 → 샤딩에 유리
|
|
||||||
- **개선 필요**: `tenant_id` 인덱스 첫 번째 컬럼 여부 전수 검사, `deleted_at` 누적 데이터 파티셔닝
|
|
||||||
|
|
||||||
### 10.2 권한 시스템 최적화
|
|
||||||
|
|
||||||
3중 UNION 쿼리가 매 요청 실행된다. 개선: ① Redis 권한 캐시(TTL 5분) → ② 변경 시 해당 사용자 캐시만 무효화 → ③ JWT 클레임에 권한 포함(DB 조회 0회).
|
|
||||||
|
|
||||||
### 10.3 219개 테이블 샤딩 분류
|
|
||||||
|
|
||||||
| 분류 | 예시 | 처리 |
|
|
||||||
|------|------|------|
|
|
||||||
| 테넌트 데이터 | orders, products | 샤딩 대상 |
|
|
||||||
| 시스템 공통 | permissions, common_codes | 공유 DB 유지 |
|
|
||||||
| 감사 로그 | audit_logs | 별도 시계열 DB |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 관련 문서
|
|
||||||
|
|
||||||
| 문서 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| [system-overview.md](system-overview.md) | 현재 시스템 아키텍처 |
|
|
||||||
| [security-policy.md](security-policy.md) | 현재 보안 구조 |
|
|
||||||
| [docker-setup.md](../specs/docker-setup.md) | 현재 Docker 구성 |
|
|
||||||
| [server-how-it-works.md](../guides/server-how-it-works.md) | 서버 동작 원리 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**최종 업데이트**: 2026-02-22
|
|
||||||
@@ -1,784 +0,0 @@
|
|||||||
# SAM API 보안 가이드
|
|
||||||
|
|
||||||
## 개요
|
|
||||||
|
|
||||||
SAM API는 다층 보안 구조를 통해 무단 접근과 악의적 공격으로부터 시스템을 보호합니다.
|
|
||||||
|
|
||||||
**최종 업데이트:** 2025-12-26
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 보안 아키텍처
|
|
||||||
|
|
||||||
### 다층 방어 구조 (Defense in Depth)
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────┐
|
|
||||||
│ Layer 1: Nginx (L7 Application Layer) │
|
|
||||||
│ - 악의적 경로 패턴 차단 │
|
|
||||||
│ - 의심스러운 User-Agent 차단 │
|
|
||||||
│ - Rate Limiting (Nginx 레벨) │
|
|
||||||
└─────────────────────────────────────────────────┘
|
|
||||||
↓
|
|
||||||
┌─────────────────────────────────────────────────┐
|
|
||||||
│ Layer 2: Laravel Rate Limiting │
|
|
||||||
│ - IP 기반 속도 제한 (10회/분) │
|
|
||||||
│ - API Key 없는 요청 차단 │
|
|
||||||
└─────────────────────────────────────────────────┘
|
|
||||||
↓
|
|
||||||
┌─────────────────────────────────────────────────┐
|
|
||||||
│ Layer 3: API Key 검증 (글로벌 미들웨어) │
|
|
||||||
│ - 모든 요청 API Key 필수 │
|
|
||||||
│ - 화이트리스트 라우트 제외 │
|
|
||||||
│ - 보안 로그 자동 기록 │
|
|
||||||
└─────────────────────────────────────────────────┘
|
|
||||||
↓
|
|
||||||
┌─────────────────────────────────────────────────┐
|
|
||||||
│ Layer 4: Sanctum 토큰 인증 │
|
|
||||||
│ - Bearer 토큰 검증 │
|
|
||||||
│ - 사용자 컨텍스트 설정 │
|
|
||||||
│ - 테넌트 격리 │
|
|
||||||
└─────────────────────────────────────────────────┘
|
|
||||||
↓
|
|
||||||
┌─────────────────────────────────────────────────┐
|
|
||||||
│ Layer 5: 권한 검증 (Permission Check) │
|
|
||||||
│ - 메뉴 기반 권한 체크 │
|
|
||||||
│ - Role 기반 접근 제어 │
|
|
||||||
└─────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Layer 1: Nginx 보안
|
|
||||||
|
|
||||||
### 악의적 경로 패턴 차단
|
|
||||||
|
|
||||||
**위치:** `docker/nginx/nginx.conf`
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
# 경로 탐색 공격 차단
|
|
||||||
if ($request_uri ~* "(\.\.\/|\.\.\\|etc\/passwd|\.env|\.git|\.htaccess|\.sql|@fs\/)") {
|
|
||||||
return 403;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**차단 패턴:**
|
|
||||||
- `../`, `..\` - 디렉토리 탐색 공격
|
|
||||||
- `etc/passwd` - 시스템 파일 접근 시도
|
|
||||||
- `.env` - 환경 변수 파일 접근
|
|
||||||
- `.git`, `.htaccess`, `.sql` - 민감한 파일 접근
|
|
||||||
- `@fs/` - Vite 경로 탐색 공격
|
|
||||||
|
|
||||||
**응답:** 403 Forbidden
|
|
||||||
|
|
||||||
### 의심스러운 User-Agent 차단
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
# 보안 스캔 도구 차단
|
|
||||||
if ($http_user_agent ~* "(sqlmap|nikto|nmap|masscan|metasploit|nessus)") {
|
|
||||||
return 403;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**차단 도구:**
|
|
||||||
- sqlmap - SQL 인젝션 스캐너
|
|
||||||
- nikto - 웹 서버 스캐너
|
|
||||||
- nmap - 포트 스캐너
|
|
||||||
- masscan - 대량 포트 스캐너
|
|
||||||
- metasploit - 침투 테스트 프레임워크
|
|
||||||
- nessus - 취약점 스캐너
|
|
||||||
|
|
||||||
**응답:** 403 Forbidden
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Layer 2: Rate Limiting
|
|
||||||
|
|
||||||
### Laravel Rate Limiter
|
|
||||||
|
|
||||||
**위치:** `app/Http/Middleware/ApiRateLimiter.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
// IP 기반 속도 제한
|
|
||||||
$key = 'api-key-attempts:' . $request->ip();
|
|
||||||
|
|
||||||
if ($this->limiter->tooManyAttempts($key, 10)) {
|
|
||||||
return response()->json([
|
|
||||||
'message' => 'Too many attempts. Please try again later.',
|
|
||||||
'retry_after' => $seconds,
|
|
||||||
], 429);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->limiter->hit($key, 60); // 1분 동안 유지
|
|
||||||
```
|
|
||||||
|
|
||||||
**설정:**
|
|
||||||
- **제한:** 10회/분 (IP별)
|
|
||||||
- **대상:** API Key 없는 요청
|
|
||||||
- **유지 시간:** 60초
|
|
||||||
- **응답 코드:** 429 Too Many Requests
|
|
||||||
|
|
||||||
**로그:**
|
|
||||||
```php
|
|
||||||
Log::warning('API Rate Limit Exceeded', [
|
|
||||||
'ip' => $request->ip(),
|
|
||||||
'uri' => $request->getRequestUri(),
|
|
||||||
'retry_after' => $seconds,
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Layer 3: API Key 인증
|
|
||||||
|
|
||||||
### 글로벌 미들웨어
|
|
||||||
|
|
||||||
**위치:** `bootstrap/app.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
$middleware->append(ApiRateLimiter::class); // 1. Rate Limiting
|
|
||||||
$middleware->append(ApiKeyMiddleware::class); // 2. API Key 검증
|
|
||||||
```
|
|
||||||
|
|
||||||
**실행 순서:** Rate Limiting → API Key 검증
|
|
||||||
|
|
||||||
### API Key 검증 로직
|
|
||||||
|
|
||||||
**위치:** `app/Http/Middleware/ApiKeyMiddleware.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
// 1. 화이트리스트 체크
|
|
||||||
$publicRoutes = [
|
|
||||||
'api/v1/login',
|
|
||||||
'api/v1/signup',
|
|
||||||
'api/v1/register',
|
|
||||||
'api/v1/refresh',
|
|
||||||
'api/v1/debug-apikey',
|
|
||||||
'api-docs', // Swagger UI
|
|
||||||
'api-docs/*', // Swagger 하위 경로
|
|
||||||
'docs/api-docs.json', // Swagger JSON
|
|
||||||
'up', // Health check
|
|
||||||
];
|
|
||||||
|
|
||||||
// 2. API Key 검증
|
|
||||||
$apiKey = $request->header('X-API-KEY');
|
|
||||||
$validApiKey = DB::table('api_keys')
|
|
||||||
->where('key', $apiKey)
|
|
||||||
->where('is_active', true)
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
// 3. 보안 로그 기록
|
|
||||||
if (!$validApiKey) {
|
|
||||||
Log::warning('Unauthorized API access attempt', [
|
|
||||||
'ip' => $request->ip(),
|
|
||||||
'uri' => $request->getRequestUri(),
|
|
||||||
'method' => $request->method(),
|
|
||||||
'user_agent' => $request->userAgent(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 화이트리스트 (인증 제외 라우트)
|
|
||||||
|
|
||||||
**공개 엔드포인트:**
|
|
||||||
- `api/v1/login` - 로그인
|
|
||||||
- `api/v1/signup` - 회원가입
|
|
||||||
- `api/v1/register` - 테넌트 등록
|
|
||||||
- `api/v1/refresh` - 토큰 갱신
|
|
||||||
- `api/v1/debug-apikey` - API Key 디버깅
|
|
||||||
- `api-docs/*` - Swagger UI
|
|
||||||
- `docs/api-docs.json` - Swagger JSON
|
|
||||||
- `up` - Health check
|
|
||||||
|
|
||||||
**특징:**
|
|
||||||
- 와일드카드 지원 (`fnmatch()` 사용)
|
|
||||||
- 공개 라우트는 로깅 제외
|
|
||||||
- API Key 검증 스킵
|
|
||||||
|
|
||||||
### 보안 로그
|
|
||||||
|
|
||||||
**로그 레벨:**
|
|
||||||
- **Log::info** - 정상 API 요청
|
|
||||||
- **Log::warning** - 무단 접근 시도
|
|
||||||
|
|
||||||
**로그 내용:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ip": "213.136.76.215",
|
|
||||||
"uri": "/@fs/etc/passwd",
|
|
||||||
"method": "GET",
|
|
||||||
"user_agent": "Mozilla/5.0 ..."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**민감 정보 제외:**
|
|
||||||
- `password`
|
|
||||||
- `password_confirmation`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Layer 4: Sanctum 토큰 인증
|
|
||||||
|
|
||||||
### 토큰 구조
|
|
||||||
|
|
||||||
**액세스 토큰:**
|
|
||||||
- 만료 시간: 2시간 (120분)
|
|
||||||
- 용도: API 호출 인증
|
|
||||||
- 형식: `{token_id}|{plain_text_token}`
|
|
||||||
|
|
||||||
**리프레시 토큰:**
|
|
||||||
- 만료 시간: 7일 (10080분)
|
|
||||||
- 용도: 액세스 토큰 갱신
|
|
||||||
- 특징: 일회성 사용 (사용 후 삭제)
|
|
||||||
|
|
||||||
### 토큰 갱신 플로우
|
|
||||||
|
|
||||||
```
|
|
||||||
1. 클라이언트: POST /api/v1/refresh
|
|
||||||
Headers: X-API-KEY, Authorization: Bearer {refresh_token}
|
|
||||||
|
|
||||||
2. 서버: 리프레시 토큰 검증
|
|
||||||
- 유효성 체크
|
|
||||||
- 만료 시간 체크
|
|
||||||
- 사용자 확인
|
|
||||||
|
|
||||||
3. 서버: 기존 리프레시 토큰 삭제
|
|
||||||
- 일회성 사용 보장
|
|
||||||
|
|
||||||
4. 서버: 새 토큰 발급
|
|
||||||
- 새 액세스 토큰 생성
|
|
||||||
- 새 리프레시 토큰 생성
|
|
||||||
|
|
||||||
5. 응답:
|
|
||||||
{
|
|
||||||
"access_token": "...",
|
|
||||||
"refresh_token": "...",
|
|
||||||
"expires_in": 7200,
|
|
||||||
"expires_at": "2025-11-13 21:30:00"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 토큰 만료 에러 처리
|
|
||||||
|
|
||||||
**위치:** `app/Exceptions/Handler.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
if ($exception instanceof AuthenticationException) {
|
|
||||||
$bearerToken = $request->bearerToken();
|
|
||||||
if ($bearerToken) {
|
|
||||||
$token = PersonalAccessToken::findToken($bearerToken);
|
|
||||||
if ($token && $token->expires_at && $token->expires_at->isPast()) {
|
|
||||||
return response()->json([
|
|
||||||
'success' => false,
|
|
||||||
'message' => __('error.token_expired'),
|
|
||||||
'error_code' => 'TOKEN_EXPIRED',
|
|
||||||
], 401);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**프론트엔드 처리:**
|
|
||||||
```javascript
|
|
||||||
if (response.error_code === 'TOKEN_EXPIRED') {
|
|
||||||
// 자동 리프레시 토큰으로 재발급
|
|
||||||
const newTokens = await refreshToken(refreshToken);
|
|
||||||
// 원래 요청 재시도
|
|
||||||
return retryRequest(originalRequest, newTokens.access_token);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Layer 5: 권한 검증 (Permission System)
|
|
||||||
|
|
||||||
### 권한 시스템 개요
|
|
||||||
|
|
||||||
SAM은 **Spatie Permission** 패키지를 기반으로 한 다층 권한 시스템을 사용합니다.
|
|
||||||
|
|
||||||
**3단계 권한 구조:**
|
|
||||||
```
|
|
||||||
┌────────────────────────────────────────┐
|
|
||||||
│ 1. 사용자 역할 권한 │
|
|
||||||
│ User → Role → Permissions │
|
|
||||||
│ (model_has_roles → role_has_perms) │
|
|
||||||
└────────────────────────────────────────┘
|
|
||||||
+
|
|
||||||
┌────────────────────────────────────────┐
|
|
||||||
│ 2. 사용자 직접 권한 │
|
|
||||||
│ User → Permissions │
|
|
||||||
│ (model_has_permissions) │
|
|
||||||
└────────────────────────────────────────┘
|
|
||||||
+
|
|
||||||
┌────────────────────────────────────────┐
|
|
||||||
│ 3. 부서 역할 권한 │
|
|
||||||
│ User → Department → Role → Perms │
|
|
||||||
│ (department_user → model_has_roles) │
|
|
||||||
└────────────────────────────────────────┘
|
|
||||||
↓
|
|
||||||
┌────────────────────────────────────────┐
|
|
||||||
│ UNION (중복 제거) │
|
|
||||||
│ → 최종 사용자 권한 목록 │
|
|
||||||
└────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
**특징:**
|
|
||||||
- 멀티테넌트 지원 (tenant_id로 격리)
|
|
||||||
- 메뉴 기반 세분화된 권한
|
|
||||||
- 다형성(Polymorphic) 구조로 유연한 확장
|
|
||||||
- Permission Override로 임시/긴급 권한 제어
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 권한 패턴 및 타입
|
|
||||||
|
|
||||||
**권한 명명 규칙:**
|
|
||||||
```
|
|
||||||
menu:{menu_id}.{permission_type}
|
|
||||||
```
|
|
||||||
|
|
||||||
**권한 타입 (7가지):**
|
|
||||||
|
|
||||||
| 타입 | 약자 | 설명 | 예시 |
|
|
||||||
|------|------|------|------|
|
|
||||||
| view | V | 조회 | 목록/상세 보기 |
|
|
||||||
| create | C | 생성 | 신규 데이터 등록 |
|
|
||||||
| update | U | 수정 | 기존 데이터 편집 |
|
|
||||||
| delete | D | 삭제 | 데이터 삭제 |
|
|
||||||
| approve | A | 승인 | 워크플로우 승인 |
|
|
||||||
| export | E | 내보내기 | Excel/PDF 다운로드 |
|
|
||||||
| manage | M | 관리 | 전체 관리 권한 |
|
|
||||||
|
|
||||||
**권한 예시:**
|
|
||||||
```
|
|
||||||
menu:1.view → 대시보드 보기
|
|
||||||
menu:2.create → 제품 생성
|
|
||||||
menu:2.update → 제품 수정
|
|
||||||
menu:2.delete → 제품 삭제
|
|
||||||
menu:3.approve → 주문 승인
|
|
||||||
menu:4.export → 재고 내보내기
|
|
||||||
menu:5.manage → 사용자 관리
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 권한 조회 로직
|
|
||||||
|
|
||||||
**구현 위치:**
|
|
||||||
- **API:** `app/Services/MemberService.php` - `getUserInfoForLogin()`
|
|
||||||
- **Admin:** `app/Filament/Resources/Users/Tables/UsersTable.php` - `getAccessibleMenusCount()`
|
|
||||||
|
|
||||||
**권한 조회 쿼리 구조:**
|
|
||||||
|
|
||||||
```php
|
|
||||||
// 1. 사용자 역할 권한
|
|
||||||
$userRolePermissions = DB::table('model_has_roles')
|
|
||||||
->join('role_has_permissions', 'model_has_roles.role_id', '=', 'role_has_permissions.role_id')
|
|
||||||
->join('permissions', 'role_has_permissions.permission_id', '=', 'permissions.id')
|
|
||||||
->where('model_has_roles.model_type', User::class)
|
|
||||||
->where('model_has_roles.model_id', $userId)
|
|
||||||
->where('model_has_roles.tenant_id', $tenantId)
|
|
||||||
->where('permissions.name', 'like', 'menu:%.view')
|
|
||||||
->select('permissions.name');
|
|
||||||
|
|
||||||
// 2. 사용자 직접 권한
|
|
||||||
$userDirectPermissions = DB::table('model_has_permissions')
|
|
||||||
->join('permissions', 'model_has_permissions.permission_id', '=', 'permissions.id')
|
|
||||||
->where('model_has_permissions.model_type', User::class)
|
|
||||||
->where('model_has_permissions.model_id', $userId)
|
|
||||||
->where('model_has_permissions.tenant_id', $tenantId)
|
|
||||||
->where('permissions.name', 'like', 'menu:%.view')
|
|
||||||
->select('permissions.name');
|
|
||||||
|
|
||||||
// 3. 부서 역할 권한
|
|
||||||
$departmentRolePermissions = DB::table('department_user')
|
|
||||||
->join('model_has_roles', function ($join) {
|
|
||||||
$join->on('department_user.department_id', '=', 'model_has_roles.model_id')
|
|
||||||
->where('model_has_roles.model_type', '=', Department::class);
|
|
||||||
})
|
|
||||||
->join('role_has_permissions', 'model_has_roles.role_id', '=', 'role_has_permissions.role_id')
|
|
||||||
->join('permissions', 'role_has_permissions.permission_id', '=', 'permissions.id')
|
|
||||||
->where('department_user.user_id', $userId)
|
|
||||||
->where('department_user.tenant_id', $tenantId)
|
|
||||||
->where('permissions.name', 'like', 'menu:%.view')
|
|
||||||
->select('permissions.name');
|
|
||||||
|
|
||||||
// 4. 모든 권한 통합 (UNION + 중복 제거)
|
|
||||||
$allPermissions = $userRolePermissions
|
|
||||||
->union($userDirectPermissions)
|
|
||||||
->union($departmentRolePermissions)
|
|
||||||
->pluck('name')
|
|
||||||
->toArray();
|
|
||||||
```
|
|
||||||
|
|
||||||
**권한 파싱:**
|
|
||||||
```php
|
|
||||||
// menu:123.view → 메뉴 ID 123 추출
|
|
||||||
foreach ($allPermissions as $permName) {
|
|
||||||
if (preg_match('/^menu:(\d+)\.view$/', $permName, $matches)) {
|
|
||||||
$allowedMenuIds[] = (int) $matches[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Permission Override (우선순위 제어)
|
|
||||||
|
|
||||||
**시간 기반 권한 제어:**
|
|
||||||
|
|
||||||
```php
|
|
||||||
// permission_overrides 테이블
|
|
||||||
[
|
|
||||||
'tenant_id' => 1,
|
|
||||||
'model_type' => 'App\Models\Members\User',
|
|
||||||
'model_id' => 123,
|
|
||||||
'permission_id' => 456,
|
|
||||||
'effect' => 1, // 1=ALLOW, -1=DENY
|
|
||||||
'effective_from' => '2025-11-13 00:00:00',
|
|
||||||
'effective_to' => '2025-11-20 23:59:59',
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
**우선순위:**
|
|
||||||
1. **Override DENY** (-1) - 최우선 차단
|
|
||||||
2. **Override ALLOW** (1) - 명시적 허용
|
|
||||||
3. **Base Permission** - 역할/부서/직접 권한
|
|
||||||
|
|
||||||
**최종 권한 계산:**
|
|
||||||
```php
|
|
||||||
foreach ($allMenuPermissions as $permName) {
|
|
||||||
if (preg_match('/^menu:(\d+)\.view$/', $permName, $matches)) {
|
|
||||||
$menuId = (int) $matches[1];
|
|
||||||
|
|
||||||
// Override DENY 체크 (강제 차단)
|
|
||||||
if (isset($overrides[$permName]) && $overrides[$permName]->effect === -1) {
|
|
||||||
continue; // 이 메뉴는 차단됨
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override ALLOW 또는 기본 권한
|
|
||||||
if (
|
|
||||||
(isset($overrides[$permName]) && $overrides[$permName]->effect === 1) ||
|
|
||||||
in_array($permName, $basePermissions, true)
|
|
||||||
) {
|
|
||||||
$allowedMenuIds[] = $menuId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**사용 사례:**
|
|
||||||
- **임시 권한 부여:** 프로젝트 기간 동안만 특정 메뉴 접근 허용
|
|
||||||
- **긴급 권한 차단:** 보안 사고 발생 시 즉시 권한 제거
|
|
||||||
- **휴가 기간 제한:** 특정 기간 동안 권한 자동 차단
|
|
||||||
- **시간대별 접근 제어:** 업무 시간에만 권한 부여
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 메뉴별 권한 매트릭스 뷰
|
|
||||||
|
|
||||||
**Admin 패널:** `http://admin.sam.kr/admin/permissions`
|
|
||||||
|
|
||||||
**테이블 구조:**
|
|
||||||
|
|
||||||
| 메뉴 ID | 메뉴명 | V (조회) | C (생성) | U (수정) | D (삭제) | A (승인) | E (내보내기) | M (관리) |
|
|
||||||
|---------|--------|----------|----------|----------|----------|----------|-------------|----------|
|
|
||||||
| 1 | 대시보드 | 홍길동, 김철수 | - | - | - | - | - | - |
|
|
||||||
| 2 | 제품 관리 | 홍길동, 김철수 | 홍길동 | 홍길동 | 관리자 | - | 김철수 | 관리자 |
|
|
||||||
| 3 | 주문 관리 | 전체팀 | 영업팀 | 영업팀 | 관리자 | 관리자 | 회계팀 | 관리자 |
|
|
||||||
|
|
||||||
**특징:**
|
|
||||||
- 각 Row = 하나의 메뉴
|
|
||||||
- 각 권한 타입별 Column에 해당 권한을 가진 사용자 목록 표시
|
|
||||||
- 사용자 배지에 마우스 오버 시 `user_id` 툴팁 표시
|
|
||||||
- 권한 없는 경우 `-` 표시
|
|
||||||
- 3가지 권한 소스 (역할/부서/직접) 모두 통합하여 표시
|
|
||||||
|
|
||||||
**구현 코드:**
|
|
||||||
```php
|
|
||||||
// app/Filament/Resources/Permissions/Tables/PermissionsTable.php
|
|
||||||
protected static function getUsersWithPermission(int $menuId, string $permissionType): string
|
|
||||||
{
|
|
||||||
$permissionName = "menu:{$menuId}.{$permissionType}";
|
|
||||||
|
|
||||||
// 3가지 권한 소스 UNION
|
|
||||||
$userIds = $userRoleQuery
|
|
||||||
->union($userDirectQuery)
|
|
||||||
->union($departmentRoleQuery)
|
|
||||||
->pluck('user_id')
|
|
||||||
->unique()
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
// 사용자 배지 HTML 생성
|
|
||||||
$users = User::whereIn('id', $userIds)->orderBy('name')->get();
|
|
||||||
foreach ($users as $user) {
|
|
||||||
$badges[] = sprintf(
|
|
||||||
'<span title="%s">%s</span>',
|
|
||||||
htmlspecialchars($user->user_id),
|
|
||||||
htmlspecialchars($user->name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode(', ', $badges);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 권한 할당 방법
|
|
||||||
|
|
||||||
**1. 역할에 권한 할당:**
|
|
||||||
```php
|
|
||||||
$role = Role::findByName('영업팀', 'web');
|
|
||||||
$role->givePermissionTo([
|
|
||||||
'menu:2.view',
|
|
||||||
'menu:2.create',
|
|
||||||
'menu:3.view',
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. 사용자에게 직접 권한 할당:**
|
|
||||||
```php
|
|
||||||
$user = User::find(123);
|
|
||||||
$user->givePermissionTo('menu:5.manage');
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. 부서에 역할 할당:**
|
|
||||||
```php
|
|
||||||
$department = Department::find(1);
|
|
||||||
$department->assignRole('영업팀');
|
|
||||||
```
|
|
||||||
|
|
||||||
**4. Permission Override 설정:**
|
|
||||||
```php
|
|
||||||
DB::table('permission_overrides')->insert([
|
|
||||||
'tenant_id' => 1,
|
|
||||||
'model_type' => User::class,
|
|
||||||
'model_id' => 123,
|
|
||||||
'permission_id' => 456,
|
|
||||||
'effect' => -1, // DENY
|
|
||||||
'effective_from' => now(),
|
|
||||||
'effective_to' => now()->addDays(7),
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 권한 체크 (Controller/Service)
|
|
||||||
|
|
||||||
**CheckPermission Middleware:**
|
|
||||||
```php
|
|
||||||
// routes/api.php
|
|
||||||
Route::get('/products', [ProductController::class, 'index'])
|
|
||||||
->middleware(['auth:sanctum', 'permission:menu:2.view']);
|
|
||||||
```
|
|
||||||
|
|
||||||
**서비스 레이어:**
|
|
||||||
```php
|
|
||||||
if (!auth()->user()->can('menu:2.create')) {
|
|
||||||
throw new \Exception(__('error.permission_denied'), 403);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**권한 확인 헬퍼:**
|
|
||||||
```php
|
|
||||||
// 단일 권한 체크
|
|
||||||
auth()->user()->can('menu:2.view');
|
|
||||||
|
|
||||||
// 여러 권한 중 하나라도 있으면
|
|
||||||
auth()->user()->hasAnyPermission(['menu:2.view', 'menu:2.manage']);
|
|
||||||
|
|
||||||
// 모든 권한 필요
|
|
||||||
auth()->user()->hasAllPermissions(['menu:2.view', 'menu:2.create']);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 보안 모니터링
|
|
||||||
|
|
||||||
### 로그 파일
|
|
||||||
|
|
||||||
**1. 보안 로그**
|
|
||||||
```bash
|
|
||||||
# 무단 접근 시도
|
|
||||||
tail -f storage/logs/laravel.log | grep "Unauthorized API access attempt"
|
|
||||||
|
|
||||||
# Rate Limit 초과
|
|
||||||
tail -f storage/logs/laravel.log | grep "API Rate Limit Exceeded"
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. Nginx 로그**
|
|
||||||
```bash
|
|
||||||
# 접근 로그
|
|
||||||
tail -f /var/log/nginx/api.sam.kr_access.log
|
|
||||||
|
|
||||||
# 에러 로그 (403 차단)
|
|
||||||
tail -f /var/log/nginx/api.sam.kr_error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### 공격 패턴 분석
|
|
||||||
|
|
||||||
**자주 발생하는 공격:**
|
|
||||||
|
|
||||||
1. **경로 탐색 (Path Traversal)**
|
|
||||||
```
|
|
||||||
GET /@fs/etc/passwd
|
|
||||||
GET /../../../etc/passwd
|
|
||||||
GET /api/../.env
|
|
||||||
```
|
|
||||||
**대응:** Nginx에서 403 차단
|
|
||||||
|
|
||||||
2. **보안 스캔**
|
|
||||||
```
|
|
||||||
User-Agent: sqlmap/1.0
|
|
||||||
User-Agent: nikto/2.1.5
|
|
||||||
```
|
|
||||||
**대응:** Nginx User-Agent 필터링
|
|
||||||
|
|
||||||
3. **무차별 대입 (Brute Force)**
|
|
||||||
```
|
|
||||||
POST /api/v1/login (반복)
|
|
||||||
```
|
|
||||||
**대응:** Rate Limiting (10회/분)
|
|
||||||
|
|
||||||
4. **API Key 누락**
|
|
||||||
```
|
|
||||||
GET /api/v1/users (X-API-KEY 없음)
|
|
||||||
```
|
|
||||||
**대응:** 401 Unauthorized + 보안 로그
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 보안 체크리스트
|
|
||||||
|
|
||||||
### 개발 시
|
|
||||||
|
|
||||||
- [ ] 모든 API 엔드포인트에 `auth.apikey` 미들웨어 적용
|
|
||||||
- [ ] 민감한 정보 로깅 제외 (`password`, `password_confirmation`)
|
|
||||||
- [ ] FormRequest로 입력 검증
|
|
||||||
- [ ] SQL 인젝션 방지 (Eloquent ORM 사용)
|
|
||||||
- [ ] XSS 방지 (출력 시 이스케이핑)
|
|
||||||
- [ ] CSRF 보호 (Sanctum 자동 적용)
|
|
||||||
|
|
||||||
### 배포 전
|
|
||||||
|
|
||||||
- [ ] `.env` 파일 보안 설정 확인
|
|
||||||
- [ ] API Key 로테이션
|
|
||||||
- [ ] Nginx 보안 규칙 테스트
|
|
||||||
- [ ] Rate Limiting 임계값 검토
|
|
||||||
- [ ] HTTPS 인증서 유효성 확인
|
|
||||||
- [ ] 방화벽 규칙 설정
|
|
||||||
|
|
||||||
### 운영 중
|
|
||||||
|
|
||||||
- [ ] 매일 보안 로그 검토
|
|
||||||
- [ ] 주간 공격 패턴 분석
|
|
||||||
- [ ] 월간 토큰 만료 정책 검토
|
|
||||||
- [ ] 분기별 API Key 갱신
|
|
||||||
- [ ] 반기별 침투 테스트
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 보안 사고 대응
|
|
||||||
|
|
||||||
### 1단계: 즉시 조치
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 의심스러운 IP 차단 (Nginx)
|
|
||||||
# /etc/nginx/conf.d/blocked_ips.conf
|
|
||||||
deny 213.136.76.215;
|
|
||||||
|
|
||||||
# 2. Nginx 재시작
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
|
|
||||||
# 3. 활성 세션 강제 종료
|
|
||||||
php artisan sanctum:prune-expired --hours=0
|
|
||||||
|
|
||||||
# 4. API Key 비활성화
|
|
||||||
UPDATE api_keys SET is_active = 0 WHERE key = 'suspicious_key';
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2단계: 로그 분석
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 공격 패턴 분석
|
|
||||||
grep "213.136.76.215" /var/log/nginx/api.sam.kr_access.log
|
|
||||||
|
|
||||||
# 영향받은 엔드포인트 확인
|
|
||||||
grep "Unauthorized API access attempt" storage/logs/laravel.log | grep "213.136.76.215"
|
|
||||||
|
|
||||||
# 시간대별 요청 횟수
|
|
||||||
awk '{print $4}' /var/log/nginx/api.sam.kr_access.log | cut -d: -f1-2 | uniq -c
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3단계: 복구 및 강화
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 모든 사용자 비밀번호 초기화 (필요 시)
|
|
||||||
# 2. 새 API Key 발급
|
|
||||||
# 3. 토큰 만료 시간 단축 (임시)
|
|
||||||
# 4. Rate Limiting 임계값 강화
|
|
||||||
# 5. 추가 보안 규칙 적용
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
### Q1. API Key는 어디서 발급받나요?
|
|
||||||
|
|
||||||
**A:** 관리자 패널(admin.sam.kr)에서 발급합니다.
|
|
||||||
```sql
|
|
||||||
-- api_keys 테이블 구조
|
|
||||||
id, tenant_id, name, key, is_active, created_at, updated_at
|
|
||||||
```
|
|
||||||
|
|
||||||
### Q2. Rate Limiting이 너무 엄격해요.
|
|
||||||
|
|
||||||
**A:** `ApiRateLimiter.php`에서 임계값 조정:
|
|
||||||
```php
|
|
||||||
if ($this->limiter->tooManyAttempts($key, 10)) { // 10 → 20으로 변경
|
|
||||||
```
|
|
||||||
|
|
||||||
### Q3. 화이트리스트에 라우트를 추가하려면?
|
|
||||||
|
|
||||||
**A:** `ApiKeyMiddleware.php` 수정:
|
|
||||||
```php
|
|
||||||
$publicRoutes = [
|
|
||||||
// 기존 라우트...
|
|
||||||
'api/v1/public-data', // 추가
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
### Q4. 특정 IP만 허용하려면?
|
|
||||||
|
|
||||||
**A:** Nginx 설정 추가:
|
|
||||||
```nginx
|
|
||||||
# 화이트리스트 IP만 허용
|
|
||||||
allow 203.0.113.0/24;
|
|
||||||
allow 198.51.100.50;
|
|
||||||
deny all;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Q5. 토큰 만료 시간을 변경하려면?
|
|
||||||
|
|
||||||
**A:** `.env` 파일 수정:
|
|
||||||
```env
|
|
||||||
SANCTUM_ACCESS_TOKEN_EXPIRATION=120 # 2시간 → 4시간 (240)
|
|
||||||
SANCTUM_REFRESH_TOKEN_EXPIRATION=10080 # 7일 → 14일 (20160)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 참고 문서
|
|
||||||
|
|
||||||
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
|
|
||||||
- [Laravel Security Best Practices](https://laravel.com/docs/12.x/security)
|
|
||||||
- [Sanctum Documentation](https://laravel.com/docs/12.x/sanctum)
|
|
||||||
- [Nginx Security Tips](https://nginx.org/en/docs/http/ngx_http_access_module.html)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**작성일:** 2025-12-26
|
|
||||||
**버전:** 1.0
|
|
||||||
**담당자:** SAM Development Team
|
|
||||||
@@ -1,392 +0,0 @@
|
|||||||
# SAM 시스템 아키텍처
|
|
||||||
|
|
||||||
**업데이트**: 2026-01-28
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 전체 아키텍처
|
|
||||||
|
|
||||||
SAM은 다중 애플리케이션 Laravel 기반 시스템으로 구성됩니다:
|
|
||||||
|
|
||||||
```
|
|
||||||
SAM/
|
|
||||||
├── api/ # Laravel 12 REST API (백엔드)
|
|
||||||
├── mng/ # Laravel 12 + Plain Blade/Tailwind (관리자 패널)
|
|
||||||
├── react/ # Next.js 15.5.7 프론트엔드
|
|
||||||
├── docs/ # 기술 문서
|
|
||||||
├── design/ # 디자인 시스템 (Storybook)
|
|
||||||
├── planning/ # 기획 문서
|
|
||||||
├── sales/ # 영업자 사이트 (추후 개발)
|
|
||||||
├── 5130/ # 레거시 PHP 애플리케이션
|
|
||||||
└── docker/ # Docker 설정
|
|
||||||
```
|
|
||||||
|
|
||||||
## 애플리케이션별 상세
|
|
||||||
|
|
||||||
### mng/ - 관리자 패널
|
|
||||||
|
|
||||||
**기술 스택:**
|
|
||||||
- Laravel 12
|
|
||||||
- PHP 8.4
|
|
||||||
- Pure Blade + Tailwind CSS 3.x
|
|
||||||
- Sanctum (인증)
|
|
||||||
|
|
||||||
**주요 기능:**
|
|
||||||
- 테넌트 관리
|
|
||||||
- 사용자 관리
|
|
||||||
- 권한 관리 (RBAC)
|
|
||||||
- 메뉴 관리
|
|
||||||
- 역할 및 부서 관리
|
|
||||||
|
|
||||||
**주요 특징:**
|
|
||||||
- AI 없이 수정 가능한 단순 구조
|
|
||||||
- 좌측 사이드바 + 상단 헤더 레이아웃
|
|
||||||
|
|
||||||
**개발 명령어:**
|
|
||||||
```bash
|
|
||||||
php artisan serve # Laravel 서버
|
|
||||||
npm run dev # Vite HMR (Tailwind)
|
|
||||||
```
|
|
||||||
|
|
||||||
### api/ - REST API
|
|
||||||
|
|
||||||
**기술 스택:**
|
|
||||||
- Laravel 12
|
|
||||||
- PHP 8.4
|
|
||||||
- Sanctum (인증)
|
|
||||||
- l5-swagger 9.0 (API 문서화)
|
|
||||||
|
|
||||||
**주요 기능:**
|
|
||||||
- RESTful API 엔드포인트
|
|
||||||
- Swagger 문서화
|
|
||||||
- Multi-tenant 지원
|
|
||||||
- 권한 기반 접근 제어
|
|
||||||
|
|
||||||
**API 구조:**
|
|
||||||
- **인증**: `/v1/login`, `/v1/logout`, `/v1/signup`
|
|
||||||
- **사용자**: `/v1/users/*`
|
|
||||||
- **테넌트**: `/v1/tenants/*`
|
|
||||||
- **제품**: `/v1/products/*`
|
|
||||||
- **자재**: `/v1/materials/*`
|
|
||||||
- **카테고리**: `/v1/categories/*`
|
|
||||||
- **파일**: `/v1/file/*`
|
|
||||||
- **디자인**: `/v1/design/*`
|
|
||||||
|
|
||||||
**API 문서:**
|
|
||||||
- Swagger UI: `http://api.sam.kr/api-docs/index.html`
|
|
||||||
- JSON Spec: `http://api.sam.kr/docs/api-docs.json`
|
|
||||||
|
|
||||||
### react/ - Next.js 프론트엔드
|
|
||||||
|
|
||||||
**기술 스택:**
|
|
||||||
- Next.js 15.5.7
|
|
||||||
- React 19.2.1
|
|
||||||
- TypeScript 5.x
|
|
||||||
- Tailwind CSS v4
|
|
||||||
- Zustand (상태 관리)
|
|
||||||
- React Hook Form
|
|
||||||
- shadcn/ui
|
|
||||||
- next-intl (i18n)
|
|
||||||
|
|
||||||
**주요 기능:**
|
|
||||||
- 모던 UI/UX
|
|
||||||
- Server Components 및 App Router
|
|
||||||
- 실시간 데이터 동기화
|
|
||||||
- 역할 전환 기능
|
|
||||||
- 대시보드
|
|
||||||
- 다국어 지원 (i18n)
|
|
||||||
|
|
||||||
## Multi-tenant 아키텍처
|
|
||||||
|
|
||||||
### 데이터 격리
|
|
||||||
|
|
||||||
- **방식**: `tenant_id` 컬럼 기반 격리
|
|
||||||
- **스코프**: BelongsToTenant global scope 자동 적용
|
|
||||||
- **모델**: `shared/Models/` 디렉토리의 공통 모델 사용
|
|
||||||
|
|
||||||
### 테넌트 구조
|
|
||||||
|
|
||||||
```
|
|
||||||
Tenant (회사/조직)
|
|
||||||
├── Users (사용자)
|
|
||||||
├── Departments (부서)
|
|
||||||
├── Roles (역할)
|
|
||||||
├── Permissions (권한)
|
|
||||||
└── Data (비즈니스 데이터)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 테넌트 전환
|
|
||||||
|
|
||||||
- 사용자는 여러 테넌트에 속할 수 있음 (`user_tenants` 테이블)
|
|
||||||
- 기본 테넌트 설정 가능
|
|
||||||
- API: `POST /v1/users/me/tenants/switch`
|
|
||||||
|
|
||||||
## 인증 및 권한
|
|
||||||
|
|
||||||
### 인증 흐름
|
|
||||||
|
|
||||||
1. **API Key 인증** (모든 요청)
|
|
||||||
- 헤더: `X-API-KEY`
|
|
||||||
- 미들웨어: `auth.apikey`
|
|
||||||
|
|
||||||
2. **사용자 인증** (보호된 라우트)
|
|
||||||
- 엔드포인트: `POST /v1/login`
|
|
||||||
- 토큰: Sanctum Bearer Token
|
|
||||||
- 미들웨어: `auth:sanctum`
|
|
||||||
|
|
||||||
### 권한 시스템
|
|
||||||
|
|
||||||
**3단계 권한 구조:**
|
|
||||||
1. **사용자 역할 권한**: User → Role → Permissions
|
|
||||||
2. **사용자 직접 권한**: User → Permissions
|
|
||||||
3. **부서 역할 권한**: User → Department → Role → Permissions
|
|
||||||
|
|
||||||
**권한 명명 규칙:**
|
|
||||||
```
|
|
||||||
menu:{menu_id}.{permission_type}
|
|
||||||
```
|
|
||||||
|
|
||||||
**권한 타입:**
|
|
||||||
- `view` - 조회
|
|
||||||
- `create` - 생성
|
|
||||||
- `update` - 수정
|
|
||||||
- `delete` - 삭제
|
|
||||||
- `approve` - 승인
|
|
||||||
- `export` - 내보내기
|
|
||||||
- `manage` - 관리
|
|
||||||
|
|
||||||
## 데이터베이스 구조
|
|
||||||
|
|
||||||
### 핵심 테이블
|
|
||||||
|
|
||||||
**인증 및 권한:**
|
|
||||||
- `api_keys` - API 키 관리
|
|
||||||
- `users` - 사용자 계정
|
|
||||||
- `user_tenants` - 사용자-테넌트 관계
|
|
||||||
- `permissions` - 권한 정의
|
|
||||||
- `roles` - 역할 정의
|
|
||||||
- `model_has_permissions/roles` - 권한 할당
|
|
||||||
|
|
||||||
**멀티테넌트:**
|
|
||||||
- `tenants` - 테넌트 마스터
|
|
||||||
- `tenant_user_profiles` - 테넌트별 사용자 프로필
|
|
||||||
- `departments` - 부서 구조
|
|
||||||
- `department_user` - 사용자-부서 관계
|
|
||||||
|
|
||||||
**제품 관리:**
|
|
||||||
- `categories` - 카테고리 계층
|
|
||||||
- `category_fields` - 동적 필드 정의
|
|
||||||
- `products` - 제품 카탈로그
|
|
||||||
- `product_components` - BOM 관계
|
|
||||||
- `materials` - 자재 마스터
|
|
||||||
|
|
||||||
**디자인 및 제조:**
|
|
||||||
- `models` - 디자인 모델
|
|
||||||
- `model_versions` - 모델 버전
|
|
||||||
- `bom_templates` - BOM 템플릿
|
|
||||||
- `bom_template_items` - BOM 항목
|
|
||||||
|
|
||||||
**주문 및 운영:**
|
|
||||||
- `orders` - 주문/견적 마스터
|
|
||||||
- `order_items` - 주문 항목
|
|
||||||
- `order_item_components` - 주문 항목 구성
|
|
||||||
- `clients` - 고객/벤더 마스터
|
|
||||||
|
|
||||||
**시스템:**
|
|
||||||
- `audit_logs` - 감사 로그 (13개월 보관)
|
|
||||||
- `files` - 다형성 파일 첨부
|
|
||||||
- `common_codes` - 공통 코드
|
|
||||||
|
|
||||||
### 공통 컬럼 패턴
|
|
||||||
|
|
||||||
모든 테이블에 공통으로 포함:
|
|
||||||
- `id` - 기본 키
|
|
||||||
- `tenant_id` - 테넌트 ID (필수)
|
|
||||||
- `created_by` - 생성자 ID
|
|
||||||
- `updated_by` - 수정자 ID
|
|
||||||
- `deleted_by` - 삭제자 ID
|
|
||||||
- `created_at`, `updated_at` - 타임스탬프
|
|
||||||
- `deleted_at` - Soft Delete
|
|
||||||
|
|
||||||
## 미들웨어 스택
|
|
||||||
|
|
||||||
**실행 순서:**
|
|
||||||
1. `ApiRateLimiter` - Rate Limiting
|
|
||||||
2. `ApiVersionMiddleware` - API 버전 선택 및 폴백 처리
|
|
||||||
3. `ApiKeyMiddleware` - API Key 검증
|
|
||||||
4. `CheckSwaggerAuth` - Swagger 인증 체크
|
|
||||||
5. `CorsMiddleware` - CORS 처리
|
|
||||||
6. `CheckPermission` - 권한 검증
|
|
||||||
7. `PermMapper` - 권한 매핑
|
|
||||||
|
|
||||||
## 라우팅 구조
|
|
||||||
|
|
||||||
### 도메인별 라우트 분리
|
|
||||||
|
|
||||||
API 라우트는 도메인별로 분리되어 관리됩니다:
|
|
||||||
|
|
||||||
```
|
|
||||||
routes/api/
|
|
||||||
├── v1/ # v1 API 라우트 (13개 도메인)
|
|
||||||
│ ├── auth.php # 인증 (login, logout, signup)
|
|
||||||
│ ├── admin.php # 관리자 기능
|
|
||||||
│ ├── users.php # 사용자 관리
|
|
||||||
│ ├── tenants.php # 테넌트 관리
|
|
||||||
│ ├── hr.php # HR/인사 관리
|
|
||||||
│ ├── finance.php # 재무/회계
|
|
||||||
│ ├── sales.php # 영업/판매
|
|
||||||
│ ├── inventory.php # 재고/품목
|
|
||||||
│ ├── production.php # 생산 관리
|
|
||||||
│ ├── design.php # 설계/모델
|
|
||||||
│ ├── files.php # 파일 관리
|
|
||||||
│ ├── boards.php # 게시판
|
|
||||||
│ └── common.php # 공통 기능
|
|
||||||
├── v2/ # v2 API (필요시 생성)
|
|
||||||
└── api.php # 라우트 로더
|
|
||||||
```
|
|
||||||
|
|
||||||
### API 버전 관리
|
|
||||||
|
|
||||||
**ApiVersionMiddleware**가 버전 선택 및 폴백을 처리합니다:
|
|
||||||
|
|
||||||
**버전 지정 방법:**
|
|
||||||
- `Accept-Version` 헤더 (권장)
|
|
||||||
- `X-API-Version` 헤더
|
|
||||||
- `api_version` 쿼리 파라미터
|
|
||||||
- 미지정 시 기본값: `v1`
|
|
||||||
|
|
||||||
**폴백 동작:**
|
|
||||||
- v2 요청 시 해당 라우트가 v2에 없으면 v1으로 자동 폴백
|
|
||||||
- 응답 헤더 `X-API-Version`에 실제 사용 버전 표시
|
|
||||||
|
|
||||||
### 기본 경로 그룹
|
|
||||||
|
|
||||||
```php
|
|
||||||
// routes/api.php - 라우트 로더
|
|
||||||
Route::prefix('v1')->middleware(['auth.apikey'])->group(function () {
|
|
||||||
require __DIR__.'/api/v1/auth.php';
|
|
||||||
require __DIR__.'/api/v1/admin.php';
|
|
||||||
require __DIR__.'/api/v1/users.php';
|
|
||||||
// ... 13개 도메인 파일 로드
|
|
||||||
});
|
|
||||||
|
|
||||||
// v2 라우트 (존재하는 경우)
|
|
||||||
if (is_dir(__DIR__.'/api/v2')) {
|
|
||||||
Route::prefix('v2')->middleware(['auth.apikey'])->group(function () {
|
|
||||||
// v2 전용 라우트
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 공유 모델 구조
|
|
||||||
|
|
||||||
`shared/Models/` 디렉토리 구조:
|
|
||||||
- **Members/** - 사용자 및 테넌트 관리
|
|
||||||
- **Products/** - 제품 카탈로그 및 BOM
|
|
||||||
- **Materials/** - 자재 사양 및 재고
|
|
||||||
- **Orders/** - 주문 처리 워크플로우
|
|
||||||
- **Tenants/** - 멀티테넌트 설정
|
|
||||||
- **Commons/** - 공유 유틸리티 및 공통 데이터
|
|
||||||
|
|
||||||
## Docker 설정
|
|
||||||
|
|
||||||
**위치**: `docker/` 디렉토리
|
|
||||||
|
|
||||||
### 서비스 구성
|
|
||||||
|
|
||||||
**docker-compose.yml**에 정의된 주요 서비스:
|
|
||||||
|
|
||||||
1. **nginx** - 리버스 프록시 서버
|
|
||||||
- 포트: 80
|
|
||||||
- 도메인: `api.sam.kr`, `mng.sam.kr`, `admin.sam.kr`, `dev.sam.kr`
|
|
||||||
- 보안 규칙 적용 (경로 탐색 공격 차단, User-Agent 필터링)
|
|
||||||
|
|
||||||
2. **api** - Laravel 12 API 서버
|
|
||||||
- 이미지: `php:8.4-fpm`
|
|
||||||
- PHP 확장: zip, mysqli, pdo, pdo_mysql, intl
|
|
||||||
- Supervisor로 nginx + php-fpm 동시 실행
|
|
||||||
|
|
||||||
3. **mng** - Laravel 12 관리자 패널
|
|
||||||
- 이미지: `php:8.4-fpm`
|
|
||||||
- Pure Blade + Tailwind CSS
|
|
||||||
- Supervisor로 nginx + php-fpm 동시 실행
|
|
||||||
|
|
||||||
4. **react** - Next.js 15.5.7 프론트엔드
|
|
||||||
- 이미지: `node:20-alpine`
|
|
||||||
- 포트: 3000 (내부)
|
|
||||||
- HMR 지원 (WebSocket)
|
|
||||||
|
|
||||||
5. **mysql** - MySQL 8.0 데이터베이스
|
|
||||||
- 포트: 3306
|
|
||||||
- 데이터베이스: `samdb`
|
|
||||||
- 사용자: `samuser` / `sampass`
|
|
||||||
|
|
||||||
6. **design** - 디자인 시스템 (Storybook)
|
|
||||||
- 포트: 6006
|
|
||||||
|
|
||||||
### 네트워크 구조
|
|
||||||
|
|
||||||
```
|
|
||||||
samnet (bridge network)
|
|
||||||
├── nginx (리버스 프록시)
|
|
||||||
├── api (Laravel API)
|
|
||||||
├── mng (Laravel 관리자)
|
|
||||||
├── react (Next.js)
|
|
||||||
├── design (Storybook)
|
|
||||||
└── mysql (데이터베이스)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 도메인 매핑
|
|
||||||
|
|
||||||
| 도메인 | 대상 서비스 | 포트 | 용도 |
|
|
||||||
|--------|-----------|------|------|
|
|
||||||
| `api.sam.kr` | api (Laravel) | 80 | REST API |
|
|
||||||
| `mng.sam.kr` | mng (Laravel) | 80 | 관리자 패널 |
|
|
||||||
| `admin.sam.kr` | mng (Laravel) | 80 | 관리자 패널 (별칭) |
|
|
||||||
| `dev.sam.kr` | react (Next.js) | 3000 | 프론트엔드 |
|
|
||||||
|
|
||||||
### 주요 설정 파일
|
|
||||||
|
|
||||||
**nginx/nginx.conf**
|
|
||||||
- 리버스 프록시 설정
|
|
||||||
- 보안 규칙 (경로 탐색, User-Agent 필터링)
|
|
||||||
- WebSocket 지원 (Next.js HMR)
|
|
||||||
|
|
||||||
**api/Dockerfile, mng/Dockerfile**
|
|
||||||
- PHP 8.4-fpm 기반
|
|
||||||
- Composer 2 포함
|
|
||||||
- Supervisor 설정
|
|
||||||
|
|
||||||
**react/Dockerfile**
|
|
||||||
- Node.js 20 Alpine
|
|
||||||
- Next.js 15 개발 서버
|
|
||||||
|
|
||||||
**mysql/init.sql**
|
|
||||||
- 초기 데이터베이스 설정
|
|
||||||
|
|
||||||
## 저장소 구조
|
|
||||||
|
|
||||||
이 프로젝트는 **독립적인 Git 저장소들**로 구성됩니다:
|
|
||||||
|
|
||||||
1. **api/** - REST API 저장소
|
|
||||||
2. **mng/** - 관리자 패널 저장소
|
|
||||||
3. **react/** - Next.js 프론트엔드 저장소
|
|
||||||
4. **docs/** - 기술 문서 저장소
|
|
||||||
5. **design/** - 디자인 시스템 저장소
|
|
||||||
6. **planning/** - 기획 문서 저장소
|
|
||||||
|
|
||||||
각 저장소는 독립적으로 운영되며:
|
|
||||||
- 개별 Git 히스토리 및 브랜치
|
|
||||||
- 독립적인 환경 설정 (`.env` 파일)
|
|
||||||
- 독립적인 의존성 및 빌드 프로세스
|
|
||||||
|
|
||||||
## 관련 문서
|
|
||||||
|
|
||||||
- [API 개발 규칙](./api_rules.md)
|
|
||||||
- [데이터베이스 스키마](./database_schema.md)
|
|
||||||
- [보안 가이드](./security.md)
|
|
||||||
- [Git 컨벤션](./git_conventions.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**최종 업데이트**: 2025-12-26 (admin→mng 전환, Next.js 15.5.7, React 19.2.1 반영)
|
|
||||||
@@ -211,7 +211,7 @@ class ProductResource extends Resource
|
|||||||
|
|
||||||
## 🔗 관련 문서
|
## 🔗 관련 문서
|
||||||
|
|
||||||
- 이전 작업: `/Users/hskwon/Works/@KD_SAM/SAM/docs/changes/20251111_1354_admin_users_improvement.md`
|
- 이전 작업: `docs/changes/20251111_admin_users_improvement.md`
|
||||||
- CLAUDE.md: `/Users/hskwon/Works/@KD_SAM/SAM/CLAUDE.md`
|
- CLAUDE.md: `/Users/hskwon/Works/@KD_SAM/SAM/CLAUDE.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
| 문서 | 설명 | 대상 |
|
| 문서 | 설명 | 대상 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| [시스템 스펙](../../specs/board-system-spec.md) | 게시판 전체 설계 스펙 | 설계 참고 |
|
| [시스템 스펙](../../system/board-system-spec.md) | 게시판 전체 설계 스펙 | 설계 참고 |
|
||||||
| [MNG 구현](./mng-implementation.md) | MNG 관리자 패널 구현 상세 | MNG 개발 |
|
| [MNG 구현](./mng-implementation.md) | MNG 관리자 패널 구현 상세 | MNG 개발 |
|
||||||
|
|
||||||
## 개요
|
## 개요
|
||||||
|
|||||||
@@ -243,6 +243,6 @@ public function update($id)
|
|||||||
|
|
||||||
## 관련 문서
|
## 관련 문서
|
||||||
|
|
||||||
- [SAM API Rules](/SAM/API_RULES.md)
|
- [SAM API Rules](../../standards/api-rules.md)
|
||||||
- [MNG Critical Rules](/SAM/mng/docs/MNG_CRITICAL_RULES.md)
|
- [MNG Critical Rules](../../../mng/docs/MNG_CRITICAL_RULES.md)
|
||||||
- [Board System Spec](/SAM/docs/specs/board-system-spec.md)
|
- [Board System Spec](../../system/board-system-spec.md)
|
||||||
|
|||||||
@@ -332,8 +332,8 @@
|
|||||||
| 파일 | 설명 |
|
| 파일 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `docs/rules/attendance-api.md` | API 비즈니스 규칙 |
|
| `docs/rules/attendance-api.md` | API 비즈니스 규칙 |
|
||||||
| `docs/specs/erp-analysis/03-gps-attendance.md` | GPS 출퇴근 스펙 |
|
| `docs/system/erp-analysis/03-gps-attendance.md` | GPS 출퇴근 스펙 |
|
||||||
| `docs/specs/erp-analysis/04-hr-management.md` | HR 시스템 분석 |
|
| `docs/system/erp-analysis/04-hr-management.md` | HR 시스템 분석 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ class ExampleModel extends Model
|
|||||||
|
|
||||||
### SAM 전체 문서
|
### SAM 전체 문서
|
||||||
```
|
```
|
||||||
docs/specs/ # 시스템 스펙
|
docs/system/ # 시스템 현황
|
||||||
docs/reference/ # 레퍼런스
|
docs/reference/ # 레퍼런스
|
||||||
docs/guides/ # 가이드 (이 문서 포함)
|
docs/guides/ # 가이드 (이 문서 포함)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ sh 'export NODE_OPTIONS="--max-old-space-size=2048" && npm run build'
|
|||||||
|
|
||||||
- [운영 환경 배포 계획서](../plans/production-deployment-plan.md) - Jenkinsfile 상세, 브랜치 전략
|
- [운영 환경 배포 계획서](../plans/production-deployment-plan.md) - Jenkinsfile 상세, 브랜치 전략
|
||||||
- [.env 동기화 절차](production-env-sync.md) - 환경 변수 분리
|
- [.env 동기화 절차](production-env-sync.md) - 환경 변수 분리
|
||||||
- [Docker 환경 스펙](../specs/docker-setup.md) - 현재 개발 환경
|
- [Docker 환경 스펙](../system/docker-setup.md) - 현재 개발 환경
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ fastcgi_param SCRIPT_FILENAME /var/www/mng/public$fastcgi_script_name;
|
|||||||
|
|
||||||
| 문서 | 설명 |
|
| 문서 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 |
|
| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ docker exec sam-mng-1 supervisorctl status
|
|||||||
|
|
||||||
| 문서 | 설명 |
|
| 문서 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 |
|
| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ docker exec sam-mng-1 php artisan config:clear
|
|||||||
|
|
||||||
## 관련 문서
|
## 관련 문서
|
||||||
|
|
||||||
- [Docker 환경 구성](../specs/docker-setup.md)
|
- [Docker 환경 구성](../system/docker-setup.md)
|
||||||
- [시스템 아키텍처](../architecture/system-overview.md)
|
- [시스템 아키텍처](../system/overview.md)
|
||||||
- [바로빌 카카오톡 연동](../features/barobill-kakaotalk/README.md)
|
- [바로빌 카카오톡 연동](../features/barobill-kakaotalk/README.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -249,8 +249,8 @@ API 호출 시 → Next.js API Route 프록시 → api.sam.kr
|
|||||||
|
|
||||||
| 문서 | 설명 |
|
| 문서 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 |
|
| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||||
| [system-overview.md](../architecture/system-overview.md) | 시스템 아키텍처 레퍼런스 |
|
| [overview.md](../system/overview.md) | 시스템 아키텍처 레퍼런스 |
|
||||||
| [production-deployment-plan.md](../plans/production-deployment-plan.md) | 운영 배포 계획 |
|
| [production-deployment-plan.md](../plans/production-deployment-plan.md) | 운영 배포 계획 |
|
||||||
| [dev-commands.md](../quickstart/dev-commands.md) | 개발 명령어 모음 |
|
| [dev-commands.md](../quickstart/dev-commands.md) | 개발 명령어 모음 |
|
||||||
|
|
||||||
|
|||||||
@@ -237,8 +237,8 @@ php artisan l5-swagger:generate
|
|||||||
|
|
||||||
## 관련 문서
|
## 관련 문서
|
||||||
|
|
||||||
- [API 개발 규칙](./api_rules.md)
|
- [API 개발 규칙](../standards/api-rules.md)
|
||||||
- [개발 명령어](./dev_commands.md)
|
- [개발 명령어](../quickstart/dev-commands.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ SAM/
|
|||||||
├── CURRENT_WORKS.md # 현재 작업 현황
|
├── CURRENT_WORKS.md # 현재 작업 현황
|
||||||
│
|
│
|
||||||
└── docs/ # 상세 문서
|
└── docs/ # 상세 문서
|
||||||
├── architecture/ # 시스템 아키텍처
|
├── system/ # 시스템 현황 (아키텍처, DB, 인프라)
|
||||||
├── standards/ # 개발 표준
|
├── standards/ # 개발 표준
|
||||||
├── quickstart/ # 빠른 시작 가이드
|
├── quickstart/ # 빠른 시작 가이드
|
||||||
└── mes/ # MES/ERP 프로젝트 문서
|
└── mes/ # MES/ERP 프로젝트 문서
|
||||||
@@ -229,13 +229,13 @@ SAM/
|
|||||||
| 주제 | 문서 |
|
| 주제 | 문서 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| **프로젝트 개요** | [`CLAUDE.md`](../../CLAUDE.md) |
|
| **프로젝트 개요** | [`CLAUDE.md`](../../CLAUDE.md) |
|
||||||
| **현재 작업** | [`CURRENT_WORKS.md`](../../CURRENT_WORKS.md) |
|
| **현재 작업** | [`CURRENT_WORKS.md`](../CURRENT_WORKS.md) |
|
||||||
| **API 규칙** | [`docs/standards/api-rules.md`](../standards/api-rules.md) |
|
| **API 규칙** | [`docs/standards/api-rules.md`](../standards/api-rules.md) |
|
||||||
| **개발 명령어** | [`docs/quickstart/dev-commands.md`](./dev-commands.md) |
|
| **개발 명령어** | [`docs/quickstart/dev-commands.md`](./dev-commands.md) |
|
||||||
| **품질 체크리스트** | [`docs/standards/quality-checklist.md`](../standards/quality-checklist.md) |
|
| **품질 체크리스트** | [`docs/standards/quality-checklist.md`](../standards/quality-checklist.md) |
|
||||||
| **Git 규칙** | [`docs/standards/git-conventions.md`](../standards/git-conventions.md) |
|
| **Git 규칙** | [`docs/standards/git-conventions.md`](../standards/git-conventions.md) |
|
||||||
| **DB 스키마** | [`docs/architecture/database-schema.md`](../architecture/database-schema.md) |
|
| **DB 스키마** | [`docs/system/database/README.md`](../system/database/README.md) |
|
||||||
| **MES 프로젝트** | [`docs/mes/README.md`](../mes/README.md) |
|
| **MES 프로젝트** | [`docs/projects/mes/README.md`](../projects/mes/README.md) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -7,21 +7,29 @@
|
|||||||
- 개발 시 규칙 기반 구현 가이드
|
- 개발 시 규칙 기반 구현 가이드
|
||||||
- 검증 로직의 근거 제공
|
- 검증 로직의 근거 제공
|
||||||
|
|
||||||
## 포함 내용
|
|
||||||
- 품목코드 생성 규칙
|
|
||||||
- 필드 검증 규칙
|
|
||||||
- 상태 전이 규칙
|
|
||||||
- 권한/접근 제어 규칙
|
|
||||||
- 데이터 무결성 규칙
|
|
||||||
|
|
||||||
## 문서 목록
|
## 문서 목록
|
||||||
|
|
||||||
| 문서 | 설명 |
|
| 문서 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [item-policy.md](item-policy.md) | 품목 정책 (유형 체계, 예약어, API 규칙) |
|
| [item-policy.md](item-policy.md) | 품목 정책 (유형 체계, 예약어, API 규칙) |
|
||||||
| [pricing-policy.md](pricing-policy.md) | 단가 정책 (원가/판매가 계산, 리비전 관리) |
|
| [pricing-policy.md](pricing-policy.md) | 단가 정책 (원가/판매가 계산, 리비전 관리) |
|
||||||
|
| [customer-pricing.md](customer-pricing.md) | 고객 안내용 서비스 요금표 |
|
||||||
|
| [partner-commission.md](partner-commission.md) | 영업파트너 수당 체계 및 정산 |
|
||||||
|
| [billing-policy.md](billing-policy.md) | 내부용 원가/마진/코드참조 (CONFIDENTIAL) |
|
||||||
|
| [client-policy.md](client-policy.md) | 고객사 관리 정책 |
|
||||||
|
| [attendance-api.md](attendance-api.md) | 근태 API 규칙 |
|
||||||
|
| [department-tree-api.md](department-tree-api.md) | 부서 트리 API 규칙 |
|
||||||
|
| [employee-api.md](employee-api.md) | 직원 API 규칙 |
|
||||||
|
| [numbering-rules.md](numbering-rules.md) | 채번규칙 (패턴 기반 자동 번호 생성) |
|
||||||
|
|
||||||
|
## 첨부 파일
|
||||||
|
|
||||||
|
| 파일 | 설명 |
|
||||||
|
|------|------|
|
||||||
|
| billing-policy.pptx | 과금 정책 프레젠테이션 |
|
||||||
|
| customer-pricing.pptx | 고객 요금 프레젠테이션 |
|
||||||
|
| partner-commission.pptx | 파트너 수당 프레젠테이션 |
|
||||||
|
|
||||||
## 관련 폴더
|
## 관련 폴더
|
||||||
- [standards/](../standards/) - 개발 표준 (어떻게 코드를 작성할 것인가)
|
- [standards/](../standards/) - 개발 표준 (어떻게 코드를 작성할 것인가)
|
||||||
- [architecture/](../architecture/) - 설계 원칙 (왜 이렇게 설계하는가)
|
- [system/](../system/) - 시스템 현황 (아키텍처, DB, 인프라)
|
||||||
- [specs/](../specs/) - 기술 스펙 (무엇을 구현할 것인가)
|
|
||||||
@@ -394,7 +394,7 @@ WHERE deleted_at IS NULL;
|
|||||||
## 10. 관련 문서
|
## 10. 관련 문서
|
||||||
|
|
||||||
- [API 개발 규칙](../standards/api-rules.md)
|
- [API 개발 규칙](../standards/api-rules.md)
|
||||||
- [데이터베이스 스키마](../specs/database-schema.md)
|
- [데이터베이스 스키마](../system/database/README.md)
|
||||||
- [프론트엔드 요청서](../front/[API-2025-12-08]%20pricing-api-enhancement-request.md)
|
- [프론트엔드 요청서](../front/[API-2025-12-08]%20pricing-api-enhancement-request.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,523 +0,0 @@
|
|||||||
# 게시판 시스템 스펙
|
|
||||||
|
|
||||||
**작성일**: 2025-11-27
|
|
||||||
**상태**: 설계 완료, 구현 대기
|
|
||||||
**관련 프로젝트**: mng, api
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
### 1.1 목적
|
|
||||||
- mng에서 **시스템 게시판**을 생성하여 모든 테넌트에게 제공
|
|
||||||
- sam(api)에서 테넌트별 **자체 게시판** 생성 가능
|
|
||||||
- 공지사항, 1:1 문의, FAQ 등 다양한 게시판 유형 지원
|
|
||||||
|
|
||||||
### 1.2 핵심 개념
|
|
||||||
|
|
||||||
| 구분 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| **시스템 게시판** | mng에서 생성, `is_system=true`, 모든 테넌트에서 접근 가능 |
|
|
||||||
| **테넌트 게시판** | sam에서 생성, `is_system=false`, 해당 테넌트만 접근 |
|
|
||||||
| **board_type** | 자유 입력 (notice, qna, faq, free 등 제한 없음) |
|
|
||||||
|
|
||||||
### 1.3 역할 분리
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ mng (상위 관리자) │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ • 시스템 게시판 CRUD (is_system = true) │
|
|
||||||
│ • 게시판 필드 정의 (board_settings) │
|
|
||||||
│ • 게시판 유형 자유 설정 (board_type) │
|
|
||||||
│ • tenant_id = NULL │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
↓ 전체 테넌트 공개
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ sam (api - 테넌트용) │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ • 테넌트 게시판 CRUD (is_system = false) │
|
|
||||||
│ • 시스템 게시판 사용 (읽기 전용 구조) │
|
|
||||||
│ • 게시글 CRUD (posts) │
|
|
||||||
│ • tenant_id = 현재 테넌트 │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 데이터베이스 스키마
|
|
||||||
|
|
||||||
### 2.1 기존 테이블 현황
|
|
||||||
|
|
||||||
현재 구현된 테이블 (6개):
|
|
||||||
- `boards` - 게시판 정의
|
|
||||||
- `board_settings` - EAV 커스텀 필드 정의
|
|
||||||
- `posts` - 게시글
|
|
||||||
- `post_custom_field_values` - EAV 커스텀 필드 값
|
|
||||||
- `board_comments` - 댓글
|
|
||||||
- `board_files` - 파일 첨부
|
|
||||||
|
|
||||||
### 2.2 boards 테이블 확장
|
|
||||||
|
|
||||||
**추가 컬럼:**
|
|
||||||
|
|
||||||
| 컬럼 | 타입 | 설명 |
|
|
||||||
|------|------|------|
|
|
||||||
| `is_system` | TINYINT(1) DEFAULT 0 | 시스템 게시판 여부 (1=전체 공개) |
|
|
||||||
| `board_type` | VARCHAR(50) NULL | 게시판 유형 (자유 입력) |
|
|
||||||
|
|
||||||
**변경 컬럼:**
|
|
||||||
|
|
||||||
| 컬럼 | 변경 내용 |
|
|
||||||
|------|----------|
|
|
||||||
| `tenant_id` | NOT NULL → **NULL 허용** (시스템 게시판용) |
|
|
||||||
|
|
||||||
**최종 boards 테이블 구조:**
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE boards (
|
|
||||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
tenant_id BIGINT UNSIGNED NULL COMMENT '테넌트 ID (NULL=시스템 게시판)',
|
|
||||||
is_system TINYINT(1) DEFAULT 0 COMMENT '시스템 게시판 여부 (1=전체 테넌트 공개)',
|
|
||||||
board_type VARCHAR(50) NULL COMMENT '게시판 유형 (notice, qna, faq, free 등)',
|
|
||||||
board_code VARCHAR(50) NOT NULL COMMENT '게시판 코드 (URL용)',
|
|
||||||
name VARCHAR(100) NOT NULL COMMENT '게시판명',
|
|
||||||
description TEXT NULL COMMENT '게시판 설명',
|
|
||||||
editor_type VARCHAR(20) DEFAULT 'wysiwyg' COMMENT '에디터 타입',
|
|
||||||
allow_files TINYINT(1) DEFAULT 1 COMMENT '파일 첨부 허용',
|
|
||||||
max_file_count INT DEFAULT 5 COMMENT '최대 파일 수',
|
|
||||||
max_file_size INT DEFAULT 20480 COMMENT '최대 파일 크기 (KB)',
|
|
||||||
extra_settings JSON NULL COMMENT '추가 설정 (권한, 옵션 등)',
|
|
||||||
is_active TINYINT(1) DEFAULT 1 COMMENT '활성 여부',
|
|
||||||
created_at TIMESTAMP NULL,
|
|
||||||
updated_at TIMESTAMP NULL,
|
|
||||||
created_by BIGINT UNSIGNED NULL,
|
|
||||||
updated_by BIGINT UNSIGNED NULL,
|
|
||||||
deleted_at TIMESTAMP NULL,
|
|
||||||
deleted_by BIGINT UNSIGNED NULL,
|
|
||||||
|
|
||||||
INDEX idx_boards_tenant (tenant_id),
|
|
||||||
INDEX idx_boards_is_system (is_system),
|
|
||||||
INDEX idx_boards_board_type (board_type),
|
|
||||||
UNIQUE INDEX uk_boards_code (tenant_id, board_code)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 board_settings 테이블 (EAV 필드 정의)
|
|
||||||
|
|
||||||
현재 구조 유지:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE board_settings (
|
|
||||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
board_id BIGINT UNSIGNED NOT NULL COMMENT '게시판 ID',
|
|
||||||
name VARCHAR(100) NOT NULL COMMENT '필드명',
|
|
||||||
field_key VARCHAR(50) NOT NULL COMMENT '필드 키',
|
|
||||||
field_type VARCHAR(30) NOT NULL COMMENT '필드 타입 (text, number, select, date 등)',
|
|
||||||
field_meta JSON NULL COMMENT '필드 메타 (옵션, 유효성 등)',
|
|
||||||
is_required TINYINT(1) DEFAULT 0 COMMENT '필수 여부',
|
|
||||||
sort_order INT DEFAULT 0 COMMENT '정렬 순서',
|
|
||||||
created_at TIMESTAMP NULL,
|
|
||||||
updated_at TIMESTAMP NULL,
|
|
||||||
created_by BIGINT UNSIGNED NULL,
|
|
||||||
updated_by BIGINT UNSIGNED NULL,
|
|
||||||
|
|
||||||
INDEX idx_board_settings_board (board_id),
|
|
||||||
FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.4 posts 테이블
|
|
||||||
|
|
||||||
현재 구조 유지 (SoftDeletes 적용):
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE posts (
|
|
||||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
|
|
||||||
board_id BIGINT UNSIGNED NOT NULL COMMENT '게시판 ID',
|
|
||||||
user_id BIGINT UNSIGNED NOT NULL COMMENT '작성자 ID',
|
|
||||||
title VARCHAR(255) NOT NULL COMMENT '제목',
|
|
||||||
content LONGTEXT NULL COMMENT '내용',
|
|
||||||
editor_type VARCHAR(20) DEFAULT 'wysiwyg' COMMENT '에디터 타입',
|
|
||||||
ip_address VARCHAR(45) NULL COMMENT 'IP 주소',
|
|
||||||
is_notice TINYINT(1) DEFAULT 0 COMMENT '공지 여부',
|
|
||||||
is_secret TINYINT(1) DEFAULT 0 COMMENT '비밀글 여부',
|
|
||||||
views INT DEFAULT 0 COMMENT '조회수',
|
|
||||||
status VARCHAR(20) DEFAULT 'active' COMMENT '상태',
|
|
||||||
created_at TIMESTAMP NULL,
|
|
||||||
updated_at TIMESTAMP NULL,
|
|
||||||
created_by BIGINT UNSIGNED NULL,
|
|
||||||
updated_by BIGINT UNSIGNED NULL,
|
|
||||||
deleted_at TIMESTAMP NULL,
|
|
||||||
deleted_by BIGINT UNSIGNED NULL,
|
|
||||||
|
|
||||||
INDEX idx_posts_tenant_board (tenant_id, board_id),
|
|
||||||
INDEX idx_posts_status (status),
|
|
||||||
FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 post_custom_field_values 테이블 (EAV 값)
|
|
||||||
|
|
||||||
현재 구조 유지:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE post_custom_field_values (
|
|
||||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
post_id BIGINT UNSIGNED NOT NULL COMMENT '게시글 ID',
|
|
||||||
field_id BIGINT UNSIGNED NOT NULL COMMENT '필드 ID (board_settings.id)',
|
|
||||||
value TEXT NULL COMMENT '필드 값',
|
|
||||||
created_at TIMESTAMP NULL,
|
|
||||||
updated_at TIMESTAMP NULL,
|
|
||||||
created_by BIGINT UNSIGNED NULL,
|
|
||||||
updated_by BIGINT UNSIGNED NULL,
|
|
||||||
|
|
||||||
INDEX idx_pcfv_post (post_id),
|
|
||||||
INDEX idx_pcfv_field (field_id),
|
|
||||||
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (field_id) REFERENCES board_settings(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. 게시판 유형 (board_type)
|
|
||||||
|
|
||||||
### 3.1 권장 유형
|
|
||||||
|
|
||||||
| board_type | 설명 | 특징 |
|
|
||||||
|------------|------|------|
|
|
||||||
| `notice` | 공지사항 | 관리자만 작성, 전체 공개 |
|
|
||||||
| `qna` | 1:1 문의 | 작성자+관리자만 열람, 비밀글 기본 |
|
|
||||||
| `faq` | FAQ | 관리자 작성, 카테고리 분류 |
|
|
||||||
| `free` | 자유게시판 | 댓글 허용, 전체 공개 |
|
|
||||||
| `gallery` | 갤러리 | 이미지 중심 |
|
|
||||||
| `download` | 자료실 | 파일 첨부 중심 |
|
|
||||||
|
|
||||||
### 3.2 유형별 extra_settings 예시
|
|
||||||
|
|
||||||
```json
|
|
||||||
// notice (공지사항)
|
|
||||||
{
|
|
||||||
"write_roles": ["admin", "manager"],
|
|
||||||
"allow_comment": false,
|
|
||||||
"allow_secret": false
|
|
||||||
}
|
|
||||||
|
|
||||||
// qna (1:1 문의)
|
|
||||||
{
|
|
||||||
"write_roles": ["*"],
|
|
||||||
"allow_comment": true,
|
|
||||||
"default_secret": true,
|
|
||||||
"only_author_view": true
|
|
||||||
}
|
|
||||||
|
|
||||||
// faq
|
|
||||||
{
|
|
||||||
"write_roles": ["admin"],
|
|
||||||
"use_category": true,
|
|
||||||
"allow_comment": false
|
|
||||||
}
|
|
||||||
|
|
||||||
// free (자유게시판)
|
|
||||||
{
|
|
||||||
"write_roles": ["*"],
|
|
||||||
"allow_comment": true,
|
|
||||||
"allow_secret": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. API 설계
|
|
||||||
|
|
||||||
### 4.1 mng API (시스템 게시판 관리)
|
|
||||||
|
|
||||||
```
|
|
||||||
# 시스템 게시판 CRUD
|
|
||||||
GET /mng/boards # 시스템 게시판 목록
|
|
||||||
POST /mng/boards # 시스템 게시판 생성
|
|
||||||
GET /mng/boards/{id} # 시스템 게시판 상세
|
|
||||||
PUT /mng/boards/{id} # 시스템 게시판 수정
|
|
||||||
DELETE /mng/boards/{id} # 시스템 게시판 삭제
|
|
||||||
|
|
||||||
# 게시판 필드 관리
|
|
||||||
GET /mng/boards/{id}/fields # 필드 목록
|
|
||||||
POST /mng/boards/{id}/fields # 필드 추가
|
|
||||||
PUT /mng/boards/{id}/fields/{fid} # 필드 수정
|
|
||||||
DELETE /mng/boards/{id}/fields/{fid} # 필드 삭제
|
|
||||||
POST /mng/boards/{id}/fields/reorder # 필드 순서 변경
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 sam API (테넌트용)
|
|
||||||
|
|
||||||
```
|
|
||||||
# 게시판 조회 (시스템 + 테넌트)
|
|
||||||
GET /v1/boards # 접근 가능한 게시판 목록
|
|
||||||
GET /v1/boards/{code} # 게시판 상세
|
|
||||||
|
|
||||||
# 테넌트 게시판 관리
|
|
||||||
POST /v1/boards # 테넌트 게시판 생성
|
|
||||||
PUT /v1/boards/{code} # 테넌트 게시판 수정
|
|
||||||
DELETE /v1/boards/{code} # 테넌트 게시판 삭제
|
|
||||||
|
|
||||||
# 게시글 CRUD
|
|
||||||
GET /v1/boards/{code}/posts # 게시글 목록
|
|
||||||
POST /v1/boards/{code}/posts # 게시글 작성
|
|
||||||
GET /v1/boards/{code}/posts/{id} # 게시글 상세
|
|
||||||
PUT /v1/boards/{code}/posts/{id} # 게시글 수정
|
|
||||||
DELETE /v1/boards/{code}/posts/{id} # 게시글 삭제
|
|
||||||
|
|
||||||
# 댓글
|
|
||||||
GET /v1/posts/{id}/comments # 댓글 목록
|
|
||||||
POST /v1/posts/{id}/comments # 댓글 작성
|
|
||||||
PUT /v1/comments/{id} # 댓글 수정
|
|
||||||
DELETE /v1/comments/{id} # 댓글 삭제
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 모델 설계
|
|
||||||
|
|
||||||
### 5.1 Board 모델
|
|
||||||
|
|
||||||
```php
|
|
||||||
// api/app/Models/Boards/Board.php
|
|
||||||
|
|
||||||
namespace App\Models\Boards;
|
|
||||||
|
|
||||||
use App\Traits\BelongsToTenant;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
||||||
|
|
||||||
class Board extends Model
|
|
||||||
{
|
|
||||||
use SoftDeletes;
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'tenant_id', 'is_system', 'board_type', 'board_code', 'name',
|
|
||||||
'description', 'editor_type', 'allow_files', 'max_file_count',
|
|
||||||
'max_file_size', 'extra_settings', 'is_active',
|
|
||||||
'created_by', 'updated_by', 'deleted_by',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $casts = [
|
|
||||||
'is_system' => 'boolean',
|
|
||||||
'is_active' => 'boolean',
|
|
||||||
'allow_files' => 'boolean',
|
|
||||||
'extra_settings' => 'array',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 현재 테넌트에서 접근 가능한 게시판
|
|
||||||
* - 시스템 게시판 (is_system = true)
|
|
||||||
* - 해당 테넌트 게시판 (tenant_id = 현재 테넌트)
|
|
||||||
*/
|
|
||||||
public function scopeAccessible($query, int $tenantId)
|
|
||||||
{
|
|
||||||
return $query->where(function ($q) use ($tenantId) {
|
|
||||||
$q->where('is_system', true)
|
|
||||||
->orWhere('tenant_id', $tenantId);
|
|
||||||
})->where('is_active', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 시스템 게시판만 (mng용)
|
|
||||||
*/
|
|
||||||
public function scopeSystemOnly($query)
|
|
||||||
{
|
|
||||||
return $query->where('is_system', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 테넌트 게시판만
|
|
||||||
*/
|
|
||||||
public function scopeTenantOnly($query, int $tenantId)
|
|
||||||
{
|
|
||||||
return $query->where('is_system', false)
|
|
||||||
->where('tenant_id', $tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 관계
|
|
||||||
public function fields()
|
|
||||||
{
|
|
||||||
return $this->hasMany(BoardSetting::class, 'board_id')
|
|
||||||
->orderBy('sort_order');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function posts()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Post::class, 'board_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper
|
|
||||||
public function getSetting(string $key, $default = null)
|
|
||||||
{
|
|
||||||
return data_get($this->extra_settings, $key, $default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 BoardService
|
|
||||||
|
|
||||||
```php
|
|
||||||
// api/app/Services/Boards/BoardService.php
|
|
||||||
|
|
||||||
namespace App\Services\Boards;
|
|
||||||
|
|
||||||
use App\Models\Boards\Board;
|
|
||||||
use App\Services\Service;
|
|
||||||
|
|
||||||
class BoardService extends Service
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 접근 가능한 게시판 목록 (시스템 + 테넌트)
|
|
||||||
*/
|
|
||||||
public function getAccessibleBoards(array $filters = [])
|
|
||||||
{
|
|
||||||
return Board::accessible($this->tenantId())
|
|
||||||
->when(isset($filters['board_type']), fn($q) =>
|
|
||||||
$q->where('board_type', $filters['board_type']))
|
|
||||||
->orderBy('is_system', 'desc')
|
|
||||||
->orderBy('name')
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 시스템 게시판 목록 (mng용)
|
|
||||||
*/
|
|
||||||
public function getSystemBoards()
|
|
||||||
{
|
|
||||||
return Board::systemOnly()
|
|
||||||
->orderBy('name')
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 시스템 게시판 생성 (mng용)
|
|
||||||
*/
|
|
||||||
public function createSystemBoard(array $data): Board
|
|
||||||
{
|
|
||||||
$data['is_system'] = true;
|
|
||||||
$data['tenant_id'] = null;
|
|
||||||
$data['created_by'] = $this->apiUserId();
|
|
||||||
|
|
||||||
return Board::create($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 테넌트 게시판 생성 (sam용)
|
|
||||||
*/
|
|
||||||
public function createTenantBoard(array $data): Board
|
|
||||||
{
|
|
||||||
$data['is_system'] = false;
|
|
||||||
$data['tenant_id'] = $this->tenantId();
|
|
||||||
$data['created_by'] = $this->apiUserId();
|
|
||||||
|
|
||||||
return Board::create($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 게시판 코드로 조회
|
|
||||||
*/
|
|
||||||
public function getBoardByCode(string $code): ?Board
|
|
||||||
{
|
|
||||||
return Board::accessible($this->tenantId())
|
|
||||||
->where('board_code', $code)
|
|
||||||
->first();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. 권한 모델
|
|
||||||
|
|
||||||
### 6.1 extra_settings 기반 권한
|
|
||||||
|
|
||||||
게시판별 권한은 `extra_settings` JSON 필드로 관리:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"read": ["*"], // 모든 역할 읽기 가능
|
|
||||||
"write": ["admin", "user"], // admin, user 역할만 작성
|
|
||||||
"manage": ["admin"] // admin만 관리
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.2 권한 검증
|
|
||||||
|
|
||||||
```php
|
|
||||||
// Board 모델에 추가
|
|
||||||
public function canRead(User $user): bool
|
|
||||||
{
|
|
||||||
$roles = $this->getSetting('permissions.read', ['*']);
|
|
||||||
return in_array('*', $roles) ||
|
|
||||||
$user->hasAnyRole($roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canWrite(User $user): bool
|
|
||||||
{
|
|
||||||
$roles = $this->getSetting('permissions.write', ['*']);
|
|
||||||
return in_array('*', $roles) ||
|
|
||||||
$user->hasAnyRole($roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canManage(User $user): bool
|
|
||||||
{
|
|
||||||
$roles = $this->getSetting('permissions.manage', ['admin']);
|
|
||||||
return $user->hasAnyRole($roles);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. 구현 계획
|
|
||||||
|
|
||||||
### 7.1 Phase 1: DB 마이그레이션 (api/)
|
|
||||||
|
|
||||||
1. `boards` 테이블 확장
|
|
||||||
- `tenant_id` nullable 변경
|
|
||||||
- `is_system` 컬럼 추가
|
|
||||||
- `board_type` 컬럼 추가
|
|
||||||
- `deleted_at`, `deleted_by` 추가 (없으면)
|
|
||||||
- 인덱스 추가
|
|
||||||
|
|
||||||
### 7.2 Phase 2: 모델/서비스 수정 (api/)
|
|
||||||
|
|
||||||
1. `Board` 모델 업데이트
|
|
||||||
- 스코프 추가 (accessible, systemOnly, tenantOnly)
|
|
||||||
- SoftDeletes 적용
|
|
||||||
- 권한 헬퍼 메서드
|
|
||||||
|
|
||||||
2. `BoardService` 구현
|
|
||||||
- 시스템/테넌트 게시판 분리 로직
|
|
||||||
|
|
||||||
### 7.3 Phase 3: mng 화면 개발
|
|
||||||
|
|
||||||
1. 게시판 목록 (`/mng/boards`)
|
|
||||||
2. 게시판 생성/수정 폼
|
|
||||||
3. 게시판 필드 관리
|
|
||||||
|
|
||||||
### 7.4 Phase 4: sam API 개발
|
|
||||||
|
|
||||||
1. 게시판 API (`/v1/boards`)
|
|
||||||
2. 게시글 API (`/v1/boards/{code}/posts`)
|
|
||||||
3. Swagger 문서
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. 관련 문서
|
|
||||||
|
|
||||||
- [데이터베이스 스키마](./database-schema.md)
|
|
||||||
- [API 개발 규칙](../reference/api-rules.md)
|
|
||||||
- [MNG Critical Rules](../../mng/docs/MNG_CRITICAL_RULES.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**최종 업데이트**: 2025-11-27
|
|
||||||
**버전**: 1.0
|
|
||||||
**상태**: 설계 완료
|
|
||||||
@@ -1,545 +0,0 @@
|
|||||||
# SAM 데이터베이스 스키마
|
|
||||||
|
|
||||||
**업데이트**: 2026-01-29
|
|
||||||
**데이터베이스**: samdb (MySQL 8.0.44)
|
|
||||||
**전체 테이블**: 219개
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Multi-tenant 데이터 아키텍처
|
|
||||||
|
|
||||||
### 데이터 격리 방식
|
|
||||||
|
|
||||||
- **방식**: `tenant_id` 컬럼 기반 격리
|
|
||||||
- **스코프**: BelongsToTenant global scope 자동 적용
|
|
||||||
- **모델**: `shared/Models/` 디렉토리의 공통 모델 사용
|
|
||||||
- **Soft Deletes**: 대부분의 엔티티에 적용
|
|
||||||
- **감사 컬럼**: `created_by`, `updated_by`, `deleted_by`
|
|
||||||
|
|
||||||
## 핵심 테이블 구조
|
|
||||||
|
|
||||||
### 인증 및 권한
|
|
||||||
|
|
||||||
#### users (24 컬럼) - Phase 4 완료
|
|
||||||
**용도**: 시스템 사용자 정보 (관리자, 일반 사용자)
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `id` (PK), `user_id` (UK), `name`, `email` (UK), `password`
|
|
||||||
- `phone`, `role` (deprecated), `is_active`, `is_super_admin`
|
|
||||||
- `email_verified_at`, `last_login_at`
|
|
||||||
- 2FA: `two_factor_secret`, `two_factor_recovery_codes`, `two_factor_confirmed_at`
|
|
||||||
- `remember_token`, `current_team_id`, `profile_photo_path`
|
|
||||||
- `options` (JSON)
|
|
||||||
- Audit: `created_by`, `updated_by`, `deleted_by`
|
|
||||||
- Timestamps: `created_at`, `updated_at`, `deleted_at` (Soft Delete)
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- Laravel Sanctum 인증
|
|
||||||
- Multi-tenant via `user_tenants` pivot
|
|
||||||
- 2FA 지원
|
|
||||||
- Soft Delete 지원
|
|
||||||
|
|
||||||
#### roles (11 컬럼) - Phase 4 완료, Spatie Permission
|
|
||||||
**용도**: 사용자 역할 정의
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `id` (PK), `tenant_id`, `name`, `guard_name`, `description`
|
|
||||||
- Audit: `created_by`, `updated_by`, `deleted_by`
|
|
||||||
- Timestamps: `created_at`, `updated_at`, `deleted_at`
|
|
||||||
|
|
||||||
인덱스:
|
|
||||||
- `UNIQUE (tenant_id, name, guard_name)`
|
|
||||||
- `INDEX (tenant_id)`
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- Spatie Laravel Permission 패키지
|
|
||||||
- Multi-tenant 지원
|
|
||||||
- Soft Delete 지원
|
|
||||||
|
|
||||||
#### permissions (8 컬럼) - Phase 4 완료, Spatie Permission
|
|
||||||
**용도**: 시스템 권한 정의
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `id` (PK), `tenant_id` (nullable), `name`, `guard_name`
|
|
||||||
- Audit: `created_by`, `updated_by`
|
|
||||||
- Timestamps: `created_at`, `updated_at`
|
|
||||||
|
|
||||||
인덱스:
|
|
||||||
- `UNIQUE (name, guard_name, tenant_id)`
|
|
||||||
- `INDEX (tenant_id)`
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- tenant_id nullable (마스터 권한 지원)
|
|
||||||
- Spatie Laravel Permission 패키지
|
|
||||||
|
|
||||||
#### model_has_roles (4 컬럼) - Spatie Permission
|
|
||||||
**용도**: 사용자-역할 연결 (Many-to-Many)
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `role_id` (PK, FK), `model_type` (PK), `model_id` (PK), `tenant_id` (PK)
|
|
||||||
|
|
||||||
외래키:
|
|
||||||
- `role_id` → `roles.id` (ON DELETE CASCADE)
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- Polymorphic 관계
|
|
||||||
- Multi-tenant 지원
|
|
||||||
|
|
||||||
#### role_has_permissions (2 컬럼) - Spatie Permission
|
|
||||||
**용도**: 역할-권한 연결 (Many-to-Many)
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `permission_id` (PK, FK), `role_id` (PK, FK)
|
|
||||||
|
|
||||||
외래키:
|
|
||||||
- `permission_id` → `permissions.id` (ON DELETE CASCADE)
|
|
||||||
- `role_id` → `roles.id` (ON DELETE CASCADE)
|
|
||||||
|
|
||||||
#### user_tenants
|
|
||||||
- 사용자-테넌트 다대다 관계
|
|
||||||
- `active`, `default` 플래그
|
|
||||||
|
|
||||||
#### personal_access_tokens
|
|
||||||
- Sanctum 토큰 저장
|
|
||||||
|
|
||||||
#### api_keys
|
|
||||||
- API 키 관리
|
|
||||||
- `is_active` 상태 관리
|
|
||||||
|
|
||||||
#### permission_overrides
|
|
||||||
- 수동 권한 허용/거부
|
|
||||||
- 시간 기반 유효성
|
|
||||||
|
|
||||||
### 멀티테넌트 조직
|
|
||||||
|
|
||||||
#### tenants (32 컬럼) - Phase 4 완료
|
|
||||||
**용도**: 다중 회사/조직 관리 (Multi-tenant 핵심)
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `id` (PK), `company_name`, `code` (UK)
|
|
||||||
- `email`, `phone`, `address`, `business_num`, `corp_reg_no`, `ceo_name`
|
|
||||||
- `homepage`, `fax`, `logo`, `admin_memo`, `options` (JSON)
|
|
||||||
- `tenant_st_code` (trial/active/none), `plan_id`, `subscription_id`
|
|
||||||
- `max_users`, `trial_ends_at`, `expires_at`, `last_paid_at`, `billing_tp_code`
|
|
||||||
- 저장소: `storage_limit`, `storage_used`, `storage_warning_sent_at`, `storage_grace_period_until`
|
|
||||||
- Audit: `created_by`, `updated_by`, `deleted_by`
|
|
||||||
- Timestamps: `created_at`, `updated_at`, `deleted_at`
|
|
||||||
|
|
||||||
인덱스:
|
|
||||||
- `UNIQUE (code)`
|
|
||||||
- `INDEX (storage_used)`
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- Multi-tenant 시스템의 핵심 테이블
|
|
||||||
- 구독/결제 관리
|
|
||||||
- 저장소 용량 관리 (기본 10GB)
|
|
||||||
- Soft Delete 지원
|
|
||||||
|
|
||||||
#### departments (14 컬럼) - Phase 4 완료
|
|
||||||
**용도**: 조직 부서 정보 (계층 구조)
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `id` (PK), `tenant_id`, `parent_id` (Self-referential)
|
|
||||||
- `code`, `name`, `description`
|
|
||||||
- `is_active`, `sort_order`
|
|
||||||
- Audit: `created_by`, `updated_by`, `deleted_by`
|
|
||||||
- Timestamps: `created_at`, `updated_at`, `deleted_at`
|
|
||||||
|
|
||||||
인덱스:
|
|
||||||
- `UNIQUE (tenant_id, code)`
|
|
||||||
- `INDEX (tenant_id, name)`
|
|
||||||
- `INDEX (tenant_id, is_active)`
|
|
||||||
- `INDEX (parent_id)`
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- Self-referential 관계 (무제한 depth)
|
|
||||||
- 활성 상태 관리
|
|
||||||
- 정렬 순서 지원
|
|
||||||
- Soft Delete 지원
|
|
||||||
|
|
||||||
#### tenant_user_profiles
|
|
||||||
- 테넌트별 확장 사용자 프로필
|
|
||||||
|
|
||||||
#### department_user
|
|
||||||
- 사용자-부서 할당
|
|
||||||
- `primary` 부서 플래그
|
|
||||||
|
|
||||||
### 제품 관리
|
|
||||||
|
|
||||||
#### categories
|
|
||||||
- 계층적 제품 분류
|
|
||||||
- Soft Deletes 적용
|
|
||||||
|
|
||||||
#### category_fields
|
|
||||||
- 카테고리별 동적 필드 정의
|
|
||||||
|
|
||||||
#### category_templates
|
|
||||||
- 버전 관리된 카테고리 필드 스냅샷
|
|
||||||
|
|
||||||
#### products
|
|
||||||
- 제품 카탈로그
|
|
||||||
- 타입 분류: `PRODUCT`, `PART`, `SUBASSEMBLY`
|
|
||||||
|
|
||||||
#### product_components
|
|
||||||
- BOM 관계
|
|
||||||
- `MATERIAL` 또는 `PRODUCT` 참조
|
|
||||||
|
|
||||||
#### materials
|
|
||||||
- 자재 마스터
|
|
||||||
- 동적 속성 지원
|
|
||||||
|
|
||||||
#### classifications
|
|
||||||
- 그룹별 플랫 코드 테이블
|
|
||||||
- 예: `product_type`, `payment_method`
|
|
||||||
|
|
||||||
### 디자인 및 제조
|
|
||||||
|
|
||||||
#### models
|
|
||||||
- 디자인 모델 마스터
|
|
||||||
- 생명주기 상태 관리
|
|
||||||
|
|
||||||
#### model_versions
|
|
||||||
- 버전 관리된 모델 릴리스
|
|
||||||
- 상태: `DRAFT`, `RELEASED`
|
|
||||||
|
|
||||||
#### bom_templates
|
|
||||||
- 모델 버전에 연결된 BOM 템플릿
|
|
||||||
|
|
||||||
#### bom_template_items
|
|
||||||
- 템플릿 BOM 라인 항목
|
|
||||||
- 수량 및 낭비율 포함
|
|
||||||
|
|
||||||
### 주문 및 운영
|
|
||||||
|
|
||||||
#### orders
|
|
||||||
- 주문/견적 마스터
|
|
||||||
- 워크플로우 상태
|
|
||||||
|
|
||||||
#### order_items
|
|
||||||
- 주문 라인 항목
|
|
||||||
- 디자인 코드 포함
|
|
||||||
|
|
||||||
#### order_item_components
|
|
||||||
- 주문 항목별 필수 자재/제품
|
|
||||||
|
|
||||||
#### order_histories
|
|
||||||
- 주문 변경 추적 및 메모
|
|
||||||
|
|
||||||
#### clients
|
|
||||||
- 고객/벤더 마스터
|
|
||||||
|
|
||||||
### 재고 및 자재
|
|
||||||
|
|
||||||
#### material_receipts
|
|
||||||
- 입고 자재 수령
|
|
||||||
- 로트 추적
|
|
||||||
|
|
||||||
#### material_inspections
|
|
||||||
- 품질 검사 기록
|
|
||||||
|
|
||||||
#### material_inspection_items
|
|
||||||
- 검사 체크리스트 항목
|
|
||||||
|
|
||||||
#### lots
|
|
||||||
- 자재 로트 관리
|
|
||||||
|
|
||||||
#### lot_sales
|
|
||||||
- 로트 소비 추적
|
|
||||||
|
|
||||||
#### price_histories
|
|
||||||
- 시간 기반 유효성을 가진 가격 이력
|
|
||||||
|
|
||||||
### 시스템 및 설정
|
|
||||||
|
|
||||||
#### menus (17 컬럼) - Phase 4 완료
|
|
||||||
**용도**: 시스템 메뉴 트리 구조 (사이드바, 권한 연동)
|
|
||||||
|
|
||||||
주요 컬럼:
|
|
||||||
- `id` (PK), `tenant_id` (nullable), `parent_id` (Self-referential)
|
|
||||||
- `name`, `url`, `icon`
|
|
||||||
- `is_active`, `hidden`, `is_external`, `external_url`
|
|
||||||
- `sort_order`
|
|
||||||
- Audit: `created_by`, `updated_by`, `deleted_by`
|
|
||||||
- Timestamps: `created_at`, `updated_at`, `deleted_at`
|
|
||||||
|
|
||||||
인덱스:
|
|
||||||
- `INDEX (tenant_id)`
|
|
||||||
- `INDEX (parent_id)`
|
|
||||||
- `INDEX (sort_order)`
|
|
||||||
- `INDEX (tenant_id, is_active, hidden)`
|
|
||||||
- `INDEX (tenant_id, deleted_at)`
|
|
||||||
- `INDEX (deleted_at)`
|
|
||||||
|
|
||||||
특징:
|
|
||||||
- Self-referential 관계 (무제한 depth)
|
|
||||||
- tenant_id nullable (마스터 메뉴 지원)
|
|
||||||
- 활성/숨김 상태 토글
|
|
||||||
- 내부/외부 링크 지원
|
|
||||||
- Soft Delete 지원
|
|
||||||
|
|
||||||
#### common_codes
|
|
||||||
- 계층적 마스터 코드
|
|
||||||
- 테넌트 지원
|
|
||||||
|
|
||||||
#### files
|
|
||||||
- 다형성 파일 첨부
|
|
||||||
|
|
||||||
#### audit_logs
|
|
||||||
- 포괄적인 감사 추적
|
|
||||||
- 13개월 보관
|
|
||||||
|
|
||||||
#### setting_field_defs
|
|
||||||
- 전역 필드 정의
|
|
||||||
|
|
||||||
#### tenant_field_settings
|
|
||||||
- 테넌트별 필드 설정
|
|
||||||
|
|
||||||
#### tenant_option_groups / tenant_option_values
|
|
||||||
- 테넌트 관리 드롭다운 옵션
|
|
||||||
|
|
||||||
### 콘텐츠 관리
|
|
||||||
|
|
||||||
#### boards
|
|
||||||
- 설정 가능한 게시판 시스템
|
|
||||||
|
|
||||||
#### posts
|
|
||||||
- 커스텀 필드를 가진 게시판 게시물
|
|
||||||
|
|
||||||
#### board_settings
|
|
||||||
- 게시판별 동적 필드 정의
|
|
||||||
|
|
||||||
#### board_comments
|
|
||||||
- 계층적 댓글 시스템
|
|
||||||
|
|
||||||
## 주요 모델 관계
|
|
||||||
|
|
||||||
### 관계 구조
|
|
||||||
|
|
||||||
```
|
|
||||||
Tenant → Users (many-to-many via user_tenants)
|
|
||||||
Products ↔ Materials (via product_components with ref_type)
|
|
||||||
Models → Versions → BOM Templates (design workflow)
|
|
||||||
Orders → Items → Components (order breakdown)
|
|
||||||
Categories ↔ Fields ↔ Templates (dynamic forms with versioning)
|
|
||||||
Audit Logs (polymorphic tracking across all major entities)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 공통 컬럼 패턴
|
|
||||||
|
|
||||||
### 필수 컬럼
|
|
||||||
|
|
||||||
모든 테이블에 포함되어야 하는 컬럼:
|
|
||||||
|
|
||||||
```php
|
|
||||||
Schema::create('products', function (Blueprint $table) {
|
|
||||||
$table->id()->comment('ID');
|
|
||||||
$table->foreignId('tenant_id')->comment('테넌트 ID');
|
|
||||||
|
|
||||||
// 비즈니스 컬럼...
|
|
||||||
|
|
||||||
$table->foreignId('created_by')->nullable()->comment('생성자 ID');
|
|
||||||
$table->foreignId('updated_by')->nullable()->comment('수정자 ID');
|
|
||||||
$table->foreignId('deleted_by')->nullable()->comment('삭제자 ID');
|
|
||||||
$table->timestamps();
|
|
||||||
$table->softDeletes();
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 컬럼 규칙
|
|
||||||
|
|
||||||
- **tenant_id**: 필수, 인덱스 권장
|
|
||||||
- **created_by, updated_by, deleted_by**: nullable, COMMENT 필수
|
|
||||||
- **deleted_at**: Soft Delete용
|
|
||||||
- **timestamps**: created_at, updated_at
|
|
||||||
|
|
||||||
## 인덱스 최적화
|
|
||||||
|
|
||||||
### 필수 인덱스
|
|
||||||
|
|
||||||
- `tenant_id` - 모든 테이블에 권장
|
|
||||||
- 검색/정렬에 사용되는 컬럼
|
|
||||||
- 복합 인덱스 고려
|
|
||||||
|
|
||||||
### 주요 유니크 제약
|
|
||||||
|
|
||||||
- `models(code)` - 모델 코드
|
|
||||||
- `model_versions(version_no)` - 버전 번호
|
|
||||||
- `bom_items(parent, order)` - BOM 항목 순서
|
|
||||||
|
|
||||||
## Foreign Key 제약조건
|
|
||||||
|
|
||||||
### 정책
|
|
||||||
|
|
||||||
- **개발 환경**: 설계 단계에서 제약조건 생성
|
|
||||||
- **운영 환경**: 최소화 또는 제거
|
|
||||||
|
|
||||||
### 이유
|
|
||||||
|
|
||||||
- 성능 최적화
|
|
||||||
- 유연한 데이터 관리
|
|
||||||
- 마이그레이션 복잡도 감소
|
|
||||||
|
|
||||||
## 감사 로그
|
|
||||||
|
|
||||||
### 테이블 구조
|
|
||||||
|
|
||||||
**audit_logs:**
|
|
||||||
- `tenant_id` - 테넌트 ID
|
|
||||||
- `target_type` - 대상 모델 타입 (polymorphic)
|
|
||||||
- `target_id` - 대상 ID
|
|
||||||
- `action` - 액션 타입
|
|
||||||
- `before` - 변경 전 데이터 (JSON)
|
|
||||||
- `after` - 변경 후 데이터 (JSON)
|
|
||||||
- `actor_id` - 수행자 ID
|
|
||||||
- `ip` - IP 주소
|
|
||||||
- `ua` - User Agent
|
|
||||||
- `created_at` - 생성 시간
|
|
||||||
|
|
||||||
### 보관 정책
|
|
||||||
|
|
||||||
- **기본 보관 기간**: 13개월
|
|
||||||
- **정리**: `audit:prune` 스케줄러 (매일 03:10)
|
|
||||||
- **실패 허용**: 감사 로그 실패 시 비즈니스 로직 계속 진행
|
|
||||||
|
|
||||||
## 데이터베이스 작업 시 주의사항
|
|
||||||
|
|
||||||
### 마이그레이션 작성
|
|
||||||
|
|
||||||
```
|
|
||||||
✓ 명확한 파일명 (YYYY_MM_DD_HHMMSS_action_table.php)
|
|
||||||
✓ up/down 메서드 모두 구현
|
|
||||||
✓ 롤백 테스트 완료
|
|
||||||
✓ COMMENT 추가 (tenant_id, created_by 등)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 모델 작성
|
|
||||||
|
|
||||||
```
|
|
||||||
✓ BelongsToTenant scope 적용
|
|
||||||
✓ ModelTrait 사용
|
|
||||||
✓ SoftDeletes 적용
|
|
||||||
✓ tenant_id 필터링 확인
|
|
||||||
```
|
|
||||||
|
|
||||||
### 쿼리 작성
|
|
||||||
|
|
||||||
```
|
|
||||||
✓ tenant_id 필터링 필수
|
|
||||||
✓ Eager Loading 사용 (N+1 문제 방지)
|
|
||||||
✓ 인덱스 활용 고려
|
|
||||||
```
|
|
||||||
|
|
||||||
## 관련 문서
|
|
||||||
|
|
||||||
- [API 개발 규칙](./api_rules.md)
|
|
||||||
- [아키텍처](./architecture.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 4 구현 상세 (2025-11-24)
|
|
||||||
|
|
||||||
### 완료된 테이블 (8개)
|
|
||||||
1. **users** - 사용자 관리 (Sanctum 인증, 2FA)
|
|
||||||
2. **roles** - 역할 관리 (Spatie Permission)
|
|
||||||
3. **permissions** - 권한 관리 (Spatie Permission)
|
|
||||||
4. **model_has_roles** - 사용자-역할 연결
|
|
||||||
5. **role_has_permissions** - 역할-권한 연결
|
|
||||||
6. **departments** - 부서 관리 (계층 구조)
|
|
||||||
7. **menus** - 메뉴 관리 (트리 구조)
|
|
||||||
8. **tenants** - 테넌트 관리 (구독/저장소)
|
|
||||||
|
|
||||||
### Spatie Permission 통합
|
|
||||||
```php
|
|
||||||
// 역할 할당
|
|
||||||
$user->assignRole('admin');
|
|
||||||
|
|
||||||
// 권한 확인
|
|
||||||
$user->hasPermissionTo('users.view');
|
|
||||||
|
|
||||||
// 역할에 권한 할당
|
|
||||||
$role->syncPermissions(['users.view', 'users.create']);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 공통 패턴
|
|
||||||
- **Soft Delete**: deleted_at, deleted_by
|
|
||||||
- **Audit**: created_by, updated_by, deleted_by
|
|
||||||
- **Multi-tenant**: tenant_id (nullable for master data)
|
|
||||||
- **Self-referential**: parent_id (departments, menus)
|
|
||||||
- **Active Status**: is_active
|
|
||||||
- **Sort Order**: sort_order
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**최종 업데이트**: 2026-01-30
|
|
||||||
**Phase 4**: 완료 (8개 테이블 상세화)
|
|
||||||
**테이블 수 갱신**: samdb 219개 + sam_stat 20개 = 239개
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## sam_stat 데이터베이스 (통계 전용)
|
|
||||||
|
|
||||||
> 별도 MySQL 데이터베이스. Laravel `sam_stat` 커넥션 사용. 마이그레이션 경로: `database/migrations/stats/`
|
|
||||||
|
|
||||||
### 메타/관리 테이블
|
|
||||||
|
|
||||||
| 테이블 | 설명 | 주요 컬럼 |
|
|
||||||
|--------|------|----------|
|
|
||||||
| `stat_definitions` | 통계 정의 마스터 | domain, stat_type, table_name, is_active |
|
|
||||||
| `stat_job_logs` | 집계 작업 로그 | tenant_id, job_type, target_date, status, records_processed, duration_ms |
|
|
||||||
|
|
||||||
### 차원 테이블
|
|
||||||
|
|
||||||
| 테이블 | 설명 | 주요 컬럼 |
|
|
||||||
|--------|------|----------|
|
|
||||||
| `dim_date` | 날짜 차원 (2020~2030) | date, year, quarter, month, day, day_of_week, is_weekend, is_holiday |
|
|
||||||
| `dim_client` | 고객 차원 (samdb 동기화) | tenant_id, source_client_id, client_name, group_name |
|
|
||||||
| `dim_product` | 제품 차원 (samdb 동기화) | tenant_id, source_product_id, product_name, product_type |
|
|
||||||
|
|
||||||
### 일간 팩트 테이블 (7개)
|
|
||||||
|
|
||||||
| 테이블 | 도메인 | UK | 주요 지표 |
|
|
||||||
|--------|--------|------|----------|
|
|
||||||
| `stat_sales_daily` | 매출/수주 | (tenant_id, stat_date) | order_count/amount, sales_count/amount, new/active_client_count, shipment_count/amount |
|
|
||||||
| `stat_finance_daily` | 재무/회계 | (tenant_id, stat_date) | deposit/withdrawal count/amount, net_cashflow, purchase_count/amount, bank_balance_total |
|
|
||||||
| `stat_production_daily` | 생산/작업 | (tenant_id, stat_date) | work_order_count, completed/in_progress_count, defect_count/rate, total_quantity |
|
|
||||||
| `stat_inventory_daily` | 재고 | (tenant_id, stat_date) | receipt_count/quantity, shipment_count/quantity, total_stock_value, low_stock_count |
|
|
||||||
| `stat_quote_pipeline_daily` | 견적/영업 | (tenant_id, stat_date) | new/sent/won/lost_quote_count, pipeline_value, conversion_rate, avg_quote_amount |
|
|
||||||
| `stat_hr_attendance_daily` | 인사/근태 | (tenant_id, stat_date) | total/present/absent/late/leave_count, overtime_hours, attendance_rate |
|
|
||||||
| `stat_system_daily` | 시스템/감사 | (tenant_id, stat_date) | api_request/error_count, active_user_count, audit_create/update/delete_count, fcm_sent/failed_count |
|
|
||||||
|
|
||||||
### 월간 요약 테이블 (4개)
|
|
||||||
|
|
||||||
| 테이블 | 도메인 | UK | 주요 지표 |
|
|
||||||
|--------|--------|------|----------|
|
|
||||||
| `stat_sales_monthly` | 매출/수주 | (tenant_id, stat_year, stat_month) | order/sales/shipment count/amount, unique_client_count, avg_order_amount, mom/yoy_growth_rate |
|
|
||||||
| `stat_finance_monthly` | 재무/회계 | (tenant_id, stat_year, stat_month) | deposit/withdrawal/purchase_total, net_cashflow, bank_balance_end, mom_cashflow_change |
|
|
||||||
| `stat_production_monthly` | 생산/작업 | (tenant_id, stat_year, stat_month) | total_work_orders, completed/in_progress_count, avg_defect_rate, total_production_quantity |
|
|
||||||
| `stat_project_monthly` | 건설/프로젝트 | (tenant_id, stat_year, stat_month) | active/completed_site_count, new_contract_count/amount, gross_profit/rate |
|
|
||||||
|
|
||||||
### KPI/알림/이벤트 테이블
|
|
||||||
|
|
||||||
| 테이블 | 설명 | 주요 컬럼 |
|
|
||||||
|--------|------|----------|
|
|
||||||
| `stat_kpi_targets` | KPI 목표값 | tenant_id, domain, metric_code, target_year/month, target_value, actual_value |
|
|
||||||
| `stat_alerts` | 통계 알림 | tenant_id, domain, alert_type, severity(enum: info/warning/critical), title, message, is_read, is_resolved |
|
|
||||||
| `stat_events` | 실시간 이벤트 로그 | tenant_id, domain, event_type, entity_type, entity_id, payload(JSON), occurred_at |
|
|
||||||
| `stat_snapshots` | 상태 스냅샷 | tenant_id, snapshot_date, domain, snapshot_type, data(JSON) |
|
|
||||||
|
|
||||||
### Artisan 커맨드
|
|
||||||
|
|
||||||
| 커맨드 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| `stat:aggregate-daily` | 일간 통계 집계 (스케줄러: 매일 01:00) |
|
|
||||||
| `stat:aggregate-monthly` | 월간 통계 집계 (스케줄러: 매월 1일 02:00) |
|
|
||||||
| `stat:sync-dimensions` | 차원 테이블 동기화 (스케줄러: 매일 00:30) |
|
|
||||||
| `stat:backfill --from= --to=` | 과거 데이터 일괄 백필 |
|
|
||||||
| `stat:verify --date=` | 원본 DB vs sam_stat 정합성 검증 |
|
|
||||||
|
|
||||||
### API 엔드포인트
|
|
||||||
|
|
||||||
| Method | Path | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| GET | `/api/v1/stats/summary` | 대시보드 통계 요약 |
|
|
||||||
| GET | `/api/v1/stats/daily` | 도메인별 일간 통계 (domain, start_date, end_date) |
|
|
||||||
| GET | `/api/v1/stats/monthly` | 도메인별 월간 통계 (domain, year, month?) |
|
|
||||||
| GET | `/api/v1/stats/alerts` | 통계 알림 목록 (limit?, unread_only?) |
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
# Docker 설정 가이드
|
|
||||||
|
|
||||||
## 개요
|
|
||||||
|
|
||||||
SAM 프로젝트는 Docker Compose를 사용하여 로컬 개발 환경을 구성합니다.
|
|
||||||
|
|
||||||
## 서비스 구성
|
|
||||||
|
|
||||||
### docker-compose.yml 구조
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
nginx: # 리버스 프록시
|
|
||||||
api: # Laravel 12 API (PHP 8.4)
|
|
||||||
mng: # Laravel 12 관리자 패널 (PHP 8.4)
|
|
||||||
react: # Next.js 15 (Node 20)
|
|
||||||
design: # 디자인 시스템 (Storybook)
|
|
||||||
mysql: # MySQL 8.0
|
|
||||||
```
|
|
||||||
|
|
||||||
## 서비스별 상세
|
|
||||||
|
|
||||||
### 1. nginx - 리버스 프록시
|
|
||||||
|
|
||||||
**이미지**: `nginx:latest`
|
|
||||||
|
|
||||||
**포트**: 80
|
|
||||||
|
|
||||||
**도메인 매핑**:
|
|
||||||
- `api.sam.kr` → Laravel API 서버
|
|
||||||
- `mng.sam.kr`, `admin.sam.kr` → Laravel 관리자 패널
|
|
||||||
- `dev.sam.kr` → Next.js 프론트엔드
|
|
||||||
|
|
||||||
**주요 기능**:
|
|
||||||
- 보안 규칙 적용 (경로 탐색 공격 차단)
|
|
||||||
- User-Agent 필터링 (보안 스캔 도구 차단)
|
|
||||||
- WebSocket 지원 (Next.js HMR)
|
|
||||||
- 정적 자산 캐싱
|
|
||||||
|
|
||||||
**설정 파일**: `docker/nginx/nginx.conf`
|
|
||||||
|
|
||||||
### 2. api - Laravel 12 API 서버
|
|
||||||
|
|
||||||
**이미지**: `php:8.4-fpm`
|
|
||||||
|
|
||||||
**기술 스택**:
|
|
||||||
- PHP 8.4-fpm
|
|
||||||
- Composer 2
|
|
||||||
- Supervisor (nginx + php-fpm)
|
|
||||||
|
|
||||||
**PHP 확장**:
|
|
||||||
- zip
|
|
||||||
- mysqli
|
|
||||||
- pdo
|
|
||||||
- pdo_mysql
|
|
||||||
- intl
|
|
||||||
|
|
||||||
**환경 변수**:
|
|
||||||
- `DB_HOST=sam-mysql-1`
|
|
||||||
- `DB_PORT=3306`
|
|
||||||
- `DB_DATABASE=samdb`
|
|
||||||
- `DB_USERNAME=samuser`
|
|
||||||
- `DB_PASSWORD=sampass`
|
|
||||||
|
|
||||||
**볼륨**:
|
|
||||||
- `../api:/var/www/api` - 소스 코드
|
|
||||||
- `../docker/api/nginx.conf` - Nginx 설정
|
|
||||||
- `../docker/api/supervisord.conf` - Supervisor 설정
|
|
||||||
- `../docker/api/uploads.ini` - PHP 업로드 설정
|
|
||||||
|
|
||||||
**작업 디렉토리**: `/var/www/api`
|
|
||||||
|
|
||||||
### 3. mng - Laravel 12 관리자 패널
|
|
||||||
|
|
||||||
**이미지**: `php:8.4-fpm`
|
|
||||||
|
|
||||||
**기술 스택**:
|
|
||||||
- PHP 8.4-fpm
|
|
||||||
- Pure Blade + Tailwind CSS
|
|
||||||
- Composer 2
|
|
||||||
- Supervisor (nginx + php-fpm)
|
|
||||||
|
|
||||||
**환경 변수**: api와 동일
|
|
||||||
|
|
||||||
**볼륨**:
|
|
||||||
- `../mng:/var/www/mng` - 소스 코드
|
|
||||||
- `../docker/mng/nginx.conf` - Nginx 설정
|
|
||||||
- `../docker/mng/supervisord.conf` - Supervisor 설정
|
|
||||||
- `../docker/mng/uploads.ini` - PHP 업로드 설정
|
|
||||||
|
|
||||||
**작업 디렉토리**: `/var/www/mng`
|
|
||||||
|
|
||||||
### 4. react - Next.js 15 프론트엔드
|
|
||||||
|
|
||||||
**이미지**: `node:20-alpine`
|
|
||||||
|
|
||||||
**기술 스택**:
|
|
||||||
- Node.js 20
|
|
||||||
- Next.js 15
|
|
||||||
- React 19.2.0
|
|
||||||
|
|
||||||
**포트**: 3000 (내부)
|
|
||||||
|
|
||||||
**환경 변수**:
|
|
||||||
- `NEXT_PUBLIC_API_BASE_URL=http://api.sam.kr`
|
|
||||||
- `NEXT_PUBLIC_ADMIN_URL=http://admin.sam.kr`
|
|
||||||
- `NEXT_PUBLIC_API_KEY` (선택)
|
|
||||||
- `NEXT_PUBLIC_APP_NAME=SAM`
|
|
||||||
- `NODE_ENV=development`
|
|
||||||
|
|
||||||
**볼륨**:
|
|
||||||
- `../react:/app` - 소스 코드
|
|
||||||
- `/app/node_modules` - node_modules 격리
|
|
||||||
- `/app/.next` - Next.js 빌드 캐시
|
|
||||||
|
|
||||||
**작업 디렉토리**: `/app`
|
|
||||||
|
|
||||||
**개발 서버**: `npm run dev` (포트 3000)
|
|
||||||
|
|
||||||
### 5. mysql - MySQL 데이터베이스
|
|
||||||
|
|
||||||
**이미지**: `mysql:8.0`
|
|
||||||
|
|
||||||
**포트**: 3306
|
|
||||||
|
|
||||||
**환경 변수**:
|
|
||||||
- `MYSQL_DATABASE=samdb`
|
|
||||||
- `MYSQL_USER=samuser`
|
|
||||||
- `MYSQL_PASSWORD=sampass`
|
|
||||||
- `MYSQL_ROOT_PASSWORD=root`
|
|
||||||
|
|
||||||
**볼륨**:
|
|
||||||
- `db_data:/var/lib/mysql` - 데이터 영구 저장
|
|
||||||
- `../docker/mysql/init.sql` - 초기화 스크립트
|
|
||||||
|
|
||||||
## 네트워크
|
|
||||||
|
|
||||||
### samnet (bridge network)
|
|
||||||
|
|
||||||
모든 서비스가 `samnet` 네트워크에 연결되어 서로 통신할 수 있습니다.
|
|
||||||
|
|
||||||
**서비스 간 통신**:
|
|
||||||
- `api.sam.kr` → `mysql:3306`
|
|
||||||
- `mng.sam.kr` → `mysql:3306`
|
|
||||||
- `nginx` → `api:9000` (PHP-FPM)
|
|
||||||
- `nginx` → `mng:9000` (PHP-FPM)
|
|
||||||
- `nginx` → `react:3000` (Next.js)
|
|
||||||
|
|
||||||
## 사용 방법
|
|
||||||
|
|
||||||
### 초기 설정
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Docker 디렉토리로 이동
|
|
||||||
cd docker
|
|
||||||
|
|
||||||
# 2. 서비스 시작
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 3. 서비스 상태 확인
|
|
||||||
docker-compose ps
|
|
||||||
```
|
|
||||||
|
|
||||||
### 개발 워크플로우
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 서비스 시작
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 로그 확인
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# 특정 서비스 재시작
|
|
||||||
docker-compose restart api
|
|
||||||
|
|
||||||
# 서비스 중지
|
|
||||||
docker-compose down
|
|
||||||
```
|
|
||||||
|
|
||||||
### 컨테이너 내부 작업
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# API 컨테이너에서 마이그레이션
|
|
||||||
docker-compose exec api php artisan migrate
|
|
||||||
|
|
||||||
# MNG 컨테이너에서 Composer 설치
|
|
||||||
docker-compose exec mng composer install
|
|
||||||
|
|
||||||
# React 컨테이너에서 npm 설치
|
|
||||||
docker-compose exec react npm install
|
|
||||||
|
|
||||||
# MySQL 접속
|
|
||||||
docker-compose exec mysql mysql -u samuser -psampass samdb
|
|
||||||
```
|
|
||||||
|
|
||||||
## 환경 변수 설정
|
|
||||||
|
|
||||||
### .env 파일
|
|
||||||
|
|
||||||
각 애플리케이션 디렉토리(`api/`, `mng/`, `react/`)에 `.env` 파일을 생성해야 합니다.
|
|
||||||
|
|
||||||
**api/.env 예시**:
|
|
||||||
```env
|
|
||||||
APP_NAME=SAM API
|
|
||||||
APP_ENV=local
|
|
||||||
APP_KEY=
|
|
||||||
APP_DEBUG=true
|
|
||||||
APP_URL=http://api.sam.kr
|
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
|
||||||
DB_HOST=sam-mysql-1
|
|
||||||
DB_PORT=3306
|
|
||||||
DB_DATABASE=samdb
|
|
||||||
DB_USERNAME=samuser
|
|
||||||
DB_PASSWORD=sampass
|
|
||||||
```
|
|
||||||
|
|
||||||
**mng/.env 예시**:
|
|
||||||
```env
|
|
||||||
APP_NAME=SAM MNG
|
|
||||||
APP_ENV=local
|
|
||||||
APP_KEY=
|
|
||||||
APP_DEBUG=true
|
|
||||||
APP_URL=http://mng.sam.kr
|
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
|
||||||
DB_HOST=sam-mysql-1
|
|
||||||
DB_PORT=3306
|
|
||||||
DB_DATABASE=samdb
|
|
||||||
DB_USERNAME=samuser
|
|
||||||
DB_PASSWORD=sampass
|
|
||||||
```
|
|
||||||
|
|
||||||
**react/.env.local 예시**:
|
|
||||||
```env
|
|
||||||
NEXT_PUBLIC_API_BASE_URL=http://api.sam.kr
|
|
||||||
NEXT_PUBLIC_ADMIN_URL=http://admin.sam.kr
|
|
||||||
NEXT_PUBLIC_API_KEY=your-api-key
|
|
||||||
NEXT_PUBLIC_APP_NAME=SAM
|
|
||||||
```
|
|
||||||
|
|
||||||
## 호스트 파일 설정
|
|
||||||
|
|
||||||
로컬에서 도메인 접근을 위해 `/etc/hosts` 파일에 다음을 추가:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
127.0.0.1 api.sam.kr
|
|
||||||
127.0.0.1 mng.sam.kr
|
|
||||||
127.0.0.1 admin.sam.kr
|
|
||||||
127.0.0.1 dev.sam.kr
|
|
||||||
```
|
|
||||||
|
|
||||||
## 트러블슈팅
|
|
||||||
|
|
||||||
### 포트 충돌
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 포트 사용 확인
|
|
||||||
lsof -i :80
|
|
||||||
lsof -i :3306
|
|
||||||
|
|
||||||
# 포트를 사용하는 프로세스 종료
|
|
||||||
kill -9 <PID>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 볼륨 권한 문제
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# storage 디렉토리 권한 설정
|
|
||||||
docker-compose exec api chmod -R 775 storage
|
|
||||||
docker-compose exec mng chmod -R 775 storage
|
|
||||||
```
|
|
||||||
|
|
||||||
### 컨테이너 재빌드
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 특정 서비스 재빌드
|
|
||||||
docker-compose build --no-cache api
|
|
||||||
|
|
||||||
# 모든 서비스 재빌드
|
|
||||||
docker-compose build --no-cache
|
|
||||||
```
|
|
||||||
|
|
||||||
### 로그 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 모든 서비스 로그
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# 특정 서비스 로그
|
|
||||||
docker-compose logs -f api
|
|
||||||
docker-compose logs -f react
|
|
||||||
|
|
||||||
# Nginx 에러 로그
|
|
||||||
docker-compose exec nginx tail -f /var/log/nginx/api.sam.kr_error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### 데이터베이스 초기화
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 볼륨 삭제 (주의: 모든 데이터 삭제)
|
|
||||||
docker-compose down -v
|
|
||||||
|
|
||||||
# 재시작
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## 보안 설정
|
|
||||||
|
|
||||||
### Nginx 보안 규칙
|
|
||||||
|
|
||||||
`docker/nginx/nginx.conf`에 다음 보안 규칙이 적용되어 있습니다:
|
|
||||||
|
|
||||||
1. **경로 탐색 공격 차단**:
|
|
||||||
- `../`, `..\`, `etc/passwd`, `.env`, `.git` 등 차단
|
|
||||||
|
|
||||||
2. **보안 스캔 도구 차단**:
|
|
||||||
- sqlmap, nikto, nmap, masscan 등 User-Agent 필터링
|
|
||||||
|
|
||||||
3. **정적 자산 캐싱**:
|
|
||||||
- 30일 캐시 설정
|
|
||||||
|
|
||||||
## 프로덕션 배포
|
|
||||||
|
|
||||||
프로덕션 환경에서는 다음을 고려해야 합니다:
|
|
||||||
|
|
||||||
1. **HTTPS 설정**: SSL/TLS 인증서 적용
|
|
||||||
2. **환경 변수**: `.env` 파일 보안 관리
|
|
||||||
3. **볼륨 백업**: 데이터베이스 정기 백업
|
|
||||||
4. **리소스 제한**: 컨테이너 메모리/CPU 제한 설정
|
|
||||||
5. **로그 관리**: 로그 로테이션 설정
|
|
||||||
|
|
||||||
## 관련 문서
|
|
||||||
|
|
||||||
- [시스템 아키텍처](./02-architecture.md)
|
|
||||||
- [개발 명령어](./05-development.md)
|
|
||||||
- [보안 가이드](./08-security.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**업데이트**: 2025-12-26 (admin→mng 전환, design 서비스 추가)
|
|
||||||
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
# SAM ERP 스토리보드 분석 개요
|
|
||||||
|
|
||||||
> 분석 대상: SAM_ERP_Storyboard_D0.8_251216 (113 슬라이드)
|
|
||||||
> 분석일: 2025-12-17
|
|
||||||
> 버전: D0.8
|
|
||||||
|
|
||||||
## 1. 문서 개요
|
|
||||||
|
|
||||||
### 1.1 버전 히스토리
|
|
||||||
| 날짜 | 버전 | 내용 |
|
|
||||||
|------|------|------|
|
|
||||||
| 2025.12.01 | D0.6 | 프론트 초안 - 인사관리 & 전자결재 작성 |
|
|
||||||
| 2025.12.01 | D0.7 | 프론트 작성 - 인사관리 & 전자결재 피드백 반영 |
|
|
||||||
| 2025.12.16 | D0.8 | 회계 & 보고서 작성, GPS 출퇴근, 카드/계좌관리, 보고서 추가 |
|
|
||||||
|
|
||||||
### 1.2 슬라이드 구성
|
|
||||||
- **총 113 슬라이드**
|
|
||||||
- 공통 UI 가이드 + 8개 주요 기능 모듈
|
|
||||||
|
|
||||||
## 2. 메뉴 구조 (GNB/LNB)
|
|
||||||
|
|
||||||
```
|
|
||||||
SAM ERP
|
|
||||||
├── 대시보드
|
|
||||||
├── MES 메뉴 (영업관리, 판매관리, 구매관리 등)
|
|
||||||
├── 인사관리
|
|
||||||
│ ├── 부서관리
|
|
||||||
│ ├── 사원관리
|
|
||||||
│ ├── 근태관리
|
|
||||||
│ └── 휴가관리
|
|
||||||
├── 전자결재
|
|
||||||
│ ├── 기안함
|
|
||||||
│ ├── 결재함
|
|
||||||
│ └── 참조함
|
|
||||||
├── 게시판
|
|
||||||
├── 회계관리
|
|
||||||
│ ├── 거래처관리
|
|
||||||
│ ├── 매출관리
|
|
||||||
│ ├── 매입관리
|
|
||||||
│ ├── 입금관리
|
|
||||||
│ ├── 출금관리
|
|
||||||
│ ├── 어음관리
|
|
||||||
│ ├── 거래처원장
|
|
||||||
│ ├── 일일 일보
|
|
||||||
│ ├── 지출 예상 내역서
|
|
||||||
│ ├── 미수금 현황
|
|
||||||
│ ├── 악성채권 추심관리
|
|
||||||
│ ├── 입출금 계좌 조회
|
|
||||||
│ └── 카드 내역 조회
|
|
||||||
├── 기준정보
|
|
||||||
│ ├── 직급관리
|
|
||||||
│ ├── 직책관리
|
|
||||||
│ ├── 권한관리
|
|
||||||
│ ├── 근무관리
|
|
||||||
│ ├── 출퇴근관리
|
|
||||||
│ ├── 휴가관리
|
|
||||||
│ ├── 카드관리
|
|
||||||
│ ├── 계좌관리
|
|
||||||
│ ├── 팝업관리
|
|
||||||
│ ├── 게시판관리
|
|
||||||
│ ├── 일반설정
|
|
||||||
│ └── 알림설정
|
|
||||||
├── 보고서 및 분석
|
|
||||||
├── 계정정보
|
|
||||||
├── 회사정보
|
|
||||||
├── 구독관리
|
|
||||||
├── 결제내역
|
|
||||||
└── 고객센터
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. 기능 그룹별 슬라이드 매핑
|
|
||||||
|
|
||||||
| 그룹 | 슬라이드 범위 | 주요 내용 | 분석 문서 |
|
|
||||||
|------|---------------|----------|----------|
|
|
||||||
| 공통 | 3-13 | UI 컴포넌트, 인터랙션, 알림 | [01-common.md](./01-common.md) |
|
|
||||||
| 인증/영업 | 14-22 | 가입, 로그인, 약관동의 | [02-auth.md](./02-auth.md) |
|
|
||||||
| GPS 출퇴근 | 23-27 | 모바일 출퇴근 | [03-gps-attendance.md](./03-gps-attendance.md) |
|
|
||||||
| 인사관리 | 28-46 | 부서/사원/근태/휴가 | [04-hr-management.md](./04-hr-management.md) |
|
|
||||||
| 전자결재 | 47-59 | 기안/결재/참조함 | [05-approval.md](./05-approval.md) |
|
|
||||||
| 회계관리 | 60-91 | 거래처/매출/매입/입출금 | [06-accounting.md](./06-accounting.md) |
|
|
||||||
| 기준정보 | 92-104 | 직급/직책/휴가/카드/계좌 | [07-master-data.md](./07-master-data.md) |
|
|
||||||
| 보고서 | 105-113 | 분석/AI 리포트 | [08-reports.md](./08-reports.md) |
|
|
||||||
|
|
||||||
## 4. 사용자 역할
|
|
||||||
|
|
||||||
### 4.1 영업사원 (Sales)
|
|
||||||
- 운영 로그인
|
|
||||||
- 회사 등록 신청
|
|
||||||
- 테넌트 추가 알림
|
|
||||||
|
|
||||||
### 4.2 관리자 (Admin)
|
|
||||||
- 자료 확인
|
|
||||||
- 가입 승인/거절
|
|
||||||
- 이메일로 URL 발송
|
|
||||||
|
|
||||||
### 4.3 고객사 (Customer/Tenant)
|
|
||||||
- 약관 동의
|
|
||||||
- 비밀번호 설정
|
|
||||||
- SAM 로그인
|
|
||||||
- 테넌트 추가
|
|
||||||
|
|
||||||
## 5. 핵심 비즈니스 플로우
|
|
||||||
|
|
||||||
### 5.1 가입 및 로그인 플로우 (슬라이드 15)
|
|
||||||
```
|
|
||||||
영업사원: 운영 로그인 → 사업자등록번호 입력 → 회사정보 등록 → 가입신청 완료
|
|
||||||
↓ (거절)
|
|
||||||
관리자: 자료 확인 → 승인? → 이메일로 URL 발송 거절 알림
|
|
||||||
↓
|
|
||||||
고객사: 약관 동의 → 비밀번호 설정 → SAM 로그인 → 테넌트 추가?
|
|
||||||
↓
|
|
||||||
매니저: 테넌트 추가 알림 → 사업자등록번호 입력
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 회계관리 플로우 (슬라이드 61)
|
|
||||||
```
|
|
||||||
매출: 거래처 선택 → 매출 등록 → 세금계산서 발행
|
|
||||||
입금: 입금 등록 → 전액 입금? → 어음 수취?
|
|
||||||
매입: 거래처 선택 → 매입 등록 → 세금계산서 수취
|
|
||||||
출금: 출금 등록 → 전액 출금? → 어음 발행?
|
|
||||||
추심: 미수금 현황 → 연체? → 악성주심? → 악성 추심
|
|
||||||
조회: 입출금 계좌 조회, 카드 내역 조회
|
|
||||||
장부/보고서: 거래처원장, 지출 예상 내역서, 일일 일보
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. 기술 스펙
|
|
||||||
|
|
||||||
### 6.1 반응형 웹 브레이크포인트
|
|
||||||
- 모바일: < 640px (기본)
|
|
||||||
- 태블릿: 768px ~ 1023px (md)
|
|
||||||
- 데스크탑: 1024px+ (lg)
|
|
||||||
- 대형 모니터: 1280px+ (xl)
|
|
||||||
|
|
||||||
### 6.2 인터랙션
|
|
||||||
| 타입 | 적용 |
|
|
||||||
|------|------|
|
|
||||||
| Tap | Yes |
|
|
||||||
| Touch & Hold | No |
|
|
||||||
| Double Tap | No |
|
|
||||||
| Drag & Drop | Yes |
|
|
||||||
| Scroll Up/Down | Yes |
|
|
||||||
| Swipe Left/Right | Yes |
|
|
||||||
| Pinch Zoom In/Out | Yes |
|
|
||||||
|
|
||||||
### 6.3 알림 타입
|
|
||||||
- Alert (알림): 사용자에게 상황 알림
|
|
||||||
- Confirm Alert (확인): 확인/취소 선택
|
|
||||||
- Toast Message: 2-3초 후 Fade out
|
|
||||||
|
|
||||||
## 7. 다음 단계
|
|
||||||
|
|
||||||
1. 각 기능 그룹별 상세 분석 문서 작성
|
|
||||||
2. API 엔드포인트 도출
|
|
||||||
3. 데이터 모델 설계
|
|
||||||
4. 개발 우선순위 결정
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
# 공통 UI 컴포넌트 (슬라이드 3-13)
|
|
||||||
|
|
||||||
## 1. 화면 템플릿 (슬라이드 6)
|
|
||||||
|
|
||||||
### 1.1 모바일 화면 구조
|
|
||||||
```
|
|
||||||
┌─────────────────────────────┐
|
|
||||||
│ A. Status bar (OS 관리) │
|
|
||||||
├─────────────────────────────┤
|
|
||||||
│ B. Browser 영역 │
|
|
||||||
├──────┬──────────────────────┤
|
|
||||||
│Button│ Title │Button│ C. Title 영역
|
|
||||||
├──────┴──────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ D. Content 영역 │
|
|
||||||
│ │
|
|
||||||
├─────────────────────────────┤
|
|
||||||
│ E. Browser bar 영역 │
|
|
||||||
├─────────────────────────────┤
|
|
||||||
│ F. Keypad 영역 (입력 시) │
|
|
||||||
└─────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 영역 설명
|
|
||||||
- **A. Status bar**: 안테나, 통화, 배터리 등 시스템 OS 관리 영역
|
|
||||||
- **B. Browser 영역**: 브라우저 기능 영역
|
|
||||||
- **C. Title 영역**: 텍스트 또는 기능 버튼으로 구현, 텍스트 기본 가운데 정렬
|
|
||||||
- **D. Content 영역**: 컨텐츠 내용 표시, 컨텐츠 길이가 길어질 경우 스크롤 제공
|
|
||||||
- **E. Browser bar 영역**: 브라우저 유틸 바 영역
|
|
||||||
- **F. Keypad 영역**: 키보드 입력할 때 활성화, 모든 페이지 위에 덮어쓰기 구현
|
|
||||||
|
|
||||||
## 2. GNB/LNB/푸터 (슬라이드 8)
|
|
||||||
|
|
||||||
### 2.1 알림 버튼
|
|
||||||
- 클릭: 알림 팝업 표시
|
|
||||||
|
|
||||||
### 2.2 개인 정보 버튼
|
|
||||||
- 등록: 디폴트 이미지, 이름, 직급
|
|
||||||
- 클릭: 마이페이지 팝업 표시
|
|
||||||
|
|
||||||
### 2.3 회사 로고
|
|
||||||
- 회사정보 화면에서 등록한 로고 표시
|
|
||||||
- 회사 변경 선택 시 해당 로고 변경
|
|
||||||
|
|
||||||
### 2.4 메뉴 영역
|
|
||||||
- 메뉴 클릭:
|
|
||||||
- 하위 메뉴가 있을 경우: 하위 메뉴 하단에 표시
|
|
||||||
- 하위 메뉴 없을 경우: 해당 메뉴 화면으로 이동
|
|
||||||
- 목록 길 경우 해당 영역 내 스크롤 처리
|
|
||||||
|
|
||||||
### 2.5 MES 메뉴 영역
|
|
||||||
- 영업관리, 판매관리, 구매관리 등 해당하는 MES 메뉴 영역 표시
|
|
||||||
|
|
||||||
### 2.6 푸터 영역
|
|
||||||
- 모든 화면 하단 공통 표시
|
|
||||||
|
|
||||||
## 3. 알림 팝업 (슬라이드 9)
|
|
||||||
|
|
||||||
### 3.1 알림 목록
|
|
||||||
- 항목: 디폴트 원형일, 종류(공지사항), 안내/제목/내용, 전송일시 표시
|
|
||||||
- 클릭: 해당 상세 화면으로 이동
|
|
||||||
- 최신순 10개까지 표시
|
|
||||||
|
|
||||||
### 3.2 New 아이콘
|
|
||||||
- 새 알림일 경우 New 아이콘 표시
|
|
||||||
- 해당 알림 클릭 시 사라짐
|
|
||||||
|
|
||||||
### 3.3 빨간 점 아이콘
|
|
||||||
- 새 알림이 있을 경우 표시
|
|
||||||
- 해당 알림 모두 클릭 시 사라짐
|
|
||||||
|
|
||||||
## 4. 마이페이지 팝업 (슬라이드 10)
|
|
||||||
|
|
||||||
### 4.1 계정 아이디 (이메일) 표시
|
|
||||||
|
|
||||||
### 4.2 회사 셀렉트 박스
|
|
||||||
- 종류: 회사명, 회사명... (해당 계정이 생성한 회사(테넌트) 목록 표시)
|
|
||||||
- 정렬: 등록순
|
|
||||||
- 한 회사만 소유중일 경우에는 해당 영역 숨김
|
|
||||||
|
|
||||||
### 4.3 로그아웃 버튼
|
|
||||||
- 클릭: "정말 로그아웃하시겠습니까?" 로그아웃 확인 Alert 표시
|
|
||||||
- 확인 버튼 클릭 시 로그아웃 처리
|
|
||||||
|
|
||||||
## 5. 셀렉트 박스 (슬라이드 11)
|
|
||||||
|
|
||||||
### 5.1 기본 셀렉트 박스
|
|
||||||
- 클릭: 하단에 종류 목록 표시
|
|
||||||
|
|
||||||
### 5.2 종류 목록
|
|
||||||
- 목록 중 하나만 선택 가능
|
|
||||||
|
|
||||||
### 5.3 다중 선택 셀렉트 박스
|
|
||||||
- 선택된 첫번째 항목명 + 추가 수 표시
|
|
||||||
- 텍스트 영역 부족할 경우 '항목..+3' 형태로 표시
|
|
||||||
|
|
||||||
### 5.4 다중 선택 종류 목록
|
|
||||||
- 목록 중 복수 선택 가능
|
|
||||||
- 전체 선택 시 전체 선택/해제 토글
|
|
||||||
|
|
||||||
### 5.5 검색 영역
|
|
||||||
- 검색어 입력 후 엔터 또는 검색 아이콘 클릭 시 (5-1) 형태로 표시되며 (5-2) 영역에 검색 결과 표시
|
|
||||||
|
|
||||||
### 5.6 삭제 버튼
|
|
||||||
- 클릭: 검색어 삭제 처리, 전체 종류 목록 표시
|
|
||||||
|
|
||||||
## 6. 입력 필드 가이드 메시지 (슬라이드 12)
|
|
||||||
|
|
||||||
### 6.1 가이드 메시지 표시 위치
|
|
||||||
- 상황에 따라 입력 필드 하단 또는 Alert에 표시
|
|
||||||
|
|
||||||
### 6.2 가이드 메시지 색상
|
|
||||||
- 긍정일 경우: 녹색
|
|
||||||
- (1-1) 부정일 경우: 붉은색
|
|
||||||
|
|
||||||
## 7. 공지 팝업 (슬라이드 13)
|
|
||||||
|
|
||||||
### 7.1 대상
|
|
||||||
- 전체, 설정 부서
|
|
||||||
- 내용: 설정 기간동안 대상에게 팝업 표시
|
|
||||||
|
|
||||||
### 7.2 팝업 내용 영역
|
|
||||||
- 이미지, 텍스트
|
|
||||||
|
|
||||||
### 7.3 "1일간 이 창을 열지 않음" 체크박스
|
|
||||||
- 클릭: 체크 설정/해제 토글
|
|
||||||
- 디폴트: 체크 해제 상태
|
|
||||||
- 체크 설정 시 1일 동안 팝업 미표시 (차정 기준)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 공통 API
|
|
||||||
```
|
|
||||||
GET /api/notifications # 알림 목록 조회
|
|
||||||
POST /api/notifications/{id}/read # 알림 읽음 처리
|
|
||||||
GET /api/user/profile # 마이페이지 정보
|
|
||||||
GET /api/user/companies # 사용자 소속 회사 목록
|
|
||||||
POST /api/auth/logout # 로그아웃
|
|
||||||
GET /api/announcements # 공지 팝업 조회
|
|
||||||
POST /api/announcements/{id}/dismiss # 공지 팝업 닫기 (1일간 안보기)
|
|
||||||
```
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
# 인증/영업 (슬라이드 14-22)
|
|
||||||
|
|
||||||
## 1. 가입 및 로그인 플로우차트 (슬라이드 15)
|
|
||||||
|
|
||||||
### 1.1 영업사원 플로우
|
|
||||||
```
|
|
||||||
운영 로그인 → 사업자등록번호 입력 → 사업자번호 조회?
|
|
||||||
↓ Yes
|
|
||||||
회사정보 등록 → 가입신청 완료
|
|
||||||
↓ (거절)
|
|
||||||
거절 알림
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 관리자 플로우
|
|
||||||
```
|
|
||||||
자료 확인 → 승인? → (Yes) → 이메일로 URL 발송
|
|
||||||
↓ (No)
|
|
||||||
계약금50% 결제 확인
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.3 고객사 플로우
|
|
||||||
```
|
|
||||||
약관 동의 → 비밀번호 설정 → SAM 로그인 → 테넌트 추가?
|
|
||||||
↓ (Yes)
|
|
||||||
매니저: 테넌트 추가 알림
|
|
||||||
↓
|
|
||||||
사업자등록번호 입력
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. 운영 로그인 (슬라이드 16)
|
|
||||||
|
|
||||||
### 2.1 아이디 인풋박스
|
|
||||||
- 테넌트 생성자일 경우 이메일
|
|
||||||
- 사용자일 경우 이메일 또는 아이디
|
|
||||||
- (1-1) 상황별 가이드 메시지
|
|
||||||
|
|
||||||
### 2.2 비밀번호 인풋박스
|
|
||||||
- 입력 시 마지막 글자 제외 후 마스킹 처리
|
|
||||||
- (2-1) 상황별 가이드 메시지
|
|
||||||
|
|
||||||
### 2.3 열람 버튼
|
|
||||||
- 클릭: 열람/숨김 토글
|
|
||||||
- 디폴트: 숨김 상태
|
|
||||||
- 열람 상태일 시 (2) 영역 마스킹 해제 처리
|
|
||||||
|
|
||||||
### 2.4 자동 로그인 체크박스
|
|
||||||
- 클릭: 체크 설정/해제 토글
|
|
||||||
- 체크 시 로그아웃 전까지 세션 유지
|
|
||||||
|
|
||||||
### 2.5 로그인 버튼
|
|
||||||
- 클릭: 유효할 경우 대시보드 화면으로 이동
|
|
||||||
|
|
||||||
### 2.6 가이드 메시지
|
|
||||||
| 상황 | 가이드 메시지 |
|
|
||||||
|------|---------------|
|
|
||||||
| 필수 정보 미 입력 시 | 필수 정보입니다. |
|
|
||||||
| 4글자 미만 입력 시 | 이메일은 4자 이상 가능합니다 |
|
|
||||||
| 이메일 형식에 유효 하지 않을 경우 | 이메일 주소를 다시 확인해주세요. |
|
|
||||||
| 8자 미만 입력 시 | 8자 이상으로 만들어주세요. |
|
|
||||||
| 영문+숫자+특수문자 조합이 아닐 경우 | 영문, 숫자, 특수문자를 포함해주세요. 다음의 특수기호는 보안 사항을 가능합니다., ; - @ ! |
|
|
||||||
|
|
||||||
## 3. 사업자등록번호 조회 (슬라이드 17)
|
|
||||||
|
|
||||||
### 3.1 제조 데모
|
|
||||||
- 클릭: 제조 데모 화면으로 이동
|
|
||||||
|
|
||||||
### 3.2 시공 데모
|
|
||||||
- 클릭: 시공 데모 화면으로 이동
|
|
||||||
|
|
||||||
### 3.3 사업자등록번호 인풋박스
|
|
||||||
- 숫자만 가능, 10자리
|
|
||||||
|
|
||||||
### 3.4 다음 버튼
|
|
||||||
- 클릭:
|
|
||||||
1. 바로 빌 사업자등록번호 조회 후 사용 불가 경우: "중복된 사업자등록번호입니다." 알림 Alert 표시
|
|
||||||
2. 바로 빌 사업자등록번호 조회 후 사용 가능한 경우:
|
|
||||||
- [1] 테넌트 등록된 사업자등록번호일 경우: 테넌트 등록 전이어도 다른 영업사원이 등록중을 경우에는 사업자등록번호 사용 불가 (어드민에서는 해제 가능)
|
|
||||||
- "등록된 사업자등록번호 입니다." 알림 Alert 표시
|
|
||||||
- [2] 등록되지 않은 사업자등록번호일 경우: 회사정보 등록 화면으로 이동
|
|
||||||
|
|
||||||
## 4. 회사정보 등록 (슬라이드 18)
|
|
||||||
|
|
||||||
### 4.1 회사(테넌트) 상태
|
|
||||||
- 신청: 신청 완료 입력
|
|
||||||
- 승인: 자동 입금 외 계약금 50% 입금, 이메일로 URL 발송 선택
|
|
||||||
- 최초 로그인 시 ERP만 표시
|
|
||||||
- 거절: 프로젝트 설정 완료, 잔금 50% 입금 및 인도, 당월 말일까지는 무료, 익월부터 익월말까지 사용하고 구독료 청구
|
|
||||||
- 만료: 기간 종료, 안료외 연체 상태 구분?? 영업사원에게 알림, 서비스에는 접근 불가, 배너
|
|
||||||
- 해지: 오퍼 대기기간 단계 필요??
|
|
||||||
- 해지: 서비스 이용 불가
|
|
||||||
- 탈퇴: 로그인 불가, 복구 불가??
|
|
||||||
- 미사: 서비스 이용 불가
|
|
||||||
|
|
||||||
### 4.2 회사 로고 이미지 영역
|
|
||||||
- 디폴드 이미지 표시
|
|
||||||
- 클릭: 파일탐색기 팝업 표시, 10MB 이하의 PNG, JPEG, GIF 중 하나 선택 가능
|
|
||||||
|
|
||||||
### 4.3 우편번호 찾기 버튼
|
|
||||||
- 클릭: 선정한 주소 팝업 표시
|
|
||||||
|
|
||||||
### 4.4 찾기 버튼
|
|
||||||
- 클릭: 파일탐색기 팝업 표시, 이미지 또는 파일 하나 선택 가능
|
|
||||||
|
|
||||||
### 4.5 가입 신청 버튼
|
|
||||||
- 클릭: 사업자등록번호 조회 화면으로 이동
|
|
||||||
- 회사 로고만 선택, 나머지는 필수 정보
|
|
||||||
- 클릭: 가입 신청 완료 화면으로 이동
|
|
||||||
|
|
||||||
### 4.6 입력 필드
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 회사 로고 | N | 750x250px, 10MB 이하 PNG, JPEG, GIF |
|
|
||||||
| 회사명 | Y | |
|
|
||||||
| 대표자명 | Y | |
|
|
||||||
| 업태 | Y | |
|
|
||||||
| 업종 | Y | |
|
|
||||||
| 주소 | Y | 우편번호 찾기 + 상세주소 |
|
|
||||||
| 이메일 (아이디) | Y | |
|
|
||||||
| 세금계산서 이메일 | Y | |
|
|
||||||
| 담당자명 | Y | |
|
|
||||||
| 담당자 연락처 | Y | |
|
|
||||||
| 사업자등록증 | Y | 파일 첨부 |
|
|
||||||
|
|
||||||
## 5. 가입 신청 완료 (슬라이드 19)
|
|
||||||
|
|
||||||
### 5.1 가입 신청 완료 안내 문구 표시
|
|
||||||
- SAM은 폐쇄형 네트워크이므로 플랫폼의 무결성을 보장하기 위해 모든 계정을 검토해야 합니다.
|
|
||||||
- (회사명)의 계정 세부 정보를 추가로 확인하기 위해 추가 정보를 요청할 수 있습니다.
|
|
||||||
- 영업일 기준 3일 이내에 계정에 대한 업데이트를 받게 됩니다.
|
|
||||||
|
|
||||||
### 5.2 가입 신청 취소 버튼
|
|
||||||
- 클릭: "가입 신청 취소 시 등록한 모든 정보가 삭제됩니다. 정말 가입 신청을 취소하시겠습니까?" 확인 Alert 표시
|
|
||||||
|
|
||||||
## 6. 가입 신청 승인 성공 이메일 (슬라이드 20)
|
|
||||||
|
|
||||||
### 6.1 계정 활성화 버튼
|
|
||||||
- 클릭: 약관 동의 화면으로 이동
|
|
||||||
|
|
||||||
### 6.2 지원, 블로그 버튼
|
|
||||||
- 클릭: 해당 운영 노션 링크로 이동
|
|
||||||
|
|
||||||
## 7. 약관 동의 (슬라이드 21)
|
|
||||||
|
|
||||||
### 7.1 약관 영역
|
|
||||||
- 클릭: (1-1) 약관 내용 영역 열림/닫힘 토글
|
|
||||||
- 디폴트: 닫힘
|
|
||||||
|
|
||||||
### 7.2 체크박스
|
|
||||||
- 클릭: 체크 설정/해제 토글
|
|
||||||
- 디폴트: 체크 설정 해제
|
|
||||||
|
|
||||||
### 7.3 약관에 동의합니다 버튼
|
|
||||||
- 모든 필수 약관 동의 시 버튼 활성화
|
|
||||||
- 클릭: 비밀번호 설정 화면으로 이동
|
|
||||||
|
|
||||||
### 7.4 약관에 동의합니다 버튼
|
|
||||||
- 클릭: 모든 필수, 선택 약관에 동의 처리, 비밀번호 설정 화면으로 이동
|
|
||||||
|
|
||||||
### 7.5 약관 목록
|
|
||||||
| 약관명 | 필수 |
|
|
||||||
|--------|------|
|
|
||||||
| [필수] 서비스 이용약관 | Y |
|
|
||||||
| [필수] 개인정보 취급방침 | Y |
|
|
||||||
| [필수] 약관명 | Y |
|
|
||||||
| 마케팅 정보 수신 동의 (선택) | N |
|
|
||||||
| - 이메일 수신 동의 | N |
|
|
||||||
| - SMS 수신 동의 | N |
|
|
||||||
|
|
||||||
## 8. 비밀번호 설정 (슬라이드 22)
|
|
||||||
|
|
||||||
### 8.1 계정 활성화 버튼
|
|
||||||
- 클릭: 로그인 화면으로 이동
|
|
||||||
|
|
||||||
### 8.2 비밀번호 요구사항
|
|
||||||
- 최소 8자 이상 영문+숫자+특수문자 조합
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 인증 API
|
|
||||||
```
|
|
||||||
POST /api/auth/login # 로그인
|
|
||||||
POST /api/auth/logout # 로그아웃
|
|
||||||
POST /api/auth/password/reset # 비밀번호 재설정
|
|
||||||
POST /api/auth/password/change # 비밀번호 변경
|
|
||||||
```
|
|
||||||
|
|
||||||
### 회원가입/영업 API
|
|
||||||
```
|
|
||||||
GET /api/business-registration/verify # 사업자등록번호 조회
|
|
||||||
POST /api/registration/company # 회사정보 등록
|
|
||||||
POST /api/registration/cancel # 가입신청 취소
|
|
||||||
GET /api/terms # 약관 목록 조회
|
|
||||||
POST /api/terms/agree # 약관 동의
|
|
||||||
POST /api/account/activate # 계정 활성화
|
|
||||||
```
|
|
||||||
|
|
||||||
### 테넌트 API
|
|
||||||
```
|
|
||||||
GET /api/tenants # 테넌트 목록
|
|
||||||
POST /api/tenants # 테넌트 추가
|
|
||||||
PUT /api/tenants/{id} # 테넌트 수정
|
|
||||||
GET /api/tenants/{id}/switch # 테넌트 전환
|
|
||||||
```
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
# GPS 출퇴근 (슬라이드 23-27)
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
GPS 기반 모바일 출퇴근 관리 시스템으로, 위치 정보를 활용하여 출근/퇴근을 기록합니다.
|
|
||||||
|
|
||||||
## 2. 마이페이지 팝업 > 출퇴근하기 (슬라이드 24)
|
|
||||||
|
|
||||||
### 2.1 출퇴근 버튼
|
|
||||||
- GPS 출퇴근 사용 시에만 표시
|
|
||||||
- 모바일일 경우에만 버튼 활성화
|
|
||||||
- 클릭: 출퇴근하기 화면으로 이동
|
|
||||||
|
|
||||||
### 2.2 출퇴근 허용 반경
|
|
||||||
- 기준 화표로부터의 출퇴근 허용 반경을 m 형으로 표시 (기준정보 > 출퇴근관리에서 설정)
|
|
||||||
|
|
||||||
### 2.3 현재 위치 버튼
|
|
||||||
- 클릭: (3-1) 해당 현재 위치를 지도 중심으로 표시
|
|
||||||
|
|
||||||
### 2.4 [+] 버튼
|
|
||||||
- 클릭: 지도 영역 확대
|
|
||||||
|
|
||||||
### 2.5 확대/축소 슬라이드바
|
|
||||||
- 드래그&드랍 또는 클릭: 지도 영역 확대/축소
|
|
||||||
|
|
||||||
### 2.6 [-] 버튼
|
|
||||||
- 클릭: 지도 영역 축소
|
|
||||||
|
|
||||||
### 2.7 개인 정보 영역
|
|
||||||
- 항목: 프로필 이미지, 이름, 부서명, 직급명
|
|
||||||
|
|
||||||
### 2.8 현재 시:분:초 표시
|
|
||||||
- HH:MM:SS
|
|
||||||
|
|
||||||
### 2.9 출근하기 버튼
|
|
||||||
- 클릭:
|
|
||||||
1) 출근 위치 미설정 상태일 경우: "출근 위치를 설정해주세요." 알림 Alert 표시
|
|
||||||
2) 출근 위치 설정 상태일 경우:
|
|
||||||
- (1) 출근 위치가 기준 설정 반경 초과일 경우: "출근 가능 위치가 아닙니다. 출근 위치를 확인해주세요." 알림 Alert 표시
|
|
||||||
- [2] GPS 출근 위치 기준 설정 반경 이내: 출근하기 화면으로 이동 (출근 기록 저장)
|
|
||||||
|
|
||||||
## 3. 출근하기 (슬라이드 25)
|
|
||||||
|
|
||||||
### 3.1 퇴근하기 버튼
|
|
||||||
- 클릭:
|
|
||||||
1) 퇴근 위치 미설정 상태일 경우: "퇴근 위치를 설정해주세요." 알림 Alert 표시
|
|
||||||
2) 퇴근 위치 설정 상태일 경우:
|
|
||||||
- (1) 퇴근 위치가 기준 설정 반경 초과일 경우: "퇴근 가능 위치가 아닙니다. 퇴근 위치를 확인해주세요." 알림 Alert 표시
|
|
||||||
- [2] GPS 퇴근 위치 기준 설정 반경 이내: 퇴근하기 화면으로 이동 (퇴근 기록 저장)
|
|
||||||
|
|
||||||
### 3.2 출근 완료 아이콘 이미지 표시
|
|
||||||
|
|
||||||
### 3.3 출근 완료 정보
|
|
||||||
- 항목: 출근 완료 문구, 시:분:초, 일자(요일)
|
|
||||||
|
|
||||||
### 3.4 출근 화표의 본사/현장명 표시
|
|
||||||
|
|
||||||
### 3.5 확인 버튼
|
|
||||||
- 클릭: 대시보드로 이동
|
|
||||||
|
|
||||||
## 4. 퇴근하기 (슬라이드 26)
|
|
||||||
|
|
||||||
### 4.1 퇴근 완료 아이콘 이미지 표시
|
|
||||||
|
|
||||||
### 4.2 퇴근 완료 정보
|
|
||||||
- 항목: 퇴근 완료 문구, 시:분:초, 일자(요일)
|
|
||||||
|
|
||||||
### 4.3 퇴근 화표의 본사/현장명 표시
|
|
||||||
|
|
||||||
### 4.4 확인 버튼
|
|
||||||
- 클릭: 대시보드로 이동
|
|
||||||
|
|
||||||
## 5. 현장 등록 (슬라이드 27)
|
|
||||||
|
|
||||||
### 5.1 위치 정보 설정
|
|
||||||
- 각 현장의 GPS 중심값으로 설정
|
|
||||||
|
|
||||||
### 5.2 입력 필드
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 주소 | Y | 우편번호 찾기 + 상세주소 |
|
|
||||||
| 경도 | Y | |
|
|
||||||
| 위도 | Y | |
|
|
||||||
| 첨부파일 | N | |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터 모델
|
|
||||||
|
|
||||||
### Attendance (출퇴근 기록)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- user_id: bigint (FK)
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- type: enum('check_in', 'check_out')
|
|
||||||
- check_time: datetime
|
|
||||||
- latitude: decimal(10,8)
|
|
||||||
- longitude: decimal(11,8)
|
|
||||||
- location_id: bigint (FK, nullable) # 본사/현장
|
|
||||||
- location_name: string
|
|
||||||
- is_valid: boolean # 유효 위치 여부
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### Location (본사/현장)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- name: string
|
|
||||||
- address: string
|
|
||||||
- detail_address: string
|
|
||||||
- latitude: decimal(10,8)
|
|
||||||
- longitude: decimal(11,8)
|
|
||||||
- allowed_radius: int # 허용 반경 (m)
|
|
||||||
- is_active: boolean
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### GPS 출퇴근 API
|
|
||||||
```
|
|
||||||
POST /api/attendance/check-in # 출근 기록
|
|
||||||
POST /api/attendance/check-out # 퇴근 기록
|
|
||||||
GET /api/attendance/today # 오늘 출퇴근 현황
|
|
||||||
GET /api/attendance/status # 현재 출퇴근 상태
|
|
||||||
GET /api/attendance/location/validate # 위치 유효성 검증
|
|
||||||
```
|
|
||||||
|
|
||||||
### 현장 관리 API
|
|
||||||
```
|
|
||||||
GET /api/locations # 현장 목록
|
|
||||||
POST /api/locations # 현장 등록
|
|
||||||
PUT /api/locations/{id} # 현장 수정
|
|
||||||
DELETE /api/locations/{id} # 현장 삭제
|
|
||||||
```
|
|
||||||
|
|
||||||
### 출퇴근 설정 API
|
|
||||||
```
|
|
||||||
GET /api/settings/attendance # 출퇴근 설정 조회
|
|
||||||
PUT /api/settings/attendance # 출퇴근 설정 수정
|
|
||||||
```
|
|
||||||
@@ -1,381 +0,0 @@
|
|||||||
# 인사관리 (슬라이드 28-46)
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
인사관리 모듈은 부서, 사원, 근태, 휴가를 관리합니다.
|
|
||||||
|
|
||||||
## 2. 부서관리 (슬라이드 30-31)
|
|
||||||
|
|
||||||
### 2.1 전체 선택 체크박스
|
|
||||||
- 클릭: 전체 선택 설정/해제 토글
|
|
||||||
- 디폴트: 설정 해제 상태
|
|
||||||
|
|
||||||
### 2.2 개별 선택 체크박스
|
|
||||||
- 클릭: 개별 선택 설정/해제 토글
|
|
||||||
- 디폴트: 설정 해제 상태
|
|
||||||
|
|
||||||
### 2.3 추가 버튼
|
|
||||||
- 클릭: 선택된 부서의 하위 부서 일괄 생성
|
|
||||||
- 관리 권한이 없을 경우 숨김
|
|
||||||
|
|
||||||
### 2.4 삭제 버튼
|
|
||||||
- 클릭: "선택한 부서 N개를 삭제하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 선택 시 삭제된 부서 사원의 인원은 회사(기본) 인원으로 변경
|
|
||||||
|
|
||||||
### 2.5 확대 버튼
|
|
||||||
- 클릭: (6) 확대 버튼으로 변경, 하위 부서 숨김 처리
|
|
||||||
|
|
||||||
### 2.6 축소 버튼
|
|
||||||
- 클릭: (5) 축소 버튼으로 변경, 하위 부서 표시 처리
|
|
||||||
|
|
||||||
### 2.7 추가 버튼
|
|
||||||
- 클릭: 부서 추가 팝업 표시
|
|
||||||
|
|
||||||
### 2.8 수정 버튼
|
|
||||||
- 클릭: 부서 수정 팝업 표시
|
|
||||||
|
|
||||||
### 2.9 부서 추가/수정 팝업
|
|
||||||
- 부서명 인풋박스: 기존 부서명 표시, 수정 가능
|
|
||||||
|
|
||||||
## 3. 사원관리 (슬라이드 32-40)
|
|
||||||
|
|
||||||
### 3.1 기간 설정 영역
|
|
||||||
- 입사일 기준
|
|
||||||
|
|
||||||
### 3.2 기간 설정 버튼 영역
|
|
||||||
- 종류: 당해년도, 전전월, 전월, 당월, 어제, 오늘
|
|
||||||
- 클릭: 해당 기간이 (1) 영역에 설정되며 화면 전체에 적용 처리
|
|
||||||
|
|
||||||
### 3.3 CSV 일괄 등록 버튼
|
|
||||||
- 클릭: CSV 일괄 등록 화면으로 이동
|
|
||||||
|
|
||||||
### 3.4 사원 등록 버튼
|
|
||||||
- 클릭: 사원 상세 화면으로 이동
|
|
||||||
|
|
||||||
### 3.5 사용자 초대 버튼
|
|
||||||
- 클릭: 사용자 초대 팝업 표시
|
|
||||||
|
|
||||||
### 3.6 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 사용자 아이디 보유, 사용자 아이디 미보유, 재직, 휴직, 퇴직
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.7 정렬 셀렉트 박스
|
|
||||||
- 종류: 직급순, 부서 오름차순, 부서 내림차순, 이름 오름차순, 이름 내림차순
|
|
||||||
- 디폴트: 직급순
|
|
||||||
|
|
||||||
### 3.8 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 현직 | 전체 현직 사원 수 |
|
|
||||||
| 휴직 | 전체 휴직 사원 수 |
|
|
||||||
| 퇴직 | (1) 해당 기간의 퇴직 사원 수 |
|
|
||||||
| 평균근속년수 | 전체 현직 사원 기준 |
|
|
||||||
|
|
||||||
## 4. 사원 상세 (슬라이드 33-36)
|
|
||||||
|
|
||||||
### 4.1 사원 정보 영역 (필수)
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 이름 | Y | |
|
|
||||||
| 주민등록번호 | Y | |
|
|
||||||
| 휴대폰 | Y | |
|
|
||||||
| 이메일 | Y | |
|
|
||||||
| 연봉 | N | |
|
|
||||||
| 급여계좌 은행 | N | 은행 선택 |
|
|
||||||
| 계좌 | N | |
|
|
||||||
| 예금주 | N | |
|
|
||||||
|
|
||||||
### 4.2 사용자 정보 영역
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 아이디 | N | 이메일 또는 아이디 |
|
|
||||||
| 비밀번호 | N | 최소 8자 이상 영문+숫자+특수문자 조합 |
|
|
||||||
| 권한 | N | 권한관리의 목록 표시 |
|
|
||||||
| 상태 | N | 종류: 정상, 재직, 중지. 재직 상태인 경우 로그아웃 처리, 로그인 시 '재정중인 아이디입니다.' 팝업 |
|
|
||||||
|
|
||||||
### 4.3 사원 상세 영역 (선택)
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 프로필 사진 | N | 1250x250px, 10MB 이하 PNG, JPEG, GIF |
|
|
||||||
| 사원코드 | N | |
|
|
||||||
| 성별 | N | 남성/여성 |
|
|
||||||
| 주소 | N | 우편번호 찾기 + 상세주소 |
|
|
||||||
|
|
||||||
### 4.4 인사 정보 영역
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 입사일 | N | |
|
|
||||||
| 고용 형태 | N | 종류: 정규직, 계약직, 파견직, 용역직, 시간제 근로자 |
|
|
||||||
| 직급 | N | 직급관리 화면에서 설정 |
|
|
||||||
| 상태 | N | 종류: 재직, 병가휴직, 육아휴직, 개인사정휴직, 무급휴직, 퇴사, 해고, 권고사직, 계약만료, 정년퇴직 |
|
|
||||||
| 부서 | N | 부서관리 화면에서 설정 |
|
|
||||||
| 직책 | N | 직책관리 화면에서 설정 |
|
|
||||||
| 출근 위치 | N | 본사, 현장 목록 |
|
|
||||||
| 퇴근 위치 | N | 본사, 현장 목록 |
|
|
||||||
| 퇴사일 | N | |
|
|
||||||
| 퇴사 사유 | N | |
|
|
||||||
|
|
||||||
### 4.5 항목 설정 버튼
|
|
||||||
- 클릭: 항목 설정 팝업 표시
|
|
||||||
|
|
||||||
### 4.6 항목 설정 팝업 (슬라이드 34)
|
|
||||||
- 전체 설정 ON/OFF 버튼
|
|
||||||
- 개별 설정 ON/OFF 버튼
|
|
||||||
- 디폴트: 설정 OFF 상태
|
|
||||||
|
|
||||||
## 5. CSV 일괄 등록 (슬라이드 39-40)
|
|
||||||
|
|
||||||
### 5.1 양식 다운로드 버튼
|
|
||||||
- 클릭: 등록된 양식 CSV 다운로드
|
|
||||||
|
|
||||||
### 5.2 파일 선택 버튼
|
|
||||||
- 클릭: 파일 탐색기 팝업, CSV 1개만 등록
|
|
||||||
|
|
||||||
### 5.3 파일 변환 버튼
|
|
||||||
- 클릭: CSV 데이터를 (3-1) 정보 등록 영역에 변환값 표시
|
|
||||||
- 범위: 사원 상세 화면의 전체 항목
|
|
||||||
|
|
||||||
### 5.4 등록 버튼
|
|
||||||
- 파일변환 완료 & (2) 체크 설정 항목 있을 경우에만 버튼 활성화
|
|
||||||
- 클릭: "(등록)의 정보를 정말 등록하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 클릭 시 (2) 체크 된 정보만 등록, "정보 등록이 완료되었습니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
## 6. 사용자 초대 (슬라이드 37-38)
|
|
||||||
|
|
||||||
### 6.1 사용자 초대 프로세스
|
|
||||||
- 초대 이메일로 발송 → 약관 동의 (아이디를 이메일로 사용) → 비밀번호 설정 → 로그인
|
|
||||||
|
|
||||||
### 6.2 초대할 이메일 주소 인풋박스
|
|
||||||
- ','로 구분하여 여러 주소 입력 가능
|
|
||||||
|
|
||||||
### 6.3 권한 셀렉트 박스, 검색
|
|
||||||
- 종류: 권한관리의 목록 표시
|
|
||||||
|
|
||||||
### 6.4 초대 메시지 인풋박스
|
|
||||||
|
|
||||||
### 6.5 초대 버튼
|
|
||||||
- 클릭: 사용자 초대 이메일 발송
|
|
||||||
- 이메일 주소 기준 사원 정보가 있을 경우에는 대량하여 사용자 등록 처리
|
|
||||||
- 없을 경우에는 사용자에만 등록하고 나머지 사원 정보는 직접 입력 필요
|
|
||||||
- 사용자 아이디 중복 불가
|
|
||||||
|
|
||||||
## 7. 근태관리 (슬라이드 41-42)
|
|
||||||
|
|
||||||
### 7.1 근태관리 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 정시 출근 | 전체 정시 출근 수 |
|
|
||||||
| 지각 | 전체 지각 수 |
|
|
||||||
| 결근 | 전체 결근 수 |
|
|
||||||
| 휴가 | 전체 휴가 수 |
|
|
||||||
|
|
||||||
### 7.2 기간 설정 버튼 영역
|
|
||||||
- 종류: 당해년도, 전전월, 전월, 당월, 어제, 오늘
|
|
||||||
- 클릭: 해당 기간이 설정되며 화면 전체에 적용 처리
|
|
||||||
- 근태관리 자동 설정 시: 모든 사원이 정시 출퇴근한 것으로 기록, 예외사항만 경우 작성
|
|
||||||
|
|
||||||
### 7.3 근태 등록 버튼
|
|
||||||
- 클릭: 근태 정보 팝업 표시
|
|
||||||
|
|
||||||
### 7.4 사유 등록 버튼
|
|
||||||
- 클릭: 사유 정보 팝업 표시
|
|
||||||
|
|
||||||
### 7.5 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 정시 출근, 지각, 결근, 휴가, 출장, 외근, 연장근무
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 7.6 정렬 셀렉트 박스
|
|
||||||
- 종류: 직급순, 부서 오름차순, 부서 내림차순, 이름 오름차순, 이름 내림차순
|
|
||||||
- 디폴트: 직급순
|
|
||||||
|
|
||||||
### 7.7 근태 정보 팝업
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 대상 | 사원 셀렉트 박스, 검색&다중 선택 |
|
|
||||||
| 기준일 | 달력 팝업 표시, 일자 다중 선택 가능, 디폴트: 당일 |
|
|
||||||
| 출근 시간 | 시/분 선택 |
|
|
||||||
| 퇴근 시간 | 시/분 선택 |
|
|
||||||
| 야간 연장 시간 | 주당 연장 근로 시간에서 주말 연장 시간을 차감한 이내에만 설정 가능 |
|
|
||||||
| 주말 연장 시간 | 주당 연장 근로 시간에서 야간 연장 시간을 차감한 이내에만 설정 가능 |
|
|
||||||
|
|
||||||
### 7.8 사유 정보 팝업
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 대상 | 사원 셀렉트 박스 |
|
|
||||||
| 기준일 | 달력 팝업 |
|
|
||||||
| 내용 | 내용 입력 |
|
|
||||||
|
|
||||||
## 8. 휴가관리 (슬라이드 43-46)
|
|
||||||
|
|
||||||
### 8.1 휴가관리 탭
|
|
||||||
- 휴가 사용 현황
|
|
||||||
- 휴가 부여 현황
|
|
||||||
- 휴가 신청 현황
|
|
||||||
|
|
||||||
### 8.2 휴가관리 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 휴가 승인 대기 | |
|
|
||||||
| 연차 | 전체 연차 사원 수 |
|
|
||||||
| 결조사 | |
|
|
||||||
| 연간 연차 사용률 | |
|
|
||||||
|
|
||||||
### 8.3 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 모든 사원 목록
|
|
||||||
- 항목: 부서명, 직급명, 사원명 표시
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 8.4 정렬 셀렉트 박스
|
|
||||||
- 종류: 직급순, 부서 오름차순, 부서 내림차순, 이름 오름차순, 이름 내림차순
|
|
||||||
- 디폴트: 직급순
|
|
||||||
|
|
||||||
### 8.5 휴가 부여 팝업
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 유형 | 종류: 연차, 보상, 경조, 보건, 병가, 반차, 반수 선택 |
|
|
||||||
| 사유 | |
|
|
||||||
| 일수 | 개월/일/시간 선택 |
|
|
||||||
|
|
||||||
### 8.6 휴가 신청 팝업
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 잔여 | 잔여 일수 표시 |
|
|
||||||
| 유형 | 종류: 연차, 보상, 경조, 보건, 병가, 반차 |
|
|
||||||
| 기간 | 날짜 선택, (5) 반차 선택 시에는 시간으로 변경 |
|
|
||||||
|
|
||||||
### 8.7 휴가 신청 현황 필터
|
|
||||||
- 종류: 승인, 거절
|
|
||||||
- 1/3 완료: 결재선 승인 진행도에 따라 표시
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터 모델
|
|
||||||
|
|
||||||
### Department (부서)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- parent_id: bigint (FK, nullable)
|
|
||||||
- name: string
|
|
||||||
- order: int
|
|
||||||
- is_active: boolean
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### Employee (사원)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- user_id: bigint (FK, nullable)
|
|
||||||
- department_id: bigint (FK, nullable)
|
|
||||||
- employee_code: string
|
|
||||||
- name: string
|
|
||||||
- resident_number: string (encrypted)
|
|
||||||
- phone: string
|
|
||||||
- email: string
|
|
||||||
- salary: decimal
|
|
||||||
- bank_code: string
|
|
||||||
- account_number: string
|
|
||||||
- account_holder: string
|
|
||||||
- profile_image: string
|
|
||||||
- gender: enum('male', 'female')
|
|
||||||
- address: string
|
|
||||||
- hire_date: date
|
|
||||||
- employment_type: enum('regular', 'contract', 'dispatch', 'service', 'part_time')
|
|
||||||
- position_id: bigint (FK)
|
|
||||||
- job_title_id: bigint (FK)
|
|
||||||
- status: enum('active', 'leave', 'sick_leave', 'parental_leave', 'personal_leave', 'unpaid_leave', 'resigned', 'dismissed', 'recommended_resignation', 'contract_expired', 'retired')
|
|
||||||
- check_in_location_id: bigint (FK, nullable)
|
|
||||||
- check_out_location_id: bigint (FK, nullable)
|
|
||||||
- resignation_date: date
|
|
||||||
- resignation_reason: text
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### AttendanceRecord (근태 기록)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- employee_id: bigint (FK)
|
|
||||||
- date: date
|
|
||||||
- check_in_time: time
|
|
||||||
- check_out_time: time
|
|
||||||
- status: enum('on_time', 'late', 'absent', 'leave', 'business_trip', 'outside_work', 'overtime')
|
|
||||||
- night_overtime_hours: decimal
|
|
||||||
- weekend_overtime_hours: decimal
|
|
||||||
- reason: text
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### Leave (휴가)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- employee_id: bigint (FK)
|
|
||||||
- type: enum('annual', 'reward', 'congratulation', 'health', 'sick', 'half_day', 'half_day_am', 'half_day_pm')
|
|
||||||
- start_date: date
|
|
||||||
- end_date: date
|
|
||||||
- days: decimal
|
|
||||||
- reason: text
|
|
||||||
- status: enum('pending', 'approved', 'rejected')
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### LeaveBalance (휴가 잔여)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- employee_id: bigint (FK)
|
|
||||||
- year: int
|
|
||||||
- type: enum('annual', 'reward', ...)
|
|
||||||
- granted: decimal
|
|
||||||
- used: decimal
|
|
||||||
- remaining: decimal
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 부서관리 API
|
|
||||||
```
|
|
||||||
GET /api/departments # 부서 목록 (트리 구조)
|
|
||||||
POST /api/departments # 부서 추가
|
|
||||||
PUT /api/departments/{id} # 부서 수정
|
|
||||||
DELETE /api/departments/{id} # 부서 삭제
|
|
||||||
DELETE /api/departments/bulk # 부서 일괄 삭제
|
|
||||||
```
|
|
||||||
|
|
||||||
### 사원관리 API
|
|
||||||
```
|
|
||||||
GET /api/employees # 사원 목록
|
|
||||||
POST /api/employees # 사원 등록
|
|
||||||
GET /api/employees/{id} # 사원 상세
|
|
||||||
PUT /api/employees/{id} # 사원 수정
|
|
||||||
DELETE /api/employees/{id} # 사원 삭제
|
|
||||||
POST /api/employees/import # CSV 일괄 등록
|
|
||||||
GET /api/employees/template # CSV 템플릿 다운로드
|
|
||||||
POST /api/employees/invite # 사용자 초대
|
|
||||||
```
|
|
||||||
|
|
||||||
### 근태관리 API
|
|
||||||
```
|
|
||||||
GET /api/attendance # 근태 목록
|
|
||||||
POST /api/attendance # 근태 등록
|
|
||||||
PUT /api/attendance/{id} # 근태 수정
|
|
||||||
GET /api/attendance/summary # 근태 현황 요약
|
|
||||||
POST /api/attendance/reason # 사유 등록
|
|
||||||
```
|
|
||||||
|
|
||||||
### 휴가관리 API
|
|
||||||
```
|
|
||||||
GET /api/leaves # 휴가 목록
|
|
||||||
POST /api/leaves # 휴가 신청
|
|
||||||
PUT /api/leaves/{id} # 휴가 수정
|
|
||||||
DELETE /api/leaves/{id} # 휴가 취소
|
|
||||||
POST /api/leaves/{id}/approve # 휴가 승인
|
|
||||||
POST /api/leaves/{id}/reject # 휴가 거절
|
|
||||||
GET /api/leaves/balance/{employee_id} # 휴가 잔여 조회
|
|
||||||
POST /api/leaves/grant # 휴가 부여
|
|
||||||
GET /api/leaves/summary # 휴가 현황 요약
|
|
||||||
```
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
# 전자결재 (슬라이드 47-59)
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
전자결재 모듈은 기안함, 결재함, 참조함으로 구성되며, 품의서, 지출결의서, 지출 예상 내역서 등의 문서를 처리합니다.
|
|
||||||
|
|
||||||
## 2. 기안함 (슬라이드 48-54)
|
|
||||||
|
|
||||||
### 2.1 문서 상태
|
|
||||||
| 상태 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 임시저장 | 문서 작성 중, 임시저장된 상태 |
|
|
||||||
| 진행 | 모든 결재자 중 일부 승인된 상태, 결재 요청을 받은 상태 |
|
|
||||||
| 결재요청 | 결재 요청을 받은 상태 |
|
|
||||||
| 반려 | 결재자 중 반려한 사람이 있는 상태 |
|
|
||||||
|
|
||||||
### 2.2 기안함 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 진행 | 진행 중인 문서 수 |
|
|
||||||
| 전체 | 전체 문서 수 |
|
|
||||||
| 반려 | 반려된 문서 수 |
|
|
||||||
| 임시 저장 | 임시저장 문서 수 |
|
|
||||||
|
|
||||||
### 2.3 문서 작성 버튼
|
|
||||||
- 클릭: 문서 작성 화면으로 이동
|
|
||||||
|
|
||||||
### 2.4 상세 버튼
|
|
||||||
- 클릭: 문서 상세 팝업 표시
|
|
||||||
|
|
||||||
### 2.5 삭제 버튼
|
|
||||||
- 클릭:
|
|
||||||
1) 임시저장 상태일 경우: "정말 이(1)건을 삭제 처리하시겠습니까?" 확인 Alert 표시, 확인 시 해당 문서 삭제 처리
|
|
||||||
2) 임시저장 상태가 아닐 경우: "임시저장 상태만 삭제가 가능합니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
### 2.6 수정 버튼
|
|
||||||
- 클릭:
|
|
||||||
1) 임시저장 상태일 경우: 문서 작성 화면으로 이동
|
|
||||||
2) 임시저장 상태가 아닐 경우: 문서 상세 팝업 표시
|
|
||||||
|
|
||||||
### 2.7 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 임시저장, 진행, 완료, 반려
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 2.8 정렬 셀렉트 박스
|
|
||||||
- 종류: 최신순, 등록순
|
|
||||||
- 디폴트: 최신순
|
|
||||||
|
|
||||||
## 3. 문서 작성 (슬라이드 49-54)
|
|
||||||
|
|
||||||
### 3.1 상세 버튼
|
|
||||||
- 클릭: 문서 상세 팝업 표시
|
|
||||||
|
|
||||||
### 3.2 문서 유형 셀렉트 박스, 검색
|
|
||||||
- 종류: 품의서, 지출결의서, 지출 예상 내역서
|
|
||||||
- 선택한 문서 유형의 화면으로 변경 표시
|
|
||||||
|
|
||||||
### 3.3 결재자 셀렉트 박스, 검색&다중 선택
|
|
||||||
- 항목: 부서명, 직책명, 사원명 표시
|
|
||||||
- 종류: 전체, 모든 사원 목록
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.4 참조자 셀렉트 박스, 검색&다중 선택
|
|
||||||
- 항목: 부서명, 직책명, 사원명 표시
|
|
||||||
- 종류: 전체, 모든 사원 목록
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.5 버튼 영역
|
|
||||||
| 버튼 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 상세 | 문서 상세 팝업 표시 |
|
|
||||||
| 삭제 | 임시저장 상태만 삭제 가능 |
|
|
||||||
| 삼신 | 결재선 마감 경우 숨김 |
|
|
||||||
| 임시저장 | 임시저장 처리 |
|
|
||||||
|
|
||||||
## 4. 품의서 (슬라이드 50)
|
|
||||||
|
|
||||||
### 4.1 구매처 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 구매처 | Y | |
|
|
||||||
| 구매처 결제일 | Y | |
|
|
||||||
|
|
||||||
### 4.2 품의서 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 제목 | Y | |
|
|
||||||
| 품의 내역 | Y | 녹음 버튼: 마이크 사용 가능할 경우에만 버튼 활성화, 녹음 중지 버튼으로 변경, 음성 내용을 텍스트로 변경하여 (1-1) 인풋박스 영역에 표시 |
|
|
||||||
| 품의 사유 | Y | |
|
|
||||||
| 예상 비용 | Y | |
|
|
||||||
|
|
||||||
### 4.3 참고 이미지 정보
|
|
||||||
- 첨부파일 찾기
|
|
||||||
|
|
||||||
## 5. 지출결의서 (슬라이드 51-52)
|
|
||||||
|
|
||||||
### 5.1 지출 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 지출 요청일 | Y | |
|
|
||||||
| 결제일 | Y | |
|
|
||||||
|
|
||||||
### 5.2 지출결의서 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 적요 | Y | |
|
|
||||||
| 금액 | Y | |
|
|
||||||
| 비고 | N | |
|
|
||||||
|
|
||||||
### 5.3 결제 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 카드 | Y | 종류: 등록된 카드 목록, 디폴트: 첫번째 카드 |
|
|
||||||
| 총 비용 | - | 지출결의서 정보의 금액 합계 표시 |
|
|
||||||
|
|
||||||
### 5.4 참고 이미지 정보
|
|
||||||
- 첨부파일 찾기
|
|
||||||
|
|
||||||
## 6. 지출 예상 내역서 (슬라이드 53-54)
|
|
||||||
|
|
||||||
### 6.1 지출 예상 내역서 목록
|
|
||||||
- 체크 설정/해제 토글
|
|
||||||
- 1) 지출 예상 내역서 화면에서 찾을 경우: 설정된 체크 상태 유지
|
|
||||||
- 2) 문서 작성 화면에서 설정했을 경우: 모든 체크 항목 설정된 상태
|
|
||||||
|
|
||||||
### 6.2 항목
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 예상 지급일 | |
|
|
||||||
| 품목 | |
|
|
||||||
| 지출금액 | |
|
|
||||||
| 거래처 | |
|
|
||||||
| 계좌 | |
|
|
||||||
|
|
||||||
### 6.3 합계
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 지출 합계 | |
|
|
||||||
| 계좌 잔액 | |
|
|
||||||
| 최종 차액 | |
|
|
||||||
|
|
||||||
## 7. 결재함 (슬라이드 55-58)
|
|
||||||
|
|
||||||
### 7.1 상태
|
|
||||||
| 상태 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 진행 | 결재 하위 상태 |
|
|
||||||
| 예정 | 결재 순번에 의한 대기 |
|
|
||||||
| 결재요청 | 결재 요청을 받은 상태 |
|
|
||||||
|
|
||||||
### 7.2 결재함 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 결재 요청 | 결재 요청 문서 수 |
|
|
||||||
| 완료 | 완료 문서 수 |
|
|
||||||
| 반려 | 반려 문서 수 |
|
|
||||||
| 예정 | 예정 문서 수 |
|
|
||||||
|
|
||||||
### 7.3 승인 버튼
|
|
||||||
- 클릭: "정말 (1)건을 승인하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 버튼 클릭 시 "승인이 완료되었습니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
### 7.4 반려 버튼
|
|
||||||
- 클릭: "정말 (1)건을 반려하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 버튼 클릭 시 "반려가 완료되었습니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
### 7.5 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 결재 요청, 예정, 완료, 반려
|
|
||||||
- 1/3 완료: 결재선 승인 진행도에 따라 표시
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 7.6 수정 버튼
|
|
||||||
- 클릭: 문서 상세 팝업 표시
|
|
||||||
|
|
||||||
## 8. 참조함 (슬라이드 59)
|
|
||||||
|
|
||||||
### 8.1 열람 버튼
|
|
||||||
- 클릭: "정말 (1)건을 열람 처리하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 버튼 클릭 시 "열람 처리가 완료되었습니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
### 8.2 미열람 버튼
|
|
||||||
- 클릭: "정말 (1)건을 미열람 처리하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 버튼 클릭 시 "미열람 처리가 완료되었습니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
### 8.3 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 열람, 미열람
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
## 9. 문서 상세 팝업 (슬라이드 56-58)
|
|
||||||
|
|
||||||
### 9.1 버튼 영역
|
|
||||||
| 버튼 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 복제 | 문서 작성 화면으로 이동 (새글) |
|
|
||||||
| 수정 | 결재선 중에서는 누구나 수정 가능, 해당 문서 작성 화면으로 이동 |
|
|
||||||
| 반려 | 결재선 마감 경우 숨김 |
|
|
||||||
| 승인 | 결재선 마감 경우 숨김 |
|
|
||||||
| 인쇄 | |
|
|
||||||
| 공유 | (5-1) 팝업 표시 |
|
|
||||||
| 닫기 | |
|
|
||||||
|
|
||||||
### 9.2 결재선 영역
|
|
||||||
- 승인/반려 시 해당 아이콘 표시
|
|
||||||
|
|
||||||
### 9.3 공유 버튼
|
|
||||||
| 공유 방식 | 설명 |
|
|
||||||
|-----------|------|
|
|
||||||
| PDF | |
|
|
||||||
| 이메일 | |
|
|
||||||
| 카카오톡 | |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터 모델
|
|
||||||
|
|
||||||
### ApprovalDocument (결재 문서)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- document_number: string
|
|
||||||
- document_type: enum('request', 'expense', 'expense_estimate')
|
|
||||||
- title: string
|
|
||||||
- status: enum('draft', 'pending', 'in_progress', 'approved', 'rejected')
|
|
||||||
- drafter_id: bigint (FK) # 기안자
|
|
||||||
- content: json # 문서 내용
|
|
||||||
- attachments: json
|
|
||||||
- created_at: timestamp
|
|
||||||
- submitted_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### ApprovalLine (결재선)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- document_id: bigint (FK)
|
|
||||||
- approver_id: bigint (FK)
|
|
||||||
- order: int
|
|
||||||
- status: enum('pending', 'approved', 'rejected')
|
|
||||||
- comment: text
|
|
||||||
- approved_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### ApprovalReference (참조자)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- document_id: bigint (FK)
|
|
||||||
- referee_id: bigint (FK)
|
|
||||||
- is_read: boolean
|
|
||||||
- read_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### ExpenseItem (지출 항목)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- document_id: bigint (FK)
|
|
||||||
- description: string
|
|
||||||
- amount: decimal
|
|
||||||
- note: text
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 기안함 API
|
|
||||||
```
|
|
||||||
GET /api/approvals/drafts # 기안 목록
|
|
||||||
POST /api/approvals # 문서 작성
|
|
||||||
PUT /api/approvals/{id} # 문서 수정
|
|
||||||
DELETE /api/approvals/{id} # 문서 삭제
|
|
||||||
POST /api/approvals/{id}/submit # 문서 제출 (결재 요청)
|
|
||||||
POST /api/approvals/{id}/save-draft # 임시저장
|
|
||||||
GET /api/approvals/{id} # 문서 상세
|
|
||||||
GET /api/approvals/drafts/summary # 기안함 현황
|
|
||||||
```
|
|
||||||
|
|
||||||
### 결재함 API
|
|
||||||
```
|
|
||||||
GET /api/approvals/inbox # 결재함 목록
|
|
||||||
POST /api/approvals/{id}/approve # 승인
|
|
||||||
POST /api/approvals/{id}/reject # 반려
|
|
||||||
GET /api/approvals/inbox/summary # 결재함 현황
|
|
||||||
```
|
|
||||||
|
|
||||||
### 참조함 API
|
|
||||||
```
|
|
||||||
GET /api/approvals/references # 참조함 목록
|
|
||||||
POST /api/approvals/{id}/mark-read # 열람 처리
|
|
||||||
POST /api/approvals/{id}/mark-unread # 미열람 처리
|
|
||||||
```
|
|
||||||
|
|
||||||
### 문서 공유 API
|
|
||||||
```
|
|
||||||
GET /api/approvals/{id}/pdf # PDF 다운로드
|
|
||||||
POST /api/approvals/{id}/share/email # 이메일 공유
|
|
||||||
POST /api/approvals/{id}/share/kakao # 카카오톡 공유
|
|
||||||
```
|
|
||||||
@@ -1,427 +0,0 @@
|
|||||||
# 회계관리 (슬라이드 60-91)
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
회계관리 모듈은 거래처, 매출, 매입, 입금, 출금, 어음, 거래처원장, 미수금 현황, 입출금 계좌 조회 등을 관리합니다.
|
|
||||||
|
|
||||||
## 2. 회계관리 플로우차트 (슬라이드 61)
|
|
||||||
|
|
||||||
### 2.1 매출 플로우
|
|
||||||
```
|
|
||||||
거래처 선택 → 매출 등록 → 세금계산서 발행
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 입금 플로우
|
|
||||||
```
|
|
||||||
입금 등록 → 전액 입금? → 어음 수취?
|
|
||||||
↓ ↓
|
|
||||||
입출금 계좌 조회 어음관리
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 매입 플로우
|
|
||||||
```
|
|
||||||
거래처 선택 → 매입 등록 → 세금계산서 수취
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.4 출금 플로우
|
|
||||||
```
|
|
||||||
출금 등록 → 전액 출금? → 어음 발행?
|
|
||||||
↓ ↓
|
|
||||||
입출금 계좌 조회 어음관리
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 추심 플로우
|
|
||||||
```
|
|
||||||
미수금 현황 → 연체? → 악성주심? → 악성 추심
|
|
||||||
↓
|
|
||||||
미지급 알림
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.6 조회
|
|
||||||
- 입출금 계좌 조회
|
|
||||||
- 카드 내역 조회
|
|
||||||
|
|
||||||
### 2.7 장부/보고서
|
|
||||||
- 거래처원장
|
|
||||||
- 지출 예상 내역서
|
|
||||||
- 일일 일보
|
|
||||||
|
|
||||||
## 3. 거래처관리 (슬라이드 62-65)
|
|
||||||
|
|
||||||
### 3.1 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 전체 거래처 | |
|
|
||||||
| 매출 거래처 | |
|
|
||||||
| 매입 거래처 | |
|
|
||||||
|
|
||||||
### 3.2 삭제 버튼
|
|
||||||
- 관리 권한이 없을 경우 숨김
|
|
||||||
- 클릭: "선택한 거래처 N개를 삭제하시겠습니까?" 확인 Alert 표시
|
|
||||||
- 확인 선택 시 삭제
|
|
||||||
|
|
||||||
### 3.3 구분 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 매출, 매입, 매입매출
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.4 신용등급 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, AAA, AA, A, BBB, BB, B, CCC, CC, C, D
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.5 거래등급 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, A(우수), B(양호), C(보통), D(주의), E(위험)
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.6 약정체결 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 약정체결, 정상
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 3.7 정렬 셀렉트 박스
|
|
||||||
- 종류: 최신순, 등록순, 거래처명 오름차순, 거래처명 내림차순, 미수금 높은순, 미수금 낮은순
|
|
||||||
- 디폴트: 최신순
|
|
||||||
|
|
||||||
## 4. 거래처 상세 (슬라이드 63-65)
|
|
||||||
|
|
||||||
### 4.1 기본 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 사업자등록번호 | Y | |
|
|
||||||
| 거래처 코드 | N | |
|
|
||||||
| 거래처명 | Y | |
|
|
||||||
| 대표자명 | Y | |
|
|
||||||
| 거래처 유형 | Y | 매출매입 선택 |
|
|
||||||
| 업태 | N | |
|
|
||||||
| 업종 | N | |
|
|
||||||
|
|
||||||
### 4.2 연락처 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 주소 | N | 우편번호 찾기 + 상세주소 |
|
|
||||||
| 전화번호 | N | |
|
|
||||||
| 모바일 | N | |
|
|
||||||
| 팩스 | N | |
|
|
||||||
| 이메일 | N | |
|
|
||||||
|
|
||||||
### 4.3 담당자 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 담당자명 | N | |
|
|
||||||
| 담당자 전화 | N | |
|
|
||||||
|
|
||||||
### 4.4 시스템 관리자
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 관리자명 | N | |
|
|
||||||
|
|
||||||
### 4.5 회사 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 회사 로고 | N | 750x250px, 10MB 이하 PNG, JPEG, GIF |
|
|
||||||
|
|
||||||
### 4.6 결제 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 매입 결제일 | N | 종류: 1일~31일, 말일. 디폴트: 10일. 거래처 유형이 '매입' 또는 '매입매출'일 경우 해당 |
|
|
||||||
| 매출 결제일 | N | 종류: 1일~31일, 말일. 디폴트: 15일. 거래처 유형이 '매출' 또는 '매입매출'일 경우 표시 |
|
|
||||||
|
|
||||||
### 4.7 신용 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 신용등급 | N | 외부 신용평가 등급 표시. 예: AAA, AA, A, BBB, BB, B, CCC, CC, C, D |
|
|
||||||
| 거래등급 | N | 종류: A(우수), B(양호), C(보통), D(주의), E(위험). 디폴트: A(우수). 자사 기준 거래처 평가 등급 |
|
|
||||||
|
|
||||||
### 4.8 계좌 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 세금계산서 이메일 | N | |
|
|
||||||
| 입금계좌 은행 | N | 은행 선택 |
|
|
||||||
| 계좌 | N | |
|
|
||||||
| 예금주 | N | |
|
|
||||||
|
|
||||||
### 4.9 추가 정보
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 미수금 | 해당 거래처의 현재 미수금 잠게 표시. 읽기 전용 |
|
|
||||||
| 연체 | - ON: 연체 상태로 표시, 연체일수 표시 |
|
|
||||||
| | - OFF: 정상 상태 |
|
|
||||||
| | - 거래처 상세에서 연체 설정과 연동 |
|
|
||||||
| | - (4-1) 연체 등록 이후부터 경과일 표시 |
|
|
||||||
| 미지급 | 해당 거래처에 대한 미지급금 잠게 표시. 읽기 전용 |
|
|
||||||
| 악성채권 | - ON: 악성채권으로 등록, 악성채권 추심관리 목록에 표시 |
|
|
||||||
| | - OFF: 정상 상태 |
|
|
||||||
| | - 디폴트: OFF |
|
|
||||||
| 메모 | 추가 버튼 클릭 시 목록 최상단에 추가 |
|
|
||||||
|
|
||||||
## 5. 매출관리 (슬라이드 66-71)
|
|
||||||
|
|
||||||
### 5.1 매출 유형
|
|
||||||
- 필드 매출 시 매출 직접 등록 (삭제 가능)
|
|
||||||
- 필드 매출: 용역 매출, 공사 매출, 임대 수익, 기타 매출
|
|
||||||
|
|
||||||
### 5.2 매출 상세
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 매출번호 | - | 자동 채번 |
|
|
||||||
| 매출일 | Y | |
|
|
||||||
| 거래처명 | Y | 거래처 선택 |
|
|
||||||
| 매출 유형 | Y | 선택 |
|
|
||||||
|
|
||||||
### 5.3 품목 정보
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 품목명 | Y | |
|
|
||||||
| 수량 | Y | |
|
|
||||||
| 단가 | Y | |
|
|
||||||
| 공급가액 | - | 자동 계산 |
|
|
||||||
| 부가세 | - | 자동 계산 |
|
|
||||||
| 적요 | N | |
|
|
||||||
|
|
||||||
### 5.4 세금계산서
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 세금계산서 발행 | 토글 |
|
|
||||||
|
|
||||||
### 5.5 거래명세서
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 거래명세서 | 토글 |
|
|
||||||
|
|
||||||
## 6. 입금관리 (슬라이드 74-76)
|
|
||||||
|
|
||||||
### 6.1 입금 유형
|
|
||||||
- 종류: 매출대금, 선수금, 가수금, 입대수익, 미자수익, 보증금 반환, 차입금, 자본금, 부가세 환급, 기타, 미상정
|
|
||||||
|
|
||||||
### 6.2 입금 상세
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 입금일 | Y | |
|
|
||||||
| 입금계좌 | Y | 국민은행 1234 (계좌명) |
|
|
||||||
| 입금자명 | Y | |
|
|
||||||
| 입금금액 | Y | |
|
|
||||||
| 적요 | N | |
|
|
||||||
| 거래처 | N | 선택 |
|
|
||||||
| 입금 유형 | Y | |
|
|
||||||
|
|
||||||
## 7. 출금관리 (슬라이드 77-79)
|
|
||||||
|
|
||||||
### 7.1 출금 유형
|
|
||||||
- 종류: 매입대금, 선급금, 가지급금, 임대비용, 보증금 지급, 차입금 상환, 배당금 지급, 세금, 공과금, 경비, 4대보험, 급여
|
|
||||||
|
|
||||||
### 7.2 출금 상세
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 출금일 | Y | |
|
|
||||||
| 출금계좌 | Y | |
|
|
||||||
| 받는 분 | Y | |
|
|
||||||
| 출금금액 | Y | |
|
|
||||||
| 적요 | N | |
|
|
||||||
| 거래처 | N | |
|
|
||||||
| 출금 유형 | Y | |
|
|
||||||
|
|
||||||
## 8. 거래처원장 (슬라이드 80)
|
|
||||||
|
|
||||||
### 8.1 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 전기 이월 | |
|
|
||||||
| 매출 | |
|
|
||||||
| 수금 | |
|
|
||||||
| 잔액 | |
|
|
||||||
|
|
||||||
### 8.2 거래처원장 목록
|
|
||||||
- 거래처별 기간별 합계 금액 표시
|
|
||||||
- 클릭: 거래처원장 상세 화면으로 이동
|
|
||||||
|
|
||||||
### 8.3 엑셀 다운로드 버튼
|
|
||||||
- 클릭: 엑셀 파일 다운로드
|
|
||||||
|
|
||||||
## 9. 미수금 현황 (슬라이드 85)
|
|
||||||
|
|
||||||
### 9.1 미수금 현황 목록
|
|
||||||
- 거래처별 월별 미수금 현황 (매출, 입금, 어음, 미수금, 메모)
|
|
||||||
|
|
||||||
### 9.2 수취 어음 등록 시 표시
|
|
||||||
- 회계에는 미반영
|
|
||||||
|
|
||||||
### 9.3 연체 표시
|
|
||||||
- ON: 연체 상태로 표시, 연체일수 표시
|
|
||||||
- OFF: 정상 상태
|
|
||||||
- 거래처 상세에서 연체 설정과 연동
|
|
||||||
|
|
||||||
### 9.4 엑셀 다운로드 버튼
|
|
||||||
|
|
||||||
### 9.5 저장 버튼
|
|
||||||
|
|
||||||
## 10. 입출금 계좌 조회 (슬라이드 90)
|
|
||||||
|
|
||||||
### 10.1 설명
|
|
||||||
- 기준 정보 > 계좌 관리에 등록된 계좌의 자동 입출금 내역 수집
|
|
||||||
|
|
||||||
### 10.2 새로고침 버튼
|
|
||||||
- 클릭: 은행 계좌 입출금 내역 최신 데이터 조회
|
|
||||||
- 바로빌 API 연동 시 실시간 조회
|
|
||||||
|
|
||||||
### 10.3 구분 필터 셀렉트 박스
|
|
||||||
- 종류: 전체, 출금, 입금
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 10.4 계정과목 필터 셀렉트 박스, 검색&다중 선택
|
|
||||||
- (2) 선택에 따른 계정과목 목록 표시
|
|
||||||
- 입금 종류: 전체, 매출대금, 선수금, 가수금, 임대수익, 이자수익, 보증금 반환, 차입금, 자본금, 부가세 환급, 기타, 미상정
|
|
||||||
- 출금 종류: 전체, 매입대금, 선급금, 가지급금, 임대비용, 이자비용, 보증금 지급, 차입금 상환, 배당금 지급, 세금, 공과금, 경비, 4대보험, 급여
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 10.5 정렬 셀렉트 박스
|
|
||||||
- 종류: 최신순, 등록순, 금액순
|
|
||||||
- 디폴트: 최신순
|
|
||||||
|
|
||||||
### 10.6 수정 버튼
|
|
||||||
- 클릭: 해당 입금/출금 상세 화면으로 이동
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터 모델
|
|
||||||
|
|
||||||
### Vendor (거래처)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- business_number: string
|
|
||||||
- vendor_code: string
|
|
||||||
- name: string
|
|
||||||
- representative: string
|
|
||||||
- type: enum('sales', 'purchase', 'both')
|
|
||||||
- business_type: string
|
|
||||||
- business_category: string
|
|
||||||
- address: string
|
|
||||||
- phone: string
|
|
||||||
- mobile: string
|
|
||||||
- fax: string
|
|
||||||
- email: string
|
|
||||||
- manager_name: string
|
|
||||||
- manager_phone: string
|
|
||||||
- logo: string
|
|
||||||
- purchase_payment_day: int
|
|
||||||
- sales_payment_day: int
|
|
||||||
- credit_rating: enum('AAA', 'AA', 'A', 'BBB', 'BB', 'B', 'CCC', 'CC', 'C', 'D')
|
|
||||||
- trade_rating: enum('A', 'B', 'C', 'D', 'E')
|
|
||||||
- tax_invoice_email: string
|
|
||||||
- bank_code: string
|
|
||||||
- account_number: string
|
|
||||||
- account_holder: string
|
|
||||||
- is_overdue: boolean
|
|
||||||
- overdue_start_date: date
|
|
||||||
- is_bad_debt: boolean
|
|
||||||
- notes: json
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sales (매출)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- vendor_id: bigint (FK)
|
|
||||||
- sales_number: string
|
|
||||||
- sales_date: date
|
|
||||||
- sales_type: enum('product', 'service', 'construction', 'rental', 'other')
|
|
||||||
- total_amount: decimal
|
|
||||||
- tax_amount: decimal
|
|
||||||
- is_tax_invoice_issued: boolean
|
|
||||||
- is_statement_issued: boolean
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### SalesItem (매출 품목)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- sales_id: bigint (FK)
|
|
||||||
- item_name: string
|
|
||||||
- quantity: int
|
|
||||||
- unit_price: decimal
|
|
||||||
- supply_amount: decimal
|
|
||||||
- tax_amount: decimal
|
|
||||||
- description: string
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deposit (입금)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- vendor_id: bigint (FK, nullable)
|
|
||||||
- account_id: bigint (FK)
|
|
||||||
- deposit_date: date
|
|
||||||
- depositor_name: string
|
|
||||||
- amount: decimal
|
|
||||||
- description: string
|
|
||||||
- deposit_type: enum('sales', 'advance', 'suspense', 'rental', 'interest', 'deposit_return', 'loan', 'capital', 'vat_refund', 'other', 'unidentified')
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### Withdrawal (출금)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- vendor_id: bigint (FK, nullable)
|
|
||||||
- account_id: bigint (FK)
|
|
||||||
- withdrawal_date: date
|
|
||||||
- recipient_name: string
|
|
||||||
- amount: decimal
|
|
||||||
- description: string
|
|
||||||
- withdrawal_type: enum('purchase', 'advance', 'suspense', 'rental', 'interest', 'deposit', 'loan_repayment', 'dividend', 'tax', 'utility', 'expense', 'insurance', 'salary')
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 거래처 API
|
|
||||||
```
|
|
||||||
GET /api/vendors # 거래처 목록
|
|
||||||
POST /api/vendors # 거래처 등록
|
|
||||||
GET /api/vendors/{id} # 거래처 상세
|
|
||||||
PUT /api/vendors/{id} # 거래처 수정
|
|
||||||
DELETE /api/vendors/{id} # 거래처 삭제
|
|
||||||
DELETE /api/vendors/bulk # 거래처 일괄 삭제
|
|
||||||
GET /api/vendors/summary # 거래처 현황
|
|
||||||
```
|
|
||||||
|
|
||||||
### 매출 API
|
|
||||||
```
|
|
||||||
GET /api/sales # 매출 목록
|
|
||||||
POST /api/sales # 매출 등록
|
|
||||||
GET /api/sales/{id} # 매출 상세
|
|
||||||
PUT /api/sales/{id} # 매출 수정
|
|
||||||
DELETE /api/sales/{id} # 매출 삭제
|
|
||||||
POST /api/sales/{id}/tax-invoice # 세금계산서 발행
|
|
||||||
GET /api/sales/summary # 매출 현황
|
|
||||||
```
|
|
||||||
|
|
||||||
### 입금 API
|
|
||||||
```
|
|
||||||
GET /api/deposits # 입금 목록
|
|
||||||
POST /api/deposits # 입금 등록
|
|
||||||
GET /api/deposits/{id} # 입금 상세
|
|
||||||
PUT /api/deposits/{id} # 입금 수정
|
|
||||||
DELETE /api/deposits/{id} # 입금 삭제
|
|
||||||
```
|
|
||||||
|
|
||||||
### 출금 API
|
|
||||||
```
|
|
||||||
GET /api/withdrawals # 출금 목록
|
|
||||||
POST /api/withdrawals # 출금 등록
|
|
||||||
GET /api/withdrawals/{id} # 출금 상세
|
|
||||||
PUT /api/withdrawals/{id} # 출금 수정
|
|
||||||
DELETE /api/withdrawals/{id} # 출금 삭제
|
|
||||||
```
|
|
||||||
|
|
||||||
### 장부/보고서 API
|
|
||||||
```
|
|
||||||
GET /api/ledger/vendor # 거래처원장
|
|
||||||
GET /api/ledger/vendor/{vendor_id} # 거래처원장 상세
|
|
||||||
GET /api/ledger/vendor/export # 거래처원장 엑셀 다운로드
|
|
||||||
GET /api/receivables # 미수금 현황
|
|
||||||
GET /api/receivables/export # 미수금 현황 엑셀 다운로드
|
|
||||||
GET /api/bank-transactions # 입출금 계좌 조회
|
|
||||||
POST /api/bank-transactions/sync # 입출금 내역 동기화
|
|
||||||
```
|
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
# 기준정보 (슬라이드 92-104)
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
기준정보 모듈은 직급, 직책, 권한, 근무, 출퇴근, 휴가, 카드, 계좌, 팝업, 게시판, 일반설정, 알림설정을 관리합니다.
|
|
||||||
|
|
||||||
## 2. 직급관리 (슬라이드 93, 95)
|
|
||||||
|
|
||||||
### 2.1 직급 인풋박스
|
|
||||||
- 직급 입력 후 추가 버튼 클릭
|
|
||||||
|
|
||||||
### 2.2 추가 버튼
|
|
||||||
- 클릭: (2-1) 직급 목록 최하단에 표시
|
|
||||||
|
|
||||||
### 2.3 직급 목록
|
|
||||||
- 디폴트: 사원, 대리, 과장, 차장, 부장, 이사, 상무, 전무, 부사장, 사장
|
|
||||||
|
|
||||||
### 2.4 순서 변경 버튼
|
|
||||||
- 드래그&드랍: 해당 위치로 순서 변경
|
|
||||||
|
|
||||||
### 2.5 수정 버튼
|
|
||||||
- 클릭: 직급 수정 팝업 표시
|
|
||||||
|
|
||||||
### 2.6 삭제 버튼
|
|
||||||
- 클릭:
|
|
||||||
1) 해당 직급으로 사원 설정된 경우: "'직급명'을 사용하고 있는 사원이 있습니다. 다 변경 후 삭제가 가능합니다." 알림 Alert 표시
|
|
||||||
2) 해당 직급으로 사원 미설정된 경우: "정말 삭제하시겠습니까?" 확인 Alert 표시, 확인 클릭 시 "삭제가 완료되었습니다." 알림 Alert 표시
|
|
||||||
|
|
||||||
### 2.7 직급 수정 팝업
|
|
||||||
- 직급명 인풋박스: 기존 직급명 표시, 수정 가능
|
|
||||||
|
|
||||||
## 3. 직책관리 (슬라이드 94-95)
|
|
||||||
|
|
||||||
### 3.1 기능
|
|
||||||
- 직급관리와 동일한 구조
|
|
||||||
|
|
||||||
### 3.2 디폴트 직책
|
|
||||||
- (없음)
|
|
||||||
|
|
||||||
### 3.3 직책 수정 팝업
|
|
||||||
- 직책명 인풋박스: 기존 직책명 표시, 수정 가능
|
|
||||||
|
|
||||||
## 4. 권한관리 (슬라이드 96)
|
|
||||||
|
|
||||||
### 4.1 관리자
|
|
||||||
- 디폴트: 모든 메뉴 권한 설정
|
|
||||||
- 수정 불가, 삭제 불가
|
|
||||||
|
|
||||||
### 4.2 일반
|
|
||||||
- 디폴트: 대시보드 제외 모든 메뉴 접근 불가
|
|
||||||
|
|
||||||
### 4.3 추가 버튼
|
|
||||||
- 클릭: 권한 추가 팝업 표시
|
|
||||||
|
|
||||||
### 4.4 삭제 버튼
|
|
||||||
- 클릭:
|
|
||||||
1) 해당 권한으로 사원 설정된 경우: "'권한명'을 사용하고 있는 사원이 있습니다. 다 변경 후 삭제가 가능합니다." 알림 Alert 표시
|
|
||||||
2) 해당 권한으로 사원 미설정된 경우: "정말 삭제하시겠습니까?" 확인 Alert 표시
|
|
||||||
|
|
||||||
### 4.5 체크박스
|
|
||||||
- 클릭: 체크 설정/해제 토글
|
|
||||||
- 디폴트: 체크 해제 상태
|
|
||||||
|
|
||||||
### 4.6 관리
|
|
||||||
- 읽기 및 수정 권한
|
|
||||||
|
|
||||||
### 4.7 읽기
|
|
||||||
- 읽기만 권한
|
|
||||||
|
|
||||||
## 5. 근무관리 (슬라이드 97)
|
|
||||||
|
|
||||||
### 5.1 근무 정보
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 근무 유형 | 종류: 고정형, 변형, 맞춤형 |
|
|
||||||
| 기본 소정 근로 시간 | 주 00시간 |
|
|
||||||
| 연장 근로 시간 | 주 00시간 |
|
|
||||||
| 연장 근로 한도 | 52시간 미만 |
|
|
||||||
| 근무 요일 설정 | 클릭: 설정된 체크 활성/비활성 토글, 디폴트: 월~금 활성 |
|
|
||||||
|
|
||||||
### 5.2 출근 시간
|
|
||||||
- 09:00
|
|
||||||
|
|
||||||
### 5.3 퇴근 시간
|
|
||||||
- 18:00
|
|
||||||
|
|
||||||
### 5.4 휴게 시간
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 총 휴게 시간 | 1시간 |
|
|
||||||
| 휴게 시간 | 12:00 ~ 13:00 |
|
|
||||||
|
|
||||||
## 6. 출퇴근관리 (슬라이드 99)
|
|
||||||
|
|
||||||
### 6.1 출퇴근 설정
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| GPS 출퇴근 | 토글: 기준 좌표로 정해진 거리 기준 이내에 있을 때만 출근/퇴근 등록 가능 |
|
|
||||||
| 허용 반경 | 주 00m |
|
|
||||||
|
|
||||||
### 6.2 본사 위치 정보
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 본사 주소 | 우편번호 찾기 + 상세주소 |
|
|
||||||
| 경도 | |
|
|
||||||
| 위도 | |
|
|
||||||
|
|
||||||
### 6.3 현장 목록
|
|
||||||
- 추가 버튼: 현장 등록 팝업 표시
|
|
||||||
- 현장명, 주소, 삭제 버튼
|
|
||||||
|
|
||||||
## 7. 휴가관리 (슬라이드 100)
|
|
||||||
|
|
||||||
### 7.1 기준 셀렉트 박스
|
|
||||||
- 종류: 회계연도, 입사일
|
|
||||||
- 디폴트: 회계연도
|
|
||||||
- 입사일 선택 시 (2) 영역 비활성화
|
|
||||||
- 회계연도 기준: 회사의 회계연도를 기준으로 휴가를 부여하고 조회할 수 있습니다.
|
|
||||||
- 입사일 기준: 사원의 입사일 회계연도 기준으로 휴가를 부여하고 조회할 수 있습니다.
|
|
||||||
|
|
||||||
### 7.2 기준일 월/일 설정 영역
|
|
||||||
- 회계연도 기준 시에만 활성화
|
|
||||||
|
|
||||||
### 7.3 기본 연차 설정
|
|
||||||
- 1년간 출근율 80% 이상이면 15일
|
|
||||||
- 3년 이상 근속 시 2년에 1일 추가 (최대 25일)
|
|
||||||
- 1년 미만 또는 출근율 80% 이하인 경우 1일
|
|
||||||
- 입사일~회계연도 기준일 사정: 회년도 출근율로 판정 80% 이상이면 15일
|
|
||||||
- (3-1) 연차+1년+1일 시작, 이후 2년에 1일 추가
|
|
||||||
- 입사일~회계연도 기준으로 전환할 때는 취업규칙 변경, 노사 의견수렴, 전환 시 충북 연차 정산(입사일 기준 vs 회계연도 기준 비교 후 부족분 보전)을 반드시 검토 필요
|
|
||||||
|
|
||||||
## 8. 카드관리 (슬라이드 101-102)
|
|
||||||
|
|
||||||
### 8.1 카드 목록
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 카드사 | |
|
|
||||||
| 카드번호 | 앞4자리, 끝4자리 표시 |
|
|
||||||
| 카드명 | |
|
|
||||||
| 상태 | |
|
|
||||||
| 사용자 | 부서명 / 이름 / 직책 |
|
|
||||||
| 작업 | 상세 버튼 |
|
|
||||||
|
|
||||||
### 8.2 필터
|
|
||||||
- 종류: 전체, 사용, 정지
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 8.3 카드 상세
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 카드사 | Y | 카드사명 선택 |
|
|
||||||
| 카드번호 | Y | 1234-1234-1234-1234 |
|
|
||||||
| 유효기간 | Y | MM/YY |
|
|
||||||
| 카드 비밀번호 앞 2자리 | Y | 입력 시 마스킹 처리 |
|
|
||||||
| 카드명 | Y | |
|
|
||||||
| 상태 | Y | 종류: 사용, 정지. 정지 시 해당 카드의 자동 조회 중단 |
|
|
||||||
| 사용자 | N | 부서명 / 이름 / 직책. 선택 시 해당 카드의 사용자로 설정 |
|
|
||||||
|
|
||||||
## 9. 계좌관리 (슬라이드 103-104)
|
|
||||||
|
|
||||||
### 9.1 계좌 목록
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 은행 | |
|
|
||||||
| 계좌번호 | |
|
|
||||||
| 예금주 | |
|
|
||||||
| 상태 | |
|
|
||||||
| 사용자 | 부서명 / 이름 / 직책 |
|
|
||||||
| 작업 | 상세 버튼 |
|
|
||||||
|
|
||||||
### 9.2 필터
|
|
||||||
- 종류: 전체, 사용, 정지
|
|
||||||
- 디폴트: 전체
|
|
||||||
|
|
||||||
### 9.3 계좌 상세
|
|
||||||
| 필드명 | 필수 | 설명 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 은행 | Y | 은행 선택 |
|
|
||||||
| 계좌번호 | Y | |
|
|
||||||
| 예금주 | Y | |
|
|
||||||
| 계좌명 | Y | |
|
|
||||||
| 상태 | Y | 종류: 사용, 정지. 정지 시 해당 계좌의 자동 조회 중단 |
|
|
||||||
| 사용자 | N | 부서명 / 이름 / 직책. 선택 시 해당 계좌의 사용자로 설정 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터 모델
|
|
||||||
|
|
||||||
### Position (직급)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- name: string
|
|
||||||
- order: int
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### JobTitle (직책)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- name: string
|
|
||||||
- order: int
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### Role (권한)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- name: string
|
|
||||||
- is_system: boolean # 시스템 기본 권한 여부
|
|
||||||
- permissions: json # 메뉴별 권한 설정
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### WorkSetting (근무 설정)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- work_type: enum('fixed', 'flexible', 'custom')
|
|
||||||
- standard_hours: int # 주당 소정 근로 시간
|
|
||||||
- overtime_hours: int # 주당 연장 근로 시간
|
|
||||||
- overtime_limit: int # 연장 근로 한도
|
|
||||||
- work_days: json # ['mon', 'tue', 'wed', 'thu', 'fri']
|
|
||||||
- start_time: time
|
|
||||||
- end_time: time
|
|
||||||
- break_hours: int
|
|
||||||
- break_start: time
|
|
||||||
- break_end: time
|
|
||||||
```
|
|
||||||
|
|
||||||
### AttendanceSetting (출퇴근 설정)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- use_gps: boolean
|
|
||||||
- allowed_radius: int # 허용 반경 (m)
|
|
||||||
- headquarters_address: string
|
|
||||||
- headquarters_latitude: decimal(10,8)
|
|
||||||
- headquarters_longitude: decimal(11,8)
|
|
||||||
```
|
|
||||||
|
|
||||||
### LeaveSetting (휴가 설정)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- base_type: enum('fiscal_year', 'hire_date')
|
|
||||||
- fiscal_start_month: int
|
|
||||||
- fiscal_start_day: int
|
|
||||||
```
|
|
||||||
|
|
||||||
### Card (카드)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- card_company: string
|
|
||||||
- card_number: string (encrypted)
|
|
||||||
- expiry_date: string
|
|
||||||
- card_password: string (encrypted)
|
|
||||||
- card_name: string
|
|
||||||
- status: enum('active', 'inactive')
|
|
||||||
- user_id: bigint (FK, nullable)
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### BankAccount (계좌)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- bank_code: string
|
|
||||||
- account_number: string
|
|
||||||
- account_holder: string
|
|
||||||
- account_name: string
|
|
||||||
- status: enum('active', 'inactive')
|
|
||||||
- user_id: bigint (FK, nullable)
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 직급/직책 API
|
|
||||||
```
|
|
||||||
GET /api/positions # 직급 목록
|
|
||||||
POST /api/positions # 직급 추가
|
|
||||||
PUT /api/positions/{id} # 직급 수정
|
|
||||||
DELETE /api/positions/{id} # 직급 삭제
|
|
||||||
PUT /api/positions/reorder # 직급 순서 변경
|
|
||||||
|
|
||||||
GET /api/job-titles # 직책 목록
|
|
||||||
POST /api/job-titles # 직책 추가
|
|
||||||
PUT /api/job-titles/{id} # 직책 수정
|
|
||||||
DELETE /api/job-titles/{id} # 직책 삭제
|
|
||||||
PUT /api/job-titles/reorder # 직책 순서 변경
|
|
||||||
```
|
|
||||||
|
|
||||||
### 권한 API
|
|
||||||
```
|
|
||||||
GET /api/roles # 권한 목록
|
|
||||||
POST /api/roles # 권한 추가
|
|
||||||
GET /api/roles/{id} # 권한 상세
|
|
||||||
PUT /api/roles/{id} # 권한 수정
|
|
||||||
DELETE /api/roles/{id} # 권한 삭제
|
|
||||||
GET /api/menus # 메뉴 목록 (권한 설정용)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 설정 API
|
|
||||||
```
|
|
||||||
GET /api/settings/work # 근무 설정 조회
|
|
||||||
PUT /api/settings/work # 근무 설정 수정
|
|
||||||
GET /api/settings/attendance # 출퇴근 설정 조회
|
|
||||||
PUT /api/settings/attendance # 출퇴근 설정 수정
|
|
||||||
GET /api/settings/leave # 휴가 설정 조회
|
|
||||||
PUT /api/settings/leave # 휴가 설정 수정
|
|
||||||
```
|
|
||||||
|
|
||||||
### 카드/계좌 API
|
|
||||||
```
|
|
||||||
GET /api/cards # 카드 목록
|
|
||||||
POST /api/cards # 카드 등록
|
|
||||||
GET /api/cards/{id} # 카드 상세
|
|
||||||
PUT /api/cards/{id} # 카드 수정
|
|
||||||
DELETE /api/cards/{id} # 카드 삭제
|
|
||||||
|
|
||||||
GET /api/bank-accounts # 계좌 목록
|
|
||||||
POST /api/bank-accounts # 계좌 등록
|
|
||||||
GET /api/bank-accounts/{id} # 계좌 상세
|
|
||||||
PUT /api/bank-accounts/{id} # 계좌 수정
|
|
||||||
DELETE /api/bank-accounts/{id} # 계좌 삭제
|
|
||||||
```
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
# 보고서 및 분석 (슬라이드 105-113)
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
보고서 및 분석 모듈은 일일 일보, 지출 예상 내역서, 가지급금 인정이자 계산, AI 리포트 생성 등을 제공합니다.
|
|
||||||
|
|
||||||
## 2. 일일 일보 (슬라이드 106-107)
|
|
||||||
|
|
||||||
### 2.1 일일 일보 조회
|
|
||||||
- 매일 전일의 입출금 및 매출 매입 현황 자동 집계
|
|
||||||
|
|
||||||
### 2.2 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 전일 잔액 | 조회 기준일 전일 잔액 |
|
|
||||||
| 당일 입금액 | 전일 입금 합계 |
|
|
||||||
| 당일 출금액 | 전일 출금 합계 |
|
|
||||||
| 당일 잔액 | 조회 기준일 잔액 |
|
|
||||||
|
|
||||||
### 2.3 일일 일보 목록
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 구분 | 입금/출금 |
|
|
||||||
| 거래처명 | |
|
|
||||||
| 계정과목 | |
|
|
||||||
| 입금액 | |
|
|
||||||
| 출금액 | |
|
|
||||||
| 적요 | |
|
|
||||||
|
|
||||||
### 2.4 엑셀 다운로드 버튼
|
|
||||||
|
|
||||||
## 3. 지출 예상 내역서 (슬라이드 108-109)
|
|
||||||
|
|
||||||
### 3.1 지출 예상 내역서 조회
|
|
||||||
- 예상 지출 금액 및 일정 조회
|
|
||||||
|
|
||||||
### 3.2 현황 카드
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 예상 지출 합계 | 월별 예상 지출 합계 |
|
|
||||||
| 계좌 잔액 | 현재 계좌 잔액 |
|
|
||||||
| 예상 잔액 | 계좌 잔액 - 예상 지출 합계 |
|
|
||||||
|
|
||||||
### 3.3 지출 예상 내역서 목록
|
|
||||||
| 필드명 | 설명 |
|
|
||||||
|--------|------|
|
|
||||||
| 예상 지급일 | |
|
|
||||||
| 품목 | |
|
|
||||||
| 지출금액 | |
|
|
||||||
| 거래처 | |
|
|
||||||
| 계좌 | |
|
|
||||||
|
|
||||||
### 3.4 엑셀 다운로드 버튼
|
|
||||||
|
|
||||||
### 3.5 월별 합계
|
|
||||||
| 항목 | 설명 |
|
|
||||||
|------|------|
|
|
||||||
| 2025/11 계 | 11월 지출 합계 |
|
|
||||||
| 2025/12 계 | 12월 지출 합계 |
|
|
||||||
| 지출 합계 | 전체 지출 합계 |
|
|
||||||
| 계좌 잔액 | |
|
|
||||||
| 최종 차액 | |
|
|
||||||
|
|
||||||
## 4. 가지급금 인정이자 계산 (슬라이드 110-112)
|
|
||||||
|
|
||||||
### 4.1 가지급금 인정이자 계산 예시 (2024년 기준)
|
|
||||||
- 인정이자율 4.6% (당좌대출이자율 기준, 매년 고시)
|
|
||||||
|
|
||||||
### 4.2 계산 예시
|
|
||||||
| 항목 | 금액 |
|
|
||||||
|------|------|
|
|
||||||
| 가지급금 잔액 | 15,200,000원 |
|
|
||||||
| 인정이자 | 699,200원 |
|
|
||||||
| 법인세 추가 (19%) | 132,848원 |
|
|
||||||
| 대표자 소득세 추가 (35%) | 244,720원 |
|
|
||||||
| 대표자 지방소득세 (10%) | 24,472원 |
|
|
||||||
| **총 세금 부담** | **402,040원** |
|
|
||||||
|
|
||||||
### 4.3 계산식
|
|
||||||
```
|
|
||||||
잔액 × 0.046 = 인정이자
|
|
||||||
인정이자 × 0.19 = 법인세 추가
|
|
||||||
인정이자 × 0.35 = 대표자 소득세 추가
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.4 기본 정산 공식
|
|
||||||
```
|
|
||||||
정산차액 = 가지급금 총액 - 실사용 총액
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.5 인정이자 계산 공식 (법인세법 기준)
|
|
||||||
```
|
|
||||||
경과일수 = 정산일 - 지급일
|
|
||||||
일이자율 = 연이자율 ÷ 365
|
|
||||||
인정이자 = 가지급금 × 일이자율 × 경과일수
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. AI 리포트 생성 (슬라이드 113)
|
|
||||||
|
|
||||||
### 5.1 AI 리포트 생성 프롬프트
|
|
||||||
|
|
||||||
#### 작성 규칙
|
|
||||||
1. 문장은 간결하고 명확하게 작성
|
|
||||||
2. 숫자는 읽기 쉽게 "3,123,000원", "15%" 형식 사용
|
|
||||||
3. 계정과목명, 거래처명은 구체적으로 명시
|
|
||||||
4. 조치가 필요한 경우 구체적인 행동 권한 포함
|
|
||||||
5. 긍정적 변화도 반드시 실상 포함
|
|
||||||
6. 법인세, 소득세 영향이 있는 경우 세무 리스크 명시
|
|
||||||
|
|
||||||
#### 키워드 강조 규칙
|
|
||||||
출력 메시지 내 다음 키워드는 프론트엔드에서 색상 강조됩니다:
|
|
||||||
- **빨간색(경고)**: 초과, 증가, 발생, 필요, 불가
|
|
||||||
- **주황색(주의)**: 점검, 확인, 주의, 검토
|
|
||||||
- **녹색(긍정)**: 감소, 완료, 정상
|
|
||||||
- **파란색(양호)**: 여유, 적정, 양호
|
|
||||||
|
|
||||||
#### 예시 출력
|
|
||||||
입력 데이터 예시에 대한 출력:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"리포트": [
|
|
||||||
{"영역": "지출분석", "상태": "경고", "메시지": "이번 달 예상 지출이 전월 대비 15% 증가했습니다.", "상세": "매입 비용 증가가 주요 원인입니다."},
|
|
||||||
{"영역": "가지급금", "상태": "주의", "메시지": "50일 이상 잔기 미수금 3건(2,500만원) 발생.", "상세": "회수 조치가 필요합니다."},
|
|
||||||
{"영역": "카드/계좌", "상태": "경고", "메시지": "법인카드 사용 한도 85% 도달, 잔여 한도 600만원입니다.", "상세": "사용 계획을 점검해 주세요."},
|
|
||||||
{"영역": "미수금", "상태": "주의", "메시지": "미수금에 대한 관리가 필요한 상태입니다.", "상세": ""}
|
|
||||||
],
|
|
||||||
"요약": "지출 증가와 정기 미수금에 대한 관리가 필요한 상태입니다."}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 데이터 모델
|
|
||||||
|
|
||||||
### DailyReport (일일 일보)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- report_date: date
|
|
||||||
- previous_balance: decimal
|
|
||||||
- daily_deposit: decimal
|
|
||||||
- daily_withdrawal: decimal
|
|
||||||
- current_balance: decimal
|
|
||||||
- details: json # 입출금 상세 내역
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### ExpenseEstimate (지출 예상 내역서)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- expected_date: date
|
|
||||||
- item_name: string
|
|
||||||
- amount: decimal
|
|
||||||
- vendor_id: bigint (FK, nullable)
|
|
||||||
- account_id: bigint (FK, nullable)
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### LoanInterestCalculation (가지급금 인정이자 계산)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- calculation_date: date
|
|
||||||
- loan_balance: decimal
|
|
||||||
- interest_rate: decimal
|
|
||||||
- recognized_interest: decimal
|
|
||||||
- corporate_tax_addition: decimal
|
|
||||||
- income_tax_addition: decimal
|
|
||||||
- local_tax_addition: decimal
|
|
||||||
- total_tax_burden: decimal
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
### AIReport (AI 리포트)
|
|
||||||
```
|
|
||||||
- id: bigint
|
|
||||||
- tenant_id: bigint (FK)
|
|
||||||
- report_date: date
|
|
||||||
- report_type: string
|
|
||||||
- content: json # 리포트 내용
|
|
||||||
- summary: text
|
|
||||||
- created_at: timestamp
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API 도출
|
|
||||||
|
|
||||||
### 일일 일보 API
|
|
||||||
```
|
|
||||||
GET /api/reports/daily # 일일 일보 조회
|
|
||||||
GET /api/reports/daily/export # 일일 일보 엑셀 다운로드
|
|
||||||
```
|
|
||||||
|
|
||||||
### 지출 예상 내역서 API
|
|
||||||
```
|
|
||||||
GET /api/reports/expense-estimate # 지출 예상 내역서 조회
|
|
||||||
POST /api/reports/expense-estimate # 지출 예상 내역 등록
|
|
||||||
PUT /api/reports/expense-estimate/{id}# 지출 예상 내역 수정
|
|
||||||
DELETE /api/reports/expense-estimate/{id}# 지출 예상 내역 삭제
|
|
||||||
GET /api/reports/expense-estimate/export # 지출 예상 내역서 엑셀 다운로드
|
|
||||||
```
|
|
||||||
|
|
||||||
### 가지급금 인정이자 API
|
|
||||||
```
|
|
||||||
GET /api/reports/loan-interest # 가지급금 인정이자 계산 조회
|
|
||||||
POST /api/reports/loan-interest/calculate # 가지급금 인정이자 계산 실행
|
|
||||||
```
|
|
||||||
|
|
||||||
### AI 리포트 API
|
|
||||||
```
|
|
||||||
GET /api/reports/ai # AI 리포트 목록
|
|
||||||
POST /api/reports/ai/generate # AI 리포트 생성
|
|
||||||
GET /api/reports/ai/{id} # AI 리포트 상세
|
|
||||||
DELETE /api/reports/ai/{id} # AI 리포트 삭제
|
|
||||||
```
|
|
||||||
|
|
||||||
### 대시보드/분석 API
|
|
||||||
```
|
|
||||||
GET /api/dashboard/summary # 대시보드 요약
|
|
||||||
GET /api/dashboard/charts # 대시보드 차트 데이터
|
|
||||||
GET /api/analytics/sales # 매출 분석
|
|
||||||
GET /api/analytics/expense # 지출 분석
|
|
||||||
GET /api/analytics/receivables # 미수금 분석
|
|
||||||
```
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,661 +0,0 @@
|
|||||||
# ItemMaster 연동 설계서
|
|
||||||
|
|
||||||
**작성일**: 2025-12-05
|
|
||||||
**최종 수정**: 2025-12-08
|
|
||||||
**버전**: 1.1
|
|
||||||
**상태**: Draft
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 개요
|
|
||||||
|
|
||||||
### 1.1 목적
|
|
||||||
품목기준관리(ItemMaster)에서 정의한 필드와 실제 엔티티 데이터를 연동하여, 동적 필드 정의 및 값 저장을 가능하게 한다.
|
|
||||||
|
|
||||||
### 1.2 설계 원칙
|
|
||||||
- **기존 테이블 활용**: 신규 테이블 추가 없이 기존 `attributes` JSON 컬럼 활용
|
|
||||||
- **범용성**: 품목(products, materials) 외에도 다른 엔티티(orders, clients 등) 확장 가능
|
|
||||||
- **성능**: JOIN 없이 단일 쿼리로 조회 가능
|
|
||||||
- **유연성**: 테넌트/그룹별 다른 필드 구성 지원
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. 현재 구조
|
|
||||||
|
|
||||||
### 2.1 ItemMaster 테이블 구조
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ item_pages (페이지 정의) │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ id, tenant_id, page_name, item_type, source_table, │
|
|
||||||
│ is_active │
|
|
||||||
│ │
|
|
||||||
│ item_type: FG(완제품), PT(반제품), SM(부자재), │
|
|
||||||
│ RM(원자재), CS(소모품) │
|
|
||||||
│ │
|
|
||||||
│ source_table: 실제 저장 테이블명 │
|
|
||||||
│ - 'products' (FG, PT) │
|
|
||||||
│ - 'materials' (SM, RM, CS) │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
│ 1:N
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ item_sections (섹션 정의) │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ id, tenant_id, page_id, title, type, order_no │
|
|
||||||
│ │
|
|
||||||
│ type: fields(필드형), bom(BOM형) │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
│ 1:N
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ item_fields (필드 정의) │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ id, tenant_id, group_id, section_id (nullable) │
|
|
||||||
│ field_key ← attributes JSON 키와 매핑 │
|
|
||||||
│ field_name ← 화면 표시명 │
|
|
||||||
│ field_type ← textbox, number, dropdown, checkbox... │
|
|
||||||
│ is_required ← 필수 여부 │
|
|
||||||
│ default_value ← 기본값 │
|
|
||||||
│ placeholder ← 입력 힌트 │
|
|
||||||
│ validation_rules ← 검증 규칙 JSON │
|
|
||||||
│ options ← 선택 옵션 JSON │
|
|
||||||
│ properties ← 추가 속성 JSON │
|
|
||||||
│ category ← 필드 카테고리 │
|
|
||||||
│ is_common ← 공통 필드 여부 │
|
|
||||||
│ is_active ← 활성 여부 │
|
|
||||||
│ │
|
|
||||||
│ [내부용 매핑 컬럼 - API 응답에서 hidden] │
|
|
||||||
│ source_table ← 원본 테이블명 (products, materials 등) │
|
|
||||||
│ source_column ← 원본 컬럼명 (code, name 등) │
|
|
||||||
│ storage_type ← 저장방식 (column=DB컬럼, json=JSON) │
|
|
||||||
│ json_path ← JSON 저장 경로 (예: attributes.size) │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 엔티티 테이블 구조
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ products │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ [고정 필드] │
|
|
||||||
│ id, tenant_id, code, name, unit, category_id │
|
|
||||||
│ product_type, is_active, is_sellable, is_purchasable... │
|
|
||||||
│ │
|
|
||||||
│ [동적 필드] │
|
|
||||||
│ attributes JSON ← ItemMaster 필드 값 저장 │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ materials │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ [고정 필드] │
|
|
||||||
│ id, tenant_id, material_code, name, unit, category_id │
|
|
||||||
│ material_type, is_active... │
|
|
||||||
│ │
|
|
||||||
│ [동적 필드] │
|
|
||||||
│ attributes JSON ← ItemMaster 필드 값 저장 │
|
|
||||||
│ options JSON ← 추가 옵션 저장 │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. 연동 설계
|
|
||||||
|
|
||||||
### 3.1 매핑 규칙
|
|
||||||
|
|
||||||
```
|
|
||||||
ItemMaster Entity.attributes
|
|
||||||
┌──────────────────────┐ ┌──────────────────────┐
|
|
||||||
│ group_id: 1 │ │ │
|
|
||||||
│ field_key: "color" │ ◀═══매핑═══▶ │ {"color": "빨강"} │
|
|
||||||
│ field_key: "weight" │ ◀═══매핑═══▶ │ {"weight": 1.5} │
|
|
||||||
│ field_key: "spec" │ ◀═══매핑═══▶ │ {"spec": "10x20"} │
|
|
||||||
└──────────────────────┘ └──────────────────────┘
|
|
||||||
|
|
||||||
핵심: item_fields.field_key = attributes JSON의 key
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 Group ID 정의
|
|
||||||
|
|
||||||
| group_id | 엔티티 | 대상 테이블 | 비고 |
|
|
||||||
|----------|--------|-------------|------|
|
|
||||||
| 1 | 품목-제품 | products | product_type: FG, PT |
|
|
||||||
| 2 | 품목-자재 | materials | material_type: SM, RM, CS |
|
|
||||||
| 3 | 주문 | orders | 향후 확장 |
|
|
||||||
| 4 | 고객 | clients | 향후 확장 |
|
|
||||||
| ... | ... | ... | 필요 시 추가 |
|
|
||||||
|
|
||||||
> **참고**: group_id는 `common_codes` 테이블에서 관리하거나, 별도 enum으로 정의 가능
|
|
||||||
|
|
||||||
### 3.3 데이터 흐름
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ 1. 관리자: ItemMaster에서 필드 정의 │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ POST /api/v1/item-master/fields │
|
|
||||||
│ { │
|
|
||||||
│ "group_id": 1, │
|
|
||||||
│ "field_key": "color", │
|
|
||||||
│ "field_name": "색상", │
|
|
||||||
│ "field_type": "dropdown", │
|
|
||||||
│ "is_required": true, │
|
|
||||||
│ "options": [ │
|
|
||||||
│ {"label": "빨강", "value": "red"}, │
|
|
||||||
│ {"label": "파랑", "value": "blue"} │
|
|
||||||
│ ] │
|
|
||||||
│ } │
|
|
||||||
│ │
|
|
||||||
│ → item_fields 테이블에 저장 │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ 2. 사용자: 품목 등록 화면 진입 │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ GET /api/v1/item-master/fields?group_id=1 │
|
|
||||||
│ │
|
|
||||||
│ → 정의된 필드 목록 반환 │
|
|
||||||
│ → 프론트엔드가 동적 폼 렌더링 │
|
|
||||||
│ │
|
|
||||||
│ ┌────────────────────────────────────┐ │
|
|
||||||
│ │ [색상 ▼] ← dropdown으로 표시 │ │
|
|
||||||
│ │ 빨강 │ │
|
|
||||||
│ │ 파랑 │ │
|
|
||||||
│ └────────────────────────────────────┘ │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ 3. 사용자: 품목 저장 │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ POST /api/v1/products │
|
|
||||||
│ { │
|
|
||||||
│ "code": "P-001", ← 고정 필드 │
|
|
||||||
│ "name": "티셔츠", │
|
|
||||||
│ "unit": "EA", │
|
|
||||||
│ "product_type": "FG", │
|
|
||||||
│ "attributes": { ← 동적 필드 │
|
|
||||||
│ "color": "red", (field_key: value) │
|
|
||||||
│ "size": "XL" │
|
|
||||||
│ } │
|
|
||||||
│ } │
|
|
||||||
│ │
|
|
||||||
│ → products 테이블에 저장 │
|
|
||||||
│ → attributes JSON에 동적 필드 값 포함 │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ 4. 사용자: 품목 조회 │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ GET /api/v1/products/1 │
|
|
||||||
│ │
|
|
||||||
│ { │
|
|
||||||
│ "id": 1, │
|
|
||||||
│ "code": "P-001", │
|
|
||||||
│ "name": "티셔츠", │
|
|
||||||
│ "attributes": { │
|
|
||||||
│ "color": "red", │
|
|
||||||
│ "size": "XL" │
|
|
||||||
│ } │
|
|
||||||
│ } │
|
|
||||||
│ │
|
|
||||||
│ → JOIN 없이 한 번에 조회! │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. API 설계
|
|
||||||
|
|
||||||
### 4.1 ItemMaster API (기존)
|
|
||||||
|
|
||||||
| Method | Endpoint | 설명 |
|
|
||||||
|--------|----------|------|
|
|
||||||
| GET | `/api/v1/item-master/fields` | 필드 목록 조회 |
|
|
||||||
| GET | `/api/v1/item-master/fields/{id}` | 필드 상세 조회 |
|
|
||||||
| POST | `/api/v1/item-master/fields` | 필드 생성 |
|
|
||||||
| PUT | `/api/v1/item-master/fields/{id}` | 필드 수정 |
|
|
||||||
| DELETE | `/api/v1/item-master/fields/{id}` | 필드 삭제 |
|
|
||||||
|
|
||||||
**필터 파라미터**:
|
|
||||||
- `group_id`: 엔티티 그룹 필터
|
|
||||||
- `section_id`: 섹션 필터
|
|
||||||
- `is_active`: 활성 필터
|
|
||||||
- `is_common`: 공통 필드 필터
|
|
||||||
|
|
||||||
### 4.2 엔티티 API 수정
|
|
||||||
|
|
||||||
#### 4.2.1 Products API
|
|
||||||
|
|
||||||
**저장 시 attributes 포함**:
|
|
||||||
```json
|
|
||||||
POST /api/v1/products
|
|
||||||
{
|
|
||||||
"code": "P-001",
|
|
||||||
"name": "제품명",
|
|
||||||
"unit": "EA",
|
|
||||||
"product_type": "FG",
|
|
||||||
"attributes": {
|
|
||||||
"color": "red",
|
|
||||||
"weight": 1.5,
|
|
||||||
"custom_field": "value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**조회 시 필드 메타데이터 포함 (선택)**:
|
|
||||||
```
|
|
||||||
GET /api/v1/products/1?include_field_meta=true
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"code": "P-001",
|
|
||||||
"name": "제품명",
|
|
||||||
"attributes": {
|
|
||||||
"color": "red",
|
|
||||||
"weight": 1.5
|
|
||||||
},
|
|
||||||
"field_meta": [
|
|
||||||
{
|
|
||||||
"field_key": "color",
|
|
||||||
"field_name": "색상",
|
|
||||||
"field_type": "dropdown",
|
|
||||||
"value": "red",
|
|
||||||
"options": [...]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field_key": "weight",
|
|
||||||
"field_name": "중량",
|
|
||||||
"field_type": "number",
|
|
||||||
"value": 1.5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. 검증 로직
|
|
||||||
|
|
||||||
### 5.1 저장 시 검증 흐름
|
|
||||||
|
|
||||||
```php
|
|
||||||
class ItemFieldValidationService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* attributes 값을 ItemMaster 기준으로 검증
|
|
||||||
*/
|
|
||||||
public function validate(int $groupId, array $attributes): array
|
|
||||||
{
|
|
||||||
$errors = [];
|
|
||||||
|
|
||||||
// 1. 해당 그룹의 필드 정의 조회
|
|
||||||
$fields = ItemField::where('group_id', $groupId)
|
|
||||||
->where('is_active', true)
|
|
||||||
->get()
|
|
||||||
->keyBy('field_key');
|
|
||||||
|
|
||||||
// 2. 필수 필드 체크
|
|
||||||
foreach ($fields->where('is_required', true) as $field) {
|
|
||||||
if (!isset($attributes[$field->field_key])) {
|
|
||||||
$errors[$field->field_key] = "{$field->field_name}은(는) 필수입니다.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 타입별 검증
|
|
||||||
foreach ($attributes as $key => $value) {
|
|
||||||
if (!$fields->has($key)) {
|
|
||||||
continue; // 정의되지 않은 필드는 스킵 (또는 에러)
|
|
||||||
}
|
|
||||||
|
|
||||||
$field = $fields->get($key);
|
|
||||||
$fieldError = $this->validateFieldValue($field, $value);
|
|
||||||
if ($fieldError) {
|
|
||||||
$errors[$key] = $fieldError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 필드 타입별 값 검증
|
|
||||||
*/
|
|
||||||
private function validateFieldValue(ItemField $field, mixed $value): ?string
|
|
||||||
{
|
|
||||||
return match($field->field_type) {
|
|
||||||
'number' => $this->validateNumber($field, $value),
|
|
||||||
'dropdown' => $this->validateDropdown($field, $value),
|
|
||||||
'date' => $this->validateDate($field, $value),
|
|
||||||
'checkbox' => $this->validateCheckbox($field, $value),
|
|
||||||
default => null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private function validateNumber(ItemField $field, mixed $value): ?string
|
|
||||||
{
|
|
||||||
if (!is_numeric($value)) {
|
|
||||||
return "{$field->field_name}은(는) 숫자여야 합니다.";
|
|
||||||
}
|
|
||||||
|
|
||||||
$rules = $field->validation_rules ?? [];
|
|
||||||
if (isset($rules['min']) && $value < $rules['min']) {
|
|
||||||
return "{$field->field_name}은(는) {$rules['min']} 이상이어야 합니다.";
|
|
||||||
}
|
|
||||||
if (isset($rules['max']) && $value > $rules['max']) {
|
|
||||||
return "{$field->field_name}은(는) {$rules['max']} 이하여야 합니다.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function validateDropdown(ItemField $field, mixed $value): ?string
|
|
||||||
{
|
|
||||||
$options = $field->options ?? [];
|
|
||||||
$validValues = array_column($options, 'value');
|
|
||||||
|
|
||||||
if (!in_array($value, $validValues)) {
|
|
||||||
return "{$field->field_name}의 값이 유효하지 않습니다.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 Controller에서 사용
|
|
||||||
|
|
||||||
```php
|
|
||||||
class ProductsController extends Controller
|
|
||||||
{
|
|
||||||
public function store(ProductStoreRequest $request)
|
|
||||||
{
|
|
||||||
$validated = $request->validated();
|
|
||||||
|
|
||||||
// attributes 검증 (선택적)
|
|
||||||
if (isset($validated['attributes'])) {
|
|
||||||
$groupId = 1; // 품목-제품 그룹
|
|
||||||
$errors = $this->fieldValidationService->validate(
|
|
||||||
$groupId,
|
|
||||||
$validated['attributes']
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($errors)) {
|
|
||||||
return ApiResponse::error('검증 실패', $errors, 422);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$product = $this->productService->create($validated);
|
|
||||||
|
|
||||||
return ApiResponse::success($product, __('message.created'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. 프론트엔드 연동
|
|
||||||
|
|
||||||
### 6.1 동적 폼 렌더링 흐름
|
|
||||||
|
|
||||||
```
|
|
||||||
1. 페이지 로드 시
|
|
||||||
GET /api/v1/item-master/fields?group_id=1
|
|
||||||
|
|
||||||
2. 필드 정의 기반 폼 컴포넌트 렌더링
|
|
||||||
field_type: textbox → <Input />
|
|
||||||
field_type: number → <InputNumber />
|
|
||||||
field_type: dropdown → <Select options={field.options} />
|
|
||||||
field_type: checkbox → <Checkbox />
|
|
||||||
field_type: date → <DatePicker />
|
|
||||||
field_type: textarea → <Textarea />
|
|
||||||
|
|
||||||
3. 저장 시 attributes 객체 구성
|
|
||||||
{
|
|
||||||
[field_key]: value,
|
|
||||||
[field_key]: value,
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.2 React 컴포넌트 예시
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
interface ItemField {
|
|
||||||
id: number;
|
|
||||||
field_key: string;
|
|
||||||
field_name: string;
|
|
||||||
field_type: 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea';
|
|
||||||
is_required: boolean;
|
|
||||||
default_value?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
options?: Array<{ label: string; value: string }>;
|
|
||||||
validation_rules?: Record<string, any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function DynamicFieldRenderer({ field, value, onChange }: Props) {
|
|
||||||
switch (field.field_type) {
|
|
||||||
case 'textbox':
|
|
||||||
return (
|
|
||||||
<Input
|
|
||||||
value={value}
|
|
||||||
onChange={(e) => onChange(field.field_key, e.target.value)}
|
|
||||||
placeholder={field.placeholder}
|
|
||||||
required={field.is_required}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
case 'number':
|
|
||||||
return (
|
|
||||||
<InputNumber
|
|
||||||
value={value}
|
|
||||||
onChange={(val) => onChange(field.field_key, val)}
|
|
||||||
min={field.validation_rules?.min}
|
|
||||||
max={field.validation_rules?.max}
|
|
||||||
required={field.is_required}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
case 'dropdown':
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
value={value}
|
|
||||||
onChange={(val) => onChange(field.field_key, val)}
|
|
||||||
options={field.options}
|
|
||||||
required={field.is_required}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
// ... 기타 타입
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProductForm() {
|
|
||||||
const [fields, setFields] = useState<ItemField[]>([]);
|
|
||||||
const [attributes, setAttributes] = useState<Record<string, any>>({});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// 필드 정의 로드
|
|
||||||
fetch('/api/v1/item-master/fields?group_id=1')
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => setFields(data.data));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleFieldChange = (key: string, value: any) => {
|
|
||||||
setAttributes(prev => ({ ...prev, [key]: value }));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form>
|
|
||||||
{/* 고정 필드 */}
|
|
||||||
<Input name="code" label="품목코드" required />
|
|
||||||
<Input name="name" label="품목명" required />
|
|
||||||
|
|
||||||
{/* 동적 필드 */}
|
|
||||||
{fields.map(field => (
|
|
||||||
<DynamicFieldRenderer
|
|
||||||
key={field.id}
|
|
||||||
field={field}
|
|
||||||
value={attributes[field.field_key]}
|
|
||||||
onChange={handleFieldChange}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. 확장 가이드
|
|
||||||
|
|
||||||
### 7.1 새 엔티티 추가 시
|
|
||||||
|
|
||||||
1. **group_id 정의**: 새 그룹 ID 할당
|
|
||||||
2. **테이블 확인**: `attributes` JSON 컬럼 존재 확인 (없으면 추가)
|
|
||||||
3. **ItemMaster 필드 정의**: 해당 group_id로 필드 생성
|
|
||||||
4. **API 수정**: 저장/조회 시 attributes 처리 로직 추가
|
|
||||||
|
|
||||||
### 7.2 예시: 주문(orders) 연동
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 1. orders 테이블에 attributes 컬럼 추가 (없는 경우)
|
|
||||||
ALTER TABLE orders ADD COLUMN attributes JSON DEFAULT NULL COMMENT '동적 필드';
|
|
||||||
|
|
||||||
-- 2. ItemMaster에 주문용 필드 정의
|
|
||||||
INSERT INTO item_fields (tenant_id, group_id, field_key, field_name, field_type, ...)
|
|
||||||
VALUES (1, 3, 'urgency', '긴급도', 'dropdown', ...);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. 모델 헬퍼 메서드
|
|
||||||
|
|
||||||
### 8.1 ItemPage 모델
|
|
||||||
|
|
||||||
```php
|
|
||||||
class ItemPage extends Model
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* source_table에 해당하는 모델 클래스명 반환
|
|
||||||
*/
|
|
||||||
public function getTargetModelClass(): ?string
|
|
||||||
{
|
|
||||||
$mapping = [
|
|
||||||
'products' => \App\Models\Product::class,
|
|
||||||
'materials' => \App\Models\Material::class,
|
|
||||||
];
|
|
||||||
return $mapping[$this->source_table] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 제품 페이지인지 확인
|
|
||||||
*/
|
|
||||||
public function isProductPage(): bool
|
|
||||||
{
|
|
||||||
return $this->source_table === 'products';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 자재 페이지인지 확인
|
|
||||||
*/
|
|
||||||
public function isMaterialPage(): bool
|
|
||||||
{
|
|
||||||
return $this->source_table === 'materials';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 ItemField 모델
|
|
||||||
|
|
||||||
```php
|
|
||||||
class ItemField extends Model
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 시스템 필드 여부 확인 (DB 컬럼과 매핑된 필드)
|
|
||||||
*/
|
|
||||||
public function isSystemField(): bool
|
|
||||||
{
|
|
||||||
return !is_null($this->source_table) && !is_null($this->source_column);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 컬럼 저장 방식 여부 확인
|
|
||||||
*/
|
|
||||||
public function isColumnStorage(): bool
|
|
||||||
{
|
|
||||||
return $this->storage_type === 'column';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON 저장 방식 여부 확인
|
|
||||||
*/
|
|
||||||
public function isJsonStorage(): bool
|
|
||||||
{
|
|
||||||
return $this->storage_type === 'json';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.3 필드 저장 방식 판단
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ storage_type 판단 로직 │
|
|
||||||
├─────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ if (source_table && source_column) { │
|
|
||||||
│ // 시스템 필드 (기존 DB 컬럼과 매핑) │
|
|
||||||
│ if (storage_type === 'column') { │
|
|
||||||
│ → products.{source_column} 또는 │
|
|
||||||
│ materials.{source_column} 에서 직접 읽기/쓰기 │
|
|
||||||
│ } else if (storage_type === 'json') { │
|
|
||||||
│ → {json_path} 경로로 JSON 내 읽기/쓰기 │
|
|
||||||
│ } │
|
|
||||||
│ } else { │
|
|
||||||
│ // 커스텀 필드 (동적 정의) │
|
|
||||||
│ → attributes.{field_key} 에 저장 │
|
|
||||||
│ } │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. 구현 계획
|
|
||||||
|
|
||||||
| 순서 | 작업 | 담당 | 예상 공수 |
|
|
||||||
|------|------|------|----------|
|
|
||||||
| 1 | group_id 코드 정의 | BE | 0.5일 |
|
|
||||||
| 2 | ItemFieldValidationService 구현 | BE | 1일 |
|
|
||||||
| 3 | ProductsController 수정 (검증 연동) | BE | 0.5일 |
|
|
||||||
| 4 | MaterialsController 수정 (검증 연동) | BE | 0.5일 |
|
|
||||||
| 5 | API 응답에 field_meta 포함 옵션 | BE | 0.5일 |
|
|
||||||
| 6 | DynamicFieldRenderer 컴포넌트 | FE | 2일 |
|
|
||||||
| 7 | 품목 등록/수정 폼 연동 | FE | 1일 |
|
|
||||||
| 8 | 테스트 및 QA | 공통 | 1일 |
|
|
||||||
|
|
||||||
**총 예상 공수: 7일**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. 변경 이력
|
|
||||||
|
|
||||||
| 날짜 | 버전 | 변경 내용 | 작성자 |
|
|
||||||
|------|------|----------|--------|
|
|
||||||
| 2025-12-05 | 1.0 | 최초 작성 | - |
|
|
||||||
| 2025-12-08 | 1.1 | source_table/source_column 매핑 컬럼 추가, 모델 헬퍼 메서드 문서화 | - |
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
# 다른 장소에서 작업 환경 구축 가이드
|
|
||||||
|
|
||||||
> ⚠️ **DEPRECATED**: 이 문서는 2025-09-19에 작성되었으며, 현재 프로젝트 구조와 맞지 않습니다.
|
|
||||||
> 최신 정보는 `docs/architecture/system-overview.md` 및 `docs/specs/docker-setup.md`를 참조하세요.
|
|
||||||
|
|
||||||
**생성일**: 2025-09-19 21:50 KST
|
|
||||||
**목적**: 다른 장소에서 동일한 개발 환경으로 작업 재개
|
|
||||||
**상태**: ⚠️ DEPRECATED (2025-12-26)
|
|
||||||
|
|
||||||
## 🚀 빠른 시작 (5분 내 완료)
|
|
||||||
|
|
||||||
### 1단계: 저장소 최신 동기화
|
|
||||||
```bash
|
|
||||||
# 모든 저장소에서 실행
|
|
||||||
git pull origin develop
|
|
||||||
|
|
||||||
# 예상 결과: "Already up to date" 또는 새로운 커밋 다운로드
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2단계: Docker 서비스 실행
|
|
||||||
```bash
|
|
||||||
# Docker 데스크톱 실행 또는
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 확인
|
|
||||||
docker ps # MySQL, Redis 등 실행 확인
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3단계: API 서버 상태 확인
|
|
||||||
```bash
|
|
||||||
cd api
|
|
||||||
php artisan migrate:status # DB 상태 확인
|
|
||||||
php artisan serve # 개발 서버 실행
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4단계: 환경 검증
|
|
||||||
- 브라우저에서 `http://localhost:8000` 접속 확인
|
|
||||||
- 데이터베이스 연결 상태 확인
|
|
||||||
|
|
||||||
## 📋 상세 환경 구축 절차
|
|
||||||
|
|
||||||
### Git 저장소 상태 확인
|
|
||||||
```bash
|
|
||||||
# 각 저장소에서 실행
|
|
||||||
cd /path/to/SAM/api
|
|
||||||
git status && git log --oneline -3
|
|
||||||
|
|
||||||
cd /path/to/SAM/front/www
|
|
||||||
git status && git log --oneline -3
|
|
||||||
|
|
||||||
cd /path/to/SAM/admin
|
|
||||||
git status && git log --oneline -3
|
|
||||||
|
|
||||||
cd /path/to/SAM/shared
|
|
||||||
git status && git log --oneline -3
|
|
||||||
```
|
|
||||||
|
|
||||||
**기대값**:
|
|
||||||
- **API**: `3f30c5d` - 프로젝트 체크포인트 및 완전한 문서화 시스템 구축
|
|
||||||
- **Frontend**: `ec18d70` - 화면 생성 - 수주관리
|
|
||||||
- **Admin**: `0624422` - 빈디렉토리 설정
|
|
||||||
- **Shared**: `015b3dc` - Filament BOARD, TENANT 추가
|
|
||||||
|
|
||||||
### 환경 파일 확인
|
|
||||||
```bash
|
|
||||||
cd api
|
|
||||||
ls -la .env # API 환경 설정
|
|
||||||
cat .env | grep DB_ # 데이터베이스 설정 확인
|
|
||||||
|
|
||||||
cd ../admin
|
|
||||||
ls -la .env # Admin 환경 설정
|
|
||||||
|
|
||||||
cd ../front/www
|
|
||||||
ls -la application/config/database.php # CodeIgniter DB 설정
|
|
||||||
```
|
|
||||||
|
|
||||||
### 데이터베이스 상태 검증
|
|
||||||
```bash
|
|
||||||
cd api
|
|
||||||
php artisan migrate:status
|
|
||||||
|
|
||||||
# 예상 결과: Batch 11까지 실행됨
|
|
||||||
# 최종 마이그레이션: 2025_09_11_000100_create_audit_logs_table
|
|
||||||
```
|
|
||||||
|
|
||||||
### 의존성 설치 (필요시)
|
|
||||||
```bash
|
|
||||||
# API 저장소
|
|
||||||
cd api
|
|
||||||
composer install # PHP 의존성
|
|
||||||
npm install # Node.js 의존성
|
|
||||||
|
|
||||||
# Admin 저장소
|
|
||||||
cd ../admin
|
|
||||||
composer install
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Frontend 저장소
|
|
||||||
cd ../front/www
|
|
||||||
composer install
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 문제 해결 가이드
|
|
||||||
|
|
||||||
### Docker 연결 문제
|
|
||||||
```bash
|
|
||||||
# Docker 상태 확인
|
|
||||||
docker ps
|
|
||||||
|
|
||||||
# MySQL 컨테이너 재시작
|
|
||||||
docker-compose restart mysql
|
|
||||||
|
|
||||||
# 전체 재시작
|
|
||||||
docker-compose down && docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
### 데이터베이스 연결 실패
|
|
||||||
```bash
|
|
||||||
# 연결 테스트
|
|
||||||
cd api
|
|
||||||
php artisan tinker
|
|
||||||
> DB::select('SHOW DATABASES');
|
|
||||||
|
|
||||||
# 마이그레이션 재실행 (필요시)
|
|
||||||
php artisan migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Git 동기화 문제
|
|
||||||
```bash
|
|
||||||
# 충돌 발생시
|
|
||||||
git stash # 로컬 변경사항 저장
|
|
||||||
git pull origin develop # 최신 코드 받기
|
|
||||||
git stash pop # 로컬 변경사항 복원
|
|
||||||
|
|
||||||
# 강제 동기화 (주의: 로컬 변경사항 손실)
|
|
||||||
git reset --hard origin/develop
|
|
||||||
```
|
|
||||||
|
|
||||||
### 권한 문제 (macOS/Linux)
|
|
||||||
```bash
|
|
||||||
# 로그 디렉토리 권한
|
|
||||||
chmod -R 775 storage/
|
|
||||||
chmod -R 775 bootstrap/cache/
|
|
||||||
|
|
||||||
# Composer 캐시 정리
|
|
||||||
composer clear-cache
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📄 참조 문서들
|
|
||||||
|
|
||||||
### 프로젝트 가이드
|
|
||||||
- **`CLAUDE.md`**: 전체 프로젝트 구조 및 워크플로우
|
|
||||||
- **`CURRENT_WORKS.md`**: 최근 작업 현황 및 변경사항
|
|
||||||
- **`CHECKPOINT_2025-09-19.md`**: 복원 지점 및 복구 방법
|
|
||||||
- **`DATABASE_SCHEMA_2025-09-19.md`**: DB 스키마 상세 분석
|
|
||||||
|
|
||||||
### 개발 명령어
|
|
||||||
```bash
|
|
||||||
# API 개발 서버 실행
|
|
||||||
cd api && php artisan serve
|
|
||||||
|
|
||||||
# 프론트엔드 개발 서버
|
|
||||||
cd front/www && php -S localhost:8080
|
|
||||||
|
|
||||||
# Admin 개발 서버
|
|
||||||
cd admin && php artisan serve --port=8001
|
|
||||||
|
|
||||||
# 전체 서비스 실행 (API)
|
|
||||||
cd api && composer dev # Laravel + Queue + Log viewer + Vite
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚡ 성능 최적화 팁
|
|
||||||
|
|
||||||
### IDE 설정
|
|
||||||
```bash
|
|
||||||
# PHPStorm
|
|
||||||
cd api
|
|
||||||
php artisan ide-helper:generate
|
|
||||||
php artisan ide-helper:models
|
|
||||||
|
|
||||||
# VS Code
|
|
||||||
# - PHP Intelephense 확장 설치
|
|
||||||
# - Laravel Extension Pack 설치
|
|
||||||
```
|
|
||||||
|
|
||||||
### 개발 도구
|
|
||||||
```bash
|
|
||||||
# API 문서 확인
|
|
||||||
open http://localhost:8000/api-docs
|
|
||||||
|
|
||||||
# 로그 실시간 모니터링
|
|
||||||
cd api && php artisan pail --timeout=0
|
|
||||||
|
|
||||||
# 큐 워커 실행
|
|
||||||
cd api && php artisan queue:listen --tries=1
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔄 작업 완료 후 동기화
|
|
||||||
|
|
||||||
### 세션 종료 시
|
|
||||||
```bash
|
|
||||||
# 1. 모든 변경사항 커밋
|
|
||||||
git add . && git commit -m "작업 내용 설명"
|
|
||||||
|
|
||||||
# 2. 원격 저장소에 푸시
|
|
||||||
git push origin develop
|
|
||||||
|
|
||||||
# 3. 작업 내용 문서화
|
|
||||||
# CURRENT_WORKS.md 업데이트
|
|
||||||
|
|
||||||
# 4. 임시 파일 정리
|
|
||||||
find . -name ".DS_Store" -delete
|
|
||||||
rm -f storage/logs/laravel.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### 체크포인트 생성 (중요 작업 후)
|
|
||||||
```bash
|
|
||||||
# 새로운 체크포인트 파일 생성
|
|
||||||
cp CHECKPOINT_2025-09-19.md CHECKPOINT_$(date +%Y-%m-%d).md
|
|
||||||
|
|
||||||
# 현재 상태로 업데이트
|
|
||||||
# - Git 커밋 해시 업데이트
|
|
||||||
# - 마이그레이션 상태 업데이트
|
|
||||||
# - 변경사항 문서화
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🆘 긴급 복원 (문제 발생시)
|
|
||||||
|
|
||||||
### 완전 복원
|
|
||||||
```bash
|
|
||||||
# CHECKPOINT_2025-09-19.md 파일 참조
|
|
||||||
# 1. 데이터베이스 롤백
|
|
||||||
cd api && php artisan migrate:rollback --step=7
|
|
||||||
|
|
||||||
# 2. Git 리셋
|
|
||||||
git reset --hard 3f30c5d # API
|
|
||||||
cd ../front/www && git reset --hard ec18d70
|
|
||||||
cd ../../admin && git reset --hard 0624422
|
|
||||||
cd ../shared && git reset --hard 015b3dc
|
|
||||||
|
|
||||||
# 3. 마이그레이션 재실행
|
|
||||||
cd ../api && php artisan migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
**가이드 작성**: Claude Code
|
|
||||||
**검증 완료**: ✅ 모든 단계 테스트됨
|
|
||||||
**업데이트**: 새로운 환경에서 문제 발생시 이 문서 개선 필요
|
|
||||||
@@ -17,5 +17,5 @@
|
|||||||
| [quality-checklist.md](quality-checklist.md) | 코드 품질 체크리스트 | PR 전 |
|
| [quality-checklist.md](quality-checklist.md) | 코드 품질 체크리스트 | PR 전 |
|
||||||
|
|
||||||
## 관련 폴더
|
## 관련 폴더
|
||||||
- [architecture/](../architecture/) - 설계 원칙 (왜 이렇게 설계하는가)
|
- [system/](../system/) - 시스템 현황 (아키텍처, DB, 인프라)
|
||||||
- [rules/](../rules/) - 비즈니스 규칙 (무엇이 유효한 데이터인가)
|
- [rules/](../rules/) - 비즈니스 규칙 (무엇이 유효한 데이터인가)
|
||||||
@@ -186,7 +186,7 @@ git commit -m "fix: [auth] ..."
|
|||||||
|
|
||||||
## 관련 문서
|
## 관련 문서
|
||||||
|
|
||||||
- [개발 명령어](./dev-commands.md)
|
- [개발 명령어](../quickstart/dev-commands.md)
|
||||||
- [품질 체크리스트](./quality-checklist.md)
|
- [품질 체크리스트](./quality-checklist.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user