From 3e4ad775a6fe92faeef3166809c927db34f994a2 Mon Sep 17 00:00:00 2001 From: DEV-SERVER Date: Tue, 24 Feb 2026 01:58:32 +0900 Subject: [PATCH 01/24] ci: add Jenkinsfile for CI/CD pipeline (develop/stage/main) --- Jenkinsfile | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..456ee964 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,106 @@ +pipeline { + agent any + + environment { + DEPLOY_USER = 'hskwon' + RELEASE_ID = new Date().format('yyyyMMdd_HHmmss') + } + + stages { + stage('Checkout') { + steps { checkout scm } + } + + stage('Prepare Env') { + steps { + script { + def envFile = "/var/lib/jenkins/env-files/react/.env.${env.BRANCH_NAME}" + sh "cp ${envFile} .env.local" + } + } + } + + stage('Install') { + steps { + sh 'npm ci' + } + } + + stage('Build') { + steps { + sh 'npm run build' + } + } + + // ── develop → 개발서버 배포 ── + stage('Deploy Development') { + when { branch 'develop' } + steps { + sshagent(credentials: ['deploy-ssh-key']) { + sh """ + rsync -az --delete \ + .next/ package.json package-lock.json next.config.ts public/ node_modules/ \ + ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/ + + scp .env.local ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/.env.local + + ssh ${DEPLOY_USER}@114.203.209.83 'cd /home/webservice/react && pm2 restart sam-front' + """ + } + } + } + + // ── stage → 운영서버 Stage 배포 ── + stage('Deploy Stage') { + when { branch 'stage' } + steps { + sshagent(credentials: ['deploy-ssh-key']) { + sh """ + ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react-stage/releases/${RELEASE_ID}' + + rsync -az --delete \ + .next/ package.json package-lock.json next.config.ts public/ node_modules/ \ + ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/ + + scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/.env.local + + ssh ${DEPLOY_USER}@211.117.60.189 ' + ln -sfn /home/webservice/react-stage/releases/${RELEASE_ID} /home/webservice/react-stage/current && + cd /home/webservice && pm2 reload sam-front-stage 2>/dev/null || pm2 start react-stage/current/node_modules/.bin/next --name sam-front-stage -- start -p 3100 && + cd /home/webservice/react-stage/releases && ls -1dt */ | tail -n +4 | xargs rm -rf 2>/dev/null || true + ' + """ + } + } + } + + // ── main → 운영서버 Production 배포 ── + stage('Deploy Production') { + when { branch 'main' } + steps { + sshagent(credentials: ['deploy-ssh-key']) { + sh """ + ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react/releases/${RELEASE_ID}' + + rsync -az --delete \ + .next/ package.json package-lock.json next.config.ts public/ node_modules/ \ + ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/ + + scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/.env.local + + ssh ${DEPLOY_USER}@211.117.60.189 ' + ln -sfn /home/webservice/react/releases/${RELEASE_ID} /home/webservice/react/current && + cd /home/webservice && pm2 reload sam-front && + cd /home/webservice/react/releases && ls -1dt */ | tail -n +6 | xargs rm -rf 2>/dev/null || true + ' + """ + } + } + } + } + + post { + success { echo "✅ react 배포 완료 (${env.BRANCH_NAME})" } + failure { echo "❌ react 배포 실패 (${env.BRANCH_NAME})" } + } +} From ec492e382925dc67a4cec8e3970365a0442887a5 Mon Sep 17 00:00:00 2001 From: DEV-SERVER Date: Tue, 24 Feb 2026 02:05:27 +0900 Subject: [PATCH 02/24] =?UTF-8?q?ci:=20fix=20npm=20ci=20=E2=86=92=20npm=20?= =?UTF-8?q?install=20(package-lock.json=20not=20tracked)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 456ee964..ead090bf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,7 +22,7 @@ pipeline { stage('Install') { steps { - sh 'npm ci' + sh 'npm install --prefer-offline' } } From 6a469181cdc1a6b3b3f25878c8dcb7b5b5b14752 Mon Sep 17 00:00:00 2001 From: DEV-SERVER Date: Tue, 24 Feb 2026 02:22:36 +0900 Subject: [PATCH 03/24] =?UTF-8?q?fix(ci):=20rsync=20trailing=20slash=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20PM2=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=84=B8=EC=8A=A4=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rsync source 경로 trailing slash 제거 (.next/, node_modules/, public/ → .next, node_modules, public) - trailing slash로 디렉토리 내용이 root에 풀리는 문제 해결 - dev deploy에 --exclude .git, .env*, ecosystem.config.* 추가 - PM2 프로세스명: sam-front → sam-react (개발서버) --- Jenkinsfile | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ead090bf..a0789999 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,12 +39,15 @@ pipeline { sshagent(credentials: ['deploy-ssh-key']) { sh """ rsync -az --delete \ - .next/ package.json package-lock.json next.config.ts public/ node_modules/ \ + --exclude='.git' \ + --exclude='.env*' \ + --exclude='ecosystem.config.*' \ + .next package.json next.config.ts public node_modules \ ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/ scp .env.local ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/.env.local - ssh ${DEPLOY_USER}@114.203.209.83 'cd /home/webservice/react && pm2 restart sam-front' + ssh ${DEPLOY_USER}@114.203.209.83 'cd /home/webservice/react && pm2 restart sam-react' """ } } @@ -59,7 +62,7 @@ pipeline { ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react-stage/releases/${RELEASE_ID}' rsync -az --delete \ - .next/ package.json package-lock.json next.config.ts public/ node_modules/ \ + .next package.json next.config.ts public node_modules \ ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/ scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/.env.local @@ -83,7 +86,7 @@ pipeline { ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react/releases/${RELEASE_ID}' rsync -az --delete \ - .next/ package.json package-lock.json next.config.ts public/ node_modules/ \ + .next package.json next.config.ts public node_modules \ ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/ scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/.env.local @@ -100,7 +103,7 @@ pipeline { } post { - success { echo "✅ react 배포 완료 (${env.BRANCH_NAME})" } - failure { echo "❌ react 배포 실패 (${env.BRANCH_NAME})" } + success { echo '✅ react 배포 완료 (' + env.BRANCH_NAME + ')' } + failure { echo '❌ react 배포 실패 (' + env.BRANCH_NAME + ')' } } } From b8dfa3d88742141c3672ff32550857900fe647d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EB=B3=91=EC=B2=A0?= Date: Tue, 24 Feb 2026 13:01:41 +0900 Subject: [PATCH 04/24] =?UTF-8?q?feat(WEB):=20CEO=20=EB=8C=80=EC=8B=9C?= =?UTF-8?q?=EB=B3=B4=EB=93=9C=20=EC=BA=98=EB=A6=B0=EB=8D=94=20=EA=B0=95?= =?UTF-8?q?=ED=99=94=20=EB=B0=8F=20validation=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CalendarSection 일정 CRUD 기능 확장 (상세 모달 연동) - ScheduleDetailModal 개선 - CEO 대시보드 섹션별 API 키 통일 - validation.ts → validation/ 모듈 분리 (item-schemas, utils) - formatters.ts 확장 - date.ts 유틸 추가 - SignupPage/EmployeeForm/AddCompanyDialog 등 소규모 개선 - PaymentHistory/PopupManagement utils 정리 Co-Authored-By: Claude Opus 4.6 --- src/components/auth/SignupPage.tsx | 5 +- .../dialogs/DashboardSettingsDialog.tsx | 2 +- .../modals/ScheduleDetailModal.tsx | 77 ++-- .../CEODashboard/sections/CalendarSection.tsx | 293 +++++++++++---- .../sections/DailyAttendanceSection.tsx | 2 +- .../sections/DebtCollectionSection.tsx | 2 +- .../sections/EnhancedSections.tsx | 6 +- .../sections/PurchaseStatusSection.tsx | 2 +- .../sections/SalesStatusSection.tsx | 2 +- .../sections/StatusBoardSection.tsx | 12 +- .../sections/TodayIssueSection.tsx | 10 +- .../sections/UnshippedSection.tsx | 2 +- .../CEODashboard/sections/VatSection.tsx | 2 +- .../hr/EmployeeManagement/EmployeeForm.tsx | 5 +- .../AddCompanyDialog.tsx | 3 +- .../PaymentHistoryManagement/utils.ts | 8 +- .../settings/PopupManagement/utils.ts | 7 +- src/lib/formatters.ts | 39 +- src/lib/utils/date.ts | 11 + src/lib/utils/validation/common.ts | 110 ++++++ src/lib/utils/validation/form-schemas.ts | 191 ++++++++++ src/lib/utils/validation/index.ts | 31 ++ .../item-schemas.ts} | 342 +----------------- src/lib/utils/validation/utils.ts | 64 ++++ 24 files changed, 726 insertions(+), 502 deletions(-) create mode 100644 src/lib/utils/validation/common.ts create mode 100644 src/lib/utils/validation/form-schemas.ts create mode 100644 src/lib/utils/validation/index.ts rename src/lib/utils/{validation.ts => validation/item-schemas.ts} (52%) create mode 100644 src/lib/utils/validation/utils.ts diff --git a/src/components/auth/SignupPage.tsx b/src/components/auth/SignupPage.tsx index a7fc3465..17412831 100644 --- a/src/components/auth/SignupPage.tsx +++ b/src/components/auth/SignupPage.tsx @@ -25,6 +25,7 @@ import { } from "lucide-react"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { isNextRedirectError } from '@/lib/utils/redirect-error'; +import { extractDigits } from '@/lib/formatters'; export function SignupPage() { const router = useRouter(); @@ -64,7 +65,7 @@ export function SignupPage() { // 사업자등록번호 자동 포맷팅 (000-00-00000) const formatBusinessNumber = (value: string) => { // 숫자만 추출 - const numbers = value.replace(/[^\d]/g, ''); + const numbers = extractDigits(value); // 최대 10자리까지만 const limited = numbers.slice(0, 10); @@ -87,7 +88,7 @@ export function SignupPage() { // 핸드폰 번호 자동 포맷팅 (010-1111-1111 or 010-111-1111) const formatPhoneNumber = (value: string) => { // 숫자만 추출 - const numbers = value.replace(/[^\d]/g, ''); + const numbers = extractDigits(value); // 최대 11자리까지만 const limited = numbers.slice(0, 11); diff --git a/src/components/business/CEODashboard/dialogs/DashboardSettingsDialog.tsx b/src/components/business/CEODashboard/dialogs/DashboardSettingsDialog.tsx index 85ddff71..96d0b139 100644 --- a/src/components/business/CEODashboard/dialogs/DashboardSettingsDialog.tsx +++ b/src/components/business/CEODashboard/dialogs/DashboardSettingsDialog.tsx @@ -889,7 +889,7 @@ export function DashboardSettingsDialog({ ))} - +