## 🚨 보안 강화 - 하드코딩된 비밀번호를 환경변수로 전환 - .env.example 생성 및 보안 가이드 추가 - docker-compose.yml 환경변수 적용 - README.md에서 실제 비밀번호 제거 ## 🗑️ 중복 제거 - synology_deployment/ 디렉토리 제거 (268MB) - synology_deployment*.tar.gz 아카이브 제거 (234MB) - 총 502MB의 중복 파일 삭제 ## 🧹 백업 파일 정리 - *.backup 파일 제거 (10개) - *복사본* 파일 제거 - *이전* 파일 제거 - json(백업)/ 디렉토리 제거 ## 📋 .gitignore 업데이트 - 백업 파일 패턴 추가 - 보안 파일 제외 (.env, *.pem, *.key) - 임시 파일 제외 (*.tmp, *.new) - 빌드 아티팩트 제외 (*.tar.gz) ## 📚 문서화 - docs/ 디렉토리 구조 생성 - 리팩토링 분석 및 계획 문서 작성 - 코딩 스타일 가이드 작성 - 개발 환경 설정 가이드 작성 - 시스템 아키텍처 문서 작성 ## 변경된 파일 - .env.example (신규) - .gitignore (업데이트) - docker-compose.yml (환경변수 적용) - README.md (보안 정보 제거) - docs/* (신규 문서 7개) ## 보안 개선 효과 ✅ 비밀번호 노출 위험 제거 ✅ Git 히스토리에서 민감 정보 분리 ✅ 환경별 설정 분리 가능 ✅ 배포 보안 강화 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
27 KiB
27 KiB
시스템 아키텍처 개요
TK-FB-Project 시스템 아키텍처 및 설계 문서
📊 시스템 개요
TK-FB-Project는 Technical Korea의 일일 작업 관리 시스템으로, 작업자들의 일일 업무를 기록하고 관리하는 웹 기반 애플리케이션입니다.
주요 기능
- 작업 보고서 관리: 일일 작업 내용 기록 및 조회
- 작업자 관리: 작업자 정보 및 권한 관리
- 프로젝트 관리: 프로젝트별 작업 추적
- 근태 관리: 출퇴근 및 휴가 관리
- 대시보드: 작업 통계 및 분석
- 이슈 관리: 작업 중 발생한 이슈 추적
🏗️ 아키텍처 다이어그램
전체 시스템 구조
┌─────────────────────────────────────────────────────────────┐
│ 클라이언트 │
│ (Web Browser) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Dashboard │ │ Calendar │ │ Report │ │
│ │ (HTML/ │ │ (HTML/ │ │ (HTML/ │ │
│ │ CSS/JS) │ │ CSS/JS) │ │ CSS/JS) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ HTTP/HTTPS
▼
┌─────────────────────────────────────────────────────────────┐
│ Nginx (Port 8080) │
│ (Static File Server) │
└─────────────────────────────────────────────────────────────┘
│
│ Reverse Proxy
▼
┌─────────────────────────────────────────────────────────────┐
│ API Server (Port 20005) │
│ Node.js + Express │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Controllers │ │ Services │ │ Models │ │
│ │ (Routes) │ │ (Business │ │ (Data │ │
│ │ │ │ Logic) │ │ Access) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Middlewares │ │ Utilities │ │
│ │ (Auth, CORS) │ │ (Logger) │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ MySQL Protocol
▼
┌─────────────────────────────────────────────────────────────┐
│ MySQL 8.0 (Port 3306) │
│ (Database) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ users │ │ workers │ │ projects │ │
│ ├──────────────┤ ├──────────────┤ ├──────────────┤ │
│ │daily_work_ │ │ attendance │ │ issues │ │
│ │ reports │ │ _records │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
배포 구조 (Docker Compose)
┌─────────────────────────────────────────────────────────────┐
│ Docker Host (Synology NAS) │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Container: web-ui (Nginx) │ │
│ │ Port: 8080:80 │ │
│ │ Volume: ./web-ui:/usr/share/nginx/html │ │
│ └────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Container: api (Node.js) │ │
│ │ Port: 20005:20005 │ │
│ │ Volume: ./api.hyungi.net:/app │ │
│ └────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Container: db (MySQL 8.0) │ │
│ │ Port: 3306:3306 │ │
│ │ Volume: mysql_data:/var/lib/mysql │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Container: fastapi-bridge (Python) │ │
│ │ Port: 8000:8000 │ │
│ │ (Optional - AI 기능용) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
🔧 기술 스택
프론트엔드
| 기술 | 버전 | 용도 |
|---|---|---|
| HTML5 | - | 마크업 |
| CSS3 | - | 스타일링 |
| JavaScript (ES6+) | - | 클라이언트 로직 |
| FullCalendar | 6.x | 캘린더 UI |
| Chart.js | 3.x | 차트 시각화 |
| jQuery | 3.x | DOM 조작 (레거시) |
백엔드
| 기술 | 버전 | 용도 |
|---|---|---|
| Node.js | 20.x | 런타임 |
| Express | 4.18+ | 웹 프레임워크 |
| MySQL2 | 3.6+ | 데이터베이스 드라이버 |
| JWT | 9.0+ | 인증 |
| bcryptjs | 2.4+ | 비밀번호 해싱 |
| dotenv | 16.3+ | 환경변수 관리 |
데이터베이스
| 기술 | 버전 | 용도 |
|---|---|---|
| MySQL | 8.0+ | 관계형 데이터베이스 |
인프라
| 기술 | 버전 | 용도 |
|---|---|---|
| Docker | 24+ | 컨테이너화 |
| Docker Compose | 2.x | 오케스트레이션 |
| Nginx | 1.25+ | 웹 서버 / 리버스 프록시 |
추가 도구
| 기술 | 용도 |
|---|---|
| Python FastAPI | AI 기능 브릿지 (선택) |
| OpenAI API | 작업 내용 분석 (선택) |
📂 디렉토리 구조
현재 구조
TK-FB-Project/
├── api.hyungi.net/ # 백엔드 API 서버
│ ├── controllers/ # 컨트롤러 (라우트 핸들러)
│ │ ├── dailyWorkReportController.js
│ │ ├── workerController.js
│ │ ├── projectController.js
│ │ └── ...
│ ├── models/ # 데이터 모델
│ │ ├── dailyWorkReportModel.js
│ │ ├── workerModel.js
│ │ └── ...
│ ├── routes/ # 라우트 정의
│ │ ├── dailyWorkReportRoutes.js
│ │ ├── workerRoutes.js
│ │ └── ...
│ ├── services/ # 비즈니스 로직 (일부)
│ │ ├── authService.js
│ │ ├── emailService.js
│ │ └── ...
│ ├── middleware/ # 미들웨어
│ │ ├── errorMiddleware.js
│ │ └── uploadMiddleware.js
│ ├── utils/ # 유틸리티
│ │ └── logger.js
│ ├── uploads/ # 업로드 파일 저장소
│ ├── index.js # 애플리케이션 진입점
│ ├── package.json
│ └── .env # 환경 변수
│
├── web-ui/ # 프론트엔드
│ ├── pages/ # HTML 페이지 (51개)
│ │ ├── index.html
│ │ ├── daily-work-report.html
│ │ ├── work-report-calendar.html
│ │ └── ...
│ ├── js/ # JavaScript (49개)
│ │ ├── api-config.js
│ │ ├── daily-work-report.js
│ │ ├── work-report-calendar.js
│ │ └── ...
│ ├── css/ # CSS (22개)
│ │ ├── common.css
│ │ ├── daily-work-report.css
│ │ └── ...
│ └── assets/ # 정적 리소스
│ └── images/
│
├── fastapi-bridge/ # Python FastAPI (선택)
│ ├── main.py
│ ├── requirements.txt
│ └── ...
│
├── docs/ # 📚 프로젝트 문서
│ ├── README.md
│ ├── architecture/
│ │ └── OVERVIEW.md # 이 파일
│ ├── refactoring/
│ │ ├── ANALYSIS.md
│ │ ├── PLAN.md
│ │ └── LOG.md
│ ├── guides/
│ │ ├── SETUP.md
│ │ └── CODING_STYLE.md
│ └── api/
│
├── docker-compose.yml # Docker Compose 설정
├── .gitignore
├── README.md
└── package.json
목표 구조 (리팩토링 후)
TK-FB-Project/
├── api/ # 백엔드 (이름 변경)
│ ├── src/
│ │ ├── config/ # 설정 파일
│ │ │ ├── database.js
│ │ │ ├── cors.js
│ │ │ └── routes.js
│ │ ├── controllers/ # 라우트 핸들러만
│ │ │ └── ...
│ │ ├── services/ # 비즈니스 로직 (완성)
│ │ │ └── ...
│ │ ├── repositories/ # 데이터 접근 계층 (신규)
│ │ │ └── ...
│ │ ├── models/ # 데이터 모델 / 스키마
│ │ │ └── ...
│ │ ├── middlewares/ # 미들웨어
│ │ │ ├── auth.js
│ │ │ ├── permission.js
│ │ │ └── errorHandler.js
│ │ ├── utils/ # 유틸리티
│ │ │ ├── errors.js
│ │ │ ├── logger.js
│ │ │ └── validator.js
│ │ └── index.js # 진입점 (간결화)
│ ├── tests/ # 테스트
│ │ ├── unit/
│ │ └── integration/
│ └── package.json
│
├── web/ # 프론트엔드 (이름 변경)
│ ├── public/ # 정적 파일
│ │ └── assets/
│ ├── src/
│ │ ├── modules/ # 모듈화된 코드
│ │ │ ├── common/
│ │ │ │ ├── api-client.js
│ │ │ │ ├── utils.js
│ │ │ │ └── validator.js
│ │ │ ├── calendar/
│ │ │ │ ├── CalendarView.js
│ │ │ │ ├── CalendarAPI.js
│ │ │ │ └── CalendarUtils.js
│ │ │ └── dashboard/
│ │ ├── pages/ # 페이지별 스크립트
│ │ └── styles/ # CSS
│ │ ├── base/
│ │ ├── components/
│ │ ├── layouts/
│ │ └── pages/
│ └── index.html
│
├── database/ # 데이터베이스 관련
│ ├── migrations/ # 마이그레이션
│ ├── seeds/ # 시드 데이터
│ └── schema/ # 스키마 정의
│
├── deployment/ # 배포 스크립트
│ ├── docker/
│ │ ├── api.Dockerfile
│ │ ├── web.Dockerfile
│ │ └── nginx.conf
│ ├── docker-compose.yml
│ ├── docker-compose.dev.yml
│ └── deploy.sh
│
├── docs/ # 문서
└── scripts/ # 유틸리티 스크립트
🔄 데이터 흐름
1. 사용자 인증 플로우
┌──────┐ ┌──────┐ ┌──────────┐ ┌──────┐
│Client│ │ API │ │ Service │ │ DB │
└──┬───┘ └──┬───┘ └────┬─────┘ └──┬───┘
│ │ │ │
│ POST /login │ │ │
├────────────>│ │ │
│ │ validate │ │
│ ├───────────────>│ │
│ │ │ findByUsername│
│ │ ├──────────────>│
│ │ │<──────────────┤
│ │ │ user data │
│ │ verify pwd │ │
│ │<───────────────┤ │
│ │ generate JWT │ │
│ ├───────────────>│ │
│ JWT Token│ │ │
│<────────────┤ │ │
│ │ │ │
└─────────────┴────────────────┴───────────────┘
2. 작업 보고서 생성 플로우
┌──────┐ ┌─────┐ ┌──────────┐ ┌─────────┐ ┌────┐
│Client│ │ API │ │ Service │ │ Repo │ │ DB │
└──┬───┘ └──┬──┘ └────┬─────┘ └────┬────┘ └─┬──┘
│ │ │ │ │
│POST /reports │ │ │
├──────────>│ │ │ │
│ │ auth check │ │ │
│ │ │ │ │
│ │ validate │ │ │
│ ├───────────>│ │ │
│ │ │ checkDup │ │
│ │ ├─────────────>│ │
│ │ │ │ SELECT │
│ │ │ ├─────────>│
│ │ │ │<─────────┤
│ │ │<─────────────┤ │
│ │ │ create │ │
│ │ ├─────────────>│ │
│ │ │ │ INSERT │
│ │ │ ├─────────>│
│ │ │ │<─────────┤
│ │ │<─────────────┤ │
│ │ │ notify │ │
│ │ │ (email/push) │ │
│ │<───────────┤ │ │
│<──────────┤ │ │ │
│ 201 │ │ │ │
└───────────┴────────────┴──────────────┴──────────┘
3. 대시보드 데이터 조회 플로우
Client → API → Service → Repository → DB
↓
Cache (Redis - 향후 도입 예정)
🔐 보안 아키텍처
인증 (Authentication)
JWT 기반 인증:
// 로그인 성공 시
const token = jwt.sign(
{
userId: user.id,
username: user.username,
access_level: user.access_level
},
process.env.JWT_SECRET,
{ expiresIn: '24h' }
);
// 요청 시 헤더에 포함
Authorization: Bearer <token>
토큰 검증 플로우:
Request → Auth Middleware → Verify JWT → Attach user to req → Next
↓ (invalid)
401 Unauthorized
권한 (Authorization)
역할 기반 접근 제어 (RBAC):
| 역할 | 권한 |
|---|---|
system |
모든 권한 (시스템 관리자) |
admin |
전체 데이터 조회 및 수정 |
group_leader |
그룹 내 데이터 관리 |
worker |
본인 데이터만 조회/수정 |
권한 체크 미들웨어 (목표):
// 특정 역할 필요
router.get('/admin', requireRole('admin', 'system'), getAdminData);
// 본인 또는 관리자
router.put('/reports/:id', requireOwnerOrAdmin, updateReport);
데이터 보안
- 비밀번호: bcrypt로 해싱 (salt rounds: 10)
- 환경변수: .env 파일 (Git 제외)
- SQL Injection: Prepared Statements 사용
- XSS: 입력값 sanitization
- CORS: 허용된 origin만 접근
📊 데이터베이스 설계
ER 다이어그램
┌─────────────┐ ┌─────────────┐
│ users │ │ workers │
├─────────────┤ ├─────────────┤
│ id (PK) │ ┌───>│ id (PK) │
│ username │ │ │ name │
│ password │ │ │ email │
│ access_level│ │ │ position │
│ worker_id(FK├────┘ │ is_active │
└─────────────┘ └──────┬──────┘
│
│ 1:N
│
┌──────▼──────────┐
│daily_work_ │
│ reports │
├─────────────────┤
│ id (PK) │
│ worker_id (FK) │
│ project_id (FK) │
│ report_date │
│ work_content │
│ work_hours │
│ created_at │
└──────┬──────────┘
│ N:1
│
┌──────▼──────┐
│ projects │
├─────────────┤
│ id (PK) │
│ name │
│ description │
│ start_date │
│ end_date │
└─────────────┘
주요 테이블
| 테이블명 | 설명 | 주요 컬럼 |
|---|---|---|
users |
사용자 계정 | id, username, password, access_level |
workers |
작업자 정보 | id, name, email, position, group_id |
daily_work_reports |
일일 작업 보고서 | id, worker_id, project_id, report_date, work_content |
projects |
프로젝트 | id, name, description, start_date, end_date |
attendance_records |
근태 기록 | id, worker_id, date, clock_in, clock_out |
issues |
이슈 | id, project_id, reporter_id, title, status |
work_types |
작업 유형 | id, name, category |
work_status_types |
작업 상태 | id, name, color |
자세한 스키마는 DATABASE_SCHEMA.md 참조
🚀 배포 프로세스
현재 배포 방식
# 1. Docker Compose로 배포
docker-compose up -d
# 2. 수동 업데이트
docker-compose down
git pull origin master
docker-compose up -d --build
목표 CI/CD 파이프라인
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Push │ │ Build │ │ Test │
│ to GitHub ├─────>│ & Lint ├─────>│ (Jest) │
└────────────┘ └────────────┘ └──────┬─────┘
│
▼
┌────────────┐ ┌────────────┐
│ Deploy │<─────│ Security │
│ Production │ │ Scan │
└────────────┘ └────────────┘
GitHub Actions 예시:
name: CI/CD
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- run: npm ci
- run: npm test
- run: npm run lint
deploy:
needs: test
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- name: Deploy to Synology
run: ./deployment/deploy.sh
📈 성능 고려사항
현재 성능 이슈
- N+1 쿼리 문제: JOIN 사용 필요
- SELECT * 사용: 명시적 컬럼 지정 필요
- 인덱스 부족: 주요 컬럼에 인덱스 추가 필요
- 캐싱 없음: Redis 도입 검토
최적화 계획
// 1. 쿼리 최적화
// Before: N+1 쿼리
const reports = await getReports();
for (const report of reports) {
report.worker = await getWorker(report.worker_id);
}
// After: JOIN 사용
const reports = await db.query(`
SELECT r.*, w.name as worker_name
FROM daily_work_reports r
JOIN workers w ON r.worker_id = w.id
`);
// 2. 인덱스 추가
CREATE INDEX idx_report_date ON daily_work_reports(report_date);
CREATE INDEX idx_worker_id ON daily_work_reports(worker_id);
// 3. 캐싱 (Redis - 향후)
const cachedData = await redis.get('dashboard:stats');
if (cachedData) return JSON.parse(cachedData);
const data = await fetchDashboardStats();
await redis.setex('dashboard:stats', 300, JSON.stringify(data));
🔮 향후 계획
Phase 1: 안정화 (현재)
- 보안 강화
- 코드 리팩토링
- 테스트 작성
Phase 2: 모듈화 (3개월)
- 서비스 레이어 완성
- 프론트엔드 모듈화
- API 문서화
Phase 3: 현대화 (6개월)
- TypeScript 전환
- React/Vue 도입
- ORM 적용 (TypeORM/Prisma)
Phase 4: 확장 (12개월)
- 마이크로서비스 아키텍처
- GraphQL API
- 실시간 기능 (WebSocket)
- 모바일 앱 (React Native)
📚 관련 문서
마지막 업데이트: 2025-12-11