first commit
This commit is contained in:
474
CURRENT_WORKS.md
Normal file
474
CURRENT_WORKS.md
Normal file
@@ -0,0 +1,474 @@
|
||||
# React 프론트엔드 작업 현황
|
||||
|
||||
## 2025-10-13 (일) - React 프론트엔드 프로젝트 초기 셋팅 완료
|
||||
|
||||
### ✅ 완료된 작업
|
||||
|
||||
#### 1. 프로젝트 초기화 및 의존성 설치
|
||||
- Vite + React 19 + TypeScript 5 프로젝트 생성
|
||||
- 모든 필수 의존성 설치 완료 (242개 패키지, 0 vulnerabilities)
|
||||
|
||||
**설치된 주요 패키지:**
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@tanstack/react-query": "^5.90.2",
|
||||
"@tanstack/react-query-devtools": "^5.90.2",
|
||||
"axios": "^1.12.2",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.545.0",
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"react-hook-form": "^7.65.0",
|
||||
"react-router-dom": "^7.9.4",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"zod": "^4.1.12",
|
||||
"zustand": "^5.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.14",
|
||||
"tailwindcss": "^4.1.14",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "^7.1.7"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 프로젝트 구조 생성
|
||||
완성된 디렉토리 구조:
|
||||
```
|
||||
react/
|
||||
├── src/
|
||||
│ ├── components/ # 재사용 가능한 UI 컴포넌트
|
||||
│ ├── pages/ # 라우트별 페이지 컴포넌트
|
||||
│ ├── hooks/ # Custom React Hooks
|
||||
│ ├── services/ # API 서비스 레이어
|
||||
│ │ └── api.ts # Auth, Tenant API + CRUD 헬퍼
|
||||
│ ├── stores/ # Zustand 스토어
|
||||
│ │ └── auth.ts # 인증 스토어 (persist 포함)
|
||||
│ ├── utils/ # 유틸리티 함수
|
||||
│ ├── types/ # TypeScript 타입 정의
|
||||
│ │ └── api.ts # API 응답 타입
|
||||
│ ├── lib/ # 라이브러리 설정
|
||||
│ │ ├── utils.ts # cn(), formatDate(), getEnv()
|
||||
│ │ ├── axios.ts # Axios 인스턴스 + 인터셉터
|
||||
│ │ └── query-client.ts # React Query 설정
|
||||
│ ├── App.tsx # 메인 앱 컴포넌트
|
||||
│ ├── main.tsx # 엔트리 포인트
|
||||
│ └── index.css # Tailwind CSS + 테마
|
||||
├── public/ # 정적 파일
|
||||
├── .env.local # 환경변수 (VITE_API_BASE_URL 등)
|
||||
├── vite.config.ts # Vite 설정 (path aliases 포함)
|
||||
├── tailwind.config.js # Tailwind CSS v4 설정
|
||||
├── tsconfig.json # TypeScript 설정 (프로젝트 참조)
|
||||
├── tsconfig.app.json # 앱 TypeScript 설정 (path aliases)
|
||||
├── package.json # 의존성 정의
|
||||
└── README.md # 프로젝트 문서
|
||||
```
|
||||
|
||||
#### 3. Tailwind CSS 4.x 설정
|
||||
- PostCSS 플러그인 설치: `@tailwindcss/postcss`
|
||||
- Tailwind CSS v4 방식으로 `@theme` 설정
|
||||
- Light/Dark 모드 지원 (CSS 변수 기반)
|
||||
- shadcn/ui 호환 색상 시스템
|
||||
|
||||
**주요 설정 파일:**
|
||||
- `index.css`: `@import "tailwindcss"` + `@theme` 블록
|
||||
- `postcss.config.js`: `@tailwindcss/postcss` 플러그인
|
||||
- `tailwind.config.js`: content paths 정의
|
||||
|
||||
#### 4. Path Aliases 설정
|
||||
TypeScript 및 Vite에서 `@/` 경로 별칭 사용 가능:
|
||||
|
||||
**tsconfig.app.json:**
|
||||
```json
|
||||
{
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"@/components/*": ["./src/components/*"],
|
||||
"@/pages/*": ["./src/pages/*"],
|
||||
"@/hooks/*": ["./src/hooks/*"],
|
||||
"@/services/*": ["./src/services/*"],
|
||||
"@/stores/*": ["./src/stores/*"],
|
||||
"@/utils/*": ["./src/utils/*"],
|
||||
"@/types/*": ["./src/types/*"],
|
||||
"@/lib/*": ["./src/lib/*"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**vite.config.ts:**
|
||||
```typescript
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
'@/components': path.resolve(__dirname, './src/components'),
|
||||
// ... 기타 aliases
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5. Axios + API 인터셉터 구현
|
||||
**파일: `src/lib/axios.ts`**
|
||||
- API Key 헤더 자동 추가: `X-API-Key`
|
||||
- Bearer Token 자동 추가: `Authorization: Bearer {token}`
|
||||
- 401 Unauthorized 시 자동 로그아웃 + 리다이렉트
|
||||
- 403/404/500 에러 핸들링
|
||||
|
||||
**API 서비스 구조 (`src/services/api.ts`):**
|
||||
```typescript
|
||||
// 인증 API
|
||||
export const authApi = {
|
||||
login: (email, password) => ApiResponse<LoginResponse>
|
||||
logout: () => ApiResponse<null>
|
||||
me: () => ApiResponse<any>
|
||||
}
|
||||
|
||||
// 테넌트 API
|
||||
export const tenantApi = {
|
||||
switch: (tenantId) => ApiResponse<any>
|
||||
list: () => ApiResponse<any>
|
||||
}
|
||||
|
||||
// 제네릭 CRUD 헬퍼
|
||||
export const createCrudApi = <T>(basePath: string) => {
|
||||
list, get, create, update, delete
|
||||
}
|
||||
```
|
||||
|
||||
#### 6. React Query 설정
|
||||
**파일: `src/lib/query-client.ts`**
|
||||
```typescript
|
||||
{
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: 5 * 60 * 1000, // 5분
|
||||
gcTime: 10 * 60 * 1000 // 10분
|
||||
},
|
||||
mutations: {
|
||||
retry: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 7. Zustand 인증 스토어 구현
|
||||
**파일: `src/stores/auth.ts`**
|
||||
- LocalStorage persist 적용
|
||||
- 사용자 정보, 토큰, 현재 테넌트 관리
|
||||
- `setAuth`, `setCurrentTenant`, `logout`, `clearAuth` 액션
|
||||
|
||||
**사용 예시:**
|
||||
```typescript
|
||||
const { user, isAuthenticated, setAuth, logout } = useAuthStore()
|
||||
```
|
||||
|
||||
#### 8. TypeScript 타입 정의
|
||||
**파일: `src/types/api.ts`**
|
||||
- `ApiResponse<T>`: 표준 API 응답 구조
|
||||
- `PaginatedResponse<T>`: 페이지네이션 응답
|
||||
- `User`, `Tenant`: 기본 엔티티 타입
|
||||
- `LoginResponse`, `AuthUser`: 인증 관련 타입
|
||||
|
||||
#### 9. 유틸리티 함수
|
||||
**파일: `src/lib/utils.ts`**
|
||||
- `cn()`: Tailwind 클래스 병합 (clsx + tailwind-merge)
|
||||
- `formatDate()`: 날짜 포맷팅 (TODO: date-fns 적용 예정)
|
||||
- `delay()`: 비동기 딜레이
|
||||
- `getEnv()`: 타입 안전 환경변수 접근
|
||||
|
||||
#### 10. Docker 설정 완료
|
||||
**docker-compose.yml에 React 서비스 추가:**
|
||||
```yaml
|
||||
react:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ../docker/react/Dockerfile
|
||||
volumes:
|
||||
- ../react:/app
|
||||
- /app/node_modules
|
||||
environment:
|
||||
- VITE_API_BASE_URL=http://api.sam.kr
|
||||
- VITE_API_KEY=${VITE_API_KEY:-}
|
||||
- VITE_APP_NAME=SAM
|
||||
- VITE_APP_ENV=development
|
||||
networks:
|
||||
- samnet
|
||||
working_dir: /app
|
||||
```
|
||||
|
||||
**nginx.conf에 dev.sam.kr 설정 추가:**
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name dev.sam.kr;
|
||||
|
||||
location / {
|
||||
proxy_pass http://react:5173;
|
||||
# WebSocket support for Vite HMR
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Dockerfile (`docker/react/Dockerfile`):**
|
||||
```dockerfile
|
||||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
COPY ../../react/package*.json ./
|
||||
RUN npm ci
|
||||
COPY ../../react .
|
||||
EXPOSE 5173
|
||||
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
|
||||
```
|
||||
|
||||
#### 11. 환경변수 설정
|
||||
**파일: `.env.local`**
|
||||
```env
|
||||
VITE_API_BASE_URL=http://api.sam.kr
|
||||
VITE_API_KEY=your-api-key-here
|
||||
VITE_APP_NAME=SAM
|
||||
VITE_APP_ENV=development
|
||||
```
|
||||
|
||||
#### 12. 빌드 검증 완료
|
||||
```bash
|
||||
npm run build
|
||||
# ✅ Output:
|
||||
# dist/index.html 0.45 kB │ gzip: 0.29 kB
|
||||
# dist/assets/index-Uh-4EJ_4.css 6.56 kB │ gzip: 2.02 kB
|
||||
# dist/assets/index-DmPu9Lzh.js 250.04 kB │ gzip: 79.38 kB
|
||||
# ✓ built in 580ms
|
||||
```
|
||||
|
||||
### 📋 주요 의사 결정
|
||||
|
||||
1. **Tailwind CSS v4 채택**
|
||||
- 최신 버전 사용으로 향후 호환성 보장
|
||||
- `@theme` 방식 사용 (shadcn/ui 호환)
|
||||
- PostCSS 플러그인: `@tailwindcss/postcss`
|
||||
|
||||
2. **API 인증 전략**
|
||||
- 2단계 인증: API Key + Sanctum Bearer Token
|
||||
- 인터셉터를 통한 자동 헤더 추가
|
||||
- 401 에러 시 자동 로그아웃 처리
|
||||
|
||||
3. **상태 관리 분리**
|
||||
- 전역 상태: Zustand (인증, UI 상태)
|
||||
- 서버 상태: React Query (API 데이터)
|
||||
- LocalStorage persist로 새로고침 대응
|
||||
|
||||
4. **Path Aliases 전략**
|
||||
- `@/` 기본 경로로 통일
|
||||
- 각 주요 디렉토리별 개별 alias 제공
|
||||
- TypeScript + Vite 양쪽 설정 동기화
|
||||
|
||||
5. **Docker 개발 환경**
|
||||
- Hot Reload 지원 (Vite HMR + WebSocket)
|
||||
- Volume mount로 실시간 코드 반영
|
||||
- node_modules 별도 volume으로 성능 최적화
|
||||
|
||||
### 🎯 다음 단계 (향후 작업)
|
||||
|
||||
1. **UI 컴포넌트 개발**
|
||||
- shadcn/ui 컴포넌트 추가 설치 필요시
|
||||
- 공통 컴포넌트 제작 (Button, Input, Modal 등)
|
||||
|
||||
2. **페이지 구현**
|
||||
- 로그인 페이지
|
||||
- 대시보드
|
||||
- 주요 기능 페이지들
|
||||
|
||||
3. **라우팅 설정**
|
||||
- React Router 라우트 정의
|
||||
- Protected Routes (인증 필요 페이지)
|
||||
- 권한 기반 라우팅
|
||||
|
||||
4. **API 연동 확장**
|
||||
- 각 도메인별 API 서비스 추가
|
||||
- React Query hooks 작성
|
||||
- 에러 핸들링 강화
|
||||
|
||||
5. **테스트 환경 구축**
|
||||
- Docker Compose로 전체 환경 테스트
|
||||
- dev.sam.kr 도메인 접속 확인
|
||||
|
||||
### 🔧 개발 명령어
|
||||
|
||||
```bash
|
||||
# 개발 서버 실행
|
||||
npm run dev
|
||||
|
||||
# 프로덕션 빌드
|
||||
npm run build
|
||||
|
||||
# 빌드 결과 미리보기
|
||||
npm run preview
|
||||
|
||||
# Docker로 실행 (전체 환경)
|
||||
cd ../docker
|
||||
docker-compose up -d react
|
||||
```
|
||||
|
||||
### 📌 참고사항
|
||||
|
||||
1. **TypeScript 엄격 모드**
|
||||
- `verbatimModuleSyntax` 활성화
|
||||
- 타입 import 시 `type` 키워드 필수: `import type { ... }`
|
||||
|
||||
2. **Tailwind CSS v4 변경사항**
|
||||
- `@apply` 대신 `@theme` 사용
|
||||
- CSS 변수 직접 정의
|
||||
- 플러그인: `@tailwindcss/postcss` 필수
|
||||
|
||||
3. **API 응답 구조**
|
||||
- 모든 API는 `{ success, message, data }` 구조
|
||||
- 메시지는 i18n 키 사용 (예: `message.created`)
|
||||
|
||||
4. **환경변수 접근**
|
||||
- Vite에서는 `import.meta.env.VITE_*` 형식만 사용 가능
|
||||
- `getEnv()` 헬퍼 함수로 타입 안전 접근
|
||||
|
||||
### ✅ 검증 완료 항목
|
||||
|
||||
- [x] npm install 성공 (0 vulnerabilities)
|
||||
- [x] npm run build 성공
|
||||
- [x] TypeScript 컴파일 에러 없음
|
||||
- [x] Path aliases 정상 작동
|
||||
- [x] Tailwind CSS 빌드 성공
|
||||
- [x] Docker 설정 파일 생성
|
||||
- [x] Nginx 프록시 설정 완료
|
||||
- [x] 환경변수 파일 생성
|
||||
- [x] **Docker 컨테이너 빌드 및 실행 완료**
|
||||
- [x] **dev.sam.kr 도메인 설정 완료**
|
||||
|
||||
---
|
||||
|
||||
## 2025-10-13 (일) - Docker 환경 실행 완료 + Vite 프록시 설정 수정
|
||||
|
||||
### Docker 컨테이너 실행
|
||||
|
||||
#### 문제 해결 과정 #1: Docker Build Context
|
||||
**문제**: 초기 docker-compose.yml 설정에서 빌드 context가 잘못 설정됨
|
||||
```yaml
|
||||
# 문제 있는 설정
|
||||
react:
|
||||
build:
|
||||
context: . # /docker 디렉토리를 context로 사용
|
||||
dockerfile: ../docker/react/Dockerfile
|
||||
```
|
||||
|
||||
**해결**: Docker build context를 상위 디렉토리로 변경
|
||||
```yaml
|
||||
# 수정된 설정
|
||||
react:
|
||||
build:
|
||||
context: .. # /SAM 디렉토리를 context로 사용
|
||||
dockerfile: docker/react/Dockerfile
|
||||
```
|
||||
|
||||
#### 실행 결과
|
||||
```bash
|
||||
docker-compose up -d --build react
|
||||
# ✅ 빌드 성공 (2.5초)
|
||||
# ✅ 컨테이너 시작 완료
|
||||
|
||||
docker ps --filter "name=react"
|
||||
# CONTAINER ID IMAGE STATUS PORTS NAMES
|
||||
# 515b94586161 sam-react Up 7 seconds 5173/tcp sam-react-1
|
||||
|
||||
docker-compose restart nginx
|
||||
# ✅ Nginx 재시작 완료 (dev.sam.kr 설정 반영)
|
||||
```
|
||||
|
||||
#### 문제 해결 과정 #2: Vite allowedHosts 설정
|
||||
**오류 메시지**:
|
||||
```
|
||||
Blocked request. This host ("dev.sam.kr") is not allowed.
|
||||
To allow this host, add "dev.sam.kr" to `server.allowedHosts` in vite.config.js.
|
||||
```
|
||||
|
||||
**근본 원인 분석** (devops-architect 페르소나 사용):
|
||||
1. **Vite 보안 메커니즘**: Host Header를 검증하여 허용되지 않은 도메인 요청 차단
|
||||
2. **Docker 환경**: 컨테이너 내부에서 실행되는 Vite가 Nginx의 `Host: dev.sam.kr` 헤더를 받음
|
||||
3. **기본 설정**: `allowedHosts`가 설정되지 않아 프록시를 통한 접근 차단
|
||||
|
||||
**해결 방법**:
|
||||
`vite.config.ts`에 다음 설정 추가:
|
||||
```typescript
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 5173,
|
||||
strictPort: true,
|
||||
// Nginx 리버스 프록시 환경을 위한 설정
|
||||
hmr: {
|
||||
clientPort: 80, // HTTP 환경 (nginx port 80)
|
||||
protocol: 'ws', // WebSocket (HTTP용)
|
||||
host: 'dev.sam.kr', // HMR 연결 호스트
|
||||
},
|
||||
watch: {
|
||||
usePolling: true, // Docker 파일 감시 필수
|
||||
interval: 100,
|
||||
},
|
||||
cors: true,
|
||||
allowedHosts: [
|
||||
'dev.sam.kr', // 프로덕션 도메인
|
||||
'localhost', // 로컬 개발
|
||||
'127.0.0.1', // 로컬 IP
|
||||
'.sam.kr', // 서브도메인 와일드카드
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
**주요 변경사항**:
|
||||
- ✅ `allowedHosts` 추가: dev.sam.kr 및 와일드카드 도메인 허용
|
||||
- ✅ `hmr.clientPort`: 80 (HTTP 환경에 맞춤)
|
||||
- ✅ `hmr.protocol`: 'ws' (HTTPS가 아닌 HTTP 사용)
|
||||
- ✅ `watch.usePolling`: Docker 환경에서 파일 변경 감지
|
||||
|
||||
**재시작 결과**:
|
||||
```bash
|
||||
docker-compose restart react
|
||||
# ✅ Vite 서버 정상 재시작 (88ms)
|
||||
# ✅ Network: http://172.18.0.6:5173/ 리스닝 중
|
||||
```
|
||||
|
||||
### 접속 정보
|
||||
- **URL**: http://dev.sam.kr
|
||||
- **포트**: 80 (Nginx 프록시) → 5173 (Vite 개발 서버)
|
||||
- **HMR**: WebSocket을 통한 Hot Module Replacement 지원 (ws://dev.sam.kr)
|
||||
|
||||
### 추가 검증 항목
|
||||
- [x] Docker 이미지 빌드 성공 (263 packages, 0 vulnerabilities)
|
||||
- [x] React 컨테이너 정상 실행 중
|
||||
- [x] Nginx 프록시 설정 반영
|
||||
- [x] Vite HMR WebSocket 연결 지원
|
||||
- [x] **Vite allowedHosts 설정 완료**
|
||||
- [x] **dev.sam.kr 접속 허용 설정 완료**
|
||||
|
||||
### 🔍 사용된 도구 및 방법론
|
||||
- **SuperClaude 페르소나**: devops-architect (Docker + Nginx + Vite 통합 분석)
|
||||
- **MCP**: 없음 (devops-architect Task 에이전트 사용)
|
||||
- **Native Tools**: Edit (vite.config.ts 수정), Bash (Docker 재시작)
|
||||
|
||||
### 📚 학습 포인트
|
||||
1. **Docker 프록시 환경에서는 반드시 `allowedHosts` 설정 필요**
|
||||
2. **HMR 설정은 프로토콜(HTTP/HTTPS)에 따라 다르게 구성**
|
||||
3. **복잡한 통합 작업은 SuperClaude 페르소나 활용이 필수**
|
||||
4. **단순한 설정으로 보이는 작업도 전문가 분석이 오류 예방에 중요**
|
||||
|
||||
---
|
||||
|
||||
**작업 완료 시간**: 약 30분 (설정) + 5분 (Docker 실행) + 10분 (프록시 설정 수정)
|
||||
**생성된 파일 수**: 25개
|
||||
**수정된 파일 수**: 1개 (vite.config.ts)
|
||||
**작성된 코드 라인 수**: 약 800줄
|
||||
**사용된 도구**: Vite, npm, Tailwind CSS v4, Docker, Docker Compose, devops-architect 페르소나
|
||||
|
||||
Reference in New Issue
Block a user