Merge pull request '사용자 프로필 수정 기능 및 스크립트, 도커 파일 정리' (#7) from userProfile into dev

Reviewed-on: http://39.117.244.52:3000/kjs/ERP-node/pulls/7
This commit is contained in:
hyeonsu 2025-08-28 13:51:57 +09:00
commit f921396539
57 changed files with 894 additions and 2424 deletions

28
.gitignore vendored
View File

@ -245,3 +245,31 @@ cache/
.vscode/settings.json
.idea/workspace.xml
*.user
# ===== Gradle 관련 파일들 (레거시 Java 프로젝트) =====
# Gradle 캐시 및 빌드 파일들
.gradle/
*/.gradle/
gradle/
gradlew
gradlew.bat
gradle.properties
build/
*/build/
# Gradle Wrapper
gradle-wrapper.jar
gradle-wrapper.properties
# IntelliJ IDEA 관련 (Gradle 프로젝트)
.idea/
*.iml
*.ipr
*.iws
out/
# Eclipse 관련 (Gradle 프로젝트)
.project
.classpath
.settings/
bin/

386
DOCKER.md Normal file
View File

@ -0,0 +1,386 @@
# 🐳 Docker 가이드 - PLM 솔루션 (ERP-node)
이 문서는 PLM 솔루션의 Docker 환경 설정 및 사용법을 설명합니다.
## 📋 개요
**기술 스택:**
- **백엔드**: Node.js + TypeScript + Prisma + PostgreSQL
- **프론트엔드**: Next.js + TypeScript + Tailwind CSS
- **컨테이너**: Docker + Docker Compose
**환경:**
- **개발**: Mac (볼륨 마운트 + Hot Reload)
- **운영**: Linux 서버 (최적화된 프로덕션 빌드)
---
## 🔧 개발 환경 (Mac)
### 빠른 시작
```bash
# 전체 서비스 시작 (병렬 빌드 - 가장 빠름!)
./scripts/dev/start-all-parallel.sh
```
### 개별 서비스 시작
```bash
# 백엔드만 시작
./scripts/dev/start-backend.sh
# 프론트엔드만 시작
./scripts/dev/start-frontend.sh
```
### 개발용 Docker Compose 파일들
- **`docker/dev/docker-compose.backend.mac.yml`** - Mac 개발용 백엔드
- 볼륨 마운트: `./backend-node:/app` (Hot Reload)
- Dockerfile: `docker/dev/backend.Dockerfile`
- 포트: `8080`
- **`docker/dev/docker-compose.frontend.mac.yml`** - Mac 개발용 프론트엔드
- 볼륨 마운트: `./frontend:/app` (Hot Reload)
- Dockerfile: `docker/dev/frontend.Dockerfile`
- 포트: `3000`
### 개발 환경 특징
- ✅ **Hot Reload**: 코드 변경 시 자동 반영
- ✅ **볼륨 마운트**: 실시간 개발
- ✅ **디버그 모드**: 상세 로그 출력
- ✅ **빠른 재시작**: Docker 재빌드 불필요
### 🔥 Hot Reload 상세 가이드
#### ✅ **바로 반영되는 것들 (즉시 Hot Reload)**
**백엔드 (Node.js + TypeScript):**
```bash
backend-node/src/controllers/*.ts # API 컨트롤러 수정
backend-node/src/services/*.ts # 비즈니스 로직 수정
backend-node/src/routes/*.ts # 라우터 설정 수정
backend-node/src/middleware/*.ts # 미들웨어 수정
backend-node/src/utils/*.ts # 유틸리티 함수 수정
backend-node/src/types/*.ts # 타입 정의 수정
backend-node/src/config/*.ts # 애플리케이션 설정
```
**반영 시간**: 1-2초 (nodemon 자동 재시작)
**프론트엔드 (Next.js + TypeScript):**
```bash
frontend/components/**/*.tsx # React 컴포넌트 수정
frontend/app/**/*.tsx # 페이지 컴포넌트 수정
frontend/lib/**/*.ts # 유틸리티 함수 수정
frontend/hooks/*.ts # 커스텀 훅 수정
frontend/types/*.ts # 타입 정의 수정
frontend/constants/*.ts # 상수 정의 수정
CSS/SCSS 파일 수정 # 스타일 변경
```
**반영 시간**: 즉시 (Fast Refresh)
#### ❌ **Docker 재시작이 필요한 것들**
**의존성 변경:**
```bash
package.json 수정 # 새 패키지 추가/제거
npm install / npm uninstall # 패키지 설치/제거
package-lock.json 변경 # 의존성 잠금 파일
```
**Prisma 관련:**
```bash
backend-node/prisma/schema.prisma # DB 스키마 변경
npx prisma migrate # 마이그레이션 실행
npx prisma generate # 클라이언트 재생성
```
**설정 파일:**
```bash
next.config.mjs # Next.js 설정
tsconfig.json # TypeScript 설정
tailwind.config.js # Tailwind CSS 설정
.env / .env.local # 환경 변수
eslint.config.mjs # ESLint 설정
```
**Docker 관련:**
```bash
Dockerfile / Dockerfile.dev # 도커 파일 수정
docker-compose.*.yml # Docker Compose 설정
.dockerignore # Docker 무시 파일
```
#### 🔄 **재시작 방법**
**특정 서비스만 재시작:**
```bash
# 백엔드만 재시작
docker-compose -f docker-compose.backend.mac.yml restart backend
# 프론트엔드만 재시작
docker-compose -f docker-compose.frontend.mac.yml restart frontend
```
**전체 재빌드:**
```bash
# 의존성 변경 시 (rebuild 필요)
docker-compose -f docker-compose.backend.mac.yml up --build -d
docker-compose -f docker-compose.frontend.mac.yml up --build -d
```
---
## 🚀 운영 환경 (Linux)
### 운영 서버 배포
```bash
# Linux 서버에서 실행
./scripts/prod/start-all-linux.sh
```
### 개별 서비스 시작 (운영용)
```bash
# 직접 Docker Compose 사용
docker-compose -f docker/prod/docker-compose.backend.prod.yml up -d
docker-compose -f docker/prod/docker-compose.frontend.prod.yml up -d
```
### 운영용 Docker Compose 파일들
- **`docker/prod/docker-compose.backend.prod.yml`** - 운영용 백엔드
- Dockerfile: `docker/prod/backend.Dockerfile` (프로덕션 최적화)
- 포트: `8080`
- 환경: `NODE_ENV=production`
- **`docker/prod/docker-compose.frontend.prod.yml`** - 운영용 프론트엔드
- Dockerfile: `docker/prod/frontend.Dockerfile` (프로덕션 최적화)
- 포트: `3000`
- 환경: 최적화된 빌드
### 운영 환경 특징
- ✅ **최적화된 빌드**: 프로덕션용 이미지
- ✅ **보안 강화**: 운영 환경 설정
- ✅ **성능 최적화**: 이미지 크기 최소화
- ✅ **안정성**: 프로덕션 모드
---
## 📁 프로젝트 구조
```
ERP-node/
├── 🔧 개발용 (Mac)
│ ├── start-all-parallel.sh # 병렬 시작 (추천)
│ ├── start-backend.sh # 백엔드만
│ ├── start-frontend.sh # 프론트엔드만
│ ├── docker-compose.backend.mac.yml # Mac 개발용 백엔드
│ └── docker-compose.frontend.mac.yml# Mac 개발용 프론트엔드
├── 🚀 운영용 (Linux)
│ ├── start-all-separated-linux.sh # Linux 운영용
│ ├── start-backend-linux.sh # 백엔드만 (Linux)
│ ├── start-frontend-linux.sh # 프론트엔드만 (Linux)
│ ├── docker-compose.backend.prod.yml# 운영용 백엔드
│ └── docker-compose.frontend.prod.yml# 운영용 프론트엔드
├── 📁 백엔드
│ ├── backend-node/
│ │ ├── Dockerfile # 프로덕션용
│ │ └── Dockerfile.dev # 개발용
│ └── src/, prisma/, package.json...
├── 📁 프론트엔드
│ ├── frontend/
│ │ ├── Dockerfile # 프로덕션용
│ │ └── Dockerfile.dev # 개발용
│ └── app/, components/, hooks/...
└── 🗂️ 기타
├── db/00-create-roles.sh # DB 초기화
└── README.md, DOCKER.md...
```
---
## 🌐 접속 정보
### 개발 환경
- **프론트엔드**: http://localhost:3000
- **백엔드 API**: http://localhost:8080
- **전체 앱**: http://localhost:9771 (프록시 설정 시)
### 운영 환경
- **서버 IP에 따라 다름** (Linux 서버 설정 확인)
---
## 🛠️ 주요 명령어
### Docker 컨테이너 관리
```bash
# 실행 중인 컨테이너 확인
docker ps
# 모든 컨테이너 중지
docker stop $(docker ps -q)
# 사용하지 않는 컨테이너/이미지 정리
docker system prune -f
```
### 로그 확인
```bash
# 백엔드 로그
docker logs pms-backend-mac -f # 개발용
docker logs pms-backend-prod -f # 운영용
# 프론트엔드 로그
docker logs pms-frontend-mac -f # 개발용
docker logs pms-frontend-prod -f # 운영용
```
### 컨테이너 내부 접속
```bash
# 백엔드 컨테이너 접속
docker exec -it pms-backend-mac bash # 개발용
docker exec -it pms-backend-prod bash # 운영용
# 프론트엔드 컨테이너 접속
docker exec -it pms-frontend-mac sh # 개발용
docker exec -it pms-frontend-prod sh # 운영용
```
---
## 🚨 트러블슈팅
### 자주 발생하는 문제들
#### 1. 포트 충돌
```bash
# 포트 사용 중인 프로세스 확인
lsof -i :8080
lsof -i :3000
# 프로세스 종료
kill -9 <PID>
```
#### 2. Docker 빌드 오류
```bash
# Docker 캐시 클리어 후 재빌드
docker builder prune -f
./start-all-parallel.sh
```
#### 3. 볼륨 마운트 문제 (개발환경)
```bash
# Docker Desktop 설정에서 파일 공유 확인
# Docker Desktop > Settings > Resources > File Sharing
```
#### 4. 데이터베이스 연결 오류
```bash
# 데이터베이스 초기화
./db/00-create-roles.sh
# PostgreSQL 연결 확인
docker exec -it <db-container> psql -U postgres
```
### Warning 메시지들 (무시해도 됨)
```
WARN: the attribute `version` is obsolete
Network Error (일시적)
```
이런 메시지들은 Docker Compose 버전 차이로 발생하며, 기능에는 영향 없습니다.
---
## 📈 성능 최적화
### 개발 환경 최적화
- ✅ **병렬 빌드**: `start-all-parallel.sh` 사용
- ✅ **Docker 캐시**: `--no-cache` 제거됨
- ✅ **npm 최적화**: `--prefer-offline --no-audit` 적용
### 운영 환경 최적화
- ✅ **멀티 스테이지 빌드**: Dockerfile 최적화
- ✅ **이미지 크기 최소화**: Alpine Linux 기반
- ✅ **의존성 캐시**: 레이어 캐싱 활용
---
## 🔄 업데이트 가이드
### 개발 환경 업데이트
```bash
# 코드 변경 시 (Hot Reload 자동 반영)
# 별도 작업 불필요
# 의존성 변경 시
docker-compose -f docker-compose.backend.mac.yml up --build -d
```
### 운영 환경 업데이트
```bash
# 새로운 버전 배포
./start-all-separated-linux.sh
```
---
## 📞 지원
**문제 발생 시:**
1. 이 문서의 트러블슈팅 섹션 확인
2. Docker 로그 확인 (`docker logs <container-name>`)
3. 개발팀에 문의
**프로젝트 관련:**
- Node.js 백엔드: `backend-node/` 디렉토리
- Next.js 프론트엔드: `frontend/` 디렉토리
- 데이터베이스: PostgreSQL (JNDI 설정)
---
**버전**: 1.0.0
**마지막 업데이트**: 2024년 12월 28일
**작성자**: PLM 개발팀

View File

@ -1,321 +0,0 @@
# PLM WACE Docker 설정 가이드
## 개요
이 문서는 PLM WACE 애플리케이션을 Docker로 실행하는 방법을 설명합니다.
## 시스템 요구사항
### 리눅스 환경
- Ubuntu 18.04 이상 또는 CentOS 7 이상
- Docker 20.10 이상
- Docker Compose 1.29 이상
- Git (운영환경 배포 시)
### 필수 소프트웨어 설치
#### Docker 설치 (Ubuntu)
```bash
# Docker 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Docker 리포지토리 추가
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Docker 설치
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
# Docker Compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
```
#### Docker 설치 (CentOS)
```bash
# Docker 설치
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
# Docker Compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Docker 서비스 시작
sudo systemctl start docker
sudo systemctl enable docker
# 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
```
## 환경 설정
### 1. 환경 변수 파일 생성
#### 개발환경
```bash
# 개발환경 환경 변수 파일 생성
cp env.development.example .env.development
# 필요에 따라 설정 수정
vim .env.development
```
#### 운영환경
```bash
# 운영환경 환경 변수 파일 생성
cp env.production.example .env.production
# 운영환경에 맞게 설정 수정 (특히 비밀번호)
vim .env.production
```
### 2. 환경 변수 설정 항목
#### 주요 설정 항목
- `DB_URL`: 데이터베이스 연결 URL
- `DB_USERNAME`: 데이터베이스 사용자명
- `DB_PASSWORD`: 데이터베이스 비밀번호
- `JAVA_OPTS`: JVM 옵션 (메모리 설정 등)
- `LOG_LEVEL`: 로그 레벨 (DEBUG, INFO, WARN, ERROR)
## 스크립트 사용법
### 기본 사용법
```bash
# 실행 권한 부여 (최초 1회)
chmod +x start-docker-linux.sh
# 개발환경 실행
./start-docker-linux.sh
# 운영환경 실행
./start-docker-linux.sh -e prod
```
### 주요 옵션
#### 환경 설정
```bash
# 개발환경 실행
./start-docker-linux.sh -e dev
# 운영환경 실행
./start-docker-linux.sh -e prod
```
#### 컨테이너 관리
```bash
# 컨테이너 중지
./start-docker-linux.sh -s
# 컨테이너 재시작
./start-docker-linux.sh -r
# Docker 시스템 정리 후 실행
./start-docker-linux.sh -c
```
#### 로그 및 모니터링
```bash
# 실시간 로그 확인
./start-docker-linux.sh -l
# 도움말 확인
./start-docker-linux.sh -h
```
### 옵션 조합
```bash
# 개발환경에서 Docker 정리 후 재시작
./start-docker-linux.sh -e dev -c -r
# 운영환경에서 재시작
./start-docker-linux.sh -e prod -r
```
## 접속 정보
### 개발환경
- 애플리케이션: http://localhost:8090
- 데이터베이스: localhost:5432 (내부 DB 사용 시)
### 운영환경
- 애플리케이션: https://ilshin.esgrin.com
- 대체 도메인: https://autoclave.co.kr
## 트러블슈팅
### 일반적인 문제
#### 1. Docker 서비스 오류
```bash
# Docker 서비스 상태 확인
sudo systemctl status docker
# Docker 서비스 시작
sudo systemctl start docker
# Docker 서비스 자동 시작 설정
sudo systemctl enable docker
```
#### 2. 권한 오류
```bash
# 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
# 로그아웃 후 재로그인 또는 그룹 변경 적용
newgrp docker
```
#### 3. 포트 충돌
```bash
# 포트 사용 확인
sudo netstat -tlnp | grep :8090
# 프로세스 종료
sudo kill -9 <PID>
```
#### 4. 환경 변수 파일 오류
```bash
# 환경 변수 파일 존재 확인
ls -la .env.*
# 환경 변수 파일 내용 확인
cat .env.development
```
### 로그 확인
#### 컨테이너 로그
```bash
# 전체 로그 확인
./start-docker-linux.sh -l
# 특정 서비스 로그 확인
docker-compose -f docker-compose.dev.yml logs plm-ilshin
# 로그 파일 확인 (컨테이너 내부)
docker exec -it plm-ilshin-container tail -f /usr/local/tomcat/logs/catalina.out
```
#### 시스템 로그
```bash
# Docker 데몬 로그 확인
sudo journalctl -u docker.service
# 시스템 로그 확인
sudo journalctl -xe
```
## 고급 사용법
### 수동 Docker Compose 사용
```bash
# 개발환경 수동 실행
docker-compose -f docker-compose.dev.yml up -d
# 운영환경 수동 실행
docker-compose -f docker-compose.prod.yml up -d
# 컨테이너 중지
docker-compose -f docker-compose.dev.yml down
```
### 컨테이너 내부 접근
```bash
# 컨테이너 내부 접근
docker exec -it plm-ilshin-container bash
# 데이터베이스 접근 (내부 DB 사용 시)
docker exec -it plm-ilshin-db-container psql -U postgres -d ilshin
```
### 백업 및 복원
```bash
# 데이터베이스 백업
docker exec plm-ilshin-db-container pg_dump -U postgres ilshin > backup.sql
# 데이터베이스 복원
docker exec -i plm-ilshin-db-container psql -U postgres ilshin < backup.sql
```
## 보안 고려사항
### 운영환경 보안
1. 환경 변수 파일 권한 설정
```bash
chmod 600 .env.production
```
2. 방화벽 설정
```bash
# 필요한 포트만 열기
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
```
3. SSL 인증서 설정 (Traefik 사용)
- Let's Encrypt 자동 갱신 설정
- 도메인 검증 설정
### 개발환경 보안
1. 개발용 비밀번호 사용
2. 외부 접근 제한
3. 정기적인 이미지 업데이트
## 성능 최적화
### JVM 튜닝
```bash
# .env 파일에서 JVM 옵션 조정
JAVA_OPTS=-Xms1024m -Xmx2048m -XX:PermSize=512m -XX:MaxPermSize=1024m
```
### Docker 리소스 제한
```yaml
# docker-compose.yml에서 리소스 제한
services:
plm-ilshin:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '1.0'
memory: 1G
```
## 모니터링
### 컨테이너 상태 모니터링
```bash
# 컨테이너 상태 확인
docker ps
# 리소스 사용량 확인
docker stats
# 컨테이너 로그 모니터링
docker logs -f plm-ilshin-container
```
### 애플리케이션 모니터링
- 애플리케이션 로그 확인
- 데이터베이스 연결 상태 확인
- 메모리 사용량 모니터링
## 지원 및 문의
문제가 발생하거나 추가 도움이 필요한 경우:
1. 로그 파일 확인
2. 환경 설정 검토
3. 개발팀 문의

View File

@ -1,20 +0,0 @@
FROM localhost:8787/tomcat:7.0.94-jre7-alpine.linux AS production
# Remove default webapps
RUN rm -rf /usr/local/tomcat/webapps/*
# Copy web application content (compiled classes and web resources)
COPY WebContent /usr/local/tomcat/webapps/ROOT
COPY src /usr/local/tomcat/webapps/ROOT/WEB-INF/src
# Copy custom Tomcat context configuration for JNDI
COPY ./tomcat-conf/context.xml /usr/local/tomcat/conf/context.xml
# Copy database driver if needed (PostgreSQL driver is already in WEB-INF/lib)
# COPY path/to/postgresql-driver.jar /usr/local/tomcat/lib/
# Expose Tomcat port
EXPOSE 8080
# Start Tomcat
CMD ["catalina.sh", "run"]

View File

@ -1,20 +0,0 @@
FROM localhost:8787/tomcat:7.0.94-jre7-alpine.linux AS Development
# Remove default webapps
RUN rm -rf /usr/local/tomcat/webapps/*
# Copy web application content (compiled classes and web resources)
COPY WebContent /usr/local/tomcat/webapps/ROOT
COPY src /usr/local/tomcat/webapps/ROOT/WEB-INF/src
# Copy custom Tomcat context configuration for JNDI
COPY ./tomcat-conf/context.xml /usr/local/tomcat/conf/context.xml
# Copy database driver if needed (PostgreSQL driver is already in WEB-INF/lib)
# COPY path/to/postgresql-driver.jar /usr/local/tomcat/lib/
# Expose Tomcat port
EXPOSE 8080
# Start Tomcat
CMD ["catalina.sh", "run"]

View File

@ -1,47 +0,0 @@
# 윈도우용 PLM 애플리케이션 Dockerfile
FROM tomcat:7.0.94-jre7-alpine
# 메타데이터
LABEL maintainer="PLM Development Team"
LABEL description="PLM Application for Windows Environment"
LABEL version="1.0"
# 작업 디렉토리 설정
WORKDIR /usr/local/tomcat
# 필수 패키지 설치 (curl 포함)
RUN apk add --no-cache curl tzdata
# 환경 변수 설정
ENV CATALINA_HOME=/usr/local/tomcat
ENV CATALINA_BASE=/usr/local/tomcat
ENV JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m"
ENV TZ=Asia/Seoul
# 타임존 설정 (서울)
RUN cp /usr/share/zoneinfo/Asia/Seoul /etc/localtime && \
echo "Asia/Seoul" > /etc/timezone
# 기본 Tomcat 애플리케이션 제거
RUN rm -rf /usr/local/tomcat/webapps/*
# 애플리케이션 복사
COPY WebContent/ /usr/local/tomcat/webapps/ROOT/
COPY tomcat-conf/context.xml /usr/local/tomcat/conf/
# 로그 디렉토리 생성
RUN mkdir -p /usr/local/tomcat/logs
# 권한 설정
RUN chmod -R 755 /usr/local/tomcat/webapps/ROOT && \
chmod 644 /usr/local/tomcat/conf/context.xml
# 포트 노출
EXPOSE 8080
# 개선된 헬스체크 (윈도우 환경 고려)
HEALTHCHECK --interval=30s --timeout=15s --start-period=90s --retries=5 \
CMD curl -f http://localhost:8080/ROOT/ || curl -f http://localhost:8080/ || exit 1
# 실행 명령
CMD ["catalina.sh", "run"]

View File

@ -1,14 +0,0 @@
@echo off
echo =================================
echo 백엔드 빌드만 실행
echo =================================
cd /d %~dp0
echo [1/1] 백엔드 빌드 중...
docker-compose -f docker-compose.springboot.yml build backend
echo.
echo 백엔드 빌드 완료!
echo.
pause

View File

@ -1,32 +0,0 @@
@echo off
echo =================================
echo Gradle 백엔드 로컬 빌드
echo =================================
cd /d %~dp0\backend
echo [1/3] Gradle 권한 설정...
if not exist "gradlew.bat" (
echo gradlew.bat 파일을 찾을 수 없습니다.
pause
exit /b 1
)
echo [2/3] 이전 빌드 정리...
call gradlew clean
echo [3/3] 프로젝트 빌드...
call gradlew build -x test
if %errorlevel% equ 0 (
echo.
echo 백엔드 빌드 성공!
echo JAR 파일 위치: backend\build\libs\
echo.
) else (
echo.
echo 빌드 실패! 오류를 확인하세요.
echo.
)
pause

View File

@ -1,12 +0,0 @@
@echo off
echo =================================
echo 백엔드 로그 확인
echo =================================
cd /d %~dp0
echo 백엔드 컨테이너 로그를 실시간으로 확인합니다...
echo Ctrl+C를 눌러서 종료할 수 있습니다.
echo.
docker-compose -f docker-compose.springboot.yml logs -f backend

View File

@ -3,10 +3,13 @@ import { logger } from "../utils/logger";
import { AuthenticatedRequest } from "../types/auth";
import { ApiResponse } from "../types/common";
import { Client } from "pg";
import { PrismaClient } from "@prisma/client";
import config from "../config/environment";
import { AdminService } from "../services/adminService";
import { EncryptUtil } from "../utils/encryptUtil";
const prisma = new PrismaClient();
/**
*
*/
@ -347,10 +350,9 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
const countParams = [...queryParams];
// 총 개수 조회를 위해 기존 쿼리를 COUNT로 변환
const countQuery = query.replace(
/SELECT[\s\S]*?FROM/i,
"SELECT COUNT(*) as total FROM"
).replace(/ORDER BY.*$/i, "");
const countQuery = query
.replace(/SELECT[\s\S]*?FROM/i, "SELECT COUNT(*) as total FROM")
.replace(/ORDER BY.*$/i, "");
const countResult = await client.query(countQuery, countParams);
const totalCount = parseInt(countResult.rows[0].total);
@ -1737,6 +1739,7 @@ export const getUserInfo = async (req: AuthenticatedRequest, res: Response) => {
u.fax_no,
u.partner_objid,
u.rank,
u.photo,
u.locale,
u.company_code,
u.data_type,
@ -1789,6 +1792,9 @@ export const getUserInfo = async (req: AuthenticatedRequest, res: Response) => {
faxNo: user.fax_no,
partnerObjid: user.partner_objid,
rank: user.rank,
photo: user.photo
? `data:image/jpeg;base64,${user.photo.toString("base64")}`
: null,
locale: user.locale,
companyCode: user.company_code,
dataType: user.data_type,
@ -2686,6 +2692,127 @@ export const deleteCompany = async (
* API
* Java AdminController.resetUserPassword()
*/
export const updateProfile = async (
req: AuthenticatedRequest,
res: Response
) => {
try {
const userId = req.user?.userId;
if (!userId) {
res.status(401).json({
result: false,
error: {
code: "TOKEN_MISSING",
details: "인증 토큰이 필요합니다.",
},
});
return;
}
const {
userName,
userNameEng,
userNameCn,
email,
tel,
cellPhone,
photo,
locale,
} = req.body;
// 사용자 정보 업데이트
const updateData: any = {};
if (userName !== undefined) updateData.user_name = userName;
if (userNameEng !== undefined) updateData.user_name_eng = userNameEng;
if (userNameCn !== undefined) updateData.user_name_cn = userNameCn;
if (email !== undefined) updateData.email = email;
if (tel !== undefined) updateData.tel = tel;
if (cellPhone !== undefined) updateData.cell_phone = cellPhone;
// photo 데이터 처리 (Base64를 Buffer로 변환하여 저장)
if (photo !== undefined) {
if (photo && typeof photo === "string") {
try {
// Base64 헤더 제거 (data:image/jpeg;base64, 등)
const base64Data = photo.replace(/^data:image\/[a-z]+;base64,/, "");
// Base64를 Buffer로 변환
updateData.photo = Buffer.from(base64Data, "base64");
} catch (error) {
console.error("Base64 이미지 처리 오류:", error);
updateData.photo = null;
}
} else {
updateData.photo = null; // 빈 값이면 null로 설정
}
}
if (locale !== undefined) updateData.locale = locale;
// 업데이트할 데이터가 없으면 에러
if (Object.keys(updateData).length === 0) {
res.status(400).json({
result: false,
error: {
code: "NO_DATA",
details: "업데이트할 데이터가 없습니다.",
},
});
return;
}
// 데이터베이스 업데이트
await prisma.user_info.update({
where: { user_id: userId },
data: updateData,
});
// 업데이트된 사용자 정보 조회
const updatedUser = await prisma.user_info.findUnique({
where: { user_id: userId },
select: {
user_id: true,
user_name: true,
user_name_eng: true,
user_name_cn: true,
dept_code: true,
dept_name: true,
position_code: true,
position_name: true,
email: true,
tel: true,
cell_phone: true,
user_type: true,
user_type_name: true,
photo: true,
locale: true,
},
});
// photo가 Buffer 타입인 경우 Base64로 변환
const responseData = {
...updatedUser,
photo: updatedUser?.photo
? `data:image/jpeg;base64,${updatedUser.photo.toString("base64")}`
: null,
};
res.json({
result: true,
message: "프로필이 성공적으로 업데이트되었습니다.",
data: responseData,
});
} catch (error) {
console.error("프로필 업데이트 오류:", error);
res.status(500).json({
result: false,
error: {
code: "UPDATE_FAILED",
details: "프로필 업데이트 중 오류가 발생했습니다.",
},
});
}
};
export const resetUserPassword = async (
req: AuthenticatedRequest,
res: Response

View File

@ -166,15 +166,33 @@ export class AuthController {
const userInfo = JwtUtils.verifyToken(token);
// DB에서 최신 사용자 정보 조회 (locale 포함)
const dbUserInfo = await AuthService.getUserInfo(userInfo.userId);
if (!dbUserInfo) {
res.status(401).json({
success: false,
message: "사용자 정보를 찾을 수 없습니다.",
error: {
code: "USER_NOT_FOUND",
details: "사용자 정보가 삭제되었거나 존재하지 않습니다.",
},
});
return;
}
const userInfoResponse: UserInfo = {
userId: userInfo.userId,
userName: userInfo.userName || "",
deptName: userInfo.deptName || "",
companyCode: userInfo.companyCode || "ILSHIN",
userType: userInfo.userType || "USER",
userTypeName: userInfo.userTypeName || "일반사용자",
userId: dbUserInfo.userId,
userName: dbUserInfo.userName || "",
deptName: dbUserInfo.deptName || "",
companyCode: dbUserInfo.companyCode || "ILSHIN",
userType: dbUserInfo.userType || "USER",
userTypeName: dbUserInfo.userTypeName || "일반사용자",
email: dbUserInfo.email || "",
photo: dbUserInfo.photo,
locale: dbUserInfo.locale || "KR", // locale 정보 추가
isAdmin:
userInfo.userType === "ADMIN" || userInfo.userId === "plm_admin",
dbUserInfo.userType === "ADMIN" || dbUserInfo.userId === "plm_admin",
};
res.status(200).json({

View File

@ -12,6 +12,7 @@ import {
getUserHistory, // 사용자 변경이력 조회
changeUserStatus, // 사용자 상태 변경
resetUserPassword, // 사용자 비밀번호 초기화
updateProfile, // 프로필 수정
getDepartmentList, // 부서 목록 조회
checkDuplicateUserId, // 사용자 ID 중복 체크
saveUser, // 사용자 등록/수정
@ -45,6 +46,7 @@ router.get("/users/:userId", getUserInfo); // 사용자 상세 조회
router.get("/users/:userId/history", getUserHistory); // 사용자 변경이력 조회
router.patch("/users/:userId/status", changeUserStatus); // 사용자 상태 변경
router.post("/users", saveUser); // 사용자 등록/수정
router.put("/profile", updateProfile); // 프로필 수정
router.post("/users/check-duplicate", checkDuplicateUserId); // 사용자 ID 중복 체크
router.post("/users/reset-password", resetUserPassword); // 사용자 비밀번호 초기화

View File

@ -146,6 +146,8 @@ export class AuthService {
user_type_name: true,
partner_objid: true,
company_code: true,
locale: true,
photo: true,
},
});
@ -189,6 +191,8 @@ export class AuthService {
partnerObjid: userInfo.partner_objid || undefined,
authName: authInfo.length > 0 ? authInfo[0].auth_name : undefined,
companyCode: userInfo.company_code || "ILSHIN",
photo: userInfo.photo ? `data:image/jpeg;base64,${userInfo.photo.toString('base64')}` : undefined,
locale: userInfo.locale || "KR",
};
logger.info(`사용자 정보 조회 완료: ${userId}`);

View File

@ -15,6 +15,9 @@ export interface UserInfo {
companyCode: string;
userType?: string;
userTypeName?: string;
email?: string;
photo?: string;
locale?: string;
isAdmin?: boolean;
}
@ -47,6 +50,8 @@ export interface PersonBean {
partnerObjid?: string;
authName?: string;
companyCode?: string;
photo?: string;
locale?: string;
}
// 로그인 결과 타입 (기존 LoginService.loginPwdCheck 반환값)

View File

@ -1,126 +0,0 @@
@echo off
setlocal enabledelayedexpansion
echo ===============================================
echo Java 애플리케이션 빌드 (윈도우용)
echo ===============================================
echo.
REM Java 환경 확인
echo [빌드 1] Java 환경 확인...
java -version >nul 2>&1
if %errorlevel% neq 0 (
echo [오류] Java가 설치되지 않았거나 PATH에 설정되지 않았습니다.
echo Java 7 이상을 설치하고 PATH를 설정해주세요.
exit /b 1
)
javac -version >nul 2>&1
if %errorlevel% neq 0 (
echo [오류] Java 컴파일러(javac)를 찾을 수 없습니다.
echo JDK가 설치되어 있는지 확인해주세요.
exit /b 1
)
echo ✓ Java 환경 확인 완료
REM 빌드 디렉토리 정리
echo [빌드 2] 이전 빌드 결과 정리...
if exist "WebContent\WEB-INF\classes" (
rmdir /s /q "WebContent\WEB-INF\classes"
)
echo ✓ 이전 빌드 결과 정리 완료
REM 필요한 디렉토리 생성
echo [빌드 3] 빌드 디렉토리 생성...
if not exist "WebContent\WEB-INF\classes" mkdir "WebContent\WEB-INF\classes"
if not exist "WebContent\WEB-INF\lib" mkdir "WebContent\WEB-INF\lib"
if not exist "logs" mkdir "logs"
echo ✓ 빌드 디렉토리 생성 완료
REM Servlet API JAR 확인
echo [빌드 4] 라이브러리 의존성 확인...
set "SERVLET_JAR_1=WebContent\WEB-INF\lib\javax.servlet-api-4.0.1.jar"
set "SERVLET_JAR_2=WebContent\WEB-INF\lib\servlet-api.jar"
if not exist "%SERVLET_JAR_1%" if not exist "%SERVLET_JAR_2%" (
echo [오류] Servlet API JAR 파일을 찾을 수 없습니다.
echo 다음 중 하나가 필요합니다:
echo - %SERVLET_JAR_1%
echo - %SERVLET_JAR_2%
echo.
echo Maven Central에서 다운로드하거나 Tomcat lib 폴더에서 복사해주세요.
exit /b 1
)
echo ✓ 라이브러리 의존성 확인 완료
REM 클래스패스 설정
set "CLASSPATH=src;WebContent\WEB-INF\lib\*"
echo [빌드 5] 클래스패스: %CLASSPATH%
REM Java 소스 파일 목록 생성
echo [빌드 6] Java 소스 파일 검색...
if exist java_sources.tmp del java_sources.tmp
set "java_count=0"
for /r src %%f in (*.java) do (
echo %%f >> java_sources.tmp
set /a java_count+=1
)
if %java_count% equ 0 (
echo [경고] 컴파일할 Java 소스 파일이 없습니다.
) else (
echo%java_count%개의 Java 소스 파일을 찾았습니다.
)
REM Java 컴파일
if exist java_sources.tmp (
echo [빌드 7] Java 소스 컴파일...
javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent\WEB-INF\classes -cp "%CLASSPATH%" @java_sources.tmp
if !errorlevel! neq 0 (
echo [오류] Java 컴파일에 실패했습니다.
if exist java_sources.tmp del java_sources.tmp
exit /b 1
)
del java_sources.tmp
echo ✓ Java 컴파일 완료
)
REM 리소스 파일 복사
echo [빌드 8] 리소스 파일 복사...
set "resource_count=0"
for /r src %%f in (*.xml *.properties *.sql) do (
set "source_file=%%f"
set "relative_path=!source_file:%CD%\src\=!"
set "target_file=WebContent\WEB-INF\classes\!relative_path!"
REM 대상 디렉토리 생성
for %%d in ("!target_file!") do (
if not exist "%%~dpd" mkdir "%%~dpd" 2>nul
)
REM 파일 복사
copy "!source_file!" "!target_file!" >nul 2>&1
if !errorlevel! equ 0 (
set /a resource_count+=1
) else (
echo [경고] 리소스 파일 복사 실패: !source_file!
)
)
echo%resource_count%개의 리소스 파일 복사 완료
REM 빌드 결과 요약
echo.
echo ===============================================
echo ✓ 빌드 완료!
echo ===============================================
echo 컴파일된 클래스: WebContent\WEB-INF\classes\
echo 라이브러리: WebContent\WEB-INF\lib\
echo 로그 디렉토리: logs\
echo.
endlocal

View File

@ -1,80 +0,0 @@
#!/bin/bash
# MAC OS 만 실행
# if [[ "$(uname -s)" != "Darwin" ]]; then
# echo "This script runs on MAC OS only."
# echo "Current OS: $(uname -s)"
# exit 1
# fi
# ----------------------------------------------------------------------
# 기존 빌드 폴더 삭제 및 새로운 빌드 시작
# ----------------------------------------------------------------------
echo "Cleaning up old build artifacts..."
rm -rf WebContent/WEB-INF/classes/*
echo "Building Java application for development..."
# 필요한 디렉토리 생성
mkdir -p WebContent/WEB-INF/classes
mkdir -p WebContent/WEB-INF/lib # lib 폴더 존재 확인
# ----------------------------------------------------------------------
# Servlet API JAR 파일 존재 여부 확인 (단순화된 방식)
# ----------------------------------------------------------------------
SERVLET_API_JAR_PRIMARY_PATH="WebContent/WEB-INF/lib/javax.servlet-api-4.0.1.jar"
SERVLET_API_JAR_ALTERNATIVE_PATH="WebContent/WEB-INF/lib/servlet-api.jar"
if [ ! -f "$SERVLET_API_JAR_PRIMARY_PATH" ] && [ ! -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "---------------------------------------------------------------------------------"
echo "ERROR: Servlet API JAR (javax.servlet-api-4.0.1.jar or servlet-api.jar)"
echo " not found in WebContent/WEB-INF/lib/"
echo ""
echo "Please add the appropriate Servlet API JAR for your project."
echo "You can typically find this JAR in a Tomcat distribution's 'lib' folder,"
echo "or download it from a trusted source like Maven Central Repository."
echo ""
echo "Build cannot proceed without it."
echo "---------------------------------------------------------------------------------"
exit 1
else
if [ -f "$SERVLET_API_JAR_PRIMARY_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_PRIMARY_PATH"
elif [ -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_ALTERNATIVE_PATH"
fi
fi
# ----------------------------------------------------------------------
# 클래스패스 설정 (단순화된 방식)
EFFECTIVE_CLASSPATH="src:WebContent/WEB-INF/lib/*"
echo "DEBUG: Effective classpath for javac: $EFFECTIVE_CLASSPATH"
# src 폴더 내의 모든 .java 파일 컴파일
echo "Compiling Java files for development..."
find src -name "*.java" -print0 | xargs -0 javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent/WEB-INF/classes -cp "$EFFECTIVE_CLASSPATH"
if [ $? -ne 0 ]; then
echo "Java compilation failed. Exiting script."
exit 1
fi
echo "Java compilation successful."
# ----------------------------------------------------------------------
# src 폴더 내의 리소스 파일(.xml, .properties 등)을 classes 폴더로 복사 (macOS 호환 방식)
echo "Copying resource files for development..."
find src -type f \( -name "*.xml" -o -name "*.properties" \) | while read -r filepath; do
# 'src/' 접두사를 제거하여 상대 경로 생성
relative_path="${filepath#src/}"
target_file="WebContent/WEB-INF/classes/$relative_path"
# 대상 디렉토리 생성
mkdir -p "$(dirname "$target_file")" || { echo "Error: Failed to create directory $(dirname "$target_file")"; exit 1; }
# 파일 복사
cp "$filepath" "$target_file" || { echo "Error: Failed to copy $filepath to $target_file"; exit 1; }
done
echo "Java application build complete for development."
echo "Build process finished successfully!"

View File

@ -1,57 +0,0 @@
@echo off
chcp 65001 > nul
echo =================================
echo 백엔드 개발 관리 도구
echo =================================
cd /d %~dp0
:menu
echo.
echo 선택하세요:
echo 1. 백엔드 재시작 (완전 재빌드)
echo 2. 백엔드 빠른 재시작 (캐시 사용)
echo 3. 백엔드 빌드만 실행
echo 4. 백엔드 로그 실시간 확인
echo 5. Gradle 로컬 빌드
echo 6. 백엔드 상태 확인
echo 0. 종료
echo.
set /p choice="번호를 입력하세요: "
if "%choice%"=="1" (
call restart-backend.bat
goto menu
)
if "%choice%"=="2" (
call quick-restart-backend.bat
goto menu
)
if "%choice%"=="3" (
call backend-build-only.bat
goto menu
)
if "%choice%"=="4" (
call backend-logs.bat
goto menu
)
if "%choice%"=="5" (
call backend-gradle-build.bat
goto menu
)
if "%choice%"=="6" (
echo 백엔드 컨테이너 상태:
docker-compose -f docker-compose.springboot.yml ps backend
echo.
echo 아무 키나 누르세요...
pause > nul
goto menu
)
if "%choice%"=="0" (
echo 프로그램을 종료합니다.
exit /b 0
)
echo 잘못된 선택입니다. 다시 선택해주세요.
goto menu

View File

@ -1,173 +0,0 @@
@echo off
setlocal enabledelayedexpansion
REM ----------------------------------------------------------------------
REM 기존 빌드 폴더 삭제 및 새로운 빌드 시작
REM ----------------------------------------------------------------------
echo Cleaning up old build artifacts...
if exist "WebContent\WEB-INF\classes\*" (
rmdir /s /q "WebContent\WEB-INF\classes"
)
echo Building Java application for development...
REM 필요한 디렉토리 생성
if not exist "WebContent\WEB-INF\classes" mkdir "WebContent\WEB-INF\classes"
if not exist "WebContent\WEB-INF\lib" mkdir "WebContent\WEB-INF\lib"
REM ----------------------------------------------------------------------
REM Servlet API JAR 파일 존재 여부 확인
REM ----------------------------------------------------------------------
set "SERVLET_API_JAR_PRIMARY_PATH=WebContent\WEB-INF\lib\javax.servlet-api-4.0.1.jar"
set "SERVLET_API_JAR_ALTERNATIVE_PATH=WebContent\WEB-INF\lib\servlet-api.jar"
if not exist "%SERVLET_API_JAR_PRIMARY_PATH%" if not exist "%SERVLET_API_JAR_ALTERNATIVE_PATH%" (
echo ---------------------------------------------------------------------------------
echo ERROR: Servlet API JAR (javax.servlet-api-4.0.1.jar or servlet-api.jar^)
echo not found in WebContent\WEB-INF\lib\
echo.
echo Please add the appropriate Servlet API JAR for your project.
echo You can typically find this JAR in a Tomcat distribution's 'lib' folder,
echo or download it from a trusted source like Maven Central Repository.
echo.
echo Build cannot proceed without it.
echo ---------------------------------------------------------------------------------
exit /b 1
) else (
if exist "%SERVLET_API_JAR_PRIMARY_PATH%" (
echo DEBUG: Confirmed Servlet API JAR is present at %SERVLET_API_JAR_PRIMARY_PATH%
) else if exist "%SERVLET_API_JAR_ALTERNATIVE_PATH%" (
echo DEBUG: Confirmed Servlet API JAR is present at %SERVLET_API_JAR_ALTERNATIVE_PATH%
)
)
REM ----------------------------------------------------------------------
REM 클래스패스 설정
set "EFFECTIVE_CLASSPATH=src;WebContent\WEB-INF\lib\*"
echo DEBUG: Effective classpath for javac: %EFFECTIVE_CLASSPATH%
REM src 폴더 내의 모든 .java 파일 컴파일
echo Compiling Java files for development...
REM Java 파일 목록을 임시 파일에 저장
if exist temp_java_files.txt del temp_java_files.txt
for /r src %%f in (*.java) do echo %%f >> temp_java_files.txt
if exist temp_java_files.txt (
javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent\WEB-INF\classes -cp "%EFFECTIVE_CLASSPATH%" @temp_java_files.txt
if !errorlevel! neq 0 (
echo Java compilation failed. Exiting script.
del temp_java_files.txt
exit /b 1
)
del temp_java_files.txt
)
echo Java compilation successful.
REM ----------------------------------------------------------------------
REM src 폴더 내의 리소스 파일(.xml, .properties 등)을 classes 폴더로 복사
echo Copying resource files for development...
for /r src %%f in (*.xml *.properties) do (
set "filepath=%%f"
REM src\ 부분을 제거하여 상대 경로 생성
set "relative_path=%%f"
call set "relative_path=%%relative_path:*src\=%%"
set "target_file=WebContent\WEB-INF\classes\!relative_path!"
REM 대상 디렉토리 생성
for %%d in ("!target_file!") do (
if not exist "%%~dpd" mkdir "%%~dpd"
)
REM 파일 복사
copy "!filepath!" "!target_file!" >nul
if !errorlevel! neq 0 (
echo Error: Failed to copy !filepath! to !target_file!
exit /b 1
)
)
echo Java application build complete for development.
REM ----------------------------------------------------------------------
REM Git 변경사항 커밋 및 푸시
REM ----------------------------------------------------------------------
git add .
git commit -am "auto commit"
REM 현재 브랜치 확인
for /f "tokens=*" %%i in ('git branch --show-current') do set "current_branch=%%i"
git push origin %current_branch%
REM 마스터 브랜치와 병합 여부 확인
echo You are currently on branch: %current_branch%
set /p "proceed_merge=Would you like to merge the current branch with main? (Y/N) [Y]: "
if "%proceed_merge%"=="" set "proceed_merge=Y"
if /i "%proceed_merge%"=="Y" (
REM 마스터 브랜치로 전환 및 업데이트
git checkout main
git pull origin main
REM 현재 브랜치를 마스터에 병합
git merge --no-edit %current_branch%
REM 병합 결과 푸시
git push origin main
REM 원래 브랜치로 돌아가기
git checkout %current_branch%
)
REM 새로운 브랜치 생성
REM 현재 날짜를 YYYYMMDD 형식으로 가져오기
for /f "tokens=2 delims==" %%i in ('wmic OS Get localdatetime /value') do set "dt=%%i"
set "current_date=%dt:~0,8%"
REM 브랜치 이름에서 날짜 부분 추출
set "branch_date=%current_branch:~1,8%"
REM 현재 날짜와 브랜치 날짜가 같으면 뒤의 2자리 숫자를 증가시킴
if "%branch_date%"=="%current_date%" (
set "branch_number=%current_branch:~9,2%"
set /a "branch_number=branch_number+1"
) else (
set "branch_number=1"
)
REM 사용 가능한 브랜치 이름 찾기
:find_branch
if %branch_number% lss 10 (
set "formatted_number=0%branch_number%"
) else (
set "formatted_number=%branch_number%"
)
set "new_branch=V%current_date%%formatted_number%"
REM 로컬과 원격에 해당 이름의 브랜치가 존재하는지 확인
git show-ref --quiet refs/heads/%new_branch% >nul 2>&1
if !errorlevel! equ 0 goto increment_branch
git ls-remote --exit-code --heads origin %new_branch% >nul 2>&1
if !errorlevel! equ 0 goto increment_branch
goto create_branch
:increment_branch
set /a "branch_number=branch_number+1"
goto find_branch
:create_branch
REM 새로운 브랜치 생성
git checkout -b %new_branch%
REM 새로운 브랜치 푸시
git push origin %new_branch%
REM 변경 사항 확인
git status
endlocal

View File

@ -1,145 +0,0 @@
#!/bin/bash
# MAC OS 만 실행
# if [[ "$(uname -s)" != "Darwin" ]]; then
# echo "This script runs on MAC OS only."
# echo "Current OS: $(uname -s)"
# exit 1
# fi
# ----------------------------------------------------------------------
# 기존 빌드 폴더 삭제 및 새로운 빌드 시작
# ----------------------------------------------------------------------
echo "Cleaning up old build artifacts..."
rm -rf WebContent/WEB-INF/classes/*
echo "Building Java application for development..."
# 필요한 디렉토리 생성
mkdir -p WebContent/WEB-INF/classes
mkdir -p WebContent/WEB-INF/lib # lib 폴더 존재 확인
# ----------------------------------------------------------------------
# Servlet API JAR 파일 존재 여부 확인 (단순화된 방식)
# ----------------------------------------------------------------------
SERVLET_API_JAR_PRIMARY_PATH="WebContent/WEB-INF/lib/javax.servlet-api-4.0.1.jar"
SERVLET_API_JAR_ALTERNATIVE_PATH="WebContent/WEB-INF/lib/servlet-api.jar"
if [ ! -f "$SERVLET_API_JAR_PRIMARY_PATH" ] && [ ! -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "---------------------------------------------------------------------------------"
echo "ERROR: Servlet API JAR (javax.servlet-api-4.0.1.jar or servlet-api.jar)"
echo " not found in WebContent/WEB-INF/lib/"
echo ""
echo "Please add the appropriate Servlet API JAR for your project."
echo "You can typically find this JAR in a Tomcat distribution's 'lib' folder,"
echo "or download it from a trusted source like Maven Central Repository."
echo ""
echo "Build cannot proceed without it."
echo "---------------------------------------------------------------------------------"
exit 1
else
if [ -f "$SERVLET_API_JAR_PRIMARY_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_PRIMARY_PATH"
elif [ -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_ALTERNATIVE_PATH"
fi
fi
# ----------------------------------------------------------------------
# 클래스패스 설정 (단순화된 방식)
EFFECTIVE_CLASSPATH="src:WebContent/WEB-INF/lib/*"
echo "DEBUG: Effective classpath for javac: $EFFECTIVE_CLASSPATH"
# src 폴더 내의 모든 .java 파일 컴파일
echo "Compiling Java files for development..."
find src -name "*.java" -print0 | xargs -0 javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent/WEB-INF/classes -cp "$EFFECTIVE_CLASSPATH"
if [ $? -ne 0 ]; then
echo "Java compilation failed. Exiting script."
exit 1
fi
echo "Java compilation successful."
# ----------------------------------------------------------------------
# src 폴더 내의 리소스 파일(.xml, .properties 등)을 classes 폴더로 복사 (macOS 호환 방식)
echo "Copying resource files for development..."
find src -type f \( -name "*.xml" -o -name "*.properties" \) | while read -r filepath; do
# 'src/' 접두사를 제거하여 상대 경로 생성
relative_path="${filepath#src/}"
target_file="WebContent/WEB-INF/classes/$relative_path"
# 대상 디렉토리 생성
mkdir -p "$(dirname "$target_file")" || { echo "Error: Failed to create directory $(dirname "$target_file")"; exit 1; }
# 파일 복사
cp "$filepath" "$target_file" || { echo "Error: Failed to copy $filepath to $target_file"; exit 1; }
done
# 파이프라인의 마지막 명령어의 종료 코드를 확인하기 위해 추가적인 검사가 필요할 수 있으나,
# while 루프 내에서 오류 발생 시 exit 하므로, 이 지점에 도달하면 성공으로 간주합니다.
# 만약 find가 아무 파일도 찾지 못해도 오류가 아니어야 하므로 $? 검사는 주의해야 합니다.
echo "Java application build complete for development."
# ----------------------------------------------------------------------
# 빌드 종료
# ----------------------------------------------------------------------
# Git 변경사항 커밋 및 푸시
git add .
git commit -am "auto commit"
current_branch=$(git branch --show-current)
git push origin $current_branch
# 마스터 브랜치와 병합 여부 확인
echo "You are currently on branch: $current_branch"
echo "Would you like to merge the current branch with main? (Y/N) [Y]"
read proceed_merge
proceed_merge=${proceed_merge:-Y}
if [ "$proceed_merge" == "Y" ] || [ "$proceed_merge" == "y" ]; then
# 마스터 브랜치로 전환 및 업데이트
git checkout main
git pull origin main
# 현재 브랜치를 마스터에 병합
git merge --no-edit $current_branch
# 병합 결과 푸시
git push origin main
# 원래 브랜치로 돌아가기
git checkout $current_branch
fi
# 새로운 브랜치 생성
# 현재 날짜를 YYYYMMDD 형식으로 가져오기
current_date=$(date +'%Y%m%d')
# 브랜치 이름에서 날짜 부분 추출
branch_date=${current_branch:1:8}
# 현재 날짜와 브랜치 날짜가 같으면 뒤의 2자리 숫자를 증가시킴
if [ "$branch_date" == "$current_date" ]; then
# 브랜치 이름에서 뒤의 2자리 숫자 추출
branch_number=${current_branch:9:2}
# 숫자를 10진수로 변환하고 1 증가시킴
branch_number=$((10#$branch_number + 1))
else
# 날짜가 다르면 01부터 시작
branch_number=1
fi
# 사용 가능한 브랜치 이름 찾기
while true; do
# 2자리 숫자로 포맷팅
formatted_number=$(printf "%02d" $branch_number)
new_branch="V${current_date}${formatted_number}"
# 로컬과 원격에 해당 이름의 브랜치가 존재하는지 확인
if ! git show-ref --quiet refs/heads/$new_branch && \
! git ls-remote --exit-code --heads origin $new_branch > /dev/null 2>&1; then
break
fi
# 존재한다면 숫자 증가
branch_number=$((branch_number + 1))
done
# 새로운 브랜치 생성
git checkout -b $new_branch
# 새로운 브랜치 푸시 (원격 브랜치로 푸시하려면 git push origin $new_branch 실행)
git push origin $new_branch
# 변경 사항 확인
git status
# .env-dev 파일을 .env로 복사하여 원래 상태로 복원
# docker-compose -f docker-compose-dev.yml up -d --build

View File

@ -1,36 +0,0 @@
version: "3.8"
services:
# Node.js 백엔드
backend:
build:
context: ./backend-node
dockerfile: Dockerfile
container_name: pms-backend-linux
ports:
- "8080:8080"
environment:
- NODE_ENV=development
- PORT=8080
- DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm
- JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024
- JWT_EXPIRES_IN=24h
- CORS_ORIGIN=http://localhost:9771
- CORS_CREDENTIALS=true
- LOG_LEVEL=debug
volumes:
- ./backend-node:/app
- /app/node_modules
networks:
- pms-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
pms-network:
driver: bridge

View File

@ -1,23 +0,0 @@
version: '3.8'
services:
plm:
build:
context: .
dockerfile: dockerfile.dev
container_name: plm
ports:
- "9090:8080"
environment:
CATALINA_OPTS: >-
-DDB_URL=jdbc:postgresql://39.117.244.52:11132/plm
-DDB_USERNAME=postgres
-DDB_PASSWORD=ph0909!!
volumes:
- plm-project_data:/data_storage
- plm-app_data:/path/inside/container
restart: unless-stopped
volumes:
plm-project_data:
plm-app_data:

View File

@ -1,25 +0,0 @@
version: "3.8"
services:
# Next.js 프론트엔드만
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
container_name: pms-frontend-win
ports:
- "9771:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8080/api
volumes:
- ./frontend:/app
- /app/node_modules
- /app/.next
networks:
- pms-network
restart: unless-stopped
networks:
pms-network:
driver: bridge
external: true

View File

@ -1,54 +0,0 @@
version: '3.8'
services:
# Spring Boot 백엔드
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: pms-backend
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=dev
- SPRING_DATASOURCE_URL=jdbc:postgresql://39.117.244.52:11132/plm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=ph0909!!
- LANG=ko_KR.UTF-8
- LANGUAGE=ko_KR:ko
- LC_ALL=ko_KR.UTF-8
- TZ=Asia/Seoul
- JAVA_OPTS=-Xms512m -Xmx1024m -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Seoul -Djava.awt.headless=true
networks:
- pms-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Next.js 프론트엔드
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
container_name: pms-frontend
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8080/api
volumes:
- ./frontend:/app
- /app/node_modules
- /app/.next
networks:
- pms-network
restart: unless-stopped
depends_on:
- backend
networks:
pms-network:
driver: bridge

View File

@ -1,62 +0,0 @@
services:
# 백엔드 서비스 (기존)
plm-app:
build:
context: .
dockerfile: Dockerfile.win
platforms:
- linux/amd64
container_name: plm-windows
ports:
- "9090:8080"
environment:
- CATALINA_OPTS=-DDB_URL=jdbc:postgresql://39.117.244.52:11132/plm -DDB_USERNAME=postgres -DDB_PASSWORD=ph0909!! -Xms512m -Xmx1024m
- TZ=Asia/Seoul
- APP_ENV=development
- LOG_LEVEL=INFO
- DB_HOST=39.117.244.52
- DB_PORT=11132
- DB_NAME=plm
- DB_USERNAME=postgres
- DB_PASSWORD=ph0909!!
volumes:
- plm-win-project:/data_storage
- plm-win-app:/app_data
- ./logs:/usr/local/tomcat/logs
- ./WebContent:/usr/local/tomcat/webapps/ROOT
restart: unless-stopped
networks:
- plm-network
# 프론트엔드 서비스 (새로 추가)
plm-frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
container_name: plm-frontend
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- TZ=Asia/Seoul
- NEXT_PUBLIC_API_URL=http://localhost:9090
- WATCHPACK_POLLING=true
volumes:
- ./frontend:/app
- /app/node_modules
- /app/.next
depends_on:
- plm-app
restart: unless-stopped
networks:
- plm-network
volumes:
plm-win-project:
driver: local
plm-win-app:
driver: local
networks:
plm-network:
driver: bridge

View File

@ -0,0 +1,24 @@
# 개발용 백엔드 Dockerfile
FROM node:20-bookworm-slim
WORKDIR /app
# 시스템 패키지 설치
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# package.json 복사 및 의존성 설치 (개발 의존성 포함)
COPY package*.json ./
RUN npm ci --prefer-offline --no-audit
# 소스 코드는 볼륨 마운트로 처리
# Prisma 클라이언트 생성용 스키마만 복사
COPY prisma ./prisma
RUN npx prisma generate
# 포트 노출
EXPOSE 8080
# 개발 서버 시작 (nodemon 사용)
CMD ["npm", "run", "dev"]

View File

@ -1,11 +1,9 @@
version: "3.8"
services:
# Node.js 백엔드
backend:
build:
context: ./backend-node
dockerfile: Dockerfile
context: ../../backend-node
dockerfile: ../docker/dev/backend.Dockerfile
container_name: pms-backend-mac
ports:
- "8080:8080"
@ -18,9 +16,9 @@ services:
- CORS_ORIGIN=http://localhost:9771
- CORS_CREDENTIALS=true
- LOG_LEVEL=debug
# volumes:
# - ./backend-node:/app # 개발 모드가 아닐 때는 이 볼륨 마운트를 비활성화
# - /app/node_modules
volumes:
- ../../backend-node:/app # 개발 모드: 코드 변경 시 자동 반영
- /app/node_modules
networks:
- pms-network
restart: unless-stopped

View File

@ -1,18 +1,16 @@
version: "3.8"
services:
# Next.js 프론트엔드만
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
context: ../../frontend
dockerfile: ../docker/dev/frontend.Dockerfile
container_name: pms-frontend-mac
ports:
- "9771:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8080/api
volumes:
- ./frontend:/app
- ../../frontend:/app
- /app/node_modules
- /app/.next
networks:

View File

@ -7,8 +7,8 @@ WORKDIR /app
# package.json과 package-lock.json 복사
COPY package*.json ./
# 의존성 설치 (개발 의존성 포함)
RUN npm ci
# 의존성 설치 (개발 의존성 포함) - 최적화 옵션 추가
RUN npm ci --prefer-offline --no-audit
# 소스 코드 복사
COPY . .

View File

@ -12,7 +12,7 @@ RUN apt-get update \
# Dependencies stage (install deps and generate Prisma client)
FROM base AS deps
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
RUN npm ci --omit=dev --prefer-offline --no-audit && npm cache clean --force
# Copy prisma schema and generate client (glibc target will be detected)
COPY prisma ./prisma
ENV PRISMA_SKIP_POSTINSTALL_GENERATE=true
@ -22,21 +22,16 @@ RUN npx prisma generate
FROM node:20-bookworm-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci && npm cache clean --force
RUN npm ci --prefer-offline --no-audit && npm cache clean --force
COPY tsconfig.json ./
COPY src ./src
COPY prisma ./prisma
RUN npx prisma generate
RUN npm run build
# Runtime image
FROM node:20-bookworm-slim AS runner
WORKDIR /app
# Runtime image - base 이미지 재사용으로 중복 설치 제거
FROM base AS runner
ENV NODE_ENV=production
# Ensure OpenSSL present
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

View File

@ -1,26 +1,22 @@
version: "3.8"
services:
# Node.js 백엔드
# Node.js 백엔드 (운영용)
backend:
build:
context: ./backend-node
dockerfile: Dockerfile
container_name: pms-backend-win
context: ../../backend-node
dockerfile: ../docker/prod/backend.Dockerfile # 운영용 Dockerfile
container_name: pms-backend-prod
ports:
- "8080:8080"
environment:
- NODE_ENV=development
- NODE_ENV=production
- PORT=8080
- DATABASE_URL=postgresql://postgres:ph0909!!@39.117.244.52:11132/plm
- JWT_SECRET=ilshin-plm-super-secret-jwt-key-2024
- JWT_EXPIRES_IN=24h
- CORS_ORIGIN=http://localhost:9771
- CORS_CREDENTIALS=true
- LOG_LEVEL=debug
volumes:
- ./backend-node:/app
- /app/node_modules
- LOG_LEVEL=info
# 운영용에서는 볼륨 마운트 없음 (보안상 이유)
networks:
- pms-network
restart: unless-stopped

View File

@ -1,11 +1,9 @@
version: '3.8'
services:
# Next.js 프론트엔드만
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
context: ../../frontend
dockerfile: ../docker/prod/frontend.Dockerfile
args:
- NEXT_PUBLIC_API_URL=http://192.168.0.70:8080/api
container_name: pms-frontend-linux
@ -24,4 +22,4 @@ services:
networks:
pms-network:
driver: bridge
external: true
external: true

View File

@ -194,7 +194,7 @@ export function AppLayout({ children }: AppLayoutProps) {
const router = useRouter();
const pathname = usePathname();
const { user, logout, refreshUserData } = useAuth();
const { userMenus, adminMenus, loading } = useMenu();
const { userMenus, adminMenus, loading, refreshMenus } = useMenu();
const [sidebarOpen, setSidebarOpen] = useState(false);
const [expandedMenus, setExpandedMenus] = useState<Set<string>>(new Set());
@ -204,6 +204,7 @@ export function AppLayout({ children }: AppLayoutProps) {
formData,
selectedImage,
isSaving,
departments,
alertModal,
closeAlert,
openProfileModal,
@ -212,7 +213,7 @@ export function AppLayout({ children }: AppLayoutProps) {
selectImage,
removeImage,
saveProfile,
} = useProfile(user, refreshUserData);
} = useProfile(user, refreshUserData, refreshMenus);
// 현재 경로에 따라 어드민 모드인지 판단
const isAdminMode = pathname.startsWith("/admin");
@ -394,6 +395,7 @@ export function AppLayout({ children }: AppLayoutProps) {
formData={formData}
selectedImage={selectedImage}
isSaving={isSaving}
departments={departments}
alertModal={alertModal}
onClose={closeProfileModal}
onFormChange={updateFormData}

View File

@ -53,6 +53,10 @@ interface ProfileModalProps {
formData: ProfileFormData;
selectedImage: string;
isSaving: boolean;
departments: Array<{
deptCode: string;
deptName: string;
}>;
alertModal: {
isOpen: boolean;
title: string;
@ -76,6 +80,7 @@ export function ProfileModal({
formData,
selectedImage,
isSaving,
departments,
alertModal,
onClose,
onFormChange,
@ -99,12 +104,14 @@ export function ProfileModal({
<Avatar className="h-24 w-24">
{selectedImage ? (
<AvatarImage src={selectedImage} alt="프로필 사진 미리보기" />
) : user?.photo ? (
<AvatarImage src={user.photo} alt="기존 프로필 사진" />
) : (
<AvatarFallback className="text-lg">{formData.userName?.substring(0, 1) || "U"}</AvatarFallback>
)}
</Avatar>
{selectedImage && (
{(selectedImage || user?.photo) && (
<Button
type="button"
variant="destructive"
@ -171,12 +178,24 @@ export function ProfileModal({
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="deptName"></Label>
<Input
id="deptName"
value={formData.deptName}
onChange={(e) => onFormChange("deptName", e.target.value)}
placeholder="부서를 입력하세요"
/>
<Select value={formData.deptName} onValueChange={(value) => onFormChange("deptName", value)}>
<SelectTrigger>
<SelectValue placeholder="부서 선택" />
</SelectTrigger>
<SelectContent>
{Array.isArray(departments) && departments.length > 0 ? (
departments.map((department) => (
<SelectItem key={department.deptCode} value={department.deptName}>
{department.deptName}
</SelectItem>
))
) : (
<SelectItem value="no-data" disabled>
</SelectItem>
)}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="positionName"></Label>

View File

@ -19,6 +19,7 @@ interface UserInfo {
userTypeName?: string;
authName?: string;
partnerCd?: string;
locale?: string;
isAdmin: boolean;
sabun?: string;
photo?: string | null;

View File

@ -180,5 +180,6 @@ export const useMenu = (user: any, authLoading: boolean) => {
isMenuLoading: menuState.isLoading,
handleMenuClick,
toggleMenu,
refreshMenus: loadMenuData, // 메뉴 새로고침 함수 추가
};
};

View File

@ -1,8 +1,9 @@
"use client";
import { useState, useCallback } from "react";
import { useState, useCallback, useEffect } from "react";
import { ProfileFormData, ProfileModalState } from "@/types/profile";
import { LAYOUT_CONFIG, MESSAGES } from "@/constants/layout";
import { apiCall } from "@/lib/api/client";
// 알림 모달 상태 타입
interface AlertModalState {
@ -15,7 +16,7 @@ interface AlertModalState {
/**
*
*/
export const useProfile = (user: any, refreshUserData: () => Promise<void>) => {
export const useProfile = (user: any, refreshUserData: () => Promise<void>, refreshMenus?: () => Promise<void>) => {
// 상태 관리
const [modalState, setModalState] = useState<ProfileModalState>({
isOpen: false,
@ -39,6 +40,14 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>) => {
type: "info",
});
// 부서 목록 상태
const [departments, setDepartments] = useState<
Array<{
deptCode: string;
deptName: string;
}>
>([]);
// 알림 모달 표시 함수
const showAlert = useCallback((title: string, message: string, type: "success" | "error" | "info" = "info") => {
setAlertModal({
@ -54,11 +63,33 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>) => {
setAlertModal((prev) => ({ ...prev, isOpen: false }));
}, []);
// 부서 목록 로드 함수
const loadDepartments = useCallback(async () => {
try {
const response = await apiCall("GET", "/admin/departments");
if (response.success && response.data) {
setDepartments(response.data);
}
} catch (error) {
console.error("부서 목록 로드 실패:", error);
}
}, []);
/**
*
*/
const openProfileModal = useCallback(() => {
if (user) {
console.log("🔍 프로필 모달 열기 - 사용자 정보:", {
userName: user.userName,
email: user.email,
deptName: user.deptName,
locale: user.locale,
});
// 부서 목록 로드
loadDepartments();
setModalState((prev) => ({
...prev,
isOpen: true,
@ -67,14 +98,14 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>) => {
email: user.email || "",
deptName: user.deptName || "",
positionName: user.positionName || "",
locale: user.locale || "",
locale: user.locale || "KR", // 기본값을 KR로 설정
},
selectedImage: user.photo || "",
selectedFile: null,
isSaving: false,
}));
}
}, [user]);
}, [user, loadDepartments]);
/**
*
@ -181,48 +212,51 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>) => {
photoData = modalState.selectedImage;
}
// 사용자 정보 저장
const userSaveData = {
userId: user.userId,
// 사용자 정보 저장 데이터 준비
const updateData = {
userName: modalState.formData.userName,
email: modalState.formData.email,
deptName: modalState.formData.deptName,
positionName: modalState.formData.positionName,
locale: modalState.formData.locale,
photo: photoData,
photo: photoData !== user.photo ? photoData : undefined, // 변경된 경우만 전송
};
console.log("사용자 정보 저장 요청:", userSaveData);
console.log("프로필 업데이트 요청:", updateData);
const userResponse = await fetch(`${LAYOUT_CONFIG.API_BASE_URL}${LAYOUT_CONFIG.ENDPOINTS.USER_SAVE}`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(userSaveData),
});
// API 호출 (JWT 토큰 자동 포함)
const response = await apiCall("PUT", "/admin/profile", updateData);
if (userResponse.ok) {
const userResult = await userResponse.json();
console.log("사용자 정보 저장 응답:", userResult);
console.log("프로필 업데이트 응답:", response);
if (userResult.result) {
// 성공: 세션 정보 새로고침
await refreshUserData();
setModalState((prev) => ({
...prev,
selectedFile: null,
isOpen: false,
}));
showAlert("저장 완료", MESSAGES.PROFILE_SAVE_SUCCESS, "success");
} else {
throw new Error(userResult.msg || "사용자 정보 저장 실패");
if (response.result) {
// locale이 변경된 경우 전역 변수와 localStorage 업데이트
const localeChanged = modalState.formData.locale && modalState.formData.locale !== user.locale;
if (localeChanged) {
if (typeof window !== "undefined") {
// 전역 변수 업데이트
(window as any).__GLOBAL_USER_LANG = modalState.formData.locale;
// localStorage 업데이트
localStorage.setItem("userLocale", modalState.formData.locale);
console.log("🌍 사용자 locale 업데이트:", modalState.formData.locale);
}
}
// 성공: 사용자 정보 새로고침
await refreshUserData();
// locale이 변경된 경우 메뉴도 새로고침
if (localeChanged && refreshMenus) {
console.log("🔄 locale 변경으로 인한 메뉴 새로고침 시작");
await refreshMenus();
console.log("✅ 메뉴 새로고침 완료");
}
setModalState((prev) => ({
...prev,
selectedFile: null,
isOpen: false,
}));
showAlert("저장 완료", "프로필이 성공적으로 업데이트되었습니다.", "success");
} else {
const errorText = await userResponse.text();
console.error("API 응답 오류:", errorText);
throw new Error(`사용자 정보 저장 실패: ${userResponse.status} ${userResponse.statusText}`);
throw new Error(response.message || "프로필 업데이트 실패");
}
} catch (error) {
console.error("프로필 저장 실패:", error);
@ -239,6 +273,7 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>) => {
formData: modalState.formData,
selectedImage: modalState.selectedImage,
isSaving: modalState.isSaving,
departments,
// 알림 모달 상태
alertModal,

View File

@ -1,324 +0,0 @@
SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS
Commands marked with * may be preceded by a number, _N.
Notes in parentheses indicate the behavior if _N is given.
A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K.
h H Display this help.
q :q Q :Q ZZ Exit.
---------------------------------------------------------------------------
MMOOVVIINNGG
e ^E j ^N CR * Forward one line (or _N lines).
y ^Y k ^K ^P * Backward one line (or _N lines).
ESC-j * Forward one file line (or _N file lines).
ESC-k * Backward one file line (or _N file lines).
f ^F ^V SPACE * Forward one window (or _N lines).
b ^B ESC-v * Backward one window (or _N lines).
z * Forward one window (and set window to _N).
w * Backward one window (and set window to _N).
ESC-SPACE * Forward one window, but don't stop at end-of-file.
ESC-b * Backward one window, but don't stop at beginning-of-file.
d ^D * Forward one half-window (and set half-window to _N).
u ^U * Backward one half-window (and set half-window to _N).
ESC-) RightArrow * Right one half screen width (or _N positions).
ESC-( LeftArrow * Left one half screen width (or _N positions).
ESC-} ^RightArrow Right to last column displayed.
ESC-{ ^LeftArrow Left to first column.
F Forward forever; like "tail -f".
ESC-F Like F but stop when search pattern is found.
r ^R ^L Repaint screen.
R Repaint screen, discarding buffered input.
---------------------------------------------------
Default "window" is the screen height.
Default "half-window" is half of the screen height.
---------------------------------------------------------------------------
SSEEAARRCCHHIINNGG
/_p_a_t_t_e_r_n * Search forward for (_N-th) matching line.
?_p_a_t_t_e_r_n * Search backward for (_N-th) matching line.
n * Repeat previous search (for _N-th occurrence).
N * Repeat previous search in reverse direction.
ESC-n * Repeat previous search, spanning files.
ESC-N * Repeat previous search, reverse dir. & spanning files.
^O^N ^On * Search forward for (_N-th) OSC8 hyperlink.
^O^P ^Op * Search backward for (_N-th) OSC8 hyperlink.
^O^L ^Ol Jump to the currently selected OSC8 hyperlink.
ESC-u Undo (toggle) search highlighting.
ESC-U Clear search highlighting.
&_p_a_t_t_e_r_n * Display only matching lines.
---------------------------------------------------
Search is case-sensitive unless changed with -i or -I.
A search pattern may begin with one or more of:
^N or ! Search for NON-matching lines.
^E or * Search multiple files (pass thru END OF FILE).
^F or @ Start search at FIRST file (for /) or last file (for ?).
^K Highlight matches, but don't move (KEEP position).
^R Don't use REGULAR EXPRESSIONS.
^S _n Search for match in _n-th parenthesized subpattern.
^W WRAP search if no match found.
^L Enter next character literally into pattern.
---------------------------------------------------------------------------
JJUUMMPPIINNGG
g < ESC-< * Go to first line in file (or line _N).
G > ESC-> * Go to last line in file (or line _N).
p % * Go to beginning of file (or _N percent into file).
t * Go to the (_N-th) next tag.
T * Go to the (_N-th) previous tag.
{ ( [ * Find close bracket } ) ].
} ) ] * Find open bracket { ( [.
ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>.
ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_>.
---------------------------------------------------
Each "find close bracket" command goes forward to the close bracket
matching the (_N-th) open bracket in the top line.
Each "find open bracket" command goes backward to the open bracket
matching the (_N-th) close bracket in the bottom line.
m_<_l_e_t_t_e_r_> Mark the current top line with <letter>.
M_<_l_e_t_t_e_r_> Mark the current bottom line with <letter>.
'_<_l_e_t_t_e_r_> Go to a previously marked position.
'' Go to the previous position.
^X^X Same as '.
ESC-m_<_l_e_t_t_e_r_> Clear a mark.
---------------------------------------------------
A mark is any upper-case or lower-case letter.
Certain marks are predefined:
^ means beginning of the file
$ means end of the file
---------------------------------------------------------------------------
CCHHAANNGGIINNGG FFIILLEESS
:e [_f_i_l_e] Examine a new file.
^X^V Same as :e.
:n * Examine the (_N-th) next file from the command line.
:p * Examine the (_N-th) previous file from the command line.
:x * Examine the first (or _N-th) file from the command line.
^O^O Open the currently selected OSC8 hyperlink.
:d Delete the current file from the command line list.
= ^G :f Print current file name.
---------------------------------------------------------------------------
MMIISSCCEELLLLAANNEEOOUUSS CCOOMMMMAANNDDSS
-_<_f_l_a_g_> Toggle a command line option [see OPTIONS below].
--_<_n_a_m_e_> Toggle a command line option, by name.
__<_f_l_a_g_> Display the setting of a command line option.
___<_n_a_m_e_> Display the setting of an option, by name.
+_c_m_d Execute the less cmd each time a new file is examined.
!_c_o_m_m_a_n_d Execute the shell command with $SHELL.
#_c_o_m_m_a_n_d Execute the shell command, expanded like a prompt.
|XX_c_o_m_m_a_n_d Pipe file between current pos & mark XX to shell command.
s _f_i_l_e Save input to a file.
v Edit the current file with $VISUAL or $EDITOR.
V Print version number of "less".
---------------------------------------------------------------------------
OOPPTTIIOONNSS
Most options may be changed either on the command line,
or from within less by using the - or -- command.
Options may be given in one of two forms: either a single
character preceded by a -, or a name preceded by --.
-? ........ --help
Display help (from command line).
-a ........ --search-skip-screen
Search skips current screen.
-A ........ --SEARCH-SKIP-SCREEN
Search starts just after target line.
-b [_N] .... --buffers=[_N]
Number of buffers.
-B ........ --auto-buffers
Don't automatically allocate buffers for pipes.
-c ........ --clear-screen
Repaint by clearing rather than scrolling.
-d ........ --dumb
Dumb terminal.
-D xx_c_o_l_o_r . --color=xx_c_o_l_o_r
Set screen colors.
-e -E .... --quit-at-eof --QUIT-AT-EOF
Quit at end of file.
-f ........ --force
Force open non-regular files.
-F ........ --quit-if-one-screen
Quit if entire file fits on first screen.
-g ........ --hilite-search
Highlight only last match for searches.
-G ........ --HILITE-SEARCH
Don't highlight any matches for searches.
-h [_N] .... --max-back-scroll=[_N]
Backward scroll limit.
-i ........ --ignore-case
Ignore case in searches that do not contain uppercase.
-I ........ --IGNORE-CASE
Ignore case in all searches.
-j [_N] .... --jump-target=[_N]
Screen position of target lines.
-J ........ --status-column
Display a status column at left edge of screen.
-k _f_i_l_e ... --lesskey-file=_f_i_l_e
Use a compiled lesskey file.
-K ........ --quit-on-intr
Exit less in response to ctrl-C.
-L ........ --no-lessopen
Ignore the LESSOPEN environment variable.
-m -M .... --long-prompt --LONG-PROMPT
Set prompt style.
-n ......... --line-numbers
Suppress line numbers in prompts and messages.
-N ......... --LINE-NUMBERS
Display line number at start of each line.
-o [_f_i_l_e] .. --log-file=[_f_i_l_e]
Copy to log file (standard input only).
-O [_f_i_l_e] .. --LOG-FILE=[_f_i_l_e]
Copy to log file (unconditionally overwrite).
-p _p_a_t_t_e_r_n . --pattern=[_p_a_t_t_e_r_n]
Start at pattern (from command line).
-P [_p_r_o_m_p_t] --prompt=[_p_r_o_m_p_t]
Define new prompt.
-q -Q .... --quiet --QUIET --silent --SILENT
Quiet the terminal bell.
-r -R .... --raw-control-chars --RAW-CONTROL-CHARS
Output "raw" control characters.
-s ........ --squeeze-blank-lines
Squeeze multiple blank lines.
-S ........ --chop-long-lines
Chop (truncate) long lines rather than wrapping.
-t _t_a_g .... --tag=[_t_a_g]
Find a tag.
-T [_t_a_g_s_f_i_l_e] --tag-file=[_t_a_g_s_f_i_l_e]
Use an alternate tags file.
-u -U .... --underline-special --UNDERLINE-SPECIAL
Change handling of backspaces, tabs and carriage returns.
-V ........ --version
Display the version number of "less".
-w ........ --hilite-unread
Highlight first new line after forward-screen.
-W ........ --HILITE-UNREAD
Highlight first new line after any forward movement.
-x [_N[,...]] --tabs=[_N[,...]]
Set tab stops.
-X ........ --no-init
Don't use termcap init/deinit strings.
-y [_N] .... --max-forw-scroll=[_N]
Forward scroll limit.
-z [_N] .... --window=[_N]
Set size of window.
-" [_c[_c]] . --quotes=[_c[_c]]
Set shell quote characters.
-~ ........ --tilde
Don't display tildes after end of file.
-# [_N] .... --shift=[_N]
Set horizontal scroll amount (0 = one half screen width).
--exit-follow-on-close
Exit F command on a pipe when writer closes pipe.
--file-size
Automatically determine the size of the input file.
--follow-name
The F command changes files if the input file is renamed.
--form-feed
Stop scrolling when a form feed character is reached.
--header=[_L[,_C[,_N]]]
Use _L lines (starting at line _N) and _C columns as headers.
--incsearch
Search file as each pattern character is typed in.
--intr=[_C]
Use _C instead of ^X to interrupt a read.
--lesskey-context=_t_e_x_t
Use lesskey source file contents.
--lesskey-src=_f_i_l_e
Use a lesskey source file.
--line-num-width=[_N]
Set the width of the -N line number field to _N characters.
--match-shift=[_N]
Show at least _N characters to the left of a search match.
--modelines=[_N]
Read _N lines from the input file and look for vim modelines.
--mouse
Enable mouse input.
--no-edit-warn
Don't warn when using v command on a file opened via LESSOPEN.
--no-keypad
Don't send termcap keypad init/deinit strings.
--no-histdups
Remove duplicates from command history.
--no-number-headers
Don't give line numbers to header lines.
--no-paste
Ignore pasted input.
--no-search-header-lines
Searches do not include header lines.
--no-search-header-columns
Searches do not include header columns.
--no-search-headers
Searches do not include header lines or columns.
--no-vbell
Disable the terminal's visual bell.
--redraw-on-quit
Redraw final screen when quitting.
--rscroll=[_C]
Set the character used to mark truncated lines.
--save-marks
Retain marks across invocations of less.
--search-options=[EFKNRW-]
Set default options for every search.
--show-preproc-errors
Display a message if preprocessor exits with an error status.
--proc-backspace
Process backspaces for bold/underline.
--PROC-BACKSPACE
Treat backspaces as control characters.
--proc-return
Delete carriage returns before newline.
--PROC-RETURN
Treat carriage returns as control characters.
--proc-tab
Expand tabs to spaces.
--PROC-TAB
Treat tabs as control characters.
--status-col-width=[_N]
Set the width of the -J status column to _N characters.
--status-line
Highlight or color the entire line containing a mark.
--use-backslash
Subsequent options use backslash as escape char.
--use-color
Enables colored text.
--wheel-lines=[_N]
Each click of the mouse wheel moves _N lines.
--wordwrap
Wrap lines at spaces.
---------------------------------------------------------------------------
LLIINNEE EEDDIITTIINNGG
These keys can be used to edit text being entered
on the "command line" at the bottom of the screen.
RightArrow ..................... ESC-l ... Move cursor right one character.
LeftArrow ...................... ESC-h ... Move cursor left one character.
ctrl-RightArrow ESC-RightArrow ESC-w ... Move cursor right one word.
ctrl-LeftArrow ESC-LeftArrow ESC-b ... Move cursor left one word.
HOME ........................... ESC-0 ... Move cursor to start of line.
END ............................ ESC-$ ... Move cursor to end of line.
BACKSPACE ................................ Delete char to left of cursor.
DELETE ......................... ESC-x ... Delete char under cursor.
ctrl-BACKSPACE ESC-BACKSPACE ........... Delete word to left of cursor.
ctrl-DELETE .... ESC-DELETE .... ESC-X ... Delete word under cursor.
ctrl-U ......... ESC (MS-DOS only) ....... Delete entire line.
UpArrow ........................ ESC-k ... Retrieve previous command line.
DownArrow ...................... ESC-j ... Retrieve next command line.
TAB ...................................... Complete filename & cycle.
SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle.
ctrl-L ................................... Complete filename, list all.

View File

@ -1,19 +0,0 @@
@echo off
echo =================================
echo 백엔드 빠른 재시작 스크립트
echo =================================
cd /d %~dp0
echo [1/2] 백엔드 컨테이너 재시작 중...
docker-compose -f docker-compose.springboot.yml restart backend
echo [2/2] 상태 확인 중...
timeout /t 5 > nul
docker-compose -f docker-compose.springboot.yml ps backend
echo.
echo 백엔드 빠른 재시작 완료!
echo 접속 URL: http://localhost:8080
echo.
pause

View File

@ -1,24 +0,0 @@
@echo off
echo =================================
echo 백엔드 재시작 스크립트
echo =================================
cd /d %~dp0
echo [1/3] 백엔드 컨테이너 중지 중...
docker-compose -f docker-compose.springboot.yml stop backend
echo [2/3] 백엔드 컨테이너 재빌드 중...
docker-compose -f docker-compose.springboot.yml build --no-cache backend
echo [3/3] 백엔드 컨테이너 시작 중...
docker-compose -f docker-compose.springboot.yml up -d backend
echo.
echo 백엔드 재시작 완료!
echo 접속 URL: http://localhost:8080
echo.
echo 로그 확인을 원하시면 아무 키나 누르세요...
pause > nul
docker-compose -f docker-compose.springboot.yml logs -f backend

View File

@ -1,40 +0,0 @@
@echo off
echo =====================================
echo PLM 솔루션 - Windows 시작
echo =====================================
echo 기존 컨테이너 정리 중...
docker-compose -f docker-compose.win.yml down 2>nul
echo PLM 서비스 시작 중...
docker-compose -f docker-compose.win.yml up --build --force-recreate -d
if %errorlevel% equ 0 (
echo.
echo ✅ PLM 서비스가 성공적으로 시작되었습니다!
echo.
echo 🌐 접속 URL:
echo • 프론트엔드 (Next.js): http://localhost:3000
echo • 백엔드 (Spring/JSP): http://localhost:9090
echo.
echo 📋 서비스 상태 확인:
echo docker-compose -f docker-compose.win.yml ps
echo.
echo 📊 로그 확인:
echo docker-compose -f docker-compose.win.yml logs
echo.
echo 5초 후 프론트엔드 페이지를 자동으로 엽니다...
timeout /t 5 /nobreak >nul
start http://localhost:3000
) else (
echo.
echo ❌ PLM 서비스 시작에 실패했습니다!
echo.
echo 🔍 문제 해결 방법:
echo 1. Docker Desktop이 실행 중인지 확인
echo 2. 포트가 사용 중인지 확인 (3000, 9090)
echo 3. 로그 확인: docker-compose -f docker-compose.win.yml logs
echo.
pause
)

129
scripts/dev/start-all-parallel.sh Executable file
View File

@ -0,0 +1,129 @@
#!/bin/bash
# 시작 시간 기록
START_TIME=$(date +%s)
START_TIME_FORMATTED=$(date '+%Y-%m-%d %H:%M:%S')
echo "============================================"
echo "PLM 솔루션 - 전체 서비스 시작 (병렬 최적화)"
echo "============================================"
echo "🕐 시작 시간: $START_TIME_FORMATTED"
echo ""
echo "🚀 백엔드와 프론트엔드를 병렬로 빌드 및 시작합니다..."
echo ""
# 기존 컨테이너 강제 삭제 (이름 충돌 방지)
echo "============================================"
echo "0. 기존 컨테이너 정리 중..."
echo "============================================"
docker rm -f pms-backend-mac pms-frontend-mac 2>/dev/null || echo "기존 컨테이너가 없습니다."
docker network rm pms-network 2>/dev/null || echo "기존 네트워크가 없습니다."
docker network create pms-network 2>/dev/null || echo "네트워크를 생성했습니다."
echo ""
# 병렬 빌드 시작
PARALLEL_START=$(date +%s)
echo "============================================"
echo "1. 병렬 빌드 시작 (백엔드 + 프론트엔드)"
echo "============================================"
# 백엔드 빌드 (백그라운드)
echo "🔧 백엔드 빌드 시작..."
(
docker-compose -f docker/dev/docker-compose.backend.mac.yml build
echo "✅ 백엔드 빌드 완료"
) &
BACKEND_PID=$!
# 프론트엔드 빌드 (백그라운드)
echo "🔧 프론트엔드 빌드 시작..."
(
docker-compose -f docker/dev/docker-compose.frontend.mac.yml build
echo "✅ 프론트엔드 빌드 완료"
) &
FRONTEND_PID=$!
# 두 빌드가 모두 완료될 때까지 대기
echo "⏳ 병렬 빌드 진행 중..."
wait $BACKEND_PID
wait $FRONTEND_PID
PARALLEL_END=$(date +%s)
PARALLEL_DURATION=$((PARALLEL_END - PARALLEL_START))
echo "✅ 병렬 빌드 완료 (${PARALLEL_DURATION}초 소요)"
# 서비스 시작
echo ""
echo "============================================"
echo "2. 서비스 시작 중..."
echo "============================================"
SERVICE_START=$(date +%s)
# 기존 컨테이너 정리
docker-compose -f docker/dev/docker-compose.backend.mac.yml down -v 2>/dev/null
docker-compose -f docker/dev/docker-compose.frontend.mac.yml down -v 2>/dev/null
# 백엔드 시작 (백그라운드)
echo "🚀 백엔드 서비스 시작..."
docker-compose -f docker/dev/docker-compose.backend.mac.yml up -d &
BACKEND_START_PID=$!
# 프론트엔드 시작 (백그라운드)
echo "🚀 프론트엔드 서비스 시작..."
docker-compose -f docker/dev/docker-compose.frontend.mac.yml up -d &
FRONTEND_START_PID=$!
# 서비스 시작 완료 대기
wait $BACKEND_START_PID
wait $FRONTEND_START_PID
echo ""
echo "⏳ 서비스 안정화 대기 중... (8초)"
sleep 8
SERVICE_END=$(date +%s)
SERVICE_DURATION=$((SERVICE_END - SERVICE_START))
echo "✅ 서비스 시작 완료 (${SERVICE_DURATION}초 소요)"
echo ""
echo "============================================"
echo "🎉 모든 서비스가 시작되었습니다!"
echo "============================================"
echo ""
echo "[DATABASE] PostgreSQL: http://39.117.244.52:11132"
echo "[BACKEND] Node.js API: http://localhost:8080/api"
echo "[FRONTEND] Next.js: http://localhost:9771"
echo ""
echo "서비스 상태 확인:"
echo " 백엔드: docker-compose -f docker/dev/docker-compose.backend.mac.yml ps"
echo " 프론트엔드: docker-compose -f docker/dev/docker-compose.frontend.mac.yml ps"
echo ""
echo "로그 확인:"
echo " 백엔드: docker-compose -f docker/dev/docker-compose.backend.mac.yml logs -f"
echo " 프론트엔드: docker-compose -f docker/dev/docker-compose.frontend.mac.yml logs -f"
echo ""
echo "서비스 중지:"
echo " 백엔드: docker-compose -f docker/dev/docker-compose.backend.mac.yml down"
echo " 프론트엔드: docker-compose -f docker/dev/docker-compose.frontend.mac.yml down"
echo " 전체: ./stop-all.sh"
echo ""
echo "============================================"
# 종료 시간 계산 및 표시
END_TIME=$(date +%s)
END_TIME_FORMATTED=$(date '+%Y-%m-%d %H:%M:%S')
DURATION=$((END_TIME - START_TIME))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))
echo "🕐 종료 시간: $END_TIME_FORMATTED"
echo "⏱️ 총 소요 시간: ${MINUTES}${SECONDS}"
echo ""
echo "📊 단계별 소요 시간:"
echo " • 병렬 빌드: ${PARALLEL_DURATION}"
echo " • 서비스 시작: ${SERVICE_DURATION}"
echo "============================================"
read -p "계속하려면 아무 키나 누르세요..."

18
start-backend.sh → scripts/dev/start-backend.sh Normal file → Executable file
View File

@ -1,16 +1,16 @@
#!/bin/bash
echo "============================================"
echo "PLM 솔루션 - 백엔드 (Spring Boot) 시작"
echo "PLM 솔루션 - 백엔드 (Node.js) 시작"
echo "============================================"
echo ""
echo "1. Docker 이미지 빌드 중..."
docker-compose -f docker-compose.backend.mac.yml build --no-cache
docker-compose -f docker/dev/docker-compose.backend.mac.yml build
echo ""
echo "2. 기존 백엔드 컨테이너 정리 중..."
docker-compose -f docker-compose.backend.mac.yml down -v
docker-compose -f docker/dev/docker-compose.backend.mac.yml down -v
echo ""
echo "3. Docker 네트워크 생성 중..."
@ -18,11 +18,11 @@ docker network create pms-network 2>/dev/null || echo "네트워크가 이미
echo ""
echo "4. 백엔드 컨테이너 시작 중..."
docker-compose -f docker-compose.backend.mac.yml up -d
docker-compose -f docker/dev/docker-compose.backend.mac.yml up -d
echo ""
echo "5. 서비스 상태 확인 중..."
sleep 15
sleep 8
echo ""
echo "============================================"
@ -30,11 +30,11 @@ echo "백엔드 서비스가 시작되었습니다!"
echo "============================================"
echo ""
echo "[DATABASE] PostgreSQL: http://39.117.244.52:11132"
echo "[BACKEND] Spring Boot: http://localhost:8080/api"
echo "[BACKEND] Node.js API: http://localhost:8080/api"
echo ""
echo "상태 확인: docker-compose -f docker-compose.backend.mac.yml ps"
echo "로그 확인: docker-compose -f docker-compose.backend.mac.yml logs -f"
echo "중지하기: docker-compose -f docker-compose.backend.mac.yml down"
echo "상태 확인: docker-compose -f docker/dev/docker-compose.backend.mac.yml ps"
echo "로그 확인: docker-compose -f docker/dev/docker-compose.backend.mac.yml logs -f"
echo "중지하기: docker-compose -f docker/dev/docker-compose.backend.mac.yml down"
echo ""
echo "============================================"

View File

@ -6,29 +6,23 @@ echo "============================================"
echo ""
echo "1. Docker 이미지 빌드 중..."
docker-compose -f docker-compose.frontend.mac.yml build --no-cache
docker-compose -f docker/dev/docker-compose.frontend.mac.yml build
echo ""
echo "2. 기존 프론트엔드 컨테이너 정리 중..."
docker-compose -f docker-compose.frontend.mac.yml down -v
docker-compose -f docker/dev/docker-compose.frontend.mac.yml down -v
echo ""
echo "3. Docker 네트워크 확인 중..."
if ! docker network ls | grep -q pms-network; then
echo "❌ 백엔드가 먼저 실행되지 않았습니다!"
echo "먼저 './start-backend.sh'를 실행해주세요."
echo ""
read -p "계속하려면 아무 키나 누르세요..."
exit 1
fi
echo "3. Docker 네트워크 생성 중..."
docker network create pms-network 2>/dev/null || echo "네트워크가 이미 존재합니다."
echo ""
echo "4. 프론트엔드 컨테이너 시작 중..."
docker-compose -f docker-compose.frontend.mac.yml up -d
docker-compose -f docker/dev/docker-compose.frontend.mac.yml up -d
echo ""
echo "5. 서비스 상태 확인 중..."
sleep 10
sleep 8
echo ""
echo "============================================"
@ -39,9 +33,9 @@ echo "[FRONTEND] Next.js: http://localhost:9771"
echo ""
echo "💡 백엔드 API가 필요하므로 백엔드도 실행되어 있는지 확인하세요."
echo ""
echo "상태 확인: docker-compose -f docker-compose.frontend.mac.yml ps"
echo "로그 확인: docker-compose -f docker-compose.frontend.mac.yml logs -f"
echo "중지하기: docker-compose -f docker-compose.frontend.mac.yml down"
echo "상태 확인: docker-compose -f docker/dev/docker-compose.frontend.mac.yml ps"
echo "로그 확인: docker-compose -f docker/dev/docker-compose.frontend.mac.yml logs -f"
echo "중지하기: docker-compose -f docker/dev/docker-compose.frontend.mac.yml down"
echo ""
echo "============================================"

View File

@ -27,8 +27,8 @@ echo "0. 기존 서비스 정리 중..."
echo "============================================"
# 기존 컨테이너 중지 및 제거 (무시하고 계속)
docker-compose -f docker-compose.backend.linux.yml down -v 2>/dev/null || true
docker-compose -f docker-compose.frontend.linux.yml down -v 2>/dev/null || true
docker-compose -f docker/prod/docker-compose.backend.prod.yml down -v 2>/dev/null || true
docker-compose -f docker/prod/docker-compose.frontend.prod.yml down -v 2>/dev/null || true
# 사용하지 않는 이미지 정리
echo "사용하지 않는 Docker 이미지 정리 중..."
@ -45,10 +45,10 @@ docker network create pms-network 2>/dev/null || echo "네트워크가 이미
# 백엔드 빌드 및 시작
echo "백엔드 이미지 빌드 중..."
docker-compose -f docker-compose.backend.linux.yml build --no-cache
docker-compose -f docker/prod/docker-compose.backend.prod.yml build --no-cache
echo "백엔드 서비스 시작 중..."
docker-compose -f docker-compose.backend.linux.yml up -d
docker-compose -f docker/prod/docker-compose.backend.prod.yml up -d
echo ""
echo "⏳ 백엔드 서비스 안정화 대기 중... (30초)"
@ -56,7 +56,7 @@ sleep 30
# 백엔드 상태 확인
echo "백엔드 서비스 상태 확인:"
docker-compose -f docker-compose.backend.linux.yml ps
docker-compose -f docker/prod/docker-compose.backend.prod.yml ps
# 프론트엔드 시작
echo ""
@ -65,10 +65,10 @@ echo "2. 프론트엔드 서비스 시작 중..."
echo "============================================"
echo "프론트엔드 이미지 빌드 중..."
docker-compose -f docker-compose.frontend.linux.yml build --no-cache
docker-compose -f docker/prod/docker-compose.frontend.prod.yml build --no-cache
echo "프론트엔드 서비스 시작 중..."
docker-compose -f docker-compose.frontend.linux.yml up -d
docker-compose -f docker/prod/docker-compose.frontend.prod.yml up -d
echo ""
echo "⏳ 프론트엔드 서비스 안정화 대기 중... (15초)"
@ -76,7 +76,7 @@ sleep 15
# 프론트엔드 상태 확인
echo "프론트엔드 서비스 상태 확인:"
docker-compose -f docker-compose.frontend.linux.yml ps
docker-compose -f docker/prod/docker-compose.frontend.prod.yml ps
echo ""
echo "============================================"
@ -90,18 +90,18 @@ echo " [FRONTEND] Next.js: http://localhost:5555"
echo ""
echo "🔧 관리 명령어:"
echo " 서비스 상태 확인:"
echo " 백엔드: docker-compose -f docker-compose.backend.linux.yml ps"
echo " 프론트엔드: docker-compose -f docker-compose.frontend.linux.yml ps"
echo " 백엔드: docker-compose -f docker/prod/docker-compose.backend.prod.yml ps"
echo " 프론트엔드: docker-compose -f docker/prod/docker-compose.frontend.prod.yml ps"
echo " 전체: docker ps"
echo ""
echo " 로그 확인:"
echo " 백엔드: docker-compose -f docker-compose.backend.linux.yml logs -f"
echo " 프론트엔드: docker-compose -f docker-compose.frontend.linux.yml logs -f"
echo " 실시간: docker-compose -f docker-compose.backend.linux.yml -f docker-compose.frontend.linux.yml logs -f"
echo " 백엔드: docker-compose -f docker/prod/docker-compose.backend.prod.yml logs -f"
echo " 프론트엔드: docker-compose -f docker/prod/docker-compose.frontend.prod.yml logs -f"
echo " 실시간: docker-compose -f docker/prod/docker-compose.backend.prod.yml -f docker-compose.frontend.linux.yml logs -f"
echo ""
echo " 서비스 중지:"
echo " 백엔드: docker-compose -f docker-compose.backend.linux.yml down"
echo " 프론트엔드: docker-compose -f docker-compose.frontend.linux.yml down"
echo " 백엔드: docker-compose -f docker/prod/docker-compose.backend.prod.yml down"
echo " 프론트엔드: docker-compose -f docker/prod/docker-compose.frontend.prod.yml down"
echo " 전체: ./stop-all-linux.sh"
echo ""
echo " 시스템 모니터링:"

View File

@ -1,64 +0,0 @@
@echo off
chcp 65001 >nul
echo ============================================
echo PLM 솔루션 - 전체 서비스 시작 (분리형)
echo ============================================
echo.
echo 🚀 백엔드와 프론트엔드를 순차적으로 시작합니다...
echo.
REM 백엔드 먼저 시작
echo ============================================
echo 1. 백엔드 서비스 시작 중...
echo ============================================
docker-compose -f docker-compose.backend.win.yml build --no-cache
docker-compose -f docker-compose.backend.win.yml down -v
docker network create pms-network 2>nul || echo 네트워크가 이미 존재합니다.
docker-compose -f docker-compose.backend.win.yml up -d
echo.
echo ⏳ 백엔드 서비스 안정화 대기 중... (20초)
timeout /t 20 /nobreak >nul
REM 프론트엔드 시작
echo.
echo ============================================
echo 2. 프론트엔드 서비스 시작 중...
echo ============================================
docker-compose -f docker-compose.frontend.win.yml build --no-cache
docker-compose -f docker-compose.frontend.win.yml down -v
docker-compose -f docker-compose.frontend.win.yml up -d
echo.
echo ⏳ 프론트엔드 서비스 안정화 대기 중... (10초)
timeout /t 10 /nobreak >nul
echo.
echo ============================================
echo 🎉 모든 서비스가 시작되었습니다!
echo ============================================
echo.
echo [DATABASE] PostgreSQL: http://39.117.244.52:11132
echo [BACKEND] Spring Boot: http://localhost:8080/api
echo [FRONTEND] Next.js: http://localhost:9771
echo.
echo 서비스 상태 확인:
echo 백엔드: docker-compose -f docker-compose.backend.win.yml ps
echo 프론트엔드: docker-compose -f docker-compose.frontend.win.yml ps
echo.
echo 로그 확인:
echo 백엔드: docker-compose -f docker-compose.backend.win.yml logs -f
echo 프론트엔드: docker-compose -f docker-compose.frontend.win.yml logs -f
echo.
echo 서비스 중지:
echo 백엔드: docker-compose -f docker-compose.backend.win.yml down
echo 프론트엔드: docker-compose -f docker-compose.frontend.win.yml down
echo 전체: stop-all-separated.bat
echo.
echo ============================================
pause

View File

@ -1,71 +0,0 @@
#!/bin/bash
echo "============================================"
echo "PLM 솔루션 - 전체 서비스 시작 (분리형)"
echo "============================================"
echo ""
echo "🚀 백엔드(Node.js)와 프론트엔드(Next.js)를 순차적으로 시작합니다..."
echo ""
# 기존 컨테이너 강제 삭제 (이름 충돌 방지)
echo "============================================"
echo "0. 기존 컨테이너 정리 중..."
echo "============================================"
docker rm -f pms-backend-mac pms-frontend-mac 2>/dev/null || echo "기존 컨테이너가 없습니다."
docker network rm pms-network 2>/dev/null || echo "기존 네트워크가 없습니다."
echo ""
# 백엔드 먼저 시작
echo "============================================"
echo "1. 백엔드 서비스 시작 중... (Node.js)"
echo "============================================"
docker-compose -f docker-compose.backend.mac.yml build --no-cache
docker-compose -f docker-compose.backend.mac.yml down -v
docker network create pms-network 2>/dev/null || echo "네트워크가 이미 존재합니다."
docker-compose -f docker-compose.backend.mac.yml up -d
echo ""
echo "⏳ 백엔드 서비스 안정화 대기 중... (20초)"
sleep 20
# 프론트엔드 시작
echo ""
echo "============================================"
echo "2. 프론트엔드 서비스 시작 중... (Next.js)"
echo "============================================"
docker-compose -f docker-compose.frontend.mac.yml build --no-cache
docker-compose -f docker-compose.frontend.mac.yml down -v
docker-compose -f docker-compose.frontend.mac.yml up -d
echo ""
echo "⏳ 프론트엔드 서비스 안정화 대기 중... (10초)"
sleep 10
echo ""
echo "============================================"
echo "🎉 모든 서비스가 시작되었습니다!"
echo "============================================"
echo ""
echo "[DATABASE] PostgreSQL: http://39.117.244.52:11132"
echo "[BACKEND] Node.js API: http://localhost:8080/api"
echo "[FRONTEND] Next.js: http://localhost:9771"
echo ""
echo "서비스 상태 확인:"
echo " 백엔드: docker-compose -f docker-compose.backend.mac.yml ps"
echo " 프론트엔드: docker-compose -f docker-compose.frontend.mac.yml ps"
echo ""
echo "로그 확인:"
echo " 백엔드: docker-compose -f docker-compose.backend.mac.yml logs -f"
echo " 프론트엔드: docker-compose -f docker-compose.frontend.mac.yml logs -f"
echo ""
echo "서비스 중지:"
echo " 백엔드: docker-compose -f docker-compose.backend.mac.yml down"
echo " 프론트엔드: docker-compose -f docker-compose.frontend.mac.yml down"
echo " 전체: ./stop-all.sh"
echo ""
echo "============================================"
read -p "계속하려면 아무 키나 누르세요..."

View File

@ -1,81 +0,0 @@
#!/bin/bash
echo "============================================"
echo "PLM 솔루션 - 백엔드 (Spring Boot) 시작 - Linux"
echo "============================================"
echo ""
echo "🚀 Spring Boot 백엔드를 Linux 서버에서 시작합니다..."
echo ""
# 시스템 정보 출력
echo "시스템 정보:"
echo " OS: $(uname -s)"
echo " Architecture: $(uname -m)"
echo " Kernel: $(uname -r)"
echo ""
# Docker 버전 확인
echo "Docker 환경 확인:"
docker --version 2>/dev/null || echo " ❌ Docker가 설치되지 않았습니다."
docker-compose --version 2>/dev/null || echo " ❌ Docker Compose가 설치되지 않았습니다."
echo ""
echo "1. Docker 이미지 빌드 중..."
docker-compose -f docker-compose.backend.linux.yml build --no-cache
echo ""
echo "2. 기존 백엔드 컨테이너 정리 중..."
docker-compose -f docker-compose.backend.linux.yml down -v
echo ""
echo "3. Docker 네트워크 생성 중..."
docker network create pms-network 2>/dev/null || echo "네트워크가 이미 존재합니다."
echo ""
echo "4. 백엔드 컨테이너 시작 중..."
docker-compose -f docker-compose.backend.linux.yml up -d
echo ""
echo "5. 서비스 상태 확인 중..."
sleep 20
echo ""
echo "============================================"
echo "🎉 백엔드 서비스가 시작되었습니다!"
echo "============================================"
echo ""
echo "📊 서비스 접속 정보:"
echo " [DATABASE] PostgreSQL: http://39.117.244.52:11132"
echo " [BACKEND] Spring Boot: http://localhost:8080/api"
echo ""
echo "💡 API 테스트:"
echo " 헬스체크: curl http://localhost:8080/api/actuator/health"
echo ""
echo "🔧 관리 명령어:"
echo " 상태 확인: docker-compose -f docker-compose.backend.linux.yml ps"
echo " 로그 확인: docker-compose -f docker-compose.backend.linux.yml logs -f"
echo " 중지하기: docker-compose -f docker-compose.backend.linux.yml down"
echo ""
echo "============================================"
# 헬스체크
echo ""
echo "🏥 백엔드 헬스체크 수행 중..."
for i in {1..12}; do
if curl -s http://localhost:8080/api/actuator/health >/dev/null 2>&1; then
echo " ✅ 백엔드 서비스 정상"
echo " 📋 헬스체크 결과:"
curl -s http://localhost:8080/api/actuator/health | jq . 2>/dev/null || curl -s http://localhost:8080/api/actuator/health
break
else
echo " ⏳ 백엔드 응답 대기 중... ($i/12)"
sleep 5
fi
done
echo ""
echo "🎯 백엔드 시작 완료! API는 http://localhost:8080/api 에서 확인하세요."
echo ""
read -p "계속하려면 Enter 키를 누르세요..."

View File

@ -1,45 +0,0 @@
@echo off
chcp 65001 >nul
echo ============================================
echo PLM 솔루션 - 백엔드 서비스 시작
echo ============================================
echo.
echo 🚀 백엔드 서비스를 시작합니다...
echo.
REM 백엔드 시작
echo ============================================
echo 백엔드 서비스 시작 중...
echo ============================================
docker-compose -f docker-compose.backend.win.yml build --no-cache
docker-compose -f docker-compose.backend.win.yml down -v
docker network create pms-network 2>nul || echo 네트워크가 이미 존재합니다.
docker-compose -f docker-compose.backend.win.yml up -d
echo.
echo ⏳ 백엔드 서비스 안정화 대기 중... (15초)
timeout /t 15 /nobreak >nul
echo.
echo ============================================
echo 🎉 백엔드 서비스가 시작되었습니다!
echo ============================================
echo.
echo [DATABASE] PostgreSQL: http://39.117.244.52:11132
echo [BACKEND] Spring Boot: http://localhost:8080/api
echo.
echo 서비스 상태 확인:
echo docker-compose -f docker-compose.backend.win.yml ps
echo.
echo 로그 확인:
echo docker-compose -f docker-compose.backend.win.yml logs -f
echo.
echo 서비스 중지:
echo docker-compose -f docker-compose.backend.win.yml down
echo.
echo ============================================
pause

View File

@ -1,83 +0,0 @@
#!/bin/bash
echo "============================================"
echo "PLM 솔루션 - 프론트엔드 (Next.js) 시작 - Linux"
echo "============================================"
echo ""
echo "🚀 Next.js 프론트엔드를 Linux 서버에서 시작합니다..."
echo ""
# 시스템 정보 출력
echo "시스템 정보:"
echo " OS: $(uname -s)"
echo " Architecture: $(uname -m)"
echo " Kernel: $(uname -r)"
echo ""
# Docker 버전 확인
echo "Docker 환경 확인:"
docker --version 2>/dev/null || echo " ❌ Docker가 설치되지 않았습니다."
docker-compose --version 2>/dev/null || echo " ❌ Docker Compose가 설치되지 않았습니다."
echo ""
echo "1. Docker 이미지 빌드 중..."
docker-compose -f docker-compose.frontend.linux.yml build --no-cache
echo ""
echo "2. 기존 프론트엔드 컨테이너 정리 중..."
docker-compose -f docker-compose.frontend.linux.yml down -v
echo ""
echo "3. Docker 네트워크 확인 중..."
if ! docker network ls | grep -q pms-network; then
echo "❌ 백엔드가 먼저 실행되지 않았습니다!"
echo "먼저 백엔드를 실행해주세요."
echo ""
read -p "계속하려면 Enter 키를 누르세요..."
exit 1
fi
echo ""
echo "4. 프론트엔드 컨테이너 시작 중..."
docker-compose -f docker-compose.frontend.linux.yml up -d
echo ""
echo "5. 서비스 상태 확인 중..."
sleep 15
echo ""
echo "============================================"
echo "🎉 프론트엔드 서비스가 시작되었습니다!"
echo "============================================"
echo ""
echo "📊 서비스 접속 정보:"
echo " [FRONTEND] Next.js: http://localhost:5555"
echo ""
echo "💡 백엔드 API가 필요하므로 백엔드도 실행되어 있는지 확인하세요."
echo ""
echo "🔧 관리 명령어:"
echo " 상태 확인: docker-compose -f docker-compose.frontend.linux.yml ps"
echo " 로그 확인: docker-compose -f docker-compose.frontend.linux.yml logs -f"
echo " 중지하기: docker-compose -f docker-compose.frontend.linux.yml down"
echo ""
echo "============================================"
# 헬스체크
echo ""
echo "🏥 프론트엔드 헬스체크 수행 중..."
for i in {1..6}; do
if curl -s http://localhost:5555 >/dev/null 2>&1; then
echo " ✅ 프론트엔드 서비스 정상"
break
else
echo " ⏳ 프론트엔드 응답 대기 중... ($i/6)"
sleep 5
fi
done
echo ""
echo "🎯 프론트엔드 시작 완료! 브라우저에서 http://localhost:5555 을 확인하세요."
echo ""
read -p "계속하려면 Enter 키를 누르세요..."

View File

@ -1,43 +0,0 @@
@echo off
chcp 65001 >nul
echo ============================================
echo PLM 솔루션 - 프론트엔드 서비스 시작
echo ============================================
echo.
echo 🚀 프론트엔드 서비스를 시작합니다...
echo.
REM 프론트엔드 시작
echo ============================================
echo 프론트엔드 서비스 시작 중...
echo ============================================
docker-compose -f docker-compose.frontend.win.yml build --no-cache
docker-compose -f docker-compose.frontend.win.yml down -v
docker-compose -f docker-compose.frontend.win.yml up -d
echo.
echo ⏳ 프론트엔드 서비스 안정화 대기 중... (10초)
timeout /t 10 /nobreak >nul
echo.
echo ============================================
echo 🎉 프론트엔드 서비스가 시작되었습니다!
echo ============================================
echo.
echo [FRONTEND] Next.js: http://localhost:9771
echo.
echo 서비스 상태 확인:
echo docker-compose -f docker-compose.frontend.win.yml ps
echo.
echo 로그 확인:
echo docker-compose -f docker-compose.frontend.win.yml logs -f
echo.
echo 서비스 중지:
echo docker-compose -f docker-compose.frontend.win.yml down
echo.
echo ============================================
pause

View File

@ -1,37 +0,0 @@
@echo off
echo ============================================
echo PLM 솔루션 - Spring Boot 버전 시작
echo ============================================
echo.
echo 1. Docker 이미지 빌드 중...
docker-compose -f docker-compose.springboot.yml build --no-cache
echo.
echo 2. 기존 컨테이너 정리 중...
docker-compose -f docker-compose.springboot.yml down -v
echo.
echo 3. 컨테이너 시작 중...
docker-compose -f docker-compose.springboot.yml up -d
echo.
echo 4. 서비스 상태 확인 중...
timeout /t 10 /nobreak >nul
echo.
echo ============================================
echo 서비스가 시작되었습니다!
echo ============================================
echo.
echo [DATABASE] PostgreSQL: http://localhost:
echo [BACKEND] Spring Boot: http://localhost:8080/api
echo [FRONTEND] Next.js: http://localhost:3000
echo.
echo 로그 확인: docker-compose -f docker-compose.springboot.yml logs -f
echo 중지하기: docker-compose -f docker-compose.springboot.yml down
echo.
echo ============================================
pause

View File

@ -1,49 +0,0 @@
@echo off
echo =====================================
echo PLM 솔루션 (WACE) - 상태 확인
echo =====================================
echo.
echo 📊 컨테이너 상태 확인 중...
echo.
docker-compose -f docker-compose.win.yml ps
echo.
echo 🌐 서비스 접속 정보:
echo • 프론트엔드 (Next.js): http://localhost:3000
echo • 백엔드 (Spring/JSP): http://localhost:9090
echo.
echo 🔧 유용한 명령어:
echo • 로그 확인: docker-compose -f docker-compose.win.yml logs
echo • 실시간 로그: docker-compose -f docker-compose.win.yml logs -f
echo • 특정 서비스 로그: docker-compose -f docker-compose.win.yml logs [plm-app|plm-frontend]
echo.
echo 💻 개별 서비스 상태 확인:
echo.
echo [프론트엔드 서비스]
docker-compose -f docker-compose.win.yml ps plm-frontend
echo.
echo [백엔드 서비스]
docker-compose -f docker-compose.win.yml ps plm-app
echo.
echo 🌐 브라우저에서 접속하시겠습니까? (Y/N)
set /p choice="선택: "
if /i "%choice%"=="Y" (
echo 프론트엔드 페이지를 엽니다...
start http://localhost:3000
) else if /i "%choice%"=="y" (
echo 프론트엔드 페이지를 엽니다...
start http://localhost:3000
)
echo.
echo 아무 키나 누르면 종료됩니다...
pause >nul

View File

@ -1,42 +0,0 @@
#!/bin/bash
echo "============================================"
echo "PLM 솔루션 - 전체 서비스 중지 - Linux"
echo "============================================"
echo ""
echo "🛑 모든 서비스를 중지합니다..."
echo ""
# 프론트엔드 먼저 중지
echo "1. 프론트엔드 서비스 중지 중..."
docker-compose -f docker-compose.frontend.linux.yml down -v
echo ""
echo "2. 백엔드 서비스 중지 중..."
docker-compose -f docker-compose.backend.linux.yml down -v
echo ""
echo "3. Docker 네트워크 정리 중..."
docker network rm pms-network 2>/dev/null || echo "네트워크가 이미 제거되었거나 사용 중입니다."
echo ""
echo "4. 사용하지 않는 리소스 정리 중..."
docker system prune -f
echo ""
echo "============================================"
echo "✅ 모든 서비스가 중지되었습니다!"
echo "============================================"
echo ""
echo "정리된 항목:"
echo " ✓ 프론트엔드 컨테이너 (pms-frontend-linux)"
echo " ✓ 백엔드 컨테이너 (pms-backend-linux)"
echo " ✓ Docker 네트워크 (pms-network)"
echo " ✓ 사용하지 않는 이미지 및 볼륨"
echo ""
echo "🔄 서비스 재시작: ./start-all-separated-linux.sh"
echo ""
echo "============================================"
read -p "계속하려면 Enter 키를 누르세요..."

View File

@ -1,56 +0,0 @@
@echo off
chcp 65001 >nul
echo ============================================
echo PLM 솔루션 - 전체 서비스 중지 (분리형)
echo ============================================
echo.
echo 🛑 백엔드와 프론트엔드 서비스를 순차적으로 중지합니다...
echo.
REM 프론트엔드 먼저 중지
echo ============================================
echo 1. 프론트엔드 서비스 중지 중...
echo ============================================
docker-compose -f docker-compose.frontend.win.yml down -v
echo.
echo ⏳ 프론트엔드 서비스 완전 중지 대기 중... (5초)
timeout /t 5 /nobreak >nul
REM 백엔드 중지
echo.
echo ============================================
echo 2. 백엔드 서비스 중지 중...
echo ============================================
docker-compose -f docker-compose.backend.win.yml down -v
echo.
echo ⏳ 백엔드 서비스 완전 중지 대기 중... (5초)
timeout /t 5 /nobreak >nul
REM 네트워크 정리 (선택사항)
echo.
echo ============================================
echo 3. 네트워크 정리 중...
echo ============================================
docker network rm pms-network 2>nul || echo 네트워크가 이미 삭제되었습니다.
echo.
echo ============================================
echo ✅ 모든 서비스가 중지되었습니다!
echo ============================================
echo.
echo 서비스 상태 확인:
echo docker ps
echo.
echo 서비스 시작:
echo start-all-separated.bat
echo.
echo ============================================
pause

View File

@ -1,32 +0,0 @@
#!/bin/bash
echo "============================================"
echo "PLM 솔루션 - 전체 서비스 중지"
echo "============================================"
echo ""
echo "🛑 모든 서비스를 중지합니다..."
echo ""
echo "1. 프론트엔드 서비스 중지 중..."
docker-compose -f docker-compose.frontend.mac.yml down -v
echo ""
echo "2. 백엔드 서비스 중지 중..."
docker-compose -f docker-compose.backend.mac.yml down -v
echo ""
echo "3. Docker 네트워크 정리 중..."
docker network rm pms-network 2>/dev/null || echo "네트워크가 이미 제거되었거나 사용 중입니다."
echo ""
echo "============================================"
echo "✅ 모든 서비스가 중지되었습니다!"
echo "============================================"
echo ""
echo "컨테이너 상태 확인: docker ps -a"
echo "이미지 정리하기: docker system prune -f"
echo ""
echo "============================================"
read -p "계속하려면 아무 키나 누르세요..."

View File

@ -1,33 +0,0 @@
@echo off
echo =====================================
echo PLM 솔루션 - Windows 정지
echo =====================================
echo PLM 서비스 정지 중...
echo • 프론트엔드 (Next.js) 정지
echo • 백엔드 (Spring/JSP) 정지
echo • 볼륨 및 네트워크 정리
docker-compose -f docker-compose.win.yml down --volumes --remove-orphans
if %errorlevel% equ 0 (
echo.
echo ✅ PLM 서비스가 성공적으로 정지되었습니다.
echo.
echo 📋 정리 완료:
echo • 모든 컨테이너 정지 및 제거
echo • 볼륨 데이터 정리
echo • 네트워크 정리
echo.
) else (
echo.
echo ❌ PLM 서비스 정지 중 오류가 발생했습니다.
echo.
echo 🔍 수동으로 정리하려면:
echo docker-compose -f docker-compose.win.yml down --volumes
echo.
)
echo 작업 완료. 아무 키나 누르면 종료됩니다...
pause >nul