작업계획서대로 진행

This commit is contained in:
2026-01-11 01:29:46 +09:00
parent 1b8cd8577e
commit 01bd66d524
51 changed files with 11124 additions and 273 deletions

View File

@@ -0,0 +1,746 @@
# 주간보고 시스템 마스터 작업계획서
> 작성일: 2026-01-10
> 총 예상 기간: 6~8주
> 총 Phase 수: 30개 (통합 DB 포함)
> 총 테이블 수: 16개
---
## 1. 프로젝트 개요
### 1.1 목표
주간보고 시스템에 7개 신규 기능을 추가하여 업무 효율성 향상
### 1.2 작업 목록
| # | 작업명 | 예상 기간 | Phase | 난이도 | 의존성 |
|:-:|--------|:---------:|:-----:|:------:|:------:|
| 01 | 회의록 + TODO | 5~7일 | 4 | ⭐⭐ | 없음 |
| 02 | 사업-프로젝트 계층 | 3~5일 | 4 | ⭐⭐ | 없음 |
| 03 | 유지보수 업무관리 | 5~7일 | 4 | ⭐⭐⭐ | 없음 |
| 04 | Gmail OAuth | 5~7일 | 5 | ⭐⭐⭐ | 없음 |
| 05 | Synology SSO | 2~3일 | 2 | ⭐ | **04 완료** |
| 06 | 구글 그룹 연동 | 1~2주 | 4 | ⭐⭐⭐ | **04 완료** |
| 07 | SVN/Git 연동 | 2~3주 | 6 | ⭐⭐⭐ | 02 권장 |
### 1.3 의존성 다이어그램
```
┌─────────────────────────────────────────────────────────────────┐
│ 독립 실행 가능 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │01 회의록│ │02 사업 │ │03 유지 │ │04 OAuth│ │
│ └────────┘ └───┬────┘ └────────┘ └───┬────┘ │
│ │ │ │
│ │ (권장) │ (필수) │
│ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ 07 VCS │ │ 05 Synology│ │
│ └────────────┘ └─────┬──────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ 06 구글그룹│ │
│ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 2. 통합 실행 계획
### 2.1 전체 Phase 목록 (30개)
```
Phase 00: 통합 DB 마이그레이션 ─────────────────────── 0.5일
├─► 01-P1: 회의록 기본 구조 ─────────────────────── 2일
├─► 02-P1: 사업 CRUD ────────────────────────────── 1.5일
├─► 03-P1: 유지보수 기본 CRUD ───────────────────── 2일
└─► 04-P1: 인증 환경 설정 ───────────────────────── 1일
├─► 04-P2: 비밀번호 인증 ──────────────────── 1.5일
│ │
│ └─► 04-P3: Google OAuth ─────────────── 1.5일
│ │
│ ├─► 04-P4: 비밀번호 찾기 ──────── 1일
│ │ │
│ │ └─► 04-P5: 로그인 UI ────── 1일
│ │ │
│ │ └─► 05-P1: Synology API ─ 1.5일
│ │ │
│ │ └─► 05-P2: UI + 테스트 ─ 1일
│ │
│ └─► 06-P1: OAuth Scope 확장 ───── 2일
│ │
│ └─► 06-P2: 그룹 게시물 조회 ─ 3일
│ │
│ └─► 06-P3: 주간보고 공유 ─ 3일
│ │
│ └─► 06-P4: 테스트 ─── 2일
├─► 01-P2: AI 분석 연동 ─────────────────────────── 2일
│ │
│ └─► 01-P3: TODO 기능 ──────────────────────── 2일
│ │
│ └─► 01-P4: 주간보고 연계 ────────────── 1일
├─► 02-P2: 프로젝트-사업 연결 ───────────────────── 1일
│ │
│ └─► 02-P3: 사업 주간보고 취합 ─────────────── 1.5일
│ │
│ └─► 02-P4: 테스트 ───────────────────── 0.5일
├─► 03-P2: 파일 업로드 + AI 파싱 ────────────────── 2일
│ │
│ └─► 03-P3: 주간보고 연계 ──────────────────── 2일
│ │
│ └─► 03-P4: 통계 + 테스트 ────────────── 1일
└─► 07-P1: VCS 서버/계정 관리 ───────────────────── 3일
└─► 07-P2: 저장소 관리 ────────────────────── 2일
├─► 07-P3: Git 커밋 수집 ────────────── 3일
└─► 07-P4: SVN 커밋 수집 ────────────── 3일
└─► 07-P5: 커밋 조회 화면 ──────── 3일
└─► 07-P6: 자동화 + 테스트 ── 2일
```
---
## 3. 단계별 상세 실행 계획
### 📍 STAGE 0: 통합 DB 마이그레이션 (0.5일)
> **목표**: 모든 테이블을 한 번에 생성하여 이후 작업 효율화
| 순번 | Phase ID | 작업 내용 | 소요 |
|:----:|:--------:|----------|:----:|
| 1 | **00** | 16개 테이블 + ALTER 통합 DDL 실행 | 0.5일 |
**생성 테이블 목록**:
```sql
-- 01. 회의록/TODO
wr_meeting, wr_meeting_attendee, wr_meeting_agenda, wr_todo
-- 02. 사업
wr_business, wr_business_weekly_report
ALTER wr_project_info ADD business_id
-- 03. 유지보수
wr_maintenance_task, wr_maintenance_upload_batch
-- 04~06. 인증/그룹
ALTER wr_employee_info ADD password_hash, google_*, synology_*, token_*
wr_login_history, wr_google_group, wr_report_group_share
-- 07. VCS
wr_vcs_server, wr_employee_vcs_account, wr_repository, wr_commit_log
```
**완료 기준**: 모든 테이블 생성 확인, FK 관계 검증
---
### 📍 STAGE 1: 기반 구축 - 병렬 진행 (1주차)
> **목표**: 독립적인 기본 CRUD 4개 동시 진행
| 순번 | Phase ID | 작업 내용 | 소요 | 담당 |
|:----:|:--------:|----------|:----:|:----:|
| 2 | **01-P1** | 회의록 기본 구조 (Tiptap, CRUD) | 2일 | A |
| 3 | **02-P1** | 사업 CRUD | 1.5일 | B |
| 4 | **03-P1** | 유지보수 기본 CRUD | 2일 | C |
| 5 | **04-P1** | 인증 환경 설정 (환경변수, Google Console) | 1일 | D |
**병렬 진행 가능**: ✅ 4개 모두 독립적
**완료 기준**:
- [ ] 01-P1: 회의록 목록/작성/상세 화면 동작
- [ ] 02-P1: 사업 목록/등록/수정/삭제 동작
- [ ] 03-P1: 유지보수 목록/등록/상세/상태변경 동작
- [ ] 04-P1: Google OAuth 콘솔 설정 완료, 환경변수 설정
---
### 📍 STAGE 2: 인증 체계 구축 (1~2주차)
> **목표**: Gmail OAuth 완성 → Synology SSO 확장
| 순번 | Phase ID | 작업 내용 | 소요 | 선행 |
|:----:|:--------:|----------|:----:|:----:|
| 6 | **04-P2** | 비밀번호 인증 (bcrypt) | 1.5일 | 04-P1 |
| 7 | **04-P3** | Google OAuth 연동 | 1.5일 | 04-P2 |
| 8 | **04-P4** | 비밀번호 찾기 + 이메일 발송 | 1일 | 04-P3 |
| 9 | **04-P5** | 로그인 UI + 테스트 | 1일 | 04-P4 |
| 10 | **05-P1** | Synology SSO API | 1.5일 | **04-P5** |
| 11 | **05-P2** | Synology UI + 테스트 | 1일 | 05-P1 |
**병렬 진행 가능**: ❌ 순차 진행 필수 (의존성)
**완료 기준**:
- [ ] 04-P5: Google 로그인/비밀번호 로그인 모두 동작
- [ ] 05-P2: Synology 로그인 동작, 마이페이지 계정 연결 표시
---
### 📍 STAGE 3: 핵심 기능 개발 - 병렬 진행 (2~3주차)
> **목표**: AI 연동 기능 3개 + VCS 기반 동시 진행
| 순번 | Phase ID | 작업 내용 | 소요 | 선행 | 담당 |
|:----:|:--------:|----------|:----:|:----:|:----:|
| 12 | **01-P2** | 회의록 AI 분석 연동 | 2일 | 01-P1 | A |
| 13 | **02-P2** | 프로젝트-사업 연결 | 1일 | 02-P1 | B |
| 14 | **03-P2** | 파일 업로드 + AI 파싱 | 2일 | 03-P1 | C |
| 15 | **07-P1** | VCS 서버/계정 관리 | 3일 | 00 | D |
**병렬 진행 가능**: ✅ 4개 모두 병렬 가능
**완료 기준**:
- [ ] 01-P2: 회의록 저장 → AI 분석 → 결과 표시
- [ ] 02-P2: 프로젝트에 사업 배정, 주간보고에 사업명 표시
- [ ] 03-P2: 엑셀 업로드 → AI 파싱 → 검토 화면 표시
- [ ] 07-P1: VCS 서버 관리, 마이페이지 계정 설정
---
### 📍 STAGE 4: 핵심 기능 심화 (3~4주차)
> **목표**: 각 기능의 핵심 로직 완성
| 순번 | Phase ID | 작업 내용 | 소요 | 선행 | 담당 |
|:----:|:--------:|----------|:----:|:----:|:----:|
| 16 | **01-P3** | TODO 기능 | 2일 | 01-P2 | A |
| 17 | **02-P3** | 사업 주간보고 AI 취합 | 1.5일 | 02-P2 | B |
| 18 | **03-P3** | 유지보수-주간보고 연계 | 2일 | 03-P2 | C |
| 19 | **07-P2** | 저장소 관리 CRUD | 2일 | 07-P1 | D |
**병렬 진행 가능**: ✅ 4개 모두 병렬 가능
**완료 기준**:
- [ ] 01-P3: TODO 목록/상태변경/담당자지정
- [ ] 02-P3: 사업별 주간보고 AI 취합 생성
- [ ] 03-P3: 주간보고 작성 시 유지보수 업무 연계
- [ ] 07-P2: 프로젝트 상세에서 저장소 추가/수정/삭제
---
### 📍 STAGE 5: VCS 연동 + 구글 그룹 (4~5주차)
> **목표**: 외부 시스템 연동 완성
| 순번 | Phase ID | 작업 내용 | 소요 | 선행 | 담당 |
|:----:|:--------:|----------|:----:|:----:|:----:|
| 20 | **06-P1** | OAuth Scope 확장 + 토큰 저장 | 2일 | **04-P5** | A |
| 21 | **07-P3** | Git 커밋 수집 | 3일 | 07-P2 | B |
| 22 | **07-P4** | SVN 커밋 수집 | 3일 | 07-P2 | C |
**병렬 진행**:
- 06-P1 ↔ 07-P3, 07-P4 병렬 가능
- 07-P3 ↔ 07-P4 병렬 가능
**완료 기준**:
- [ ] 06-P1: Gmail API 토큰 저장, 갱신 로직
- [ ] 07-P3: Git 저장소 커밋 수집 → DB 저장
- [ ] 07-P4: SVN 저장소 커밋 수집 → DB 저장
---
### 📍 STAGE 6: 기능 연결 및 UI (5~6주차)
> **목표**: 각 기능의 UI 완성 및 연계
| 순번 | Phase ID | 작업 내용 | 소요 | 선행 |
|:----:|:--------:|----------|:----:|:----:|
| 23 | **01-P4** | 주간보고-TODO 연계 | 1일 | 01-P3 |
| 24 | **02-P4** | 사업 테스트 | 0.5일 | 02-P3 |
| 25 | **03-P4** | 유지보수 통계 + 테스트 | 1일 | 03-P3 |
| 26 | **06-P2** | 그룹 게시물 조회 | 3일 | 06-P1 |
| 27 | **07-P5** | 커밋 조회 화면 | 3일 | 07-P3, 07-P4 |
**완료 기준**:
- [ ] 01-P4: 주간보고 작성 시 유사 TODO 팝업
- [ ] 02-P4: 사업 전체 플로우 검증
- [ ] 03-P4: 통계 대시보드 표시
- [ ] 06-P2: 그룹 게시물 목록/상세 조회
- [ ] 07-P5: 프로젝트 커밋 조회 페이지, 주간보고 커밋 참고
---
### 📍 STAGE 7: 마무리 (6~7주차)
> **목표**: 남은 기능 완성 + 전체 테스트
| 순번 | Phase ID | 작업 내용 | 소요 | 선행 |
|:----:|:--------:|----------|:----:|:----:|
| 28 | **06-P3** | 주간보고 그룹 공유 | 3일 | 06-P2 |
| 29 | **06-P4** | 구글 그룹 테스트 | 2일 | 06-P3 |
| 30 | **07-P6** | VCS 자동화 + 테스트 | 2일 | 07-P5 |
**완료 기준**:
- [ ] 06-P4: 그룹 공유 전체 플로우 검증
- [ ] 07-P6: Cron 자동 동기화, 인증 암호화
---
### 📍 STAGE 8: 통합 테스트 (7~8주차)
> **목표**: 전체 시스템 통합 테스트 및 버그 수정
| 순번 | 작업 내용 | 소요 |
|:----:|----------|:----:|
| 31 | 전체 기능 통합 테스트 | 3일 |
| 32 | 버그 수정 및 최적화 | 2일 |
| 33 | 문서화 및 배포 준비 | 1일 |
---
## 4. 간트 차트 (주차별)
```
Week 1 2 3 4 5 6 7 8
┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Stage 0 ██ DB 마이그레이션
┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
01 회의 ████████████████████████ 회의록+TODO
02 사업 ████████████████ 사업-프로젝트
03 유지 ████████████████████████ 유지보수
04 OAuth████████████████████ Gmail OAuth
05 Syno ████████ Synology SSO
06 그룹 ████████████████████████ 구글 그룹
07 VCS ████████████████████████████████████████ SVN/Git
┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
통합테스트 ████████████
```
---
## 5. 단독 실행 가능 Phase (빠른 성과)
### 5.1 즉시 실행 가능 (의존성 없음) ⭐
| 순위 | Phase | 작업 내용 | 소요 | 난이도 |
|:----:|:-----:|----------|:----:|:------:|
| 1 | 00 | 통합 DB 마이그레이션 | 0.5일 | ⭐ |
| 2 | 02-P1 | 사업 CRUD | 1.5일 | ⭐ |
| 3 | 04-P1 | 인증 환경 설정 | 1일 | ⭐ |
| 4 | 03-P1 | 유지보수 기본 CRUD | 2일 | ⭐⭐ |
| 5 | 01-P1 | 회의록 기본 구조 | 2일 | ⭐⭐ |
### 5.2 선행 1개만 필요 (빠른 진행)
| 순위 | Phase | 작업 내용 | 소요 | 선행 | 난이도 |
|:----:|:-----:|----------|:----:|:----:|:------:|
| 6 | 02-P2 | 프로젝트-사업 연결 | 1일 | 02-P1 | ⭐ |
| 7 | 04-P2 | 비밀번호 인증 | 1.5일 | 04-P1 | ⭐⭐ |
| 8 | 07-P1 | VCS 서버/계정 관리 | 3일 | 00 | ⭐⭐ |
| 9 | 01-P3 | TODO 기능 | 2일 | 01-P2 | ⭐⭐ |
### 5.3 복사해서 빠르게 (04 완료 후)
| 순위 | Phase | 작업 내용 | 소요 | 선행 | 비고 |
|:----:|:-----:|----------|:----:|:----:|:----:|
| 10 | 05-P1~P2 | Synology SSO 전체 | 2.5일 | 04 완료 | 04 코드 90% 재사용 |
---
## 6. 자동화 대상
### 6.1 DB 관련 (Phase 00)
- [ ] 통합 DDL 스크립트 생성
- [ ] 마이그레이션 롤백 스크립트
### 6.2 CRUD API 템플릿
- [ ] 목록/상세/생성/수정/삭제 공통 패턴
- [ ] 적용 대상: meeting, business, maintenance, vcs-server, repository
### 6.3 Vue 컴포넌트 템플릿
- [ ] 목록 페이지 (필터 + 테이블/카드)
- [ ] 상세/수정 페이지
- [ ] 모달 컴포넌트
### 6.4 OAuth 공통 모듈
- [ ] OAuth 시작/콜백 공통 함수
- [ ] 토큰 저장/갱신 유틸
### 6.5 AI 프롬프트 모듈
- [ ] OpenAI 호출 공통 함수
- [ ] 프롬프트 템플릿 관리
---
## 7. 리스크 관리
### 7.1 기술 리스크
| 리스크 | 영향 | 대응 방안 |
|--------|:----:|----------|
| Google OAuth 민감 scope 승인 지연 | 06 지연 | 내부용 먼저, 승인 후 외부 공개 |
| SVN 서버 접근 불가 | 07 일부 지연 | Git만 먼저 완성 |
| Synology SSO 설정 이슈 | 05 지연 | 문서 기반 사전 테스트 |
| AI API 비용 | 운영 | 캐싱, 호출 최소화 |
### 7.2 일정 리스크
| 리스크 | 영향 | 대응 방안 |
|--------|:----:|----------|
| 개발자 부재 | 전체 지연 | 병렬 작업으로 분산 |
| 요구사항 변경 | 해당 기능 지연 | Phase 단위 완료 후 변경 |
| 테스트 이슈 | 마무리 지연 | Stage별 테스트로 분산 |
---
## 8. 마일스톤
| 마일스톤 | 목표일 | 완료 기준 |
|----------|:------:|----------|
| **M1: DB 완료** | 1주차 | 모든 테이블 생성, FK 검증 |
| **M2: 기본 CRUD 완료** | 2주차 | 01-P1, 02-P1, 03-P1, 04-P1 완료 |
| **M3: 인증 완료** | 3주차 | 04 전체 + 05 전체 완료 |
| **M4: AI 연동 완료** | 4주차 | 01-P2, 02-P3, 03-P2 완료 |
| **M5: VCS 연동 완료** | 6주차 | 07 전체 완료 |
| **M6: 구글 그룹 완료** | 7주차 | 06 전체 완료 |
| **M7: 전체 완료** | 8주차 | 통합 테스트 + 배포 |
---
## 9. Phase별 체크리스트
### Phase 00: 통합 DB 마이그레이션 ✅ 완료
- [x] 시작일: 2026-01-11 완료일: 2026-01-11 소요: 0.5시간
- [x] 01 테이블 4개 생성 (meeting, attendee, agenda, todo) ✅ 기존 존재
- [x] 02 테이블 2개 생성 (business, business_weekly_report) ✅ 기존 존재
- [x] 02 ALTER wr_project_info (business_id 추가) ✅ 기존 존재
- [x] 03 테이블 2개 생성 (maintenance_task, upload_batch) ✅ 기존 존재
- [x] 04 ALTER wr_employee_info (password, google 컬럼) ✅ 기존 존재
- [x] 04 테이블 1개 생성 (login_history) ✅ 기존 존재
- [x] 05 ALTER wr_employee_info (synology 컬럼) ✅ 기존 존재
- [x] 06 ALTER wr_employee_info (token 컬럼) ✅ 기존 존재
- [x] 06 테이블 2개 생성 (google_group, report_group_share) ✅ 기존 존재
- [x] 07 테이블 4개 생성 (vcs_server, vcs_account, repository, commit_log) ✅ commit_log 신규 생성
- [x] 인덱스 생성 확인 ✅
- [x] FK 관계 검증 ✅
---
### Phase 01-P1: 회의록 기본 구조 ✅ 완료
- [x] 시작일시: 2026-01-11 17:05 종료일시: 2026-01-11 17:45 수행시간: 40분
- [x] Tiptap 에디터 컴포넌트 구성 ⚠️ (textarea로 구현, Tiptap 설치 필요)
- [x] 회의록 CRUD API (list, detail, create, update, delete) ✅
- [x] 회의록 목록 페이지 (/meeting) ✅
- [x] 회의록 작성 페이지 (/meeting/write) ✅
- [x] 회의록 상세 페이지 (/meeting/[id]) ✅
- [x] 참석자 선택 (내부/외부) ✅
- [x] 프로젝트/내부업무 구분 ✅
### Phase 01-P2: AI 분석 연동
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] OpenAI 프롬프트 구현 (회의 정리)
- [ ] 저장 시 자동 AI 분석 실행
- [ ] AI 결과 → 안건 테이블 저장
- [ ] AI 결과 → TODO 후보 추출
- [ ] 상세 화면에 AI 분석 결과 표시
- [ ] 재분석 기능
- [ ] 확정 기능 (→ TODO 생성)
### Phase 01-P3: TODO 기능
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] TODO CRUD API
- [ ] TODO 목록 페이지 (/todo)
- [ ] 내 TODO 필터
- [ ] 상태 변경 (대기/완료/폐기)
- [ ] 담당자 지정
- [ ] 프로젝트 연결
### Phase 01-P4: 주간보고 연계
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 주간보고 작성 시 유사 TODO 감지 API
- [ ] 유사 TODO 팝업 UI
- [ ] TODO 완료 연계 처리
- [ ] 테스트 및 버그 수정
---
### Phase 02-P1: 사업 CRUD ✅ 완료
- [x] 시작일시: 2026-01-11 00:28 KST 종료일시: 2026-01-11 00:31 KST 수행시간: 3분
- [x] 사업 CRUD API (list, detail, create, update, delete) ✅
- [x] 사업 목록 페이지 (/business) ✅
- [x] 사업 상세 페이지 (/business/[id]) ✅
- [x] 사업 등록/수정 모달 ✅
- [ ] 메뉴 권한 설정 (매니저 이상) ⏳ 추후
### Phase 02-P2: 프로젝트-사업 연결 ✅ 완료
- [x] 시작일시: 2026-01-11 01:02 KST 종료일시: 2026-01-11 01:08 KST 수행시간: 6분
- [x] 프로젝트 수정 화면에 사업 선택 추가 ✅
- [x] 프로젝트 배정 API (business_id 필드) ✅
- [x] 사업 상세에 소속 프로젝트 목록 ✅
- [x] 주간보고 작성 시 사업명 표시 ⏳ 추후
### Phase 02-P3: 사업 주간보고 취합 ✅ 완료
- [x] 시작일시: 2026-01-11 01:10 KST 종료일시: 2026-01-11 01:18 KST 수행시간: 8분
- [x] OpenAI 프롬프트 구현 (취합 요약) ✅
- [x] 사업 주간보고 취합 API ✅
- [x] 사업 주간보고 상세 페이지 ✅
- [x] 확정 기능 ✅
### Phase 02-P4: 테스트 ✅ 완료
- [x] 시작일시: 2026-01-11 01:20 KST 종료일시: 2026-01-11 01:24 KST 수행시간: 4분
- [x] 전체 플로우 테스트 ✅
- [x] 기존 취합보고와 연계 확인 ✅
- [x] 버그 수정 (없음) ✅
---
### Phase 03-P1: 유지보수 기본 CRUD ✅ 완료
- [x] 시작일시: 2026-01-11 00:51 KST 종료일시: 2026-01-11 00:56 KST 수행시간: 5분
- [x] 유지보수 CRUD API ✅
- [x] 목록 페이지 (/maintenance) ✅
- [x] 상세 페이지 (/maintenance/[id]) ✅
- [x] 등록/수정 화면 ✅
- [x] 상태 변경 기능 ✅
- [x] 반영 체크 (개발/운영/고객확인) ✅
### Phase 03-P2: 파일 업로드 + AI 파싱 ✅ 완료
- [x] 시작일시: 2026-01-11 01:26 KST 종료일시: 2026-01-11 01:33 KST 수행시간: 7분
- [x] 파일 업로드 API (엑셀/CSV) ✅
- [x] SheetJS 연동 ✅ (npm install xlsx 필요)
- [x] OpenAI 프롬프트 구현 (파싱) ✅
- [x] 파싱 결과 검토 화면 ✅
- [x] 중복 감지 로직 ✅
- [x] 일괄 등록 기능 ✅
### Phase 03-P3: 주간보고 연계 🔄 진행중
- [x] 시작일시: 2026-01-11 01:35 KST 종료일시: ____ 수행시간: ____
- [ ] 주간보고 작성 시 유지보수 업무 조회 API
- [ ] OpenAI 프롬프트 (실적 문장 생성)
- [ ] 유사 실적 병합 기능
- [ ] 연계 정보 저장
- [ ] 주간보고 작성 화면 수정
### Phase 03-P4: 통계 + 테스트
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 통계 API (주간/월간/담당자별)
- [ ] 통계 대시보드 페이지
- [ ] 전체 테스트 및 버그 수정
---
### Phase 04-P1: 인증 환경 설정
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] Google Cloud Console OAuth 설정
- [ ] 환경 변수 설정 (GOOGLE_*, SMTP_*)
- [ ] wr_employee_info 컬럼 추가 완료 확인
### Phase 04-P2: 비밀번호 인증
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] bcrypt 해시 처리 유틸
- [ ] 이메일/비밀번호 로그인 API
- [ ] 비밀번호 변경 API
- [ ] 비밀번호 초기화 API (관리자)
### Phase 04-P3: Google OAuth
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] Google OAuth 시작 API (/api/auth/google)
- [ ] Google 콜백 API (/api/auth/google/callback)
- [ ] 사용자 매칭 로직 (email 기준)
- [ ] 비밀번호 미설정 시 리다이렉트
### Phase 04-P4: 비밀번호 찾기 + 이메일
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] nodemailer 설정
- [ ] 이메일 발송 유틸
- [ ] 비밀번호 찾기 API (이름+이메일+핸드폰)
- [ ] 임시 비밀번호 생성 및 발송
- [ ] 비밀번호 찾기 페이지
### Phase 04-P5: 로그인 UI + 테스트
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 로그인 페이지 수정 (OAuth + 비밀번호)
- [ ] 비밀번호 설정 페이지
- [ ] 로그인 실패 페이지
- [ ] 마이페이지 비밀번호 변경 UI
- [ ] 관리자 사용자 관리 수정
- [ ] 전체 플로우 테스트
---
### Phase 05-P1: Synology SSO API
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] Synology SSO Server 애플리케이션 등록
- [ ] 환경 변수 설정 (SYNOLOGY_*)
- [ ] Synology OAuth 시작 API (/api/auth/synology)
- [ ] Synology 콜백 API (/api/auth/synology/callback)
- [ ] 사용자 매칭 로직
### Phase 05-P2: Synology UI + 테스트
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 로그인 페이지에 Synology 버튼 추가
- [ ] 마이페이지 외부 계정 연결 표시
- [ ] 로그인 이력에 login_type 기록
- [ ] 전체 플로우 테스트
---
### Phase 06-P1: OAuth Scope 확장
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] Google Cloud Console scope 추가 (gmail.readonly, gmail.send)
- [ ] wr_employee_info 토큰 컬럼 확인
- [ ] OAuth 콜백에서 토큰 저장
- [ ] 토큰 갱신 로직
### Phase 06-P2: 그룹 게시물 조회
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] wr_google_group 테이블에 그룹 등록
- [ ] 그룹 목록 API
- [ ] 그룹 게시물 목록 API (Gmail API 연동)
- [ ] 게시물 상세 API
- [ ] 그룹 게시물 조회 페이지 (/google-group)
### Phase 06-P3: 주간보고 그룹 공유
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 그룹 공유 API (Gmail 발송)
- [ ] 공유 이력 API
- [ ] 이메일 본문 템플릿
- [ ] 주간보고 상세에 공유 UI 추가
### Phase 06-P4: 테스트 + 마무리
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 전체 플로우 테스트
- [ ] 토큰 만료 시 갱신 테스트
- [ ] 오류 처리 (권한 없음 등)
- [ ] 관리자 그룹 목록 관리 페이지
---
### Phase 07-P1: VCS 서버/계정 관리
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] VCS 서버 CRUD API (관리자)
- [ ] VCS 서버 관리 페이지 (/admin/vcs-server)
- [ ] 사용자 VCS 계정 API
- [ ] 마이페이지 VCS 계정 설정 UI
### Phase 07-P2: 저장소 관리
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 저장소 CRUD API
- [ ] 프로젝트 상세에 저장소 관리 UI
- [ ] 저장소 추가/수정 모달
### Phase 07-P3: Git 커밋 수집
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] simple-git 패키지 설치
- [ ] Git clone/pull 로직
- [ ] 커밋 로그 파싱
- [ ] 작성자 매칭 (VCS 계정 기반)
- [ ] DB 저장
### Phase 07-P4: SVN 커밋 수집
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] svn CLI 연동
- [ ] svn log 실행 및 XML 파싱
- [ ] 작성자 매칭
- [ ] DB 저장
### Phase 07-P5: 커밋 조회 화면
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] 프로젝트별 커밋 조회 API
- [ ] 프로젝트 커밋 조회 페이지 (/project/[id]/commits)
- [ ] 필터 (기간, 저장소, 작성자)
- [ ] 주간보고 작성 시 커밋 참고 UI
- [ ] 새로고침 버튼
### Phase 07-P6: 자동화 + 테스트
- [ ] 시작일: ____ 완료일: ____ 소요: ____
- [ ] Cron Job 설정 (매일 새벽 자동 동기화)
- [ ] 인증 정보 암호화
- [ ] 전체 플로우 테스트
- [ ] 오류 처리
---
## 10. 작업 완료 결과 요약
### 전체 Phase별 시간 기록
| Stage | Phase ID | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|:--------:|----------|:----:|:----:|:--------:|
| 0 | 00 | 통합 DB 마이그레이션 | 01-11 | 01-11 | 0.5h ✅ |
| 1 | 01-P1 | 회의록 기본 구조 | 01-11 17:05 | 01-11 17:45 | 40분 ✅ |
| 1 | 02-P1 | 사업 CRUD | 01-11 00:28 | 01-11 00:31 | 3분 ✅ |
| 1 | 03-P1 | 유지보수 기본 CRUD | 01-11 00:51 | 01-11 00:56 | 5분 ✅ |
| 1 | 04-P1 | 인증 환경 설정 | - | - | - |
| 2 | 04-P2 | 비밀번호 인증 | - | - | - |
| 2 | 04-P3 | Google OAuth | - | - | - |
| 2 | 04-P4 | 비밀번호 찾기 | - | - | - |
| 2 | 04-P5 | 로그인 UI | - | - | - |
| 2 | 05-P1 | Synology API | - | - | - |
| 2 | 05-P2 | Synology UI | - | - | - |
| 3 | 01-P2 | AI 분석 연동 | - | - | - |
| 3 | 02-P2 | 프로젝트-사업 연결 | - | - | - |
| 3 | 03-P2 | 파일 업로드 + AI 파싱 | - | - | - |
| 3 | 07-P1 | VCS 서버/계정 관리 | - | - | - |
| 4 | 01-P3 | TODO 기능 | - | - | - |
| 4 | 02-P3 | 사업 주간보고 취합 | - | - | - |
| 4 | 03-P3 | 유지보수-주간보고 연계 | - | - | - |
| 4 | 07-P2 | 저장소 관리 | - | - | - |
| 5 | 06-P1 | OAuth Scope 확장 | - | - | - |
| 5 | 07-P3 | Git 커밋 수집 | - | - | - |
| 5 | 07-P4 | SVN 커밋 수집 | - | - | - |
| 6 | 01-P4 | 주간보고-TODO 연계 | - | - | - |
| 6 | 02-P4 | 사업 테스트 | - | - | - |
| 6 | 03-P4 | 유지보수 통계 | - | - | - |
| 6 | 06-P2 | 그룹 게시물 조회 | - | - | - |
| 6 | 07-P5 | 커밋 조회 화면 | - | - | - |
| 7 | 06-P3 | 주간보고 그룹 공유 | - | - | - |
| 7 | 06-P4 | 구글 그룹 테스트 | - | - | - |
| 7 | 07-P6 | VCS 자동화 | - | - | - |
| 8 | - | 통합 테스트 | - | - | - |
| | | | | **총 소요시간** | **-** |
---
### 마일스톤 달성 현황
| 마일스톤 | 목표일 | 실제 완료일 | 상태 |
|----------|:------:|:----------:|:----:|
| M1: DB 완료 | 1주차 | 2026-01-11 | ✅ |
| M2: 기본 CRUD 완료 | - | - | ⬜ |
| M3: 인증 완료 | - | - | ⬜ |
| M4: AI 연동 완료 | - | - | ⬜ |
| M5: VCS 연동 완료 | - | - | ⬜ |
| M6: 구글 그룹 완료 | - | - | ⬜ |
| M7: 전체 완료 | - | - | ⬜ |
---
## 11. 참조 문서
| # | 문서명 | 파일명 |
|:-:|--------|--------|
| 01 | 회의록 + TODO 작업계획서 | 01_회의록_TODO_작업계획서.md |
| 02 | 사업-프로젝트 계층 작업계획서 | 02_사업_프로젝트_계층구조_작업계획서.md |
| 03 | 유지보수 업무관리 작업계획서 | 03_유지보수_업무관리_작업계획서.md |
| 04 | Gmail OAuth 로그인 작업계획서 | 04_Gmail_OAuth_로그인_작업계획서.md |
| 05 | Synology SSO 연동 작업계획서 | 05_Synology_SSO_연동_작업계획서.md |
| 06 | 구글 그룹 연동 작업계획서 | 06_구글그룹_연동_작업계획서.md |
| 07 | SVN/Git 커밋 연동 작업계획서 | 07_SVN_Git_커밋내역_연동_작업계획서.md |
---
## 변경 이력
| 버전 | 날짜 | 변경 내용 | 작성자 |
|:----:|:----:|----------|:------:|
| 1.0 | 2026-01-10 | 최초 작성 | - |

View File

@@ -0,0 +1,491 @@
# 회의록 + TODO 기능 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 5~7일
> 우선순위: 1 (가장 쉬움)
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- 두서없이 작성한 회의 내용을 AI가 주제별로 정리
- 결정/미결정 사항 자동 분류
- 미결정 사항 중 액션 필요한 것을 TODO로 추출
- TODO는 "언젠가 할 일" / "검토 필요한 것" / "보류된 것" 성격
### 1.2 회의록 유형
| 유형 | 설명 |
|:---:|------|
| 프로젝트 회의 | 특정 프로젝트에 종속 |
| 내부업무 회의 | 프로젝트 무관 (일반 내부 회의) |
---
## 2. 데이터 모델
### 2.1 회의록 테이블 (wr_meeting)
```sql
CREATE TABLE wr_meeting (
meeting_id SERIAL PRIMARY KEY,
-- 기본 정보
meeting_title VARCHAR(200) NOT NULL, -- 회의 제목
meeting_type VARCHAR(20) NOT NULL, -- PROJECT: 프로젝트, INTERNAL: 내부업무
project_id INTEGER REFERENCES wr_project_info(project_id), -- 프로젝트 (선택)
-- 일시/장소
meeting_date DATE NOT NULL, -- 회의 일자
start_time TIME, -- 시작 시간
end_time TIME, -- 종료 시간
location VARCHAR(100), -- 장소
-- 내용
raw_content TEXT, -- 원본 내용 (위키 에디터 HTML)
ai_summary TEXT, -- AI 정리 결과 (JSON)
ai_status VARCHAR(20) DEFAULT 'NONE', -- NONE: 미분석, PENDING: 미확정, CONFIRMED: 확정
ai_processed_at TIMESTAMP, -- AI 처리 일시
ai_confirmed_at TIMESTAMP, -- 확정 일시
-- 메타
author_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_ip VARCHAR(50),
created_email VARCHAR(100),
updated_ip VARCHAR(50),
updated_email VARCHAR(100)
);
-- 인덱스
CREATE INDEX idx_meeting_project ON wr_meeting(project_id);
CREATE INDEX idx_meeting_date ON wr_meeting(meeting_date);
CREATE INDEX idx_meeting_author ON wr_meeting(author_id);
```
### 2.2 회의 참석자 테이블 (wr_meeting_attendee)
```sql
CREATE TABLE wr_meeting_attendee (
attendee_id SERIAL PRIMARY KEY,
meeting_id INTEGER NOT NULL REFERENCES wr_meeting(meeting_id) ON DELETE CASCADE,
-- 내부 직원 (선택)
employee_id INTEGER REFERENCES wr_employee_info(employee_id),
-- 외부 참석자 (직접 입력)
external_name VARCHAR(50), -- 외부인 이름
external_company VARCHAR(100), -- 외부인 소속
-- 하나는 필수
CONSTRAINT chk_attendee CHECK (employee_id IS NOT NULL OR external_name IS NOT NULL)
);
CREATE INDEX idx_attendee_meeting ON wr_meeting_attendee(meeting_id);
```
### 2.3 회의 안건 테이블 (wr_meeting_agenda)
```sql
CREATE TABLE wr_meeting_agenda (
agenda_id SERIAL PRIMARY KEY,
meeting_id INTEGER NOT NULL REFERENCES wr_meeting(meeting_id) ON DELETE CASCADE,
agenda_no INTEGER NOT NULL, -- 안건 번호 (1, 2, 3...)
agenda_title VARCHAR(200) NOT NULL, -- 안건 제목
agenda_content TEXT, -- 안건 상세 내용
-- 결정 상태
decision_status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
-- DECIDED: 결정됨, PENDING: 미결정, IN_PROGRESS: 진행중
decision_content TEXT, -- 결정 내용 (결정된 경우)
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_agenda_meeting ON wr_meeting_agenda(meeting_id);
```
### 2.4 TODO 테이블 (wr_todo)
```sql
CREATE TABLE wr_todo (
todo_id SERIAL PRIMARY KEY,
-- 출처 (회의록에서 추출 시)
source_type VARCHAR(20), -- MEETING: 회의록, MANUAL: 직접생성
meeting_id INTEGER REFERENCES wr_meeting(meeting_id),
agenda_id INTEGER REFERENCES wr_meeting_agenda(agenda_id),
-- 프로젝트 연결 (선택)
project_id INTEGER REFERENCES wr_project_info(project_id),
-- 내용
todo_title VARCHAR(300) NOT NULL, -- TODO 제목
todo_description TEXT, -- 상세 설명
-- 담당/상태
assignee_id INTEGER REFERENCES wr_employee_info(employee_id), -- 담당자 (선택)
todo_status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
-- PENDING: 대기, COMPLETED: 완료, DISCARDED: 폐기
completed_at TIMESTAMP, -- 완료 일시
discarded_at TIMESTAMP, -- 폐기 일시
discard_reason VARCHAR(200), -- 폐기 사유
-- 주간보고 연계
linked_report_id INTEGER REFERENCES wr_weekly_report(report_id), -- 연계된 주간보고
linked_at TIMESTAMP, -- 연계 일시
-- 메타
author_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_ip VARCHAR(50),
created_email VARCHAR(100),
updated_ip VARCHAR(50),
updated_email VARCHAR(100)
);
-- 인덱스
CREATE INDEX idx_todo_assignee ON wr_todo(assignee_id);
CREATE INDEX idx_todo_status ON wr_todo(todo_status);
CREATE INDEX idx_todo_meeting ON wr_todo(meeting_id);
CREATE INDEX idx_todo_project ON wr_todo(project_id);
```
---
## 3. API 설계
### 3.1 회의록 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/meeting/list | 회의록 목록 조회 |
| GET | /api/meeting/[id]/detail | 회의록 상세 조회 |
| POST | /api/meeting/create | 회의록 작성 (저장 시 AI 분석 자동 실행) |
| PUT | /api/meeting/[id]/update | 회의록 수정 |
| DELETE | /api/meeting/[id]/delete | 회의록 삭제 |
| POST | /api/meeting/[id]/reanalyze | AI 재분석 실행 |
| POST | /api/meeting/[id]/confirm | 분석 결과 확정 (→ TODO 생성) |
### 3.2 TODO API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/todo/list | TODO 목록 조회 |
| GET | /api/todo/my | 내 TODO 목록 |
| POST | /api/todo/create | TODO 직접 생성 |
| PUT | /api/todo/[id]/update | TODO 수정 |
| PUT | /api/todo/[id]/complete | TODO 완료 처리 |
| PUT | /api/todo/[id]/discard | TODO 폐기 처리 |
| DELETE | /api/todo/[id]/delete | TODO 삭제 |
### 3.3 주간보고 연계 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/todo/suggest-for-report | 주간보고 작성 시 유사 TODO 추천 |
| POST | /api/todo/[id]/link-report | TODO-주간보고 연계 + 완료 처리 |
---
## 4. 화면 설계
### 4.0 에디터 선택: Tiptap
Vue3 네이티브 지원, 가볍고 커스터마이징 우수한 **Tiptap** 사용
```bash
npm install @tiptap/vue-3 @tiptap/starter-kit @tiptap/extension-link @tiptap/extension-placeholder
```
### 4.1 회의록 목록 (/meeting)
- 필터: 전체 / 프로젝트별 / 내부업무
- 기간 검색
- 카드형 또는 테이블형 목록
- **분석 상태 표시**: 미분석 / 미확정 / 확정
### 4.2 회의록 작성 (/meeting/write)
```
┌─────────────────────────────────────────────┐
│ 회의록 작성 │
├─────────────────────────────────────────────┤
│ 회의 유형: ○ 프로젝트 회의 ○ 내부업무 회의 │
│ 프로젝트: [선택 (프로젝트 회의 시)] │
│ │
│ 제목: [_________________________] │
│ 일시: [2026-01-10] [14:00] ~ [16:00] │
│ 장소: [회의실 A] │
│ │
│ 참석자: [내부직원 선택] [+ 외부 추가] │
│ - 조효성, 서혜원 │
│ - 홍길동 (고객사) │
│ │
│ 회의 내용: (Tiptap 위키 에디터) │
│ ┌─────────────────────────────────────────┐ │
│ │ [B] [I] [U] [H1] [H2] [•] [1.] [Link] │ │
│ │ ───────────────────────────────────────── │
│ │ 오늘 PIMS 관련해서 얘기했는데... │ │
│ │ • 화면 디자인은 기존 거 쓰기로 했고 │ │
│ │ • DB 마이그레이션은 아직... │ │
│ └─────────────────────────────────────────┘ │
│ │
│ [임시저장] [저장] │
└─────────────────────────────────────────────┘
* 저장 시 자동으로 AI 분석 실행 → 상세 페이지로 이동
```
### 4.3 회의록 상세 보기 (/meeting/[id])
```
┌─────────────────────────────────────────────────────────┐
│ 📋 PIMS 프로젝트 킥오프 회의 [수정] │
├─────────────────────────────────────────────────────────┤
│ 일시: 2026-01-10 14:00~16:00 │
│ 장소: 회의실 A │
│ 참석자: 조효성, 서혜원, 홍길동(고객사) │
├─────────────────────────────────────────────────────────┤
│ 📝 회의 내용 │
│ ─────────────────────────────────────────────────────── │
│ (위키 에디터로 작성된 원본 내용 렌더링 - HTML) │
│ │
│ 오늘 PIMS 관련해서 얘기했는데... │
│ • 화면 디자인은 기존 거 쓰기로 했고 │
│ • DB 마이그레이션은 아직 범위가... │
│ │
├─────────────────────────────────────────────────────────┤
│ 🤖 AI 분석 결과 [재분석] [확정하기] │
│ ─────────────────────────────────────────────────────── │
│ │
│ 1. 화면 디자인 │
│ ✅ 결정: 기존 디자인 재사용 │
│ │
│ 2. DB 마이그레이션 │
│ ⏳ 미결정: 범위 미확정, 다음주 재논의 │
│ ☑ TODO: DB 마이그레이션 범위 정의 │
│ │
│ 3. 테스트 서버 │
│ ⏳ 진행중 │
│ ☑ TODO: AWS 견적 확인 (@조효성) │
│ │
│ ─────────────────────────────────────────────────────── │
│ 상태: ⚠️ 미확정 (확정 시 선택된 TODO가 생성됩니다) │
└─────────────────────────────────────────────────────────┘
* [확정하기] 클릭 → 체크된 TODO 항목 자동 생성
* 이미 확정된 경우: "✅ 확정됨 (2026-01-10)" 표시, TODO 목록 링크
```
### 4.4 회의록 수정 시 플로우
```
[수정 페이지에서 저장 클릭]
내용 변경 감지?
├─ NO → 그냥 저장
└─ YES ↓
┌─────────────────────────────────────┐
│ 회의 내용이 변경되었습니다. │
│ │
│ AI 분석을 다시 실행할까요? │
│ (기존 분석 결과가 대체됩니다) │
│ │
│ [예, 재분석] [아니오] │
└─────────────────────────────────────┘
* 이미 확정된 분석이 있으면 경고:
"기존 TODO가 유지됩니다. 새 분석 결과로 추가 TODO를 생성할 수 있습니다."
```
### 4.5 AI 분석 상태
| 상태 | 값 | 설명 |
|:---:|:---:|------|
| 미분석 | `NONE` | 아직 AI 분석 안됨 |
| 미확정 | `PENDING` | 분석 완료, 사용자 확정 대기 |
| 확정 | `CONFIRMED` | 확정됨, TODO 생성 완료 |
### 4.6 TODO 목록 (/todo)
- 필터: 전체 / 내 TODO / 프로젝트별
- 상태 필터: 대기 / 완료 / 폐기
- 드래그앤드롭 또는 버튼으로 상태 변경
### 4.5 주간보고 작성 시 TODO 연계
```
┌─────────────────────────────────────────────┐
│ 💡 유사한 TODO가 있습니다 │
├─────────────────────────────────────────────┤
│ 작성 중인 실적: │
│ "AWS 테스트 서버 구축 완료" │
│ │
│ 유사 TODO: │
│ ⏳ "AWS 견적 확인" (1/8 회의에서 생성) │
│ │
│ 이 TODO도 완료 처리할까요? │
│ [예, 완료 처리] [아니오] │
└─────────────────────────────────────────────┘
```
---
## 5. AI 프롬프트 설계
### 5.1 회의 내용 정리 프롬프트
```
당신은 회의록 정리 전문가입니다.
아래 회의 내용을 분석하여 JSON 형식으로 정리해주세요.
## 입력
- 회의 제목: {title}
- 프로젝트: {project_name}
- 참석자: {attendees}
- 원본 내용:
{raw_content}
## 출력 형식
{
"agendas": [
{
"no": 1,
"title": "안건 제목",
"content": "상세 내용",
"status": "DECIDED | PENDING | IN_PROGRESS",
"decision": "결정 내용 (결정된 경우)",
"todos": [
{
"title": "TODO 제목",
"assignee": "담당자명 또는 null",
"reason": "TODO로 추출한 이유"
}
]
}
],
"summary": "전체 회의 요약 (2-3문장)"
}
## 규칙
1. 안건은 주제별로 분리하여 넘버링
2. 결정된 사항은 DECIDED, 추후 논의는 PENDING, 진행중은 IN_PROGRESS
3. 미결정/진행중 사항 중 액션이 필요한 것은 todos로 추출
4. 담당자가 언급되면 assignee에 기록 (없으면 null)
5. JSON 외 다른 텍스트 출력 금지
```
---
## 6. 작업 일정
### Phase 1: 기본 구조 (2일) ✅ 완료
- [x] 시작: 2026-01-11 17:05
- [x] 완료: 2026-01-11 17:45
- [x] 소요시간: 40분
**작업 내용:**
- [x] DB 테이블 생성 (meeting, attendee, agenda, todo) ✅ 기존 존재
- [x] Tiptap 에디터 컴포넌트 구성 ⚠️ textarea로 구현 (Tiptap 설치 필요)
- [x] 회의록 CRUD API ✅
- [x] 회의록 목록/작성 화면 ✅
**생성된 파일:**
- backend/api/meeting/list.get.ts
- backend/api/meeting/create.post.ts
- backend/api/meeting/[id]/detail.get.ts
- backend/api/meeting/[id]/update.put.ts
- backend/api/meeting/[id]/delete.delete.ts
- frontend/meeting/index.vue
- frontend/meeting/write.vue
- frontend/meeting/[id].vue
---
### Phase 2: AI 분석 연동 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 회의 내용 AI 분석 API (저장 시 자동 실행)
- [ ] AI 정리 결과 → 안건 + TODO 추출 로직
- [ ] 회의록 상세 화면 (원본 + AI 분석 결과)
- [ ] 분석 결과 확정 기능 (→ TODO 자동 생성)
---
### Phase 3: TODO 기능 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] TODO CRUD API
- [ ] TODO 목록/상세 화면
- [ ] 상태 변경 기능 (대기/완료/폐기)
- [ ] 담당자 지정 기능
---
### Phase 4: 주간보고 연계 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 주간보고 작성 시 유사 TODO 감지 (AI)
- [ ] TODO 완료 연계 처리 (확인 후 업데이트)
- [ ] 테스트 및 버그 수정
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | 기본 구조 (DB, API, 화면) | 01-11 17:05 | 01-11 17:45 | 40분 ✅ |
| 2 | AI 분석 연동 | - | - | - |
| 3 | TODO 기능 | - | - | - |
| 4 | 주간보고 연계 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_meeting | 신규 테이블 |
| **DB** | wr_meeting_attendee | 신규 테이블 |
| **DB** | wr_meeting_agenda | 신규 테이블 |
| **DB** | wr_todo | 신규 테이블 |
| **API** | backend/api/meeting/*.ts | 신규 |
| **API** | backend/api/todo/*.ts | 신규 |
| **Frontend** | frontend/pages/meeting/*.vue | 신규 |
| **Frontend** | frontend/pages/todo/*.vue | 신규 |
| **Frontend** | frontend/components/editor/TiptapEditor.vue | 신규 |
| **Utils** | backend/utils/openai.ts | 수정 (프롬프트 추가) |
---
## 7. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **에디터**: Tiptap (WYSIWYG 위키 에디터)
- **AI**: OpenAI GPT-4o-mini
- **인증**: 기존 세션 기반 (requireAuth)
---
## 8. 향후 확장 고려
1. **첨부파일**: 회의자료/사진 업로드 (2단계)
2. **알림**: TODO 담당자에게 알림 발송
3. **반복 회의**: 정기 회의 템플릿
4. **회의록 공유**: 참석자 이메일 발송
5. **음성 회의록**: 녹음 파일 → 텍스트 변환 (STT)

View File

@@ -0,0 +1,469 @@
# 사업-프로젝트 계층 구조 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 3~5일
> 우선순위: 2
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- 프로젝트 상위에 **사업(Business)** 개념 추가
- 사업 단위로 주간보고 취합
- 개발자 주간보고는 기존과 동일, 취합 시 사업 단위로 묶음
### 1.2 계층 구조
```
사업 (Business)
└─ 프로젝트 A
└─ 프로젝트 B
└─ 프로젝트 C
(사업 미지정)
└─ 프로젝트 D
└─ 프로젝트 E
```
### 1.3 결정 사항
| # | 항목 | 결정 |
|:-:|------|:----:|
| 1 | 프로젝트-사업 관계 | **선택 (NULL 허용)** |
| 2 | 기존 프로젝트 처리 | **그대로 유지, 필요 시 배정** |
| 3 | 취합보고 단위 | **사업별 1개 보고서 (프로젝트별 정리)** |
| 4 | 주간보고 작성 시 | **프로젝트 선택 → 사업 자동 표시** |
| 5 | 사업 관리 권한 | **매니저 이상** |
---
## 2. 데이터 모델
### 2.1 사업 테이블 (wr_business)
```sql
CREATE TABLE wr_business (
business_id SERIAL PRIMARY KEY,
-- 기본 정보
business_code VARCHAR(20) NOT NULL UNIQUE, -- 사업 코드 (예: BIZ-2026-001)
business_name VARCHAR(200) NOT NULL, -- 사업명
business_description TEXT, -- 사업 설명
-- 기간
start_date DATE, -- 사업 시작일
end_date DATE, -- 사업 종료일 (예정)
-- 상태
business_status VARCHAR(20) DEFAULT 'IN_PROGRESS',
-- PLANNING: 계획중, IN_PROGRESS: 진행중, COMPLETED: 완료, ON_HOLD: 보류
-- 담당
manager_id INTEGER REFERENCES wr_employee_info(employee_id), -- 사업 담당자
-- 메타
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_ip VARCHAR(50),
created_email VARCHAR(100),
updated_ip VARCHAR(50),
updated_email VARCHAR(100)
);
-- 인덱스
CREATE INDEX idx_business_status ON wr_business(business_status);
CREATE INDEX idx_business_manager ON wr_business(manager_id);
CREATE INDEX idx_business_active ON wr_business(is_active);
```
### 2.2 프로젝트 테이블 수정 (wr_project_info)
```sql
-- 기존 테이블에 컬럼 추가
ALTER TABLE wr_project_info
ADD COLUMN business_id INTEGER REFERENCES wr_business(business_id);
-- 인덱스 추가
CREATE INDEX idx_project_business ON wr_project_info(business_id);
```
### 2.3 사업 주간보고 테이블 (wr_business_weekly_report)
```sql
CREATE TABLE wr_business_weekly_report (
report_id SERIAL PRIMARY KEY,
-- 사업/주차 정보
business_id INTEGER NOT NULL REFERENCES wr_business(business_id),
report_year INTEGER NOT NULL,
report_week INTEGER NOT NULL,
week_start_date DATE NOT NULL,
week_end_date DATE NOT NULL,
-- AI 취합 결과
ai_summary TEXT, -- AI 취합 요약 (JSON)
ai_generated_at TIMESTAMP, -- AI 생성 일시
-- 상태
report_status VARCHAR(20) DEFAULT 'DRAFT', -- DRAFT: 임시, CONFIRMED: 확정
confirmed_at TIMESTAMP,
confirmed_by INTEGER REFERENCES wr_employee_info(employee_id),
-- 메타
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_ip VARCHAR(50),
created_email VARCHAR(100),
-- 유니크 제약
UNIQUE(business_id, report_year, report_week)
);
-- 인덱스
CREATE INDEX idx_biz_report_business ON wr_business_weekly_report(business_id);
CREATE INDEX idx_biz_report_week ON wr_business_weekly_report(report_year, report_week);
```
---
## 3. API 설계
### 3.1 사업 관리 API (매니저 이상)
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/business/list | 사업 목록 조회 |
| GET | /api/business/[id]/detail | 사업 상세 조회 |
| POST | /api/business/create | 사업 생성 |
| PUT | /api/business/[id]/update | 사업 수정 |
| DELETE | /api/business/[id]/delete | 사업 삭제 (비활성화) |
### 3.2 프로젝트-사업 연결 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| PUT | /api/project/[id]/assign-business | 프로젝트에 사업 배정 |
| GET | /api/business/[id]/projects | 사업 소속 프로젝트 목록 |
### 3.3 사업 주간보고 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/business/report/list | 사업 주간보고 목록 |
| GET | /api/business/report/[id]/detail | 사업 주간보고 상세 |
| POST | /api/business/[id]/report/generate | 사업 주간보고 AI 취합 생성 |
| POST | /api/business/report/[id]/regenerate | AI 재생성 |
| PUT | /api/business/report/[id]/confirm | 사업 주간보고 확정 |
---
## 4. 화면 설계
### 4.1 사업 목록 (/business)
```
┌─────────────────────────────────────────────────────────────────┐
│ 사업 관리 [+ 사업 등록] │
├─────────────────────────────────────────────────────────────────┤
│ 상태: [전체 ▼] 검색: [_______________] [검색] │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ BIZ-2026-001 │ │
│ │ PIMS 고도화 사업 🟢 진행중 │ │
│ │ 담당: 조효성 | 프로젝트 3개 | 2026.01~2026.12 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ BIZ-2025-003 │ │
│ │ NCCP 유지보수 🟢 진행중 │ │
│ │ 담당: 서혜원 | 프로젝트 2개 | 2025.01~2025.12 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.2 사업 상세/수정 (/business/[id])
```
┌─────────────────────────────────────────────────────────────────┐
│ 사업 상세 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ 사업코드: BIZ-2026-001 │
│ 사업명: PIMS 고도화 사업 │
│ 상태: 🟢 진행중 │
│ 기간: 2026-01-01 ~ 2026-12-31 │
│ 담당자: 조효성 │
│ 설명: 질병관리청 PIMS 시스템 Vue3 전환 및 기능 고도화 │
├─────────────────────────────────────────────────────────────────┤
│ 📁 소속 프로젝트 (3) [+ 프로젝트 배정] │
│ ─────────────────────────────────────────────────────────────── │
│ • 2026-001 PIMS 프론트엔드 개발 진행중 │
│ • 2026-002 PIMS 백엔드 API 개발 진행중 │
│ • 2026-003 PIMS DB 마이그레이션 계획중 │
├─────────────────────────────────────────────────────────────────┤
│ 📊 주간보고 현황 [취합보고 보기] │
│ ─────────────────────────────────────────────────────────────── │
│ 2026년 2주차: 3명 제출 / 3명 중 │
│ 2026년 1주차: 3명 제출 / 3명 중 ✅ 취합완료 │
└─────────────────────────────────────────────────────────────────┘
```
### 4.3 사업 주간보고 (취합) (/business/[id]/report/[year]/[week])
```
┌─────────────────────────────────────────────────────────────────┐
│ 📋 PIMS 고도화 사업 - 2026년 2주차 주간보고 │
│ [AI 재생성] [확정하기] │
├─────────────────────────────────────────────────────────────────┤
│ 기간: 2026-01-06 ~ 2026-01-12 │
│ 상태: ⚠️ 임시 (확정 전) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ## 📊 전체 요약 │
│ 이번 주 PIMS 고도화 사업은 프론트엔드 대시보드 개발 완료, │
│ API 연동 80% 진행, DB 설계 검토 중입니다. │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ ## 🔷 프로젝트별 상세 │
│ │
│ ### 1. PIMS 프론트엔드 개발 │
│ **금주 실적** │
│ - 대시보드 화면 개발 완료 (조효성, 16h) │
│ - 주간보고 목록 UI 개선 (서혜원, 8h) │
│ │
│ **차주 계획** │
│ - 취합보고 화면 개발 │
│ - 사용자 관리 화면 개발 │
│ │
│ ### 2. PIMS 백엔드 API 개발 │
│ **금주 실적** │
│ - 인증 API 세션 방식 전환 (조효성, 8h) │
│ - 주간보고 CRUD API 완료 (조효성, 12h) │
│ │
│ **이슈** │
│ - DB 연결 타임아웃 간헐적 발생 → 커넥션 풀 설정 조정 필요 │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ ## ⚠️ 주요 이슈 │
│ 1. DB 연결 타임아웃 - 커넥션 풀 설정 조정 예정 │
│ 2. 고객사 요구사항 추가 - 다음 주 협의 예정 │
│ │
│ ## 📅 차주 주요 일정 │
│ - 1/15(수): 고객사 중간보고 │
│ - 1/17(금): DB 마이그레이션 범위 확정 회의 │
│ │
└─────────────────────────────────────────────────────────────────┘
* 개발자들이 작성한 주간보고를 AI가 사업/프로젝트 단위로 자동 취합
* 별도 작성 없음, 취합만 실행
```
### 4.4 프로젝트 수정 시 사업 선택
```
┌─────────────────────────────────────────────────────────────────┐
│ 프로젝트 수정 │
├─────────────────────────────────────────────────────────────────┤
│ 프로젝트코드: 2026-001 │
│ 프로젝트명: [PIMS 프론트엔드 개발_______] │
│ 소속 사업: [PIMS 고도화 사업 ▼] ← 신규 추가 │
│ - 선택안함 │
│ - PIMS 고도화 사업 │
│ - NCCP 유지보수 │
│ ... │
└─────────────────────────────────────────────────────────────────┘
```
### 4.5 주간보고 작성 시 사업 표시
```
┌─────────────────────────────────────────────────────────────────┐
│ 주간보고 작성 │
├─────────────────────────────────────────────────────────────────┤
│ 프로젝트 선택: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ☑ PIMS 프론트엔드 개발 │ │
│ │ └ 📁 PIMS 고도화 사업 ← 자동 표시 │ │
│ │ ☐ NCCP 기능개선 │ │
│ │ └ 📁 NCCP 유지보수 │ │
│ │ ☐ 사내 시스템 개발 │ │
│ │ └ 📁 (사업 미지정) │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 5. AI 프롬프트 설계
### 5.1 사업 주간보고 취합 프롬프트
```
당신은 IT 프로젝트 주간보고 취합 전문가입니다.
아래 개발자들의 주간보고를 사업 단위로 취합하여 정리해주세요.
## 사업 정보
- 사업명: {business_name}
- 사업코드: {business_code}
- 보고 기간: {week_start_date} ~ {week_end_date}
## 소속 프로젝트
{projects_list}
## 개발자 주간보고 원본
{weekly_reports_raw}
## 출력 형식 (JSON)
{
"overall_summary": "전체 요약 (3-5문장)",
"projects": [
{
"project_id": 1,
"project_name": "프로젝트명",
"work_summary": "금주 실적 요약",
"work_details": [
{"task": "작업내용", "assignee": "담당자", "hours": 8}
],
"plan_summary": "차주 계획 요약",
"plan_details": ["계획1", "계획2"],
"issues": ["이슈1", "이슈2"]
}
],
"overall_issues": [
{"issue": "이슈 내용", "action": "대응 방안"}
],
"next_week_schedule": [
{"date": "1/15(수)", "event": "고객사 중간보고"}
],
"statistics": {
"total_members": 3,
"submitted_members": 3,
"total_work_hours": 120,
"completion_rate": 85
}
}
## 규칙
1. 프로젝트별로 실적/계획/이슈를 구분하여 정리
2. 동일 작업은 통합하고 담당자/시간 합산
3. 이슈는 중요도 순으로 정렬
4. 숫자(시간, 진척률 등)는 정확히 유지
5. JSON 외 다른 텍스트 출력 금지
```
---
## 6. 작업 일정
### Phase 1: 사업 CRUD (1.5일) ✅ 완료
- [x] 시작: 2026-01-11 00:28 KST
- [x] 완료: 2026-01-11 00:31 KST
- [x] 소요시간: 3분
**작업 내용:**
- [x] DB 테이블 생성 (wr_business) ✅ 기존 존재
- [x] 사업 CRUD API (매니저 이상 권한) ✅
- [x] 사업 목록/상세/등록/수정 화면 ✅
- [ ] 메뉴 권한 설정 ⏳ 추후
**생성된 파일:**
- backend/api/business/list.get.ts
- backend/api/business/create.post.ts
- backend/api/business/[id]/detail.get.ts
- backend/api/business/[id]/update.put.ts
- backend/api/business/[id]/delete.delete.ts
- frontend/business/index.vue
- frontend/business/[id].vue
---
### Phase 2: 프로젝트-사업 연결 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 프로젝트 테이블에 business_id 컬럼 추가
- [ ] 프로젝트 수정 화면에 사업 선택 추가
- [ ] 프로젝트 배정 API
- [ ] 주간보고 작성 시 사업명 표시
---
### Phase 3: 사업 주간보고 취합 (1.5일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 사업 주간보고 테이블 생성 (wr_business_weekly_report)
- [ ] 사업 주간보고 취합 API (AI 활용)
- [ ] 사업 주간보고 상세 화면
- [ ] 확정 기능
---
### Phase 4: 테스트 및 정리 (0.5일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 전체 플로우 테스트
- [ ] 기존 취합보고와 연계 확인
- [ ] 버그 수정
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | 사업 CRUD | 01-11 00:28 | 01-11 00:31 | 3분 ✅ |
| 2 | 프로젝트-사업 연결 | - | - | - |
| 3 | 사업 주간보고 취합 | - | - | - |
| 4 | 테스트 및 정리 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_business | 신규 테이블 |
| **DB** | wr_business_weekly_report | 신규 테이블 |
| **DB** | wr_project_info | 수정 (business_id 추가) |
| **API** | backend/api/business/*.ts | 신규 |
| **API** | backend/api/business/report/*.ts | 신규 |
| **API** | backend/api/project/[id]/assign-business.put.ts | 신규 |
| **Frontend** | frontend/pages/business/*.vue | 신규 |
| **Frontend** | frontend/pages/project/[id].vue | 수정 |
| **Frontend** | frontend/pages/report/weekly/write.vue | 수정 |
| **Utils** | backend/utils/openai.ts | 수정 (프롬프트 추가) |
---
## 7. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **AI**: OpenAI GPT-4o-mini (취합 요약)
- **인증**: 기존 세션 기반 (requireAuth, requireManager)
---
## 8. 기존 기능과의 관계
| 기존 기능 | 변경 사항 |
|----------|----------|
| 주간보고 작성 | 프로젝트 옆에 사업명 표시 (읽기전용) |
| 프로젝트 관리 | 사업 선택 필드 추가 |
| 전체 취합보고 | 유지 (사업 주간보고와 별개) |
---
## 9. 향후 확장 고려
1. **사업별 대시보드**: 진척률, 투입시간 통계
2. **사업 일정 관리**: 마일스톤, 일정표
3. **사업별 산출물 관리**: 문서, 결과물 링크
4. **고객사 공유**: 사업 주간보고 외부 공유 링크

View File

@@ -0,0 +1,585 @@
# 유지보수 업무 요청/처리 관리 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 5~7일
> 우선순위: 3
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- 기존 엑셀/구글시트로 관리하던 유지보수 업무를 시스템화
- **AI가 다양한 양식의 파일을 파싱** → 표준 형식으로 변환
- 파싱 결과를 사용자가 검토/수정 후 등록
- 처리 완료/진행중 업무 → **주간보고 실적 자동 반영**
### 1.2 플로우
```
[엑셀/구글시트 파일 업로드]
🤖 AI 파싱
(다양한 양식 → 표준 형식)
[검토 화면에 로드]
(사용자가 확인/수정)
[등록]
[상태 관리: 미진행→진행중→완료]
[주간보고 작성 시]
🤖 완료/진행중 업무 → 실적 자동 작성
(유사 실적 있으면 AI가 병합)
```
### 1.3 결정 사항
| # | 항목 | 결정 |
|:-:|------|:----:|
| 1 | 데이터 소스 | 엑셀/구글시트 파일 업로드 |
| 2 | 양식 | 통일 안됨 → AI 파싱 |
| 3 | 파싱 결과 | 검토 화면에서 사용자 확인 후 등록 |
| 4 | 주간보고 연계 | 완료/진행중 → 실적 자동 작성, 유사 건 병합 |
---
## 2. 데이터 모델
### 2.1 유지보수 업무 테이블 (wr_maintenance_task)
```sql
CREATE TABLE wr_maintenance_task (
task_id SERIAL PRIMARY KEY,
-- 프로젝트/사업 연결
project_id INTEGER REFERENCES wr_project_info(project_id),
business_id INTEGER REFERENCES wr_business(business_id),
-- 요청 정보
request_date DATE NOT NULL, -- 접수일자
task_title VARCHAR(300) NOT NULL, -- 제목
task_content TEXT, -- 내용
requester_name VARCHAR(50), -- 요청자
priority VARCHAR(20) DEFAULT 'MEDIUM', -- 우선순위: HIGH/MEDIUM/LOW
-- 처리 정보
assignee_id INTEGER REFERENCES wr_employee_info(employee_id), -- 담당자
task_status VARCHAR(20) DEFAULT 'PENDING', -- 상태
-- PENDING: 미진행, IN_PROGRESS: 진행중, COMPLETED: 완료
completed_date DATE, -- 작업완료일자
-- 반영 여부
is_dev_deployed BOOLEAN DEFAULT false, -- 개발서버 반영
dev_deployed_date DATE,
is_prod_deployed BOOLEAN DEFAULT false, -- 운영서버 반영
prod_deployed_date DATE,
is_customer_confirmed BOOLEAN DEFAULT false, -- 고객 확인
customer_confirmed_date DATE,
-- 주간보고 연계
linked_report_id INTEGER REFERENCES wr_weekly_report(report_id),
linked_task_id INTEGER REFERENCES wr_weekly_report_task(task_id),
-- 업로드 출처
upload_batch_id INTEGER, -- 일괄 업로드 시 배치 ID
source_row_number INTEGER, -- 원본 파일 행 번호
-- 메타
author_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
created_ip VARCHAR(50),
created_email VARCHAR(100),
updated_ip VARCHAR(50),
updated_email VARCHAR(100)
);
-- 인덱스
CREATE INDEX idx_maint_project ON wr_maintenance_task(project_id);
CREATE INDEX idx_maint_business ON wr_maintenance_task(business_id);
CREATE INDEX idx_maint_status ON wr_maintenance_task(task_status);
CREATE INDEX idx_maint_assignee ON wr_maintenance_task(assignee_id);
CREATE INDEX idx_maint_request_date ON wr_maintenance_task(request_date);
CREATE INDEX idx_maint_completed_date ON wr_maintenance_task(completed_date);
```
### 2.2 업로드 배치 테이블 (wr_maintenance_upload_batch)
```sql
CREATE TABLE wr_maintenance_upload_batch (
batch_id SERIAL PRIMARY KEY,
-- 파일 정보
file_name VARCHAR(200) NOT NULL,
file_type VARCHAR(20), -- EXCEL, GOOGLE_SHEET
-- 처리 결과
total_rows INTEGER, -- 전체 행 수
parsed_rows INTEGER, -- 파싱 성공
registered_rows INTEGER, -- 등록 완료
skipped_rows INTEGER, -- 스킵 (중복 등)
-- AI 파싱 원본
ai_parsed_json TEXT, -- AI 파싱 결과 원본
-- 메타
uploaded_by INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
uploaded_at TIMESTAMP DEFAULT NOW()
);
```
---
## 3. API 설계
### 3.1 유지보수 업무 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/maintenance/list | 업무 목록 조회 (필터: 상태, 기간, 프로젝트) |
| GET | /api/maintenance/[id]/detail | 업무 상세 조회 |
| POST | /api/maintenance/create | 업무 직접 등록 |
| PUT | /api/maintenance/[id]/update | 업무 수정 |
| PUT | /api/maintenance/[id]/status | 상태 변경 |
| DELETE | /api/maintenance/[id]/delete | 업무 삭제 |
### 3.2 파일 업로드/AI 파싱 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| POST | /api/maintenance/upload/parse | 파일 업로드 → AI 파싱 |
| POST | /api/maintenance/upload/register | 파싱 결과 검토 후 일괄 등록 |
| GET | /api/maintenance/upload/history | 업로드 이력 조회 |
### 3.3 통계 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/maintenance/stats/weekly | 주간 통계 (요청/처리 건수) |
| GET | /api/maintenance/stats/by-project | 프로젝트별 통계 |
| GET | /api/maintenance/stats/by-assignee | 담당자별 통계 |
### 3.4 주간보고 연계 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/maintenance/for-report | 주간보고용 업무 목록 (완료/진행중) |
| POST | /api/maintenance/link-to-report | 업무 → 주간보고 실적 연계 |
---
## 4. 화면 설계
### 4.1 유지보수 업무 목록 (/maintenance)
```
┌─────────────────────────────────────────────────────────────────┐
│ 유지보수 업무 관리 [파일 업로드] [+ 직접등록] │
├─────────────────────────────────────────────────────────────────┤
│ 프로젝트: [전체 ▼] 상태: [전체 ▼] 기간: [____] ~ [____] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 📊 이번 주 현황: 요청 12건 | 완료 8건 | 진행중 3건 | 미진행 1건 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ 접수일 | 제목 | 요청자 | 담당자 | 상태 | 반영 │
│ ────────────────────────────────────────────────────────────── │
│ 01/10 | 로그인 오류 수정 | 김담당 | 조효성 | ✅완료 | 🟢🟢🟢 │
│ 01/09 | 보고서 양식 변경 | 박과장 | 서혜원 | 🔄진행 | 🟢⚪⚪ │
│ 01/09 | 엑셀 다운로드 추가 | 김담당 | - | ⏳미진행| ⚪⚪⚪ │
│ 01/08 | 대시보드 통계 오류 | 이대리 | 조효성 | ✅완료 | 🟢🟢🟢 │
│ ... │
└─────────────────────────────────────────────────────────────────┘
* 반영: 개발/운영/고객확인 (🟢완료 ⚪미완료)
```
### 4.2 파일 업로드 → AI 파싱 (/maintenance/upload)
```
┌─────────────────────────────────────────────────────────────────┐
│ 유지보수 업무 파일 업로드 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 📁 엑셀 또는 구글시트 파일을 드래그하세요 │ │
│ │ │ │
│ │ [파일 선택] │ │
│ │ │ │
│ │ 지원 형식: .xlsx, .xls, .csv │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ 프로젝트: [PIMS 유지보수 ▼] ← 기본 프로젝트 선택 │
│ │
│ [업로드 및 분석] │
└─────────────────────────────────────────────────────────────────┘
↓ AI 파싱 중... ↓
┌─────────────────────────────────────────────────────────────────┐
│ 🤖 AI 분석 결과 [전체선택] [등록] │
├─────────────────────────────────────────────────────────────────┤
│ 파일: 유지보수현황_202601.xlsx │
│ 분석: 15건 감지 (신규 12건, 중복 3건) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ☑ #1 (신규) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 접수일: 2026-01-10 요청자: 김담당 │ │
│ │ 제목: [로그인 오류 수정__________________________] │ │
│ │ 내용: [세션 만료 후 재로그인 시 오류 발생________] │ │
│ │ 우선순위: [높음 ▼] 담당자: [조효성 ▼] 상태: [완료 ▼] │ │
│ │ 완료일: [2026-01-10] │ │
│ │ 반영: ☑개발 ☑운영 ☑고객확인 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ☑ #2 (신규) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 접수일: 2026-01-09 요청자: 박과장 │ │
│ │ 제목: [보고서 양식 변경__________________________] │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ☐ #3 (⚠️ 중복 - 기존 건과 유사) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 제목: 로그인 문제 수정 │ │
│ │ 💡 유사 건: #1234 "로그인 오류 수정" (01/10 등록) │ │
│ │ [병합] [별도 등록] [스킵] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ [선택 항목 등록 (10건)] │
└─────────────────────────────────────────────────────────────────┘
```
### 4.3 업무 상세/수정 (/maintenance/[id])
```
┌─────────────────────────────────────────────────────────────────┐
│ 유지보수 업무 상세 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ 프로젝트: PIMS 유지보수 │
│ 접수일: 2026-01-10 │
│ 요청자: 김담당 (고객사) │
├─────────────────────────────────────────────────────────────────┤
│ 제목: 로그인 오류 수정 │
│ 우선순위: 🔴 높음 │
├─────────────────────────────────────────────────────────────────┤
│ 내용: │
│ 세션 만료 후 재로그인 시 "잘못된 요청입니다" 오류 발생 │
│ 크롬 브라우저에서만 발생, IE는 정상 │
├─────────────────────────────────────────────────────────────────┤
│ 📋 처리 현황 │
│ ─────────────────────────────────────────────────────────────── │
│ 담당자: 조효성 │
│ 상태: ✅ 완료 (2026-01-10) │
│ │
│ ☑ 개발서버 반영 (2026-01-10) │
│ ☑ 운영서버 반영 (2026-01-10) │
│ ☑ 고객 확인 (2026-01-10) │
├─────────────────────────────────────────────────────────────────┤
│ 🔗 주간보고 연계 │
│ ─────────────────────────────────────────────────────────────── │
│ 연계됨: 2026년 2주차 주간보고 - 조효성 │
│ "PIMS 로그인 세션 오류 수정 (2h)" │
└─────────────────────────────────────────────────────────────────┘
```
### 4.4 주간보고 작성 시 연계
```
┌─────────────────────────────────────────────────────────────────┐
│ 💡 이번 주 처리한 유지보수 업무가 있습니다 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ☑ 로그인 오류 수정 (완료, 01/10) │
│ → 실적 추가: "PIMS 로그인 세션 오류 수정" │
│ → 예상 시간: [2]시간 │
│ │
│ ☑ 대시보드 통계 오류 (완료, 01/08) │
│ → 실적 추가: "대시보드 월별 통계 쿼리 수정" │
│ → 예상 시간: [1]시간 │
│ │
│ ☐ 보고서 양식 변경 (진행중) │
│ → 실적 추가 안함 (진행중은 선택) │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ ⚠️ 유사한 기존 실적이 있습니다: │
│ │
│ "로그인 오류 수정" ↔ 기존: "PIMS 인증 버그 수정 (1h)" │
│ [병합 (3h로 합산)] [별도 유지] [기존 건에 추가] │
│ │
│ [선택 항목 실적에 추가] │
└─────────────────────────────────────────────────────────────────┘
```
### 4.5 통계 대시보드 (/maintenance/stats)
```
┌─────────────────────────────────────────────────────────────────┐
│ 📊 유지보수 업무 통계 │
├─────────────────────────────────────────────────────────────────┤
│ 기간: [2026-01 ▼] 프로젝트: [전체 ▼] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 이번 달 현황 │
│ ┌──────────┬──────────┬──────────┬──────────┐ │
│ │ 총 요청 │ 완료 │ 진행중 │ 미진행 │ │
│ │ 45건 │ 32건 │ 8건 │ 5건 │ │
│ │ │ (71%) │ (18%) │ (11%) │ │
│ └──────────┴──────────┴──────────┴──────────┘ │
│ │
│ 주간 추이 (최근 4주) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 12 ████████████ │ │
│ │ 10 ██████████ ████████ │ │
│ │ 8 ████████ ██████ ████████████ │ │
│ │ 6 ██████ ████ ██████████ │ │
│ │ ────────────────────────────────── │ │
│ │ 1주차 2주차 3주차 4주차 │ │
│ │ ■ 요청 ■ 완료 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 담당자별 처리 현황 │
│ ───────────────────────────────────────────────────────────── │
│ 조효성: ████████████████ 18건 │
│ 서혜원: ████████████ 14건 │
│ 미배정: ████ 5건 │
│ │
│ 평균 처리 시간: 1.8일 │
│ SLA 준수율: 92% (24시간 내 완료 기준) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 5. AI 프롬프트 설계
### 5.1 파일 파싱 프롬프트
```
당신은 엑셀/CSV 파일에서 유지보수 업무 데이터를 추출하는 전문가입니다.
다양한 양식의 파일에서 아래 표준 형식으로 데이터를 변환해주세요.
## 입력 데이터
{file_content_as_text}
## 추출할 필드
- request_date: 접수일자 (YYYY-MM-DD)
- title: 제목/요약
- content: 상세 내용
- requester: 요청자
- priority: 우선순위 (HIGH/MEDIUM/LOW, 긴급/높음→HIGH, 보통/일반→MEDIUM, 낮음→LOW)
- assignee: 담당자
- status: 상태 (PENDING/IN_PROGRESS/COMPLETED)
- 미진행/대기/접수 → PENDING
- 진행/진행중/처리중 → IN_PROGRESS
- 완료/종료/해결 → COMPLETED
- completed_date: 완료일자 (있는 경우)
- is_dev_deployed: 개발 반영 여부 (true/false)
- is_prod_deployed: 운영 반영 여부 (true/false)
- is_customer_confirmed: 고객 확인 여부 (true/false)
## 출력 형식 (JSON)
{
"parsed_rows": [
{
"row_number": 1,
"request_date": "2026-01-10",
"title": "로그인 오류 수정",
"content": "세션 만료 후 재로그인 시 오류",
"requester": "김담당",
"priority": "HIGH",
"assignee": "조효성",
"status": "COMPLETED",
"completed_date": "2026-01-10",
"is_dev_deployed": true,
"is_prod_deployed": true,
"is_customer_confirmed": true,
"confidence": 0.95,
"parse_notes": "정상 파싱"
}
],
"summary": {
"total_rows": 15,
"parsed_successfully": 14,
"parse_failed": 1,
"notes": "1행은 헤더로 스킵"
}
}
## 규칙
1. 헤더 행은 자동 감지하여 스킵
2. 빈 행은 스킵
3. 날짜는 다양한 형식 인식 (01/10, 2026.01.10, 1월10일 등)
4. 상태/우선순위는 유사 표현 매핑
5. 파싱 불확실한 필드는 confidence 낮게, parse_notes에 이유 기재
6. JSON 외 다른 텍스트 출력 금지
```
### 5.2 중복/유사 건 감지 프롬프트
```
당신은 유지보수 업무의 중복/유사 건을 판단하는 전문가입니다.
## 신규 업무
- 제목: {new_title}
- 내용: {new_content}
- 접수일: {new_date}
## 기존 업무 목록
{existing_tasks_json}
## 판단 기준
1. 제목이 80% 이상 유사하면 중복 의심
2. 내용의 핵심 키워드가 동일하면 중복 의심
3. 같은 날짜에 동일 요청자가 등록한 유사 건은 중복 가능성 높음
## 출력 형식 (JSON)
{
"is_duplicate": true,
"similar_task_id": 1234,
"similarity_score": 0.85,
"reason": "제목과 내용이 85% 유사, 동일 요청자",
"recommendation": "MERGE | SKIP | REGISTER_SEPARATE"
}
```
### 5.3 주간보고 실적 생성 프롬프트
```
당신은 유지보수 업무를 주간보고 실적으로 변환하는 전문가입니다.
## 이번 주 처리 업무
{maintenance_tasks_json}
## 기존 주간보고 실적
{existing_report_tasks_json}
## 작업
1. 각 유지보수 업무를 주간보고 실적 문장으로 변환
2. 기존 실적 중 유사한 것이 있으면 병합 제안
3. 예상 소요 시간 추정
## 출력 형식 (JSON)
{
"generated_tasks": [
{
"maintenance_task_id": 123,
"report_description": "PIMS 로그인 세션 오류 수정",
"estimated_hours": 2,
"similar_existing": {
"task_id": 456,
"description": "PIMS 인증 버그 수정",
"merge_recommendation": "MERGE | KEEP_SEPARATE",
"merged_description": "PIMS 로그인/인증 오류 수정",
"merged_hours": 3
}
}
]
}
```
---
## 6. 작업 일정
### Phase 1: 기본 CRUD (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] DB 테이블 생성 (wr_maintenance_task, wr_maintenance_upload_batch)
- [ ] 유지보수 업무 CRUD API
- [ ] 업무 목록/상세/등록/수정 화면
- [ ] 상태 변경 기능
---
### Phase 2: 파일 업로드 + AI 파싱 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 파일 업로드 API (엑셀/CSV)
- [ ] AI 파싱 프롬프트 구현
- [ ] 파싱 결과 검토 화면
- [ ] 중복 감지 로직
- [ ] 일괄 등록 기능
---
### Phase 3: 주간보고 연계 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 주간보고 작성 시 유지보수 업무 조회
- [ ] AI 실적 문장 생성
- [ ] 유사 실적 병합 기능
- [ ] 연계 정보 저장
---
### Phase 4: 통계 + 테스트 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 통계 API (주간/월간/담당자별)
- [ ] 통계 대시보드 화면
- [ ] 전체 테스트 및 버그 수정
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | 기본 CRUD | - | - | - |
| 2 | 파일 업로드 + AI 파싱 | - | - | - |
| 3 | 주간보고 연계 | - | - | - |
| 4 | 통계 + 테스트 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_maintenance_task | 신규 테이블 |
| **DB** | wr_maintenance_upload_batch | 신규 테이블 |
| **API** | backend/api/maintenance/*.ts | 신규 |
| **API** | backend/api/maintenance/upload/*.ts | 신규 |
| **API** | backend/api/maintenance/stats/*.ts | 신규 |
| **Frontend** | frontend/pages/maintenance/*.vue | 신규 |
| **Frontend** | frontend/pages/report/weekly/write.vue | 수정 |
| **Utils** | backend/utils/openai.ts | 수정 (프롬프트 추가) |
| **Utils** | backend/utils/excel-parser.ts | 신규 |
---
## 7. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **파일 처리**: SheetJS (xlsx)
- **AI**: OpenAI GPT-4o-mini (파싱, 중복감지, 실적생성)
- **인증**: 기존 세션 기반 (requireAuth)
---
## 8. 향후 확장 고려
1. **구글 시트 직접 연동**: URL 입력 → API로 직접 읽기
2. **알림 기능**: 긴급 건 등록 시 담당자 알림
3. **SLA 관리**: 처리 기한 설정 및 초과 알림
4. **고객 포털**: 고객이 직접 요청 등록/상태 조회
5. **월간 보고서**: 월별 유지보수 현황 자동 생성

View File

@@ -0,0 +1,529 @@
# Gmail OAuth 로그인 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 5~7일
> 우선순위: 4
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- **Google OAuth + 비밀번호 인증** 모두 지원 (개발/운영 동일)
- Gmail 주소로 기존 사용자(wr_employee_info.email) 매칭
- 매칭 안되면 로그인 거부 → "관리자에게 문의하세요"
- **OAuth 로그인 후 비밀번호 미설정 시 설정 안내**
- **비밀번호 찾기**: 이름+이메일+핸드폰 매칭 → 임시 비밀번호 이메일 발송
### 1.2 로그인 플로우 (개발/운영 동일)
```
┌─────────────────────────────────────────────────────────────────┐
│ 로그인 페이지 │
│ │
│ [G] Google로 로그인 │
│ [S] Synology로 로그인 ← (5번 작업 후 추가) │
│ │
│ ──────────── 또는 ──────────── │
│ │
│ 이메일: [_______________] │
│ 비밀번호: [_______________] │
│ │
│ [로그인] [비밀번호 찾기] │
└─────────────────────────────────────────────────────────────────┘
```
### 1.3 Google OAuth 로그인 플로우
```
[Google로 로그인] 클릭
Google OAuth 인증
Gmail 주소 획득
wr_employee_info.email 매칭?
├─ NO → "등록되지 않은 사용자입니다. 관리자에게 문의하세요."
└─ YES ↓
비밀번호 설정됨?
├─ YES → 메인 페이지로 이동
└─ NO → 비밀번호 설정 페이지
"비상시 로그인을 위해 비밀번호를 설정해주세요"
```
### 1.4 비밀번호 찾기 플로우
```
[비밀번호 찾기] 클릭
┌─────────────────────────────────────┐
│ 이름: [_______________] │
│ 이메일: [_______________] │
│ 핸드폰: [_______________] │
│ │
│ [임시 비밀번호 발송] │
└─────────────────────────────────────┘
세 가지 모두 매칭되는 사용자 확인
├─ 매칭됨 → 이메일로 임시 비밀번호 발송 → "이메일을 확인해주세요"
└─ 불일치 → "일치하는 정보가 없습니다"
```
### 1.5 결정 사항
| # | 항목 | 결정 |
|:-:|------|:----:|
| 1 | 매칭 안되는 Gmail | 로그인 거부, 관리자 문의 안내 |
| 2 | 비밀번호 관리 | 필수 (OAuth 로그인 후 미설정 시 설정 유도) |
| 3 | Google 계정 연결 | 1인 1계정 |
| 4 | 환경별 로그인 | 개발/운영 동일 (OAuth + 비밀번호 모두 지원) |
| 5 | 비밀번호 찾기 | 이름+이메일+핸드폰 매칭 → 임시 비밀번호 이메일 발송 |
---
## 2. 데이터 모델
### 2.1 사용자 테이블 수정 (wr_employee_info)
```sql
-- 기존 테이블에 컬럼 추가
ALTER TABLE wr_employee_info
ADD COLUMN password_hash VARCHAR(200), -- 비밀번호 해시
ADD COLUMN google_id VARCHAR(100), -- Google 고유 ID (sub)
ADD COLUMN google_email VARCHAR(100), -- Google 이메일 (확인용)
ADD COLUMN google_linked_at TIMESTAMP, -- Google 연결 일시
ADD COLUMN last_login_at TIMESTAMP, -- 마지막 로그인
ADD COLUMN last_login_ip VARCHAR(50); -- 마지막 로그인 IP
-- 인덱스
CREATE UNIQUE INDEX idx_employee_google_id ON wr_employee_info(google_id) WHERE google_id IS NOT NULL;
```
### 2.2 로그인 이력 테이블 (wr_login_history) - 선택
```sql
CREATE TABLE wr_login_history (
history_id SERIAL PRIMARY KEY,
employee_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
login_type VARCHAR(20) NOT NULL, -- GOOGLE, PASSWORD
login_ip VARCHAR(50),
user_agent VARCHAR(500),
login_at TIMESTAMP DEFAULT NOW(),
success BOOLEAN DEFAULT true,
fail_reason VARCHAR(200) -- 실패 시 사유
);
CREATE INDEX idx_login_history_employee ON wr_login_history(employee_id);
CREATE INDEX idx_login_history_at ON wr_login_history(login_at);
```
---
## 3. API 설계
### 3.1 인증 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/auth/google | Google OAuth 시작 (리다이렉트) |
| GET | /api/auth/google/callback | Google 콜백 처리 |
| POST | /api/auth/login | 이메일/비밀번호 로그인 |
| POST | /api/auth/logout | 로그아웃 |
| GET | /api/auth/me | 현재 사용자 정보 |
### 3.2 비밀번호 관리 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| POST | /api/auth/set-password | 비밀번호 최초 설정 (OAuth 후) |
| PUT | /api/auth/change-password | 비밀번호 변경 (본인) |
| POST | /api/auth/find-password | 비밀번호 찾기 (임시 비밀번호 발송) |
| PUT | /api/admin/user/[id]/reset-password | 비밀번호 초기화 (관리자) |
---
## 4. 화면 설계
### 4.1 로그인 페이지 (/login)
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 📊 주간보고 시스템 │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ [G] Google로 로그인 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ [S] Synology로 로그인 │ │ ← 5번 작업 후
│ └─────────────────────────────────────┘ │
│ │
│ ─────────────── 또는 ─────────────── │
│ │
│ 이메일: [_________________________] │
│ 비밀번호: [_________________________] │
│ │
│ [로그인] [비밀번호 찾기] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.2 비밀번호 설정 페이지 (/auth/set-password)
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 🔐 비밀번호 설정 │
│ │
│ Google 계정으로 로그인되었습니다. │
│ 비상시 로그인을 위해 비밀번호를 설정해주세요. │
│ │
│ 새 비밀번호: [_________________________] │
│ 비밀번호 확인: [_________________________] │
│ │
│ ※ 8자 이상, 영문+숫자 조합 권장 │
│ │
│ [비밀번호 설정] │
│ │
│ [나중에 설정하기 →] │
│ │
└─────────────────────────────────────────────────────────────────┘
* "나중에 설정하기" 클릭 시 메인으로 이동하지만, 다음 로그인 시 다시 안내
```
### 4.3 비밀번호 찾기 페이지 (/auth/find-password)
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 🔑 비밀번호 찾기 │
│ │
│ 등록된 정보와 일치하면 이메일로 임시 비밀번호를 발송합니다. │
│ │
│ 이름: [_________________________] │
│ 이메일: [_________________________] │
│ 핸드폰: [_________________________] │
│ │
│ [임시 비밀번호 발송] │
│ │
│ [← 로그인으로] │
│ │
└─────────────────────────────────────────────────────────────────┘
↓ 발송 성공 시 ↓
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ✅ 발송 완료 │
│ │
│ 임시 비밀번호가 이메일로 발송되었습니다. │
│ 이메일: hyo****@company.com │
│ │
│ ※ 로그인 후 비밀번호를 변경해주세요. │
│ │
│ [로그인하러 가기] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.4 로그인 실패 시 (매칭 안됨)
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ⚠️ 로그인 실패 │
│ │
│ "unknown@gmail.com"은 등록되지 않은 사용자입니다. │
│ │
│ 시스템 사용을 위해서는 관리자에게 문의하여 │
│ 사용자 등록을 요청해주세요. │
│ │
│ 관리자 연락처: admin@company.com │
│ │
│ [다시 로그인] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.4 마이페이지 - 비밀번호 변경 (/mypage)
```
┌─────────────────────────────────────────────────────────────────┐
│ 마이페이지 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 👤 기본 정보 │
│ ─────────────────────────────────────────────────────────────── │
│ 이름: 조효성 │
│ 이메일: hyosung@company.com │
│ 소속: 개발팀 │
│ 권한: 관리자 │
│ │
│ 🔗 Google 연결 │
│ ─────────────────────────────────────────────────────────────── │
│ 상태: ✅ 연결됨 (hyosung@gmail.com) │
│ 연결일: 2026-01-10 │
│ │
│ 🔒 비밀번호 변경 │
│ ─────────────────────────────────────────────────────────────── │
│ 현재 비밀번호: [_________________________] │
│ 새 비밀번호: [_________________________] │
│ 비밀번호 확인: [_________________________] │
│ │
│ [비밀번호 변경] │
│ │
│ 마지막 로그인: 2026-01-10 09:30 (Google) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.5 관리자 - 사용자 관리 수정 (/admin/user)
```
┌─────────────────────────────────────────────────────────────────┐
│ 사용자 상세 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 기본 정보 │
│ ─────────────────────────────────────────────────────────────── │
│ 이름: 조효성 │
│ 이메일: hyosung@company.com │
│ ... │
│ │
│ 🔐 계정 관리 │
│ ─────────────────────────────────────────────────────────────── │
│ Google 연결: ✅ 연결됨 (hyosung@gmail.com) [연결 해제] │
│ 비밀번호: ******** [초기화] │
│ 마지막 로그인: 2026-01-10 09:30 │
│ │
└─────────────────────────────────────────────────────────────────┘
* [초기화] 클릭 → 임시 비밀번호 생성 → 사용자에게 전달
```
---
## 5. 환경 설정
### 5.1 환경 변수
```env
# .env (공통)
# Google OAuth
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=xxx
GOOGLE_REDIRECT_URI=https://weeklyreport.company.com/api/auth/google/callback
# 이메일 발송 (비밀번호 찾기용)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=noreply@company.com
SMTP_PASS=xxx
SMTP_FROM=주간보고시스템 <noreply@company.com>
```
### 5.2 개발/운영 분기 (필요 시)
```env
# .env.development
GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google/callback
# .env.production
GOOGLE_REDIRECT_URI=https://weeklyreport.company.com/api/auth/google/callback
```
---
## 6. Google OAuth 설정
### 6.1 Google Cloud Console 설정
1. **프로젝트 생성**: Google Cloud Console
2. **OAuth 동의 화면 설정**:
- 앱 이름: 주간보고 시스템
- 범위: email, profile
3. **사용자 인증 정보 생성**:
- OAuth 2.0 클라이언트 ID
- 승인된 리디렉션 URI: `https://weeklyreport.company.com/api/auth/google/callback`
### 6.2 OAuth 흐름
```
1. 사용자 → [Google로 로그인] 클릭
2. 서버 → Google 인증 페이지로 리다이렉트
3. 사용자 → Google 계정 선택, 권한 승인
4. Google → 콜백 URL로 리다이렉트 (code 포함)
5. 서버 → code로 access_token 요청
6. 서버 → access_token으로 사용자 정보 요청
7. 서버 → email로 wr_employee_info 조회
- 있으면: 세션 생성, 로그인 완료
- 없으면: 에러 페이지 표시
```
---
## 7. 보안 고려사항
### 7.1 비밀번호 정책
| 항목 | 정책 |
|------|------|
| 최소 길이 | 8자 이상 |
| 복잡도 | 영문 + 숫자 조합 권장 |
| 해시 알고리즘 | bcrypt (salt rounds: 10) |
| 임시 비밀번호 | 랜덤 생성 (12자, 영문+숫자+특수문자) |
### 7.2 세션 관리
| 항목 | 설정 |
|------|------|
| 세션 유효기간 | 24시간 (또는 설정 가능) |
| 세션 저장소 | 기존 방식 유지 (쿠키/메모리) |
| 동시 로그인 | 허용 (기기별 세션) |
### 7.3 비밀번호 찾기 이메일 템플릿
```
제목: [주간보고시스템] 임시 비밀번호 안내
───────────────────────────────────────
안녕하세요, {이름}님.
요청하신 임시 비밀번호를 안내드립니다.
임시 비밀번호: {임시비밀번호}
보안을 위해 로그인 후 반드시 비밀번호를 변경해주세요.
※ 본 메일은 발신 전용입니다.
※ 본인이 요청하지 않은 경우 관리자에게 문의해주세요.
───────────────────────────────────────
주간보고시스템
```
---
## 8. 작업 일정
### Phase 1: DB + 환경 설정 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] wr_employee_info 컬럼 추가 (password_hash, google_id 등)
- [ ] wr_login_history 테이블 생성 (선택)
- [ ] 환경 변수 설정 (Google OAuth, SMTP)
- [ ] Google Cloud Console OAuth 설정
---
### Phase 2: 비밀번호 인증 (1.5일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] bcrypt 해시 처리
- [ ] 이메일/비밀번호 로그인 API
- [ ] 비밀번호 변경 API
- [ ] 비밀번호 초기화 API (관리자)
---
### Phase 3: Google OAuth (1.5일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] Google OAuth 시작/콜백 API
- [ ] 사용자 매칭 로직 (email 기준)
- [ ] 비밀번호 미설정 시 설정 페이지 리다이렉트
- [ ] 비밀번호 최초 설정 API
---
### Phase 4: 비밀번호 찾기 + 이메일 발송 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 이메일 발송 유틸 (nodemailer)
- [ ] 비밀번호 찾기 API (이름+이메일+핸드폰 매칭)
- [ ] 임시 비밀번호 생성 및 발송
- [ ] 비밀번호 찾기 페이지
---
### Phase 5: 로그인 UI + 테스트 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 로그인 페이지 (OAuth + 비밀번호)
- [ ] 비밀번호 설정 페이지
- [ ] 로그인 실패 페이지
- [ ] 마이페이지 비밀번호 변경 UI
- [ ] 관리자 사용자 관리 수정 (비밀번호 초기화)
- [ ] 전체 플로우 테스트
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | DB + 환경 설정 | - | - | - |
| 2 | 비밀번호 인증 | - | - | - |
| 3 | Google OAuth | - | - | - |
| 4 | 비밀번호 찾기 + 이메일 발송 | - | - | - |
| 5 | 로그인 UI + 테스트 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_employee_info | 수정 (컬럼 추가) |
| **DB** | wr_login_history | 신규 테이블 (선택) |
| **API** | backend/api/auth/google.get.ts | 신규 |
| **API** | backend/api/auth/google/callback.get.ts | 신규 |
| **API** | backend/api/auth/login.post.ts | 수정 |
| **API** | backend/api/auth/set-password.post.ts | 신규 |
| **API** | backend/api/auth/change-password.put.ts | 신규 |
| **API** | backend/api/auth/find-password.post.ts | 신규 |
| **API** | backend/api/admin/user/[id]/reset-password.put.ts | 신규 |
| **Frontend** | frontend/pages/login.vue | 수정 |
| **Frontend** | frontend/pages/auth/set-password.vue | 신규 |
| **Frontend** | frontend/pages/auth/find-password.vue | 신규 |
| **Frontend** | frontend/pages/mypage.vue | 수정 |
| **Frontend** | frontend/pages/admin/user/[id].vue | 수정 |
| **Utils** | backend/utils/password.ts | 신규 |
| **Utils** | backend/utils/email.ts | 신규 |
| **Config** | .env | 수정 (OAuth, SMTP 설정) |
---
## 9. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **OAuth**: Google OAuth 2.0
- **비밀번호**: bcrypt
- **이메일 발송**: nodemailer
- **세션**: 기존 방식 유지
---
## 10. 향후 확장 고려
1. **Synology SSO 연동**: 다음 작업 (5번)
2. **2단계 인증 (2FA)**: TOTP 기반 추가 인증
3. **소셜 로그인 확장**: Microsoft, Kakao 등
4. **비밀번호 만료**: 90일 주기 변경 강제
5. **로그인 알림**: 새 기기 로그인 시 이메일 알림
6. **임시 비밀번호 만료**: 24시간 후 만료 처리

View File

@@ -0,0 +1,557 @@
# Synology SSO 연동 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 2~3일
> 우선순위: 5
> 선행 작업: 4번 (Gmail OAuth 로그인)
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- 사내 Synology NAS의 SSO Server를 통한 로그인
- **4번(Gmail OAuth)과 동일한 구조**로 구현
- Google OAuth와 병행 사용 가능 (사용자 선택)
- Synology 계정 이메일로 기존 사용자 매칭
### 1.2 로그인 페이지
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 📊 주간보고 시스템 │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ [G] Google로 로그인 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ [S] Synology로 로그인 │ │ ← 이번 작업
│ └─────────────────────────────────────┘ │
│ │
│ ─────────────── 또는 ─────────────── │
│ │
│ 이메일: [_________________________] │
│ 비밀번호: [_________________________] │
│ │
│ [로그인] [비밀번호 찾기] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 1.3 Synology SSO 로그인 플로우
```
[Synology로 로그인] 클릭
Synology SSO Server OAuth 인증
Synology 계정 이메일 획득
wr_employee_info.email 매칭?
├─ NO → "등록되지 않은 사용자입니다. 관리자에게 문의하세요."
└─ YES ↓
비밀번호 설정됨?
├─ YES → 메인 페이지로 이동
└─ NO → 비밀번호 설정 페이지
"비상시 로그인을 위해 비밀번호를 설정해주세요"
```
### 1.4 결정 사항
| # | 항목 | 결정 |
|:-:|------|:----:|
| 1 | 매칭 기준 | Synology 계정 이메일 ↔ wr_employee_info.email |
| 2 | 매칭 안됨 | 로그인 거부, 관리자 문의 안내 |
| 3 | 비밀번호 미설정 | 4번과 동일하게 설정 유도 |
| 4 | Google/Synology 동시 연결 | 허용 (1인 1계정씩) |
---
## 2. Synology SSO Server 개요
### 2.1 SSO Server란?
- Synology NAS에서 제공하는 OAuth 2.0 기반 인증 서버
- DSM (DiskStation Manager) 패키지로 설치
- 사내 NAS 계정으로 외부 애플리케이션 로그인 가능
### 2.2 OAuth 2.0 흐름 (Google과 동일)
```
1. 사용자 → [Synology로 로그인] 클릭
2. 서버 → Synology SSO 인증 페이지로 리다이렉트
3. 사용자 → Synology 계정 로그인, 권한 승인
4. Synology → 콜백 URL로 리다이렉트 (code 포함)
5. 서버 → code로 access_token 요청
6. 서버 → access_token으로 사용자 정보 요청
7. 서버 → email로 wr_employee_info 조회
- 있으면: 세션 생성, 로그인 완료
- 없으면: 에러 페이지 표시
```
---
## 3. 데이터 모델
### 3.1 사용자 테이블 수정 (wr_employee_info)
```sql
-- 4번 작업에서 추가한 컬럼에 Synology 관련 컬럼 추가
ALTER TABLE wr_employee_info
ADD COLUMN synology_id VARCHAR(100), -- Synology 고유 ID
ADD COLUMN synology_username VARCHAR(100), -- Synology 사용자명
ADD COLUMN synology_linked_at TIMESTAMP; -- Synology 연결 일시
-- 인덱스
CREATE UNIQUE INDEX idx_employee_synology_id ON wr_employee_info(synology_id) WHERE synology_id IS NOT NULL;
```
### 3.2 최종 사용자 테이블 구조 (4번 + 5번)
```sql
-- wr_employee_info 인증 관련 컬럼 요약
employee_id SERIAL PRIMARY KEY,
...
-- 비밀번호 (4번)
password_hash VARCHAR(200),
-- Google OAuth (4번)
google_id VARCHAR(100),
google_email VARCHAR(100),
google_linked_at TIMESTAMP,
-- Synology SSO (5번)
synology_id VARCHAR(100),
synology_username VARCHAR(100),
synology_linked_at TIMESTAMP,
-- 공통
last_login_at TIMESTAMP,
last_login_ip VARCHAR(50),
last_login_type VARCHAR(20), -- PASSWORD, GOOGLE, SYNOLOGY
...
```
---
## 4. API 설계
### 4.1 Synology SSO API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/auth/synology | Synology OAuth 시작 (리다이렉트) |
| GET | /api/auth/synology/callback | Synology 콜백 처리 |
### 4.2 기존 API와 통합
| Method | Endpoint | 설명 | 비고 |
|--------|----------|------|------|
| GET | /api/auth/me | 현재 사용자 정보 | login_type 포함 |
| POST | /api/auth/logout | 로그아웃 | 공통 |
---
## 5. Synology SSO Server 설정 가이드
### 5.1 SSO Server 패키지 설치
1. **DSM 접속**: `https://nas.company.com:5001` 관리자 계정으로 로그인
2. **패키지 센터** 열기
3. **"SSO Server"** 검색 → **설치**
4. 설치 완료 후 **열기**
```
패키지 센터 > 검색: "SSO Server" > [설치]
```
### 5.2 SSO Server 기본 설정
1. **SSO Server** 앱 열기
2. **설정** 탭 진입
3. 기본 설정 확인:
| 설정 항목 | 권장 값 |
|----------|---------|
| SSO 서비스 활성화 | ✅ 체크 |
| HTTPS 사용 | ✅ 체크 (필수) |
| 포트 | 5001 (기본값) |
### 5.3 애플리케이션 등록
1. **SSO Server** > **애플리케이션**
2. **[추가]** 버튼 클릭
3. 아래 정보 입력:
```
┌─────────────────────────────────────────────────────────────────┐
│ 애플리케이션 추가 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 애플리케이션 이름: [주간보고시스템________________] │
│ │
│ 리디렉션 URI: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ https://weeklyreport.company.com/api/auth/synology/callback │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ※ 개발용 추가 (선택): │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ http://localhost:3000/api/auth/synology/callback │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ [저장] │
└─────────────────────────────────────────────────────────────────┘
```
4. **저장****Client ID / Client Secret** 확인 및 복사
```
┌─────────────────────────────────────────────────────────────────┐
│ 애플리케이션 정보 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 애플리케이션 이름: 주간보고시스템 │
│ │
│ Client ID: abc123def456... [복사] │
│ Client Secret: xyz789ghi012... [복사] │
│ │
│ ※ Client Secret은 다시 볼 수 없으니 반드시 복사해두세요! │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.4 사용자 권한 설정
1. **SSO Server** > **권한**
2. 로그인 허용할 사용자/그룹 선택
```
┌─────────────────────────────────────────────────────────────────┐
│ 권한 설정 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 애플리케이션: 주간보고시스템 │
│ │
│ 허용된 사용자/그룹: │
│ ☑ administrators │
│ ☑ developers │
│ ☑ users │
│ ☐ guests │
│ │
│ ※ 또는 [모든 사용자 허용] 선택 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.5 HTTPS/SSL 인증서 확인
**제어판 > 보안 > 인증서**에서 유효한 SSL 인증서 확인
| 확인 항목 | 필수 여부 |
|----------|:--------:|
| 유효한 SSL 인증서 | ✅ 필수 |
| 인증서 만료일 확인 | ✅ 확인 |
| Let's Encrypt 또는 정식 인증서 | 권장 |
```
※ 자체 서명 인증서(Self-signed)는 브라우저 경고 발생할 수 있음
※ Let's Encrypt 무료 인증서 권장
```
### 5.6 방화벽/포트 설정
외부에서 NAS 접근이 필요한 경우:
| 포트 | 용도 | 필요 여부 |
|:----:|------|:--------:|
| 5001 | DSM HTTPS | ✅ 필수 |
| 443 | 역방향 프록시 사용 시 | 선택 |
```
※ 공유기/방화벽에서 5001 포트 개방 필요
※ 또는 역방향 프록시로 443 → 5001 연결
```
### 5.7 설정 완료 체크리스트
| # | 항목 | 확인 |
|:-:|------|:----:|
| 1 | SSO Server 패키지 설치 | ☐ |
| 2 | SSO 서비스 활성화 | ☐ |
| 3 | 애플리케이션 등록 (주간보고시스템) | ☐ |
| 4 | Client ID 복사 | ☐ |
| 5 | Client Secret 복사 | ☐ |
| 6 | 리디렉션 URI 설정 (운영) | ☐ |
| 7 | 리디렉션 URI 설정 (개발) - 선택 | ☐ |
| 8 | 사용자/그룹 권한 설정 | ☐ |
| 9 | SSL 인증서 유효 확인 | ☐ |
| 10 | 외부 접근 테스트 | ☐ |
### 5.8 설정 후 .env 파일 업데이트
```env
# Synology SSO (5.3에서 복사한 값 입력)
SYNOLOGY_SSO_URL=https://nas.company.com:5001
SYNOLOGY_CLIENT_ID=여기에_Client_ID_붙여넣기
SYNOLOGY_CLIENT_SECRET=여기에_Client_Secret_붙여넣기
SYNOLOGY_REDIRECT_URI=https://weeklyreport.company.com/api/auth/synology/callback
```
---
## 6. 구현 상세
### 6.1 Synology OAuth 엔드포인트
```
# 인증 요청 (Authorization)
GET https://{SYNOLOGY_SSO_URL}/webman/sso/SSOOauth.cgi
?response_type=code
&client_id={CLIENT_ID}
&redirect_uri={REDIRECT_URI}
&scope=user_id
# 토큰 요청 (Token)
POST https://{SYNOLOGY_SSO_URL}/webman/sso/SSOAccessToken.cgi
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code={CODE}
&client_id={CLIENT_ID}
&client_secret={CLIENT_SECRET}
&redirect_uri={REDIRECT_URI}
# 사용자 정보 요청 (UserInfo)
GET https://{SYNOLOGY_SSO_URL}/webman/sso/SSOUserInfo.cgi
?access_token={ACCESS_TOKEN}
```
### 6.2 사용자 정보 응답 예시
```json
{
"data": {
"email": "hyosung@company.com",
"user_id": 1001,
"user_name": "hyosung"
},
"success": true
}
```
### 6.3 API 구현 코드 (예시)
```typescript
// backend/api/auth/synology.get.ts
export default defineEventHandler((event) => {
const config = useRuntimeConfig();
const authUrl = new URL(`${config.synologySsoUrl}/webman/sso/SSOOauth.cgi`);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', config.synologyClientId);
authUrl.searchParams.set('redirect_uri', config.synologyRedirectUri);
authUrl.searchParams.set('scope', 'user_id');
return sendRedirect(event, authUrl.toString());
});
// backend/api/auth/synology/callback.get.ts
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const code = query.code as string;
if (!code) {
return sendRedirect(event, '/login?error=no_code');
}
// 1. Access Token 요청
const tokenResponse = await $fetch(`${config.synologySsoUrl}/webman/sso/SSOAccessToken.cgi`, {
method: 'POST',
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
client_id: config.synologyClientId,
client_secret: config.synologyClientSecret,
redirect_uri: config.synologyRedirectUri,
}),
});
// 2. 사용자 정보 요청
const userInfo = await $fetch(`${config.synologySsoUrl}/webman/sso/SSOUserInfo.cgi`, {
params: { access_token: tokenResponse.access_token },
});
// 3. 이메일로 사용자 매칭
const employee = await findEmployeeByEmail(userInfo.data.email);
if (!employee) {
return sendRedirect(event, '/login?error=not_registered');
}
// 4. Synology 정보 업데이트
await updateEmployeeSynologyInfo(employee.employee_id, {
synology_id: userInfo.data.user_id,
synology_username: userInfo.data.user_name,
});
// 5. 세션 생성
await createSession(event, employee, 'SYNOLOGY');
// 6. 비밀번호 설정 여부 확인
if (!employee.password_hash) {
return sendRedirect(event, '/auth/set-password');
}
return sendRedirect(event, '/');
});
```
---
## 7. 화면 설계
### 7.1 로그인 페이지 수정 (/login)
4번 작업에서 만든 로그인 페이지에 Synology 버튼 추가
```vue
<template>
<div class="login-buttons">
<!-- Google 로그인 -->
<a href="/api/auth/google" class="btn btn-outline-danger btn-lg w-100 mb-2">
<i class="bi bi-google me-2"></i> Google로 로그인
</a>
<!-- Synology 로그인 -->
<a href="/api/auth/synology" class="btn btn-outline-primary btn-lg w-100 mb-3">
<i class="bi bi-hdd-network me-2"></i> Synology로 로그인
</a>
<hr class="my-3">
<!-- 이메일/비밀번호 로그인 -->
...
</div>
</template>
```
### 7.2 마이페이지 수정 (/mypage)
```
┌─────────────────────────────────────────────────────────────────┐
│ 마이페이지 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 👤 기본 정보 │
│ ─────────────────────────────────────────────────────────────── │
│ 이름: 조효성 │
│ 이메일: hyosung@company.com │
│ ... │
│ │
│ 🔗 외부 계정 연결 │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ Google: ✅ 연결됨 (hyosung@gmail.com) [연결 해제] │
│ 연결일: 2026-01-10 │
│ │
│ Synology: ✅ 연결됨 (hyosung) [연결 해제] │
│ 연결일: 2026-01-10 │
│ │
│ 🔒 비밀번호 │
│ ─────────────────────────────────────────────────────────────── │
│ ... │
│ │
│ 마지막 로그인: 2026-01-10 09:30 (Synology) │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 8. 작업 일정
### Phase 1: Synology SSO 설정 + API (1.5일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] Synology SSO Server 애플리케이션 등록
- [ ] wr_employee_info 컬럼 추가 (synology_id 등)
- [ ] 환경 변수 설정
- [ ] Synology OAuth 시작/콜백 API
- [ ] 사용자 매칭 로직
---
### Phase 2: UI + 테스트 (1일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 로그인 페이지에 Synology 버튼 추가
- [ ] 마이페이지 외부 계정 연결 표시
- [ ] 로그인 이력에 login_type 기록
- [ ] 전체 플로우 테스트
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | Synology SSO 설정 + API | - | - | - |
| 2 | UI + 테스트 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_employee_info | 수정 (synology 컬럼 추가) |
| **API** | backend/api/auth/synology.get.ts | 신규 |
| **API** | backend/api/auth/synology/callback.get.ts | 신규 |
| **Frontend** | frontend/pages/login.vue | 수정 |
| **Frontend** | frontend/pages/mypage.vue | 수정 |
| **Config** | .env | 수정 (Synology 설정 추가) |
---
## 9. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **OAuth**: Synology SSO Server (OAuth 2.0)
- **세션**: 기존 방식 유지 (4번과 공유)
---
## 10. 주의사항
### 10.1 Synology SSO Server 요구사항
- DSM 7.0 이상 권장
- SSO Server 패키지 설치 필요
- HTTPS 필수 (유효한 SSL 인증서)
### 10.2 네트워크 설정
- 외부에서 Synology NAS 접근 가능해야 함
- 방화벽에서 5001 포트 (HTTPS) 허용 필요
- 또는 역방향 프록시 설정
### 10.3 개발 환경 제약
- localhost 콜백이 안 될 수 있음
- ngrok 또는 개발용 도메인 필요할 수 있음
---
## 11. 향후 확장 고려
1. **LDAP 연동**: Synology LDAP Server와 통합
2. **그룹 기반 권한**: Synology 그룹 → 시스템 권한 매핑
3. **자동 사용자 생성**: Synology 계정 → 자동 사용자 등록 (관리자 승인)

View File

@@ -0,0 +1,545 @@
# 구글 그룹 연동 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 1~2주
> 우선순위: 6
> 선행 작업: 4번 (Gmail OAuth 로그인)
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- 사용자가 **Google OAuth로 로그인한 상태**에서
- 본인이 속한 **Google 그룹의 게시물 조회** (가져오기)
- 본인 **주간보고를 Google 그룹에 게시** (등록)
- 모두 **그룹 멤버 권한**으로 동작 (관리자 권한 불필요)
### 1.2 권한 구조
```
┌─────────────────────────────────────────────────────────────────┐
│ Google 그룹: developers@company.com │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 멤버들: │
│ ├─ hyosung@company.com (시스템 관리자이기도 함) │
│ ├─ hyewon@company.com │
│ ├─ gildong@company.com │
│ └─ ... │
│ │
│ 멤버라면 누구나: │
│ ✅ 그룹 게시물 읽기 │
│ ✅ 그룹에 글 게시 │
│ │
└─────────────────────────────────────────────────────────────────┘
※ 시스템 관리자 ≠ 그룹 관리자
※ 시스템 관리자도 그냥 그룹 멤버로서 읽기/쓰기
```
### 1.3 기능 요약
| 기능 | 누가 | 설명 |
|------|------|------|
| **가져오기** | 그룹 멤버 | 그룹 게시물 목록/내용 조회 |
| **등록** | 그룹 멤버 | 본인 주간보고 → 그룹에 게시 |
### 1.4 결정 사항
| # | 항목 | 결정 |
|:-:|------|:----:|
| 1 | 권한 | 그룹 멤버 권한만 사용 |
| 2 | 가져오기 | 본인이 속한 그룹 게시물 조회 |
| 3 | 등록 | Gmail API로 그룹 이메일에 발송 |
| 4 | OAuth 연계 | 4번 작업(Gmail OAuth) 토큰 활용 |
---
## 2. 기능 상세
### 2.1 가져오기 (그룹 게시물 조회)
```
[주간보고시스템]
┌─────────────────────────────────────────────────────────────────┐
│ 📬 Google 그룹 게시물 [새로고침] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 그룹 선택: [developers@company.com ▼] │
│ ───────────────────────── │
│ developers@company.com │
│ team-leads@company.com │
│ all@company.com │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 📧 [주간보고] 2026년 2주차 - 서혜원 │
│ hyewon@company.com · 2026-01-10 09:30 │
│ │
│ 📧 [공지] 이번 주 회의 일정 변경 │
│ gildong@company.com · 2026-01-09 14:00 │
│ │
│ 📧 [주간보고] 2026년 2주차 - 홍길동 │
│ gildong@company.com · 2026-01-09 10:00 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**사용 API**: Gmail API (그룹 이메일 검색)
```
GET /gmail/v1/users/me/messages?q=list:developers@company.com
```
### 2.2 등록 (주간보고 → 그룹 게시)
```
[주간보고 상세]
┌─────────────────────────────────────────────────────────────────┐
│ 2026년 2주차 주간보고 - 조효성 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 금주 업무: │
│ - 로그인 기능 개발 완료 │
│ - 사용자 관리 페이지 수정 │
│ ... │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 🔗 Google 그룹 공유 │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ 공유할 그룹: [developers@company.com ▼] │
│ │
│ [📤 그룹에 공유하기] │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ 공유 이력: │
│ ✅ developers@company.com · 2026-01-10 09:30 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**발송되는 이메일 형식**:
```
From: hyosung@company.com (본인)
To: developers@company.com (그룹)
Subject: [주간보고] 2026년 2주차 - 조효성
────────────────────────────────────────
2026년 2주차 주간보고
작성자: 조효성
소속: 개발팀
────────────────────────────────────────
[금주 업무]
- 로그인 기능 개발 완료
- 사용자 관리 페이지 수정
...
[차주 계획]
...
────────────────────────────────────────
※ 주간보고시스템에서 발송됨
```
**사용 API**: Gmail API (메일 발송)
```
POST /gmail/v1/users/me/messages/send
```
---
## 3. 데이터 모델
### 3.1 그룹 공유 이력 테이블
```sql
CREATE TABLE wr_report_group_share (
share_id SERIAL PRIMARY KEY,
report_id INTEGER NOT NULL REFERENCES wr_weekly_report(report_id),
employee_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
group_email VARCHAR(200) NOT NULL, -- developers@company.com
gmail_message_id VARCHAR(100), -- Gmail 메시지 ID
shared_at TIMESTAMP DEFAULT NOW(),
share_status VARCHAR(20) DEFAULT 'SENT', -- SENT, FAILED
error_message TEXT
);
CREATE INDEX idx_report_share_report ON wr_report_group_share(report_id);
CREATE INDEX idx_report_share_employee ON wr_report_group_share(employee_id);
```
### 3.2 사용자 테이블 - OAuth 토큰 저장 (4번 작업 확장)
```sql
-- 4번 작업에서 추가 필요
ALTER TABLE wr_employee_info
ADD COLUMN google_access_token TEXT,
ADD COLUMN google_refresh_token TEXT,
ADD COLUMN google_token_expires_at TIMESTAMP;
```
---
## 4. API 설계
### 4.1 그룹 관련 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/google-group/my-groups | 내가 속한 그룹 목록 |
| GET | /api/google-group/[groupEmail]/messages | 그룹 게시물 목록 |
| GET | /api/google-group/message/[messageId] | 게시물 상세 |
| POST | /api/google-group/share | 주간보고 그룹에 공유 |
| GET | /api/report/[id]/share-history | 공유 이력 조회 |
### 4.2 API 상세
#### GET /api/google-group/my-groups
```json
// Response
{
"groups": [
{ "email": "developers@company.com", "name": "개발팀" },
{ "email": "all@company.com", "name": "전체" }
]
}
```
#### POST /api/google-group/share
```json
// Request
{
"reportId": 123,
"groupEmail": "developers@company.com"
}
// Response
{
"success": true,
"messageId": "18d1234567890abc",
"sharedAt": "2026-01-10T09:30:00Z"
}
```
---
## 5. OAuth Scope 설정
### 5.1 필요한 Scope (4번 작업 확장)
| Scope | 용도 |
|-------|------|
| `openid` | 기본 인증 |
| `email` | 이메일 주소 |
| `profile` | 프로필 정보 |
| **`https://www.googleapis.com/auth/gmail.readonly`** | 그룹 게시물 조회 |
| **`https://www.googleapis.com/auth/gmail.send`** | 그룹에 메일 발송 |
| **`https://www.googleapis.com/auth/gmail.labels`** | 라벨 조회 (선택) |
### 5.2 Google Cloud Console 설정 변경
1. **OAuth 동의 화면** > **범위 추가**
2. Gmail API 관련 scope 추가
3. **민감한 범위**로 분류되어 Google 검토 필요할 수 있음
```
⚠️ 주의: Gmail API scope는 "민감한 범위"로 분류됨
- 앱 인증 필요할 수 있음 (내부용은 대체로 OK)
- Google Workspace 도메인 내 사용 시 관리자 승인으로 해결
```
---
## 6. 화면 설계
### 6.1 메뉴 추가
```
사이드바 메뉴:
├─ 📊 대시보드
├─ 📝 주간보고
│ ├─ 작성
│ ├─ 목록
│ └─ 통계
├─ 📬 Google 그룹 ← 신규
│ └─ 게시물 조회
├─ 👥 사용자 관리
└─ ⚙️ 설정
```
### 6.2 그룹 게시물 조회 (/google-group)
```
┌─────────────────────────────────────────────────────────────────┐
│ 📬 Google 그룹 게시물 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 그룹: [developers@company.com ▼] [새로고침] │
│ │
│ ───────────────────────────────────────────────────────────────│
│ □ 제목 보낸 사람 날짜 │
│ ───────────────────────────────────────────────────────────────│
│ ☐ [주간보고] 2026년 2주차 - 서혜원 서혜원 01-10 09:30 │
│ ☐ [공지] 회의 일정 변경 홍길동 01-09 14:00 │
│ ☐ [주간보고] 2026년 2주차 - 홍길동 홍길동 01-09 10:00 │
│ ☐ [주간보고] 2026년 1주차 - 서혜원 서혜원 01-03 09:00 │
│ ... │
│ │
│ [1] [2] [3] ... [10] │
│ │
└─────────────────────────────────────────────────────────────────┘
※ Google OAuth 미연결 시:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ Google 계정 연결이 필요합니다. │
│ │
│ [Google 계정 연결하기] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 6.3 주간보고 상세 - 그룹 공유 섹션
```
┌─────────────────────────────────────────────────────────────────┐
│ 2026년 2주차 주간보고 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ (주간보고 내용...) │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 📤 Google 그룹 공유 │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ 그룹 선택: [developers@company.com ▼] [공유하기] │
│ │
│ 공유 이력: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ✅ developers@company.com 2026-01-10 09:30 │ │
│ │ ✅ team-leads@company.com 2026-01-10 09:35 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 7. 구현 상세
### 7.1 그룹 목록 조회
Gmail API로는 직접 그룹 목록 조회가 어려움.
대안:
1. **사용자가 직접 입력** (간단)
2. **시스템 설정에서 그룹 목록 관리** (권장)
3. **Directory API 사용** (Google Workspace 필요)
```sql
-- 시스템 설정 테이블에 그룹 목록 저장
CREATE TABLE wr_google_group (
group_id SERIAL PRIMARY KEY,
group_email VARCHAR(200) NOT NULL UNIQUE,
group_name VARCHAR(100),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO wr_google_group (group_email, group_name) VALUES
('developers@company.com', '개발팀'),
('team-leads@company.com', '팀장단'),
('all@company.com', '전체');
```
### 7.2 그룹 게시물 조회 로직
```typescript
// Gmail API로 특정 그룹 메일 검색
async function getGroupMessages(accessToken: string, groupEmail: string) {
const response = await fetch(
`https://gmail.googleapis.com/gmail/v1/users/me/messages?q=list:${groupEmail}`,
{
headers: { Authorization: `Bearer ${accessToken}` }
}
);
const data = await response.json();
return data.messages; // [{id, threadId}, ...]
}
// 메시지 상세 조회
async function getMessage(accessToken: string, messageId: string) {
const response = await fetch(
`https://gmail.googleapis.com/gmail/v1/users/me/messages/${messageId}`,
{
headers: { Authorization: `Bearer ${accessToken}` }
}
);
return response.json();
}
```
### 7.3 그룹에 메일 발송 로직
```typescript
async function sendToGroup(accessToken: string, to: string, subject: string, body: string) {
const email = [
`To: ${to}`,
`Subject: =?UTF-8?B?${Buffer.from(subject).toString('base64')}?=`,
'Content-Type: text/plain; charset=UTF-8',
'',
body
].join('\r\n');
const encodedEmail = Buffer.from(email)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
const response = await fetch(
'https://gmail.googleapis.com/gmail/v1/users/me/messages/send',
{
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ raw: encodedEmail })
}
);
return response.json();
}
```
---
## 8. 작업 일정
### Phase 1: OAuth Scope 확장 + 토큰 저장 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] Google Cloud Console OAuth scope 추가
- [ ] wr_employee_info에 토큰 저장 컬럼 추가
- [ ] OAuth 콜백에서 access/refresh 토큰 저장
- [ ] 토큰 갱신 로직
---
### Phase 2: 그룹 게시물 조회 (3일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] wr_google_group 테이블 생성
- [ ] 그룹 목록 API
- [ ] 그룹 게시물 목록 API (Gmail API 연동)
- [ ] 게시물 상세 API
- [ ] 그룹 게시물 조회 페이지
---
### Phase 3: 주간보고 그룹 공유 (3일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] wr_report_group_share 테이블 생성
- [ ] 그룹 공유 API (Gmail 발송)
- [ ] 공유 이력 API
- [ ] 주간보고 상세에 공유 UI 추가
- [ ] 이메일 본문 템플릿
---
### Phase 4: 테스트 + 마무리 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 전체 플로우 테스트
- [ ] 토큰 만료 시 갱신 테스트
- [ ] 오류 처리 (권한 없음, 그룹 미가입 등)
- [ ] 관리자 - 그룹 목록 관리 페이지
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | OAuth Scope 확장 + 토큰 저장 | - | - | - |
| 2 | 그룹 게시물 조회 | - | - | - |
| 3 | 주간보고 그룹 공유 | - | - | - |
| 4 | 테스트 + 마무리 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_employee_info | 수정 (토큰 컬럼 추가) |
| **DB** | wr_google_group | 신규 테이블 |
| **DB** | wr_report_group_share | 신규 테이블 |
| **API** | backend/api/google-group/my-groups.get.ts | 신규 |
| **API** | backend/api/google-group/[groupEmail]/messages.get.ts | 신규 |
| **API** | backend/api/google-group/message/[id].get.ts | 신규 |
| **API** | backend/api/google-group/share.post.ts | 신규 |
| **API** | backend/api/report/[id]/share-history.get.ts | 신규 |
| **Frontend** | frontend/pages/google-group/index.vue | 신규 |
| **Frontend** | frontend/pages/report/[id].vue | 수정 (공유 UI) |
| **Utils** | backend/utils/gmail-api.ts | 신규 |
| **Utils** | backend/utils/google-token.ts | 신규 |
---
## 9. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **외부 API**: Gmail API v1
- **인증**: OAuth 2.0 (4번 작업 확장)
---
## 10. 주의사항
### 10.1 Gmail API 제한
- **일일 할당량**: 사용자당 250개 할당량 단위/일
- **메일 발송**: 건당 100 할당량 단위
- 대량 발송 시 제한 주의
### 10.2 민감한 Scope
- Gmail readonly/send는 "민감한 범위"
- Google Workspace 내부 앱은 관리자 승인으로 해결
### 10.3 토큰 보안
- access_token, refresh_token 암호화 저장 권장
- HTTPS 필수
---
## 11. 향후 확장 고려
1. **게시물 시스템 연동**: 그룹 게시물 → 회의록/공지사항으로 저장
2. **자동 공유**: 주간보고 확정 시 자동으로 그룹 공유
3. **그룹별 자동 선택**: 프로젝트 → 그룹 매핑으로 자동 선택
4. **공유 알림**: 그룹 공유 시 시스템 알림

View File

@@ -0,0 +1,723 @@
# SVN/Git 커밋 내역 연동 작업계획서
> 작성일: 2026-01-10
> 예상 기간: 2~3주
> 우선순위: 7
> 선행 작업: 2번 (사업-프로젝트 계층 구조)
---
## 1. 기능 개요
### 1.1 핵심 컨셉
- 프로젝트별 **SVN/Git 저장소 주소 관리** (다중 가능)
- 해당 주차 **커밋 이력 자동 수집**
- 주간보고 작성 시 **커밋 코멘트 참고용 표시**
- 작성자가 커밋 내용 보고 업무 내용 작성에 활용
### 1.2 전체 흐름
```
[관리자/PM - 프로젝트 설정]
프로젝트별 저장소 주소 등록
[시스템 - 자동 수집]
주기적으로 커밋 이력 수집 (Cron)
[개발자 - 주간보고 작성]
해당 주차 본인 커밋 내역 참고하며 작성
```
### 1.3 결정 사항
| # | 항목 | 결정 |
|:-:|------|:----:|
| 1 | 저장소 타입 | SVN, Git 둘 다 지원 |
| 2 | 저장소 개수 | 프로젝트당 다중 저장소 가능 |
| 3 | 수집 방식 | **하이브리드**: 스케줄(1일1회) + 새로고침 버튼 |
| 4 | VCS 아이디 관리 | **도메인(서버) 단위**로 사용자별 아이디 관리 |
| 5 | 커밋 매칭 | VCS 서버 + 아이디 → 시스템 사용자 매칭 |
| 6 | 용도 | 참고용 표시 (자동 입력 X) |
| 7 | 조회 화면 | 프로젝트별 VCS 주소 기준 커밋 조회 |
---
## 2. 데이터 모델
### 2.1 VCS 서버 테이블 (도메인 단위)
```sql
-- VCS 서버 (도메인) 관리
CREATE TABLE wr_vcs_server (
server_id SERIAL PRIMARY KEY,
server_type VARCHAR(10) NOT NULL, -- SVN, GIT
server_url VARCHAR(300) NOT NULL, -- github.com, svn://192.168.1.100
server_name VARCHAR(100), -- 표시용 이름 (예: "사내 SVN", "GitHub")
description TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(server_url)
);
-- 예시 데이터
INSERT INTO wr_vcs_server (server_type, server_url, server_name) VALUES
('GIT', 'github.com', 'GitHub'),
('GIT', 'gitlab.company.com', '사내 GitLab'),
('SVN', 'svn://192.168.1.100', '사내 SVN');
```
### 2.2 사용자별 VCS 계정 테이블
```sql
-- 사용자별 VCS 서버 계정 (도메인별로 아이디 관리)
CREATE TABLE wr_employee_vcs_account (
account_id SERIAL PRIMARY KEY,
employee_id INTEGER NOT NULL REFERENCES wr_employee_info(employee_id),
server_id INTEGER NOT NULL REFERENCES wr_vcs_server(server_id),
vcs_username VARCHAR(100) NOT NULL, -- SVN/Git 사용자명
vcs_email VARCHAR(100), -- Git 커밋 이메일 (Git만 해당)
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(employee_id, server_id) -- 사용자당 서버별 1개
);
CREATE INDEX idx_vcs_account_employee ON wr_employee_vcs_account(employee_id);
CREATE INDEX idx_vcs_account_server ON wr_employee_vcs_account(server_id);
```
### 2.3 저장소 정보 테이블
```sql
-- 프로젝트별 저장소 (VCS 서버 하위)
CREATE TABLE wr_repository (
repo_id SERIAL PRIMARY KEY,
project_id INTEGER NOT NULL REFERENCES wr_project_info(project_id),
server_id INTEGER NOT NULL REFERENCES wr_vcs_server(server_id),
repo_name VARCHAR(100), -- 표시용 이름
repo_path VARCHAR(500) NOT NULL, -- 저장소 경로 (예: /company/frontend.git, /pims/trunk)
branch_name VARCHAR(100), -- Git: 브랜치명 (기본: main)
is_active BOOLEAN DEFAULT true,
last_sync_at TIMESTAMP,
last_sync_status VARCHAR(20), -- SUCCESS, FAILED
last_sync_message TEXT,
created_at TIMESTAMP DEFAULT NOW(),
created_by INTEGER REFERENCES wr_employee_info(employee_id)
);
CREATE INDEX idx_repository_project ON wr_repository(project_id);
CREATE INDEX idx_repository_server ON wr_repository(server_id);
-- 전체 URL = wr_vcs_server.server_url + wr_repository.repo_path
-- 예: github.com + /company/frontend.git = github.com/company/frontend.git
```
### 2.4 커밋 이력 테이블
```sql
CREATE TABLE wr_commit_log (
commit_id SERIAL PRIMARY KEY,
repo_id INTEGER NOT NULL REFERENCES wr_repository(repo_id),
commit_hash VARCHAR(100) NOT NULL, -- Git: SHA, SVN: revision
commit_message TEXT,
commit_author VARCHAR(200), -- 커밋 작성자 (원본)
commit_email VARCHAR(200), -- 커밋 이메일 (Git)
commit_date TIMESTAMP NOT NULL,
employee_id INTEGER REFERENCES wr_employee_info(employee_id), -- 매칭된 사용자
files_changed INTEGER,
insertions INTEGER,
deletions INTEGER,
synced_at TIMESTAMP DEFAULT NOW(),
UNIQUE(repo_id, commit_hash)
);
CREATE INDEX idx_commit_repo ON wr_commit_log(repo_id);
CREATE INDEX idx_commit_date ON wr_commit_log(commit_date);
CREATE INDEX idx_commit_employee ON wr_commit_log(employee_id);
```
### 2.5 데이터 관계도
```
┌─────────────────┐
│ wr_vcs_server │ (도메인 단위: github.com, svn://192.168.1.100)
└────────┬────────┘
┌────┴────┐
↓ ↓
┌─────────┐ ┌──────────────────────┐
│wr_repos │ │wr_employee_vcs_account│
│itory │ │ (사용자별 도메인 아이디)│
└────┬────┘ └──────────────────────┘
┌──────────────┐
│wr_commit_log │ (커밋 이력)
└──────────────┘
```
---
## 3. API 설계
### 3.1 VCS 서버 관리 API (관리자)
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/vcs-server | VCS 서버 목록 |
| POST | /api/vcs-server | VCS 서버 추가 |
| PUT | /api/vcs-server/[id] | VCS 서버 수정 |
| DELETE | /api/vcs-server/[id] | VCS 서버 삭제 |
### 3.2 사용자 VCS 계정 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/my/vcs-accounts | 내 VCS 계정 목록 |
| POST | /api/my/vcs-account | VCS 계정 등록/수정 |
| DELETE | /api/my/vcs-account/[serverId] | VCS 계정 삭제 |
### 3.3 저장소 관리 API
| Method | Endpoint | 설명 | 권한 |
|--------|----------|------|:----:|
| GET | /api/project/[id]/repositories | 프로젝트 저장소 목록 | 멤버 |
| POST | /api/project/[id]/repository | 저장소 추가 | PM+ |
| PUT | /api/repository/[id] | 저장소 수정 | PM+ |
| DELETE | /api/repository/[id] | 저장소 삭제 | PM+ |
| POST | /api/repository/[id]/sync | 수동 동기화 | PM+ |
### 3.4 커밋 조회 API
| Method | Endpoint | 설명 |
|--------|----------|------|
| GET | /api/project/[id]/commits | 프로젝트 커밋 목록 (필터: 기간, 작성자) |
| GET | /api/commits/my-weekly | 내 이번 주 커밋 (주간보고용) |
| POST | /api/project/[id]/commits/refresh | 최신 커밋 새로고침 |
---
## 4. 화면 설계
### 4.1 관리자 - VCS 서버 관리 (/admin/vcs-server)
```
┌─────────────────────────────────────────────────────────────────┐
│ ⚙️ VCS 서버 관리 [+ 서버 추가] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🟢 [Git] GitHub │ │
│ │ github.com │ │
│ │ [수정] [삭제] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🟢 [Git] 사내 GitLab │ │
│ │ gitlab.company.com │ │
│ │ [수정] [삭제] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🔶 [SVN] 사내 SVN │ │
│ │ svn://192.168.1.100 │ │
│ │ [수정] [삭제] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.2 마이페이지 - VCS 계정 설정
```
┌─────────────────────────────────────────────────────────────────┐
│ 마이페이지 > VCS 계정 설정 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ※ 커밋 내역 조회 시 아래 정보로 본인 커밋을 찾습니다. │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ 🟢 GitHub (github.com) │
│ 사용자명: [hyosung_______________] │
│ 이메일: [hyosung@gmail.com_____] │
│ │
│ 🟢 사내 GitLab (gitlab.company.com) │
│ 사용자명: [cho.hyosung___________] │
│ 이메일: [hyosung@company.com___] │
│ │
│ 🔶 사내 SVN (svn://192.168.1.100) │
│ 사용자명: [hyosung_______________] │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ [저장] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.3 프로젝트 상세 - 저장소 관리
```
┌─────────────────────────────────────────────────────────────────┐
│ 프로젝트: PIMS 시스템 [수정] [삭제] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 📋 기본 정보 │
│ ... │
│ │
│ 📁 저장소 관리 [+ 저장소 추가]│
│ ─────────────────────────────────────────────────────────────── │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🔶 [SVN] 메인 저장소 │ │
│ │ 사내 SVN > /pims/trunk │ │
│ │ 마지막 동기화: 2026-01-10 06:00 ✅ │ │
│ │ [동기화] [수정] [삭제] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🟢 [Git] Frontend │ │
│ │ GitHub > /company/pims-frontend.git (main) │ │
│ │ 마지막 동기화: 2026-01-10 06:00 ✅ │ │
│ │ [동기화] [수정] [삭제] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🟢 [Git] Backend │ │
│ │ GitHub > /company/pims-backend.git (main) │ │
│ │ 마지막 동기화: 2026-01-10 06:00 ✅ │ │
│ │ [동기화] [수정] [삭제] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ [📊 커밋 내역 보기] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.4 프로젝트 커밋 조회 (/project/[id]/commits)
```
┌─────────────────────────────────────────────────────────────────┐
│ 📊 PIMS 시스템 - 커밋 내역 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 기간: [2026-01-06] ~ [2026-01-10] │
│ 저장소: [전체 ▼] 작성자: [전체 ▼] │
│ [검색] [🔄 새로고침] │
│ │
│ ───────────────────────────────────────────────────────────────│
│ 날짜 저장소 작성자 메시지 │
│ ───────────────────────────────────────────────────────────────│
│ 01-10 14:30 [Git] Frontend 조효성 로그인 버그 수정 │
│ 01-10 11:00 [Git] Backend 조효성 OAuth 콜백 처리 │
│ 01-10 09:00 [Git] Frontend 서혜원 대시보드 차트 수정 │
│ 01-09 16:00 [SVN] 메인 r1234 조효성 사용자 관리 수정 │
│ 01-09 14:00 [Git] Backend 홍길동 API 엔드포인트 추가│
│ 01-08 10:30 [SVN] 메인 r1233 조효성 DB 스키마 변경 │
│ ... │
│ │
│ ───────────────────────────────────────────────────────────────│
│ 이번 주 커밋: 총 25건 | +1,234줄 / -456줄 │
│ │
│ [1] [2] [3] ... [5] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.5 주간보고 작성 - 커밋 내역 참고
```
┌─────────────────────────────────────────────────────────────────┐
│ 📝 주간보고 작성 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 연도/주차: [2026] 년 [2] 주차 │
│ 프로젝트: [PIMS 시스템 ▼] │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ 📋 이번 주 내 커밋 (참고용) [🔄 새로고침]│
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 01-10 금 14:30 [Git-Frontend] 로그인 기능 버그 수정 │ │
│ │ │ │
│ │ 01-10 금 11:00 [Git-Backend] OAuth 콜백 처리 추가 │ │
│ │ │ │
│ │ 01-09 목 16:00 [SVN] r1234 사용자 관리 페이지 수정 │ │
│ │ │ │
│ │ 01-08 수 10:30 [SVN] r1233 DB 스키마 변경 │ │
│ │ │ │
│ │ ─────────────────────────────────────── │ │
│ │ 총 4건 | +156줄 / -42줄 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ※ VCS 계정 미등록 시: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ VCS 계정이 등록되지 않았습니다. │ │
│ │ [마이페이지 > VCS 계정 설정]에서 등록해주세요. │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ 금주 업무: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ (위 커밋 내역 참고하여 작성) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 5. 커밋 수집 로직
### 5.1 수집 방식 (하이브리드)
```
┌─────────────────────────────────────────────────────────────────┐
│ 커밋 수집 방식 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [자동 스케줄] │
│ └─ 매일 새벽 6시 Cron으로 전체 저장소 동기화 │
│ └─ 수집된 커밋 → wr_commit_log 테이블에 저장 │
│ │
│ [주간보고 작성 시] │
│ └─ DB에서 바로 조회 (빠름!) │
│ │
│ [새로고침 버튼] │
│ └─ 해당 프로젝트 저장소만 최신 동기화 │
│ └─ 방금 커밋한 내용도 확인 가능 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.2 작성자 매칭 로직
```typescript
// 커밋 작성자 → 시스템 사용자 매칭
async function matchCommitAuthor(
serverId: number,
commitAuthor: string, // 커밋 작성자명
commitEmail: string // 커밋 이메일 (Git)
): Promise<number | null> {
// VCS 계정 테이블에서 매칭
// 같은 서버에서 username 또는 email이 일치하는 사용자 찾기
const matched = await db.query(`
SELECT e.employee_id
FROM wr_employee_vcs_account a
JOIN wr_employee_info e ON a.employee_id = e.employee_id
WHERE a.server_id = $1
AND (a.vcs_username = $2 OR a.vcs_email = $3)
`, [serverId, commitAuthor, commitEmail]);
if (matched.rows.length > 0) {
return matched.rows[0].employee_id;
}
return null; // 매칭 실패
}
```
### 5.2 Git 커밋 수집
```typescript
// simple-git 라이브러리 사용
import simpleGit from 'simple-git';
async function syncGitCommits(repo: Repository) {
const git = simpleGit();
// 임시 디렉토리에 clone 또는 pull
const repoPath = `/tmp/repos/${repo.repo_id}`;
if (existsSync(repoPath)) {
await git.cwd(repoPath).pull();
} else {
await git.clone(repo.repo_url, repoPath, ['--branch', repo.branch_name]);
}
// 최근 커밋 조회 (마지막 동기화 이후)
const logs = await git.cwd(repoPath).log({
'--since': repo.last_sync_at || '1 week ago',
'--format': '%H|%an|%ae|%aI|%s'
});
// DB에 저장
for (const commit of logs.all) {
await saveCommit({
repo_id: repo.repo_id,
commit_hash: commit.hash,
commit_message: commit.message,
commit_author: commit.author_email,
commit_date: commit.date,
// ...
});
}
}
```
### 5.3 SVN 커밋 수집
```typescript
// svn 명령어 실행
import { exec } from 'child_process';
async function syncSvnCommits(repo: Repository) {
const since = repo.last_sync_at
? `{${repo.last_sync_at.toISOString()}}`
: 'HEAD-100';
const command = `svn log ${repo.repo_url} -r ${since}:HEAD --xml`;
// 인증 정보 추가
if (repo.auth_username) {
command += ` --username ${repo.auth_username} --password ${repo.auth_credential}`;
}
const result = await execPromise(command);
const logs = parseXml(result); // XML 파싱
for (const entry of logs) {
await saveCommit({
repo_id: repo.repo_id,
commit_hash: entry.revision,
commit_message: entry.msg,
commit_author: entry.author,
commit_date: entry.date,
});
}
}
```
### 5.5 서버 인증 정보 관리
VCS 서버 접근 시 필요한 인증 정보 (서버 레벨)
```sql
-- VCS 서버에 인증 정보 추가 (필요 시)
ALTER TABLE wr_vcs_server
ADD COLUMN auth_type VARCHAR(20) DEFAULT 'NONE', -- NONE, BASIC, TOKEN, SSH_KEY
ADD COLUMN auth_username VARCHAR(100),
ADD COLUMN auth_credential TEXT; -- 암호화 저장
```
※ 공개 저장소는 인증 불필요
※ 사내 SVN/GitLab은 서버 레벨 인증 또는 사용자별 인증 선택
---
## 6. 환경 설정
### 6.1 필요 패키지
```bash
# Git 연동
npm install simple-git
# SVN 연동 (시스템에 svn 명령어 필요)
# Ubuntu: apt install subversion
# macOS: brew install svn
```
### 6.2 환경 변수
```env
# 커밋 수집 설정
COMMIT_SYNC_ENABLED=true
COMMIT_SYNC_CRON=0 6 * * * # 매일 새벽 6시
COMMIT_SYNC_TEMP_DIR=/tmp/repos # 임시 저장소 디렉토리
# 보안 (인증 정보 암호화 키)
REPO_CREDENTIAL_SECRET=your-secret-key
```
---
## 7. 보안 고려사항
### 7.1 인증 정보 보안
| 항목 | 처리 방식 |
|------|----------|
| 비밀번호/토큰 | AES-256 암호화 저장 |
| SSH 키 | 파일로 저장, 권한 제한 (600) |
| 환경 변수 | 민감 정보 노출 방지 |
### 7.2 접근 권한
| 역할 | 권한 |
|------|------|
| 관리자 | 모든 저장소 관리, 전체 커밋 조회 |
| PM | 담당 프로젝트 저장소 관리 |
| 멤버 | 본인 커밋만 조회 |
---
## 8. 작업 일정
### Phase 1: DB + VCS 서버/계정 관리 (3일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] wr_vcs_server 테이블 생성
- [ ] wr_employee_vcs_account 테이블 생성
- [ ] wr_repository 테이블 생성
- [ ] wr_commit_log 테이블 생성
- [ ] VCS 서버 관리 API + UI (관리자)
- [ ] 마이페이지 VCS 계정 설정 UI
---
### Phase 2: 저장소 관리 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 저장소 CRUD API
- [ ] 프로젝트 상세에 저장소 관리 UI
- [ ] 저장소 추가/수정 모달
---
### Phase 3: Git 커밋 수집 (3일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] simple-git 연동
- [ ] Git 커밋 수집 로직
- [ ] 작성자 매칭 (VCS 계정 기반)
- [ ] 수동 동기화 API
---
### Phase 4: SVN 커밋 수집 (3일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] SVN 명령어 연동
- [ ] SVN 커밋 수집 로직
- [ ] XML 파싱
- [ ] 작성자 매칭
---
### Phase 5: 커밋 조회 화면 (3일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] 프로젝트별 커밋 조회 API
- [ ] 프로젝트 커밋 조회 페이지 (/project/[id]/commits)
- [ ] 주간보고 작성 시 커밋 참고 UI
- [ ] 새로고침 버튼 (최신 동기화)
---
### Phase 6: 자동화 + 테스트 (2일)
- [ ] 시작:
- [ ] 완료:
- [ ] 소요시간:
**작업 내용:**
- [ ] Cron Job 설정 (매일 새벽 자동 동기화)
- [ ] 인증 정보 암호화
- [ ] 전체 플로우 테스트
- [ ] 오류 처리
---
## 작업 완료 결과
### Phase별 작업 시간
| Phase | 작업 내용 | 시작 | 완료 | 소요시간 |
|:-----:|----------|:----:|:----:|:--------:|
| 1 | DB + VCS 서버/계정 관리 | - | - | - |
| 2 | 저장소 관리 | - | - | - |
| 3 | Git 커밋 수집 | - | - | - |
| 4 | SVN 커밋 수집 | - | - | - |
| 5 | 커밋 조회 화면 | - | - | - |
| 6 | 자동화 + 테스트 | - | - | - |
| | | | **총 소요시간** | **-** |
---
### 생성/수정된 파일
| 구분 | 파일 | 작업 |
|------|------|:----:|
| **DB** | wr_vcs_server | 신규 테이블 |
| **DB** | wr_employee_vcs_account | 신규 테이블 |
| **DB** | wr_repository | 신규 테이블 |
| **DB** | wr_commit_log | 신규 테이블 |
| **API** | backend/api/vcs-server/* | 신규 (CRUD) |
| **API** | backend/api/my/vcs-accounts.get.ts | 신규 |
| **API** | backend/api/my/vcs-account.post.ts | 신규 |
| **API** | backend/api/project/[id]/repositories.get.ts | 신규 |
| **API** | backend/api/project/[id]/repository.post.ts | 신규 |
| **API** | backend/api/repository/[id].put.ts | 신규 |
| **API** | backend/api/repository/[id]/sync.post.ts | 신규 |
| **API** | backend/api/project/[id]/commits.get.ts | 신규 |
| **API** | backend/api/project/[id]/commits/refresh.post.ts | 신규 |
| **API** | backend/api/commits/my-weekly.get.ts | 신규 |
| **Frontend** | frontend/pages/admin/vcs-server.vue | 신규 |
| **Frontend** | frontend/pages/mypage.vue | 수정 (VCS 계정) |
| **Frontend** | frontend/pages/project/[id].vue | 수정 (저장소 관리) |
| **Frontend** | frontend/pages/project/[id]/commits.vue | 신규 |
| **Frontend** | frontend/pages/report/write.vue | 수정 (커밋 참고) |
| **Backend** | backend/services/git-sync.ts | 신규 |
| **Backend** | backend/services/svn-sync.ts | 신규 |
| **Backend** | backend/jobs/commit-sync.ts | 신규 (Cron) |
| **Utils** | backend/utils/crypto.ts | 신규 (암호화) |
---
## 9. 기술 스택
- **Backend**: Nitro (H3) + PostgreSQL
- **Frontend**: Nuxt3 + Vue3 + Bootstrap 5
- **Git 연동**: simple-git (npm 패키지)
- **SVN 연동**: svn CLI (시스템 명령어)
- **스케줄링**: node-cron 또는 시스템 crontab
- **암호화**: crypto (Node.js 내장)
---
## 10. 주의사항
### 10.1 서버 환경
- SVN 사용 시 서버에 `svn` 명령어 설치 필요
- Git 사용 시 서버에 `git` 명령어 설치 필요
- 임시 디렉토리 용량 관리 필요
### 10.2 네트워크
- 내부 SVN 서버 접근 가능해야 함
- GitHub/GitLab 등 외부 서비스 접근 가능해야 함
- 방화벽 설정 확인
### 10.3 성능
- 대용량 저장소는 shallow clone 고려
- 커밋 수집 시 서버 부하 주의 (새벽 실행 권장)
---
## 11. 향후 확장 고려
1. **AI 연동**: 커밋 메시지 → 주간보고 자동 생성 초안
2. **코드 통계**: 라인 수, 파일 수 통계 대시보드
3. **커밋-업무 연결**: 커밋을 특정 업무 항목에 연결
4. **GitLab/GitHub API**: CLI 대신 API 직접 연동
5. **WebHook**: Push 이벤트 시 실시간 수집