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:
2026-02-27 18:03:04 +09:00
parent 252cc00cda
commit 0ace50b006
46 changed files with 283 additions and 8035 deletions

729
CLAUDE.md
View File

@@ -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
View File

@@ -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 갱신 | ⏳ 대기 |

View File

@@ -1,20 +0,0 @@
# Architecture (아키텍처 & 설계 원칙)
> 시스템 설계와 아키텍처 결정의 근간 - **"왜 이렇게 설계하는가"**
## 목적
- 일관된 아키텍처 결정 기준 제공
- 기술 부채 방지
- 확장성과 유지보수성 확보
## 문서 목록
| 문서 | 설명 | 필수 확인 시점 |
|------|------|--------------|
| [system-overview.md](system-overview.md) | 전체 시스템 아키텍처 | 새 기능 설계 전 |
| [security-policy.md](security-policy.md) | 인증/인가, 보안 규칙 | 보안 관련 작업 전 |
## 관련 폴더
- [standards/](../standards/) - 개발 표준 (어떻게 코드를 작성할 것인가)
- [rules/](../rules/) - 비즈니스 규칙 (무엇이 유효한 데이터인가)
- [specs/](../specs/) - 기술 스펙 (무엇을 구현할 것인가)

View File

@@ -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

View File

@@ -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

View File

@@ -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 반영)

View File

@@ -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`
--- ---

View File

@@ -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 개발 |
## 개요 ## 개요

View File

@@ -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)

View File

@@ -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 시스템 분석 |
--- ---

View File

@@ -380,7 +380,7 @@ class ExampleModel extends Model
### SAM 전체 문서 ### SAM 전체 문서
``` ```
docs/specs/ # 시스템 스펙 docs/system/ # 시스템 현황
docs/reference/ # 레퍼런스 docs/reference/ # 레퍼런스
docs/guides/ # 가이드 (이 문서 포함) docs/guides/ # 가이드 (이 문서 포함)
``` ```

View File

@@ -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) - 현재 개발 환경
--- ---

View File

@@ -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 환경 설정값 상세 |
--- ---

View File

@@ -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 환경 설정값 상세 |
--- ---

View File

@@ -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)
--- ---

View File

@@ -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) | 개발 명령어 모음 |

View File

@@ -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)
--- ---

View File

@@ -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) |
--- ---

View File

@@ -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/) - 기술 스펙 (무엇을 구현할 것인가)

View File

@@ -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)
--- ---

View File

@@ -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
**상태**: 설계 완료

View File

@@ -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?) |

View File

@@ -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 서비스 추가)

View File

@@ -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. 개발 우선순위 결정

View File

@@ -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일간 안보기)
```

View File

@@ -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 # 테넌트 전환
```

View File

@@ -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 # 출퇴근 설정 수정
```

View File

@@ -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 # 휴가 현황 요약
```

View File

@@ -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 # 카카오톡 공유
```

View File

@@ -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 # 입출금 내역 동기화
```

View File

@@ -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} # 계좌 삭제
```

View File

@@ -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

View File

@@ -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 매핑 컬럼 추가, 모델 헬퍼 메서드 문서화 | - |

View File

@@ -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
**검증 완료**: ✅ 모든 단계 테스트됨
**업데이트**: 새로운 환경에서 문제 발생시 이 문서 개선 필요

View File

@@ -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/) - 비즈니스 규칙 (무엇이 유효한 데이터인가)

View File

@@ -186,7 +186,7 @@ git commit -m "fix: [auth] ..."
## 관련 문서 ## 관련 문서
- [개발 명령어](./dev-commands.md) - [개발 명령어](../quickstart/dev-commands.md)
- [품질 체크리스트](./quality-checklist.md) - [품질 체크리스트](./quality-checklist.md)
--- ---