refactor: Phase 1 - 긴급 보안 및 중복 제거

## 🚨 보안 강화
- 하드코딩된 비밀번호를 환경변수로 전환
- .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>
This commit is contained in:
Hyungi Ahn
2025-12-11 10:16:57 +09:00
parent 5c8f553f87
commit 1e7155b864
425 changed files with 4346 additions and 286950 deletions

686
docs/guides/CODING_STYLE.md Normal file
View File

@@ -0,0 +1,686 @@
# 코딩 스타일 가이드
> TK-FB-Project 코드 작성 규칙 및 베스트 프랙티스
## 📚 목차
1. [일반 원칙](#일반-원칙)
2. [JavaScript/Node.js](#javascriptnodejs)
3. [HTML/CSS](#htmlcss)
4. [SQL](#sql)
5. [Git 커밋 메시지](#git-커밋-메시지)
6. [파일 및 디렉토리 구조](#파일-및-디렉토리-구조)
---
## 일반 원칙
### 1. 가독성 우선
```javascript
// ❌ 나쁜 예
const x = a.filter(i => i.active).map(i => ({...i, name: i.n}));
// ✅ 좋은 예
const activeWorkers = workers
.filter(worker => worker.is_active)
.map(worker => ({
...worker,
name: worker.name
}));
```
### 2. 명확한 네이밍
```javascript
// ❌ 나쁜 예
const d = new Date();
const arr = [];
const temp = getUserData();
// ✅ 좋은 예
const currentDate = new Date();
const activeWorkers = [];
const userData = getUserData();
```
### 3. 단일 책임 원칙
```javascript
// ❌ 나쁜 예 - 하나의 함수가 너무 많은 일을 함
async function processReport(data) {
// 검증
if (!data.worker_id) throw new Error('Invalid');
// DB 저장
await db.query('INSERT INTO ...');
// 이메일 발송
await sendEmail();
// 알림 전송
await sendNotification();
}
// ✅ 좋은 예 - 책임 분리
async function processReport(data) {
validateReport(data);
const report = await saveReport(data);
await notifyReportCreation(report);
return report;
}
function validateReport(data) {
if (!data.worker_id) {
throw new ValidationError('작업자를 선택해주세요');
}
}
async function saveReport(data) {
return await reportRepository.create(data);
}
async function notifyReportCreation(report) {
await emailService.send(report);
await notificationService.send(report);
}
```
### 4. DRY (Don't Repeat Yourself)
```javascript
// ❌ 나쁜 예 - 중복 코드
if (!req.user || !['admin', 'system'].includes(req.user.access_level)) {
return res.status(403).json({ error: 'Forbidden' });
}
// ✅ 좋은 예 - 재사용 가능한 미들웨어
const requireRole = (...roles) => {
return (req, res, next) => {
if (!req.user || !roles.includes(req.user.access_level)) {
throw new ForbiddenError();
}
next();
};
};
// 사용
router.get('/admin', requireRole('admin', 'system'), getAdminData);
```
---
## JavaScript/Node.js
### 변수 선언
```javascript
// ✅ const 우선, 재할당 필요시 let, var 사용 금지
const API_URL = 'http://api.example.com';
let currentPage = 1;
// ❌ var 사용 금지
var x = 10; // NO!
```
### 함수 작성
```javascript
// ✅ 화살표 함수 사용 (콜백, 간단한 함수)
const double = (n) => n * 2;
const sum = (a, b) => a + b;
// ✅ 일반 함수 (메서드, 복잡한 로직)
function calculateTotalHours(reports) {
let total = 0;
for (const report of reports) {
total += report.work_hours;
}
return total;
}
// ✅ async/await 사용 (Promise보다 선호)
async function fetchUserData(userId) {
try {
const user = await userModel.findById(userId);
const reports = await reportModel.findByUser(userId);
return { user, reports };
} catch (error) {
logger.error('Failed to fetch user data', { userId, error });
throw error;
}
}
```
### 에러 처리
```javascript
// ❌ 나쁜 예
try {
await saveData();
} catch (error) {
console.log(error); // 단순 로그만
}
// ✅ 좋은 예
try {
await saveData(data);
} catch (error) {
logger.error('데이터 저장 실패', {
data,
error: error.message,
stack: error.stack
});
throw new AppError('데이터 저장에 실패했습니다', 500);
}
```
### 객체 및 배열
```javascript
// ✅ 구조 분해 할당
const { name, email, phone } = user;
const [first, second, ...rest] = items;
// ✅ 스프레드 연산자
const newUser = { ...user, is_active: true };
const allItems = [...items1, ...items2];
// ✅ 단축 속성
const name = 'John';
const age = 30;
const user = { name, age }; // { name: name, age: age } 대신
```
### 비동기 처리
```javascript
// ❌ 콜백 지옥
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
console.log(c);
});
});
});
// ✅ async/await
async function processData() {
const a = await getData();
const b = await getMoreData(a);
const c = await getMoreData(b);
return c;
}
// ✅ 병렬 처리가 가능한 경우
const [users, projects, reports] = await Promise.all([
fetchUsers(),
fetchProjects(),
fetchReports()
]);
```
### 조건문
```javascript
// ✅ Early Return 패턴
function processUser(user) {
if (!user) {
throw new ValidationError('User is required');
}
if (!user.is_active) {
throw new ValidationError('User is not active');
}
// 메인 로직
return processActiveUser(user);
}
// ❌ 중첩된 조건문
function processUser(user) {
if (user) {
if (user.is_active) {
// 메인 로직
return processActiveUser(user);
} else {
throw new Error('Not active');
}
} else {
throw new Error('No user');
}
}
```
### 주석
```javascript
// ✅ JSDoc 사용
/**
* 작업 보고서를 생성합니다
* @param {Object} reportData - 보고서 데이터
* @param {number} reportData.worker_id - 작업자 ID
* @param {string} reportData.work_content - 작업 내용
* @param {number} userId - 생성하는 사용자 ID
* @returns {Promise<Object>} 생성된 보고서
* @throws {ValidationError} 검증 실패 시
*/
async function createReport(reportData, userId) {
// ...
}
// ✅ 복잡한 로직 설명
// NOTE: MySQL 8.0에서는 GROUP BY 동작이 다르므로 명시적으로 컬럼 지정
const query = `
SELECT worker_id, COUNT(*) as count
FROM reports
GROUP BY worker_id
ORDER BY count DESC
`;
// ⚠️ TODO, FIXME 등 명확히 표시
// TODO: 캐싱 로직 추가 필요
// FIXME: 날짜 범위 검증 개선 필요
// HACK: 임시 해결책, 나중에 리팩토링 필요
```
### 모듈 구조
```javascript
// ✅ 명확한 import/export
// 파일 상단에 모든 import
const express = require('express');
const { ValidationError } = require('../utils/errors');
const reportService = require('../services/reportService');
// 함수 정의
function createReport(req, res, next) {
// ...
}
function getReports(req, res, next) {
// ...
}
// 파일 하단에 export
module.exports = {
createReport,
getReports
};
```
---
## HTML/CSS
### HTML
```html
<!-- ✅ 시맨틱 태그 사용 -->
<header>
<nav>
<ul>
<li><a href="/"></a></li>
</ul>
</nav>
</header>
<main>
<section>
<article>
<h1>제목</h1>
<p>내용</p>
</article>
</section>
</main>
<footer>
<p>&copy; 2025 TK-FB</p>
</footer>
<!-- ✅ 들여쓰기 2칸 -->
<div class="container">
<div class="row">
<div class="col">
내용
</div>
</div>
</div>
<!-- ✅ 속성 순서 -->
<!-- 1. class 2. id 3. data-* 4. 기타 -->
<button
class="btn btn-primary"
id="submit-btn"
data-action="submit"
type="submit"
disabled
>
제출
</button>
```
### CSS
```css
/* ✅ 클래스 네이밍: BEM 방식 */
.block {}
.block__element {}
.block--modifier {}
/* 예시 */
.card {}
.card__header {}
.card__body {}
.card__footer {}
.card--large {}
.card--primary {}
/* ✅ 속성 순서 */
.element {
/* 1. Positioning */
position: absolute;
top: 0;
left: 0;
z-index: 10;
/* 2. Box Model */
display: block;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
border: 1px solid #000;
/* 3. Typography */
font-family: Arial;
font-size: 14px;
line-height: 1.5;
color: #333;
/* 4. Visual */
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
/* 5. Other */
cursor: pointer;
transition: all 0.3s ease;
}
/* ✅ CSS 변수 사용 */
:root {
--color-primary: #007bff;
--color-success: #28a745;
--spacing-md: 1rem;
}
.button {
background-color: var(--color-primary);
padding: var(--spacing-md);
}
/* ✅ 중첩 최소화 (3단계 이하) */
.nav {}
.nav__item {}
.nav__link {}
/* ❌ 과도한 중첩 */
.nav ul li a span {} /* NO! */
```
---
## SQL
### 쿼리 작성
```sql
-- ✅ 대문자 키워드, 명시적 컬럼 지정
SELECT
id,
name,
email,
created_at
FROM users
WHERE is_active = 1
AND role = 'admin'
ORDER BY created_at DESC
LIMIT 10;
-- ❌ SELECT * 사용 금지
SELECT * FROM users; -- NO!
-- ✅ 조인 명시적 작성
SELECT
r.id,
r.work_content,
w.name AS worker_name,
p.name AS project_name
FROM daily_work_reports r
INNER JOIN workers w ON r.worker_id = w.id
LEFT JOIN projects p ON r.project_id = p.id
WHERE r.report_date BETWEEN ? AND ?;
-- ✅ 파라미터 바인딩 사용
const query = 'SELECT * FROM users WHERE id = ? AND email = ?';
const [rows] = await db.query(query, [userId, email]);
-- ❌ 문자열 연결 금지 (SQL Injection 위험)
const query = `SELECT * FROM users WHERE email = '${email}'`; -- NO!
```
### 테이블/컬럼 네이밍
```sql
-- ✅ 스네이크 케이스
CREATE TABLE daily_work_reports (
id INT PRIMARY KEY AUTO_INCREMENT,
worker_id INT NOT NULL,
report_date DATE NOT NULL,
work_content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- ✅ 복수형 테이블명
users, workers, projects, reports
-- ✅ 외래키 명확히
worker_id, project_id (_id )
```
---
## Git 커밋 메시지
### 형식
```
<type>(<scope>): <subject>
<body>
<footer>
```
### Type
- `feat`: 새로운 기능
- `fix`: 버그 수정
- `refactor`: 리팩토링
- `style`: 코드 포맷팅
- `docs`: 문서 수정
- `test`: 테스트 추가/수정
- `chore`: 빌드, 설정 변경
### 예시
```bash
# ✅ 좋은 커밋 메시지
feat(report): 작업 보고서 엑셀 내보내기 기능 추가
사용자가 작업 보고서를 엑셀 파일로 내보낼 수 있도록 기능 추가
- xlsx 라이브러리 사용
- 날짜 범위 선택 가능
- 필터링 옵션 제공
Closes #123
# ✅ 리팩토링
refactor(api): index.js를 여러 파일로 분리
- config/database.js: DB 연결 설정
- config/cors.js: CORS 설정
- middlewares/auth.js: 인증 미들웨어
- controllers/userController.js: 사용자 관리 API
index.js 파일 크기: 889줄 → 95줄
# ✅ 버그 수정
fix(calendar): 주말 날짜 선택 시 오류 수정
주말 날짜 클릭 시 TypeError 발생하는 문제 해결
Date 객체 null 체크 추가
Fixes #456
# ❌ 나쁜 커밋 메시지
update
fix bug
asdf
ㅁㄴㅇㄹ
```
---
## 파일 및 디렉토리 구조
### 백엔드
```
api.hyungi.net/
├── index.js # 진입점 (간결하게)
├── config/ # 설정 파일
│ ├── database.js
│ ├── cors.js
│ └── routes.js
├── controllers/ # 라우트 핸들러
│ ├── userController.js
│ └── reportController.js
├── services/ # 비즈니스 로직
│ ├── userService.js
│ └── reportService.js
├── models/ # 데이터 모델
│ ├── User.js
│ └── Report.js
├── middlewares/ # 미들웨어
│ ├── auth.js
│ └── errorHandler.js
├── utils/ # 유틸리티
│ ├── errors.js
│ └── logger.js
└── tests/ # 테스트
├── unit/
└── integration/
```
### 프론트엔드
```
web-ui/
├── js/
│ ├── modules/ # 모듈화된 코드
│ │ ├── common/
│ │ │ ├── api-client.js
│ │ │ └── utils.js
│ │ ├── calendar/
│ │ │ ├── CalendarView.js
│ │ │ └── CalendarAPI.js
│ │ └── dashboard/
│ └── pages/ # 페이지별 스크립트
├── css/
│ ├── base/
│ ├── components/
│ ├── layouts/
│ └── pages/
└── pages/ # HTML 파일
```
### 파일 네이밍
```javascript
// ✅ 케이스 규칙
// 파일명: kebab-case
user-controller.js
daily-work-report.js
// 클래스/컴포넌트: PascalCase
UserController.js
CalendarView.js
// 일반 함수/변수: camelCase
const getUserData = () => {};
const reportService = {};
```
---
## 코드 리뷰 체크리스트
### 제출 전 확인
- [ ] 코드가 스타일 가이드를 따르는가?
- [ ] 주석이 적절한가?
- [ ] 테스트가 작성되었는가?
- [ ] 에러 처리가 되어있는가?
- [ ] 보안 취약점이 없는가?
- [ ] 성능 이슈가 없는가?
- [ ] 문서가 업데이트되었는가?
### 리뷰어 확인사항
- [ ] 코드 로직이 명확한가?
- [ ] 중복 코드가 없는가?
- [ ] 변수명이 의미있는가?
- [ ] 함수가 단일 책임을 가지는가?
- [ ] 테스트가 충분한가?
---
## 도구 및 린터 설정
### ESLint
```json
{
"extends": ["eslint:recommended"],
"env": {
"node": true,
"es6": true
},
"rules": {
"indent": ["error", 2],
"quotes": ["error", "single"],
"semi": ["error", "always"],
"no-var": "error",
"prefer-const": "error",
"no-console": "warn"
}
}
```
### Prettier
```json
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80
}
```
---
## 참고 자료
- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript)
- [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)
- [Node.js Best Practices](https://github.com/goldbergyoni/nodebestpractices)
- [Clean Code JavaScript](https://github.com/ryanmcdermott/clean-code-javascript)
---
*마지막 업데이트: 2025-12-11*

662
docs/guides/SETUP.md Normal file
View File

@@ -0,0 +1,662 @@
# 개발 환경 설정 가이드
> TK-FB-Project 로컬 개발 환경 구축 가이드
## 📋 목차
1. [시스템 요구사항](#시스템-요구사항)
2. [필수 도구 설치](#필수-도구-설치)
3. [프로젝트 설정](#프로젝트-설정)
4. [데이터베이스 설정](#데이터베이스-설정)
5. [애플리케이션 실행](#애플리케이션-실행)
6. [개발 도구](#개발-도구)
7. [문제 해결](#문제-해결)
---
## 시스템 요구사항
### 최소 사양
- **OS**: macOS, Linux, Windows 10+
- **CPU**: 2 Core 이상
- **RAM**: 4GB 이상
- **디스크**: 10GB 이상 여유 공간
### 권장 사양
- **OS**: macOS (Apple Silicon) 또는 Ubuntu 22.04 LTS
- **CPU**: 4 Core 이상
- **RAM**: 8GB 이상
- **디스크**: SSD 20GB 이상
---
## 필수 도구 설치
### 1. Node.js & npm
**macOS (Homebrew)**:
```bash
# Homebrew 설치 (없는 경우)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Node.js 설치
brew install node@20
# 버전 확인
node --version # v20.x.x
npm --version # 10.x.x
```
**Ubuntu/Debian**:
```bash
# NodeSource repository 추가
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
# Node.js 설치
sudo apt-get install -y nodejs
# 버전 확인
node --version
npm --version
```
**Windows**:
- [Node.js 공식 사이트](https://nodejs.org/)에서 LTS 버전 다운로드 및 설치
### 2. Git
**macOS**:
```bash
brew install git
```
**Ubuntu/Debian**:
```bash
sudo apt-get install git
```
**Windows**:
- [Git for Windows](https://git-scm.com/download/win) 다운로드
**설정**:
```bash
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
```
### 3. Docker & Docker Compose
**macOS**:
```bash
# Docker Desktop 설치
brew install --cask docker
# Docker Desktop 실행 후 확인
docker --version
docker-compose --version
```
**Ubuntu/Debian**:
```bash
# Docker 설치
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Docker Compose 설치
sudo apt-get install docker-compose-plugin
# 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
newgrp docker
# 버전 확인
docker --version
docker compose version
```
**Windows**:
- [Docker Desktop for Windows](https://docs.docker.com/desktop/install/windows-install/) 설치
### 4. MySQL Client (선택사항)
**macOS**:
```bash
brew install mysql-client
```
**Ubuntu/Debian**:
```bash
sudo apt-get install mysql-client
```
---
## 프로젝트 설정
### 1. 저장소 클론
```bash
# HTTPS
git clone https://github.com/your-org/TK-FB-Project.git
# 또는 SSH
git clone git@github.com:your-org/TK-FB-Project.git
# 프로젝트 디렉토리로 이동
cd TK-FB-Project
```
### 2. 환경 변수 설정
```bash
# .env.example 복사
cp .env.example .env
# .env 파일 편집
nano .env # 또는 vi, code 등
```
**.env 파일 설정**:
```bash
# Database
DB_HOST=localhost
DB_PORT=3306
DB_NAME=hyungi
DB_USER=hyungi
DB_PASSWORD=your_secure_password_here
DB_ROOT_PASSWORD=your_root_password_here
# API
API_PORT=20005
NODE_ENV=development
# JWT
JWT_SECRET=your_jwt_secret_key_at_least_32_characters
JWT_REFRESH_SECRET=your_refresh_secret_key_at_least_32_characters
# Email (선택사항)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USER=your-email@gmail.com
EMAIL_PASSWORD=your-app-password
# OpenAI (선택사항)
OPENAI_API_KEY=your_openai_api_key
```
**보안 참고**:
```bash
# 강력한 랜덤 비밀번호 생성
openssl rand -base64 32
# 또는
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
### 3. 백엔드 의존성 설치
```bash
cd api.hyungi.net
npm install
```
**주요 의존성**:
- express: 웹 프레임워크
- mysql2: MySQL 드라이버
- jsonwebtoken: JWT 인증
- bcryptjs: 비밀번호 해싱
- cors: CORS 미들웨어
- dotenv: 환경변수 관리
### 4. 프론트엔드 설정
```bash
cd ../web-ui
# 프론트엔드는 Vanilla JS이므로 별도 빌드 불필요
```
---
## 데이터베이스 설정
### 방법 1: Docker Compose (권장)
```bash
# 프로젝트 루트에서
cd /path/to/TK-FB-Project
# Docker 컨테이너 시작
docker-compose up -d db
# 로그 확인
docker-compose logs -f db
# MySQL 준비 확인 (약 30초 소요)
docker-compose exec db mysqladmin ping -h localhost
```
**초기 데이터 로드**:
```bash
# SQL 파일 임포트
docker-compose exec -T db mysql -u hyungi -p hyungi < hyungi.sql
# 비밀번호 입력: .env 파일의 DB_PASSWORD
```
### 방법 2: 로컬 MySQL 설치
**macOS**:
```bash
# MySQL 설치
brew install mysql@8.0
# MySQL 시작
brew services start mysql@8.0
# 보안 설정
mysql_secure_installation
```
**Ubuntu/Debian**:
```bash
# MySQL 설치
sudo apt-get install mysql-server
# MySQL 시작
sudo systemctl start mysql
sudo systemctl enable mysql
# 보안 설정
sudo mysql_secure_installation
```
**데이터베이스 생성**:
```bash
# MySQL 접속
mysql -u root -p
# SQL 실행
CREATE DATABASE hyungi CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'hyungi'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON hyungi.* TO 'hyungi'@'localhost';
FLUSH PRIVILEGES;
EXIT;
# 데이터 임포트
mysql -u hyungi -p hyungi < hyungi.sql
```
### 데이터베이스 확인
```bash
# Docker 사용 시
docker-compose exec db mysql -u hyungi -p hyungi
# 로컬 MySQL 사용 시
mysql -u hyungi -p hyungi
```
```sql
-- 테이블 확인
SHOW TABLES;
-- 사용자 확인
SELECT * FROM users LIMIT 5;
-- 데이터 확인
SELECT COUNT(*) FROM daily_work_reports;
```
---
## 애플리케이션 실행
### 개발 모드 (Docker Compose)
```bash
# 전체 서비스 시작
docker-compose up
# 백그라운드 실행
docker-compose up -d
# 로그 확인
docker-compose logs -f
# 특정 서비스 로그
docker-compose logs -f api
docker-compose logs -f web
# 서비스 중지
docker-compose down
# 볼륨 포함 완전 삭제
docker-compose down -v
```
### 개발 모드 (로컬 실행)
**터미널 1 - 백엔드**:
```bash
cd api.hyungi.net
# 개발 모드 (nodemon 사용)
npm run dev
# 또는 일반 실행
npm start
```
**터미널 2 - 프론트엔드**:
```bash
cd web-ui
# 간단한 HTTP 서버 실행
python3 -m http.server 8080
# 또는 Node.js http-server
npx http-server -p 8080
# 또는 PHP
php -S localhost:8080
```
### 접속 확인
- **프론트엔드**: http://localhost:8080
- **백엔드 API**: http://localhost:20005/api
- **데이터베이스**: localhost:3306
**API 테스트**:
```bash
# Health check
curl http://localhost:20005/api/health
# 로그인 테스트
curl -X POST http://localhost:20005/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"your_password"}'
```
---
## 개발 도구
### 1. VSCode 확장 프로그램
**필수**:
- ESLint
- Prettier - Code formatter
- MySQL (cweijan.vscode-mysql-client2)
- Docker
**권장**:
- GitLens
- Thunder Client (API 테스트)
- Live Server
- JavaScript (ES6) code snippets
**설치**:
```bash
# VSCode에서
Cmd/Ctrl + Shift + X → 확장 프로그램 검색 및 설치
```
### 2. VSCode 설정
`.vscode/settings.json`:
```json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"javascript.suggest.autoImports": true,
"javascript.updateImportsOnFileMove.enabled": "always",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
```
### 3. 디버깅 설정
`.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch API Server",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/api.hyungi.net/index.js",
"env": {
"NODE_ENV": "development"
}
}
]
}
```
### 4. 유용한 명령어
```bash
# 패키지 업데이트 확인
npm outdated
# 보안 취약점 확인
npm audit
# 보안 취약점 자동 수정
npm audit fix
# 캐시 정리
npm cache clean --force
# node_modules 재설치
rm -rf node_modules package-lock.json
npm install
```
---
## 문제 해결
### 일반적인 문제
#### 1. Port already in use
**증상**:
```
Error: listen EADDRINUSE: address already in use :::20005
```
**해결**:
```bash
# 포트 사용 중인 프로세스 확인
lsof -i :20005
# 프로세스 종료
kill -9 <PID>
# 또는 다른 포트 사용
# .env 파일에서 API_PORT 변경
```
#### 2. MySQL 연결 실패
**증상**:
```
Error: connect ECONNREFUSED 127.0.0.1:3306
```
**해결**:
```bash
# Docker 사용 시
docker-compose ps # db 컨테이너 상태 확인
docker-compose up -d db # db 재시작
# 로컬 MySQL 사용 시
sudo systemctl status mysql # 상태 확인
sudo systemctl start mysql # MySQL 시작
# 연결 테스트
mysql -h localhost -u hyungi -p
```
#### 3. Permission denied
**증상**:
```
Error: EACCES: permission denied
```
**해결**:
```bash
# Docker 권한 문제
sudo usermod -aG docker $USER
newgrp docker
# 파일 권한 문제
sudo chown -R $USER:$USER /path/to/project
```
#### 4. Module not found
**증상**:
```
Error: Cannot find module 'express'
```
**해결**:
```bash
# node_modules 재설치
cd api.hyungi.net
rm -rf node_modules package-lock.json
npm install
```
#### 5. JWT 토큰 오류
**증상**:
```
Error: jwt malformed
Error: invalid signature
```
**해결**:
```bash
# .env 파일 확인
# JWT_SECRET이 올바르게 설정되어 있는지 확인
# 토큰 재발급
# 로그아웃 후 다시 로그인
```
### 데이터베이스 문제
#### MySQL 8.0 호환성
**증상**:
```
Error: ER_NOT_SUPPORTED_AUTH_MODE
```
**해결**:
```sql
-- MySQL 접속
mysql -u root -p
-- 인증 방식 변경
ALTER USER 'hyungi'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
FLUSH PRIVILEGES;
```
#### 한글 깨짐
**해결**:
```sql
-- 데이터베이스 문자셋 확인
SHOW VARIABLES LIKE 'character_set%';
-- 테이블 문자셋 변경
ALTER TABLE daily_work_reports CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```
### Docker 문제
#### 컨테이너 재시작
```bash
# 컨테이너 재시작
docker-compose restart
# 특정 서비스만
docker-compose restart api
# 완전 재빌드
docker-compose down
docker-compose build --no-cache
docker-compose up -d
```
#### 볼륨 문제
```bash
# 볼륨 확인
docker volume ls
# 볼륨 삭제 (주의: 데이터 손실)
docker-compose down -v
# 특정 볼륨만 삭제
docker volume rm tk-fb-project_mysql_data
```
---
## 추가 리소스
### 공식 문서
- [Node.js](https://nodejs.org/docs)
- [Express](https://expressjs.com/)
- [MySQL](https://dev.mysql.com/doc/)
- [Docker](https://docs.docker.com/)
### 내부 문서
- [아키텍처 개요](../architecture/OVERVIEW.md)
- [API 문서](../api/ENDPOINTS.md)
- [코딩 스타일 가이드](CODING_STYLE.md)
- [문제 해결 가이드](TROUBLESHOOTING.md)
### 커뮤니티
- [Node.js GitHub](https://github.com/nodejs/node)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/node.js)
---
## 체크리스트
설정 완료 확인:
- [ ] Node.js 설치 (v20+)
- [ ] Git 설치 및 설정
- [ ] Docker 설치 및 실행
- [ ] 프로젝트 클론
- [ ] .env 파일 생성 및 설정
- [ ] npm install 완료
- [ ] 데이터베이스 생성 및 데이터 로드
- [ ] 백엔드 서버 실행 확인
- [ ] 프론트엔드 서버 실행 확인
- [ ] API 테스트 성공
- [ ] 로그인 성공
- [ ] VSCode 확장 프로그램 설치
---
**도움이 필요하면**: 프로젝트 관리자에게 문의하세요.
*마지막 업데이트: 2025-12-11*