Files
TK-FB-Project/CODING_GUIDE.md
Hyungi Ahn 2e9d24faf2 feat: 일간작업장 점검 카테고리 추가
- 사이드바에 '일간작업장 점검' 카테고리 신설
- 일일 출퇴근을 근태 관리에서 일간작업장 점검으로 이동
- CODING_GUIDE.md 페이지 구조 업데이트
- docs/README.md 트리 구조 업데이트

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 10:13:13 +09:00

15 KiB

TK-FB-Project 통합 개발 가이드

이 문서는 프로젝트의 실행, 규칙, 테스트, 호환성 등 모든 개발 관련 사항을 통합한 가이드입니다.


🏗 프로젝트 개요 및 아키텍처

생산팀 내부 포털 개발 및 유지보수

기술 스택

  • Backend: Node.js, Express.js (Port: 20005)
  • Frontend: Vanilla HTML/CSS/JS (Port: 20000)
  • Database: MariaDB (Port: 20306), phpMyAdmin (Port: 20080)
  • Infra: Docker Compose (Synology NAS, Mac Mini)
  • Bridge: FastAPI (Port: 20010, Python 3.11+) - 2025.07 도입

아키텍처 모식도

브라우저 → FastAPI (8000) → Express (3005) → MariaDB
                         ↓
                   정적 파일 서빙

Note: 현재 개발 환경 포트는 위 기술 스택 섹션 참조


🚀 실행 가이드

필수: 환경 변수 설정

.env.example.env로 복사하고 설정하세요. 절대 커밋 금지!

Docker 실행

./start.sh        # 간편 실행 (권장)
./stop.sh         # 중지
docker-compose up -d # 수동 실행

📏 코딩 컨벤션

네이밍

대상 스타일 예시
JS 변수/함수 camelCase calculateTotal
JS 클래스 PascalCase UserReport
파일명 kebab-case work-report.js
DB 테이블/컬럼 snake_case user_accounts
API URL plural, kebab /api/work-reports

코드 품질

  • 파일 분리: 750줄 초과 시 리팩토링 고려 (Controller/Service/Model 분리 필수).
  • Early Return: 중첩 조건문 지양.
  • 주석: JSDoc 활용 권장.

🎨 UI/UX 디자인 가이드

디자인 원칙

  • 모던하고 깔끔한 디자인: 이모지 사용 지양, 아이콘 또는 심플한 텍스트 사용
  • 일관성: 모든 페이지에서 동일한 디자인 시스템 적용
  • 컴포넌트 재사용: navbar, footer 등은 컴포넌트로 관리

이모지 사용 금지

금지:

<!-- 나쁜 예 -->
<button>📊 대시보드</button>
<h1>🔧 작업 관리</h1>

권장:

<!-- 좋은 예 - 아이콘 라이브러리 사용 또는 심플한 텍스트 -->
<button class="btn-primary">
  <i class="icon-dashboard"></i>
  대시보드
</button>
<h1>작업 관리</h1>

색상 가이드

  • Primary: 하늘색 계열 (#0ea5e9, #38bdf8, #7dd3fc)
  • 기본 배경: 흰색/밝은 회색 계열
  • 텍스트: #1f2937 (dark gray)
  • 보조 텍스트: #6b7280 (medium gray)

컴포넌트 구조

  • 네비게이션: web-ui/components/navbar.html 참조
  • 일관된 헤더: 모든 페이지에서 <div id="navbar-container"></div> 사용
  • CSS 로딩 순서: design-system.css → 페이지별 CSS

페이지 구조 (2026-02-03 현행)

web-ui/pages/
├── dashboard.html              # 메인 대시보드 (작업장 현황 지도 포함)
├── work/                       # 작업 관리 (현장 입력/생산)
│   ├── tbm.html                # TBM(Tool Box Meeting) 관리
│   ├── report-create.html      # 작업보고서 작성
│   ├── report-view.html        # 작업보고서 조회
│   ├── nonconformity.html      # 부적합 현황
│   └── analysis.html           # 작업 분석
├── [일간작업장 점검]            # 일간작업장 점검 (사이드바 카테고리)
│   └── attendance/daily.html   # 일일 출퇴근 입력
├── safety/                     # 안전 관리 페이지
│   ├── report.html             # 신고 (공통)
│   ├── report-status.html      # 안전신고 현황
│   ├── issue-detail.html       # 이슈 상세
│   ├── visit-request.html      # 출입 신청
│   ├── management.html         # 안전 관리 (출입 승인)
│   └── checklist-manage.html   # 안전 체크리스트 관리
├── attendance/                 # 근태 관리 페이지
│   ├── monthly.html            # 월별 출퇴근 현황
│   ├── vacation-request.html   # 휴가 신청
│   ├── vacation-management.html # 휴가 관리 (통합)
│   ├── vacation-approval.html  # 휴가 승인 관리
│   ├── vacation-input.html     # 휴가 직접 입력
│   ├── vacation-allocation.html # 휴가 발생 입력
│   └── annual-overview.html    # 연간 연차 현황
├── admin/                      # 시스템 관리 페이지
│   ├── accounts.html           # 계정 관리
│   ├── page-access.html        # 페이지 접근 권한 관리
│   ├── workers.html            # 작업자 관리
│   ├── projects.html           # 프로젝트 관리
│   ├── tasks.html              # 작업 관리
│   ├── workplaces.html         # 작업장 관리 (지도 구역 설정)
│   ├── equipments.html         # 설비 관리
│   ├── codes.html              # 코드 관리
│   ├── issue-categories.html   # 신고 카테고리 관리
│   └── attendance-report.html  # 출퇴근-작업보고서 대조
├── profile/                    # 사용자 프로필
│   ├── info.html               # 내 정보
│   └── password.html           # 비밀번호 변경
└── .archived-*/                # 미사용 페이지 보관

폴더 분류 기준 (2026-02-03 변경):

  • work/: 현장 입력/생산 활동 (TBM, 작업보고서, 부적합)
  • [일간작업장 점검]: 일일 작업장 점검 관련 (사이드바 카테고리)
  • safety/: 안전 관리/분석 (신고, 출입)
  • attendance/: 근태/휴가 관리
  • admin/: 시스템 관리 (관리자 전용)
  • profile/: 개인 설정 페이지

네이밍 규칙:

  • 메인 페이지: 단일 명사 (dashboard.html)
  • 관리 페이지: 복수형 명사 (projects.html, workers.html)
  • 기능 페이지: 동사-명사 또는 명사 (report-create.html, daily.html)
  • 폴더명: 단수형, 소문자 (work/, safety/, attendance/, admin/, profile/)

네비게이션 구조:

  • 1차: dashboard.html (메인 진입점, 작업장 현황 지도)
  • 2차: 사이드 메뉴 또는 빠른 작업 카드를 통한 각 기능 페이지 이동
  • 모든 페이지: navbar를 통해 profile, 로그아웃 가능

대기 중인 DB 마이그레이션

페이지 구조 변경에 따른 DB 마이그레이션이 필요합니다:

cd /Users/hyungiahn/Documents/code/TK-FB-Project/api.hyungi.net
npx knex migrate:latest
  • 마이그레이션 파일: db/migrations/20260202200000_reorganize_pages.js
  • 내용: pages 테이블 경로 업데이트, role_default_pages 테이블 생성

표준 컴포넌트 (2026-01-20 업데이트)

네비게이션 헤더

모든 페이지는 표준 navbar 컴포넌트를 사용합니다:

<!-- HTML에 컨테이너 추가 -->
<div id="navbar-container"></div>

<!-- 스크립트로 로드 -->
<script src="/js/load-navbar.js"></script>

특징:

  • 자동으로 사용자 정보 표시 (이름, 역할)
  • 프로필 메뉴 (내 프로필, 비밀번호 변경, 로그아웃)
  • 관리자 전용 메뉴 자동 표시/숨김
  • 현재 시각 실시간 표시
  • 대시보드 버튼

CSS 변수 시스템

모든 스타일은 design-system.css의 CSS 변수를 사용합니다:

/* 색상 - 하늘색 계열 primary */
var(--primary-500)      /* 기본 하늘색: #0ea5e9 */
var(--primary-400)      /* 밝은 하늘색: #38bdf8 */
var(--header-gradient)  /* 헤더 그라디언트 */

/* 간격 */
var(--space-2)   /* 8px */
var(--space-4)   /* 16px */
var(--space-6)   /* 24px */

/* 타이포그래피 */
var(--text-sm)        /* 14px */
var(--text-base)      /* 16px */
var(--font-medium)    /* 500 */

/* 기타 */
var(--radius-md)         /* 8px 둥근 모서리 */
var(--shadow-md)         /* 그림자 */
var(--transition-fast)   /* 150ms */

금지: 하드코딩된 색상 값 사용 (#0ea5e9 대신 var(--primary-500) 사용)

페이지 레이아웃 템플릿

web-ui/templates/ 디렉토리에 4가지 표준 템플릿 제공:

  1. dashboard-layout.html: 메인 대시보드, 통계 페이지
  2. work-layout.html: 작업 관련 페이지 (보고서, 분석)
  3. admin-layout.html: 관리자 페이지 (테이블, CRUD)
  4. simple-layout.html: 프로필, 설정 등 단순 페이지

새 페이지 생성 시:

# 템플릿 복사
cp web-ui/templates/work-layout.html web-ui/pages/work/new-page.html

# 내용 수정
# - <title> 변경
# - 페이지별 CSS/JS 추가
# - 콘텐츠 작성

상세한 사용법은 web-ui/templates/README.md 참조.


🔐 페이지 접근 권한 관리

권한 체크 방식

  1. 관리자 전용 페이지: admin-only 클래스 사용
  2. 페이지별 권한 체크: pages 테이블 기반 권한 확인
  3. 클라이언트 측: auth-check.js에서 자동 권한 검증

페이지 등록 (pages 테이블)

새 페이지 생성 시 반드시 pages 테이블에 등록:

-- 마이그레이션 예시
INSERT INTO pages (page_name, page_url, page_category, description, display_order, is_active)
VALUES
  ('출입 신청', '/pages/work/visit-request.html', 'work', '작업장 출입 및 안전교육 신청', 150, 1),
  ('안전관리', '/pages/admin/safety-management.html', 'admin', '출입 신청 승인 및 안전교육 관리', 210, 1);

페이지 권한 할당

  • Admin: 모든 페이지 자동 접근 가능
  • 일반 사용자: page_access 테이블에 명시적 권한 부여 필요
-- 특정 사용자에게 페이지 권한 부여
INSERT INTO page_access (user_id, page_id, granted_by, granted_at)
VALUES (123, 45, 1, NOW());

HTML 페이지 설정

<!-- 관리자 전용 페이지 -->
<a href="/pages/admin/safety-management.html" class="quick-action-card admin-only">
  <div class="action-content">
    <h3>안전관리</h3>
  </div>
</a>

<!-- 모든 사용자 접근 가능 -->
<a href="/pages/work/visit-request.html" class="quick-action-card">
  <div class="action-content">
    <h3>출입 신청</h3>
  </div>
</a>

API 라우트 보호

const { verifyToken } = require('../middlewares/authMiddleware');

// 모든 라우트에 인증 필요
router.use(verifyToken);

// 관리자 전용 라우트
router.put('/requests/:id/approve', (req, res) => {
  // verifyToken에서 req.user 제공
  // 필요시 추가 권한 체크
});

📡 API 개발 가이드

  • RESTful: 명사형 리소스 사용 (POST /users O, /createUser X).
  • 응답 포맷:
    { "success": true, "data": {...}, "message": "..." }
    
  • 계층 구조:
    • Controller: 요청/응답 처리, 유효성 검사.
    • Service: 비즈니스 로직, 트랜잭션 관리.
    • Model: DB 쿼리 실행.

MySQL 8.0 호환성 주의사항 (중요)

Synology NAS(MySQL 8.0)의 Strict Mode로 인해 db.execute() 사용 시 Incorrect arguments 에러가 발생할 수 있습니다.

  • 해결책: db.query() 사용 권장 (특히 복잡한 JOIN/Subquery).
  • 가이드: models/WorkAnalysis.js 등의 getRecentWork 참조.

🕐 시간대(Timezone) 처리 가이드

핵심 원칙

이 프로젝트는 한국 시간(KST, UTC+9) 기준으로 운영됩니다.

문제 상황

서버가 UTC 시간대로 설정된 경우, NOW(), CURRENT_TIMESTAMP, new Date()를 사용하면 한국 시간과 9시간 차이가 발생합니다.

예시: 한국 시간 2026-02-03 08:00 AM에 신고 등록
- UTC 시간: 2026-02-02 11:00 PM
- DB 저장: 2026-02-02 (잘못된 날짜!)

해결 방법

백엔드 (Node.js)

공용 유틸리티 사용 (utils/dateUtils.js):

const { getKoreaDatetime, getKoreaDateString } = require('../utils/dateUtils');

// 비즈니스 날짜 저장 시
const reportDate = getKoreaDatetime();  // '2026-02-03 08:00:00'
await db.query('INSERT INTO reports (report_date, ...) VALUES (?, ...)', [reportDate, ...]);

// 날짜만 필요한 경우
const today = getKoreaDateString();  // '2026-02-03'

제공되는 함수들:

함수 반환값 용도
getKoreaDatetime() '2026-02-03 08:00:00' DB DATETIME 저장
getKoreaDateString() '2026-02-03' DB DATE 저장
getKoreaTimeString() '08:00:00' DB TIME 저장
getKoreaYear() 2026 연도
getKoreaMonth() 2 월 (1-12)
toKoreaDatetime(date) '2026-02-03 08:00:00' Date 객체 변환

프론트엔드 (JavaScript)

// 로컬 시간대 기준 날짜 문자열
function getLocalDateString() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

// ❌ 잘못된 방법 (UTC 변환됨)
const today = new Date().toISOString().split('T')[0];

// ✅ 올바른 방법 (로컬 시간)
const today = getLocalDateString();

컬럼별 적용 기준

컬럼 유형 처리 방법 비고
created_at, updated_at NOW() 또는 CURRENT_TIMESTAMP 사용 가능 감사용 메타데이터, UTC로 저장해도 무방
report_date, session_date 반드시 getKoreaDatetime() 사용 비즈니스 날짜, 사용자에게 표시됨
visit_date, attendance_date 반드시 한국 시간 기준 필터링/조회에 사용됨
API 응답 timestamp new Date().toISOString() 사용 가능 디버깅용

마이그레이션 주의사항

새 테이블 생성 시 비즈니스 날짜 컬럼은 default 값을 사용하지 말고 애플리케이션에서 명시적으로 설정:

// ❌ 잘못된 방법
table.datetime('report_date').defaultTo(knex.fn.now());

// ✅ 올바른 방법
table.datetime('report_date').notNullable();  // default 없음
// 애플리케이션에서 getKoreaDatetime()으로 값 설정

기존 데이터 보정 (필요시)

UTC로 잘못 저장된 데이터를 한국 시간으로 보정:

-- 주의: 백업 후 실행
UPDATE work_issue_reports
SET report_date = DATE_ADD(report_date, INTERVAL 9 HOUR)
WHERE report_date < '2026-02-03';

🧪 테스트 가이드 (Jest)

중요도

  1. Service Layer (최우선: 비즈니스 로직 검증)
  2. Controller Layer (요청 처리 검증)
  3. Integration (E2E)

실행

npm test                # 전체 실행
npm run test:watch      # 변경 감지
npm run test:coverage   # 커버리지 측정

작성 패턴 (Service 예시)

// Service는 DB Model을 Mocking하여 테스트
const service = require('../service');
jest.mock('../model');

it('should create report', async () => {
    Model.create.mockResolvedValue(123); // Mock DB response
    const result = await service.createReport(...);
    expect(result).toEqual(...);
});

📝 Git 관리

  • 커밋 메시지: type: subject (예: feat: 작업보고서 API 추가)
  • Types: feat, fix, docs, style, refactor, test, chore
  • 브랜치: main(배포), develop(통합), feature/*(기능)