배경:
- frontend build 의 가장 큰 시간 소비 = runner stage 의 COPY node_modules (12분 16초)
- 전체 21분 34초 중 57%
- next.config.mjs 의 output: "standalone" 가 prod 빌드에서 이미 활성 상태였으나, Dockerfile 의 runner stage 가 .next 통째 + node_modules 통째를 COPY 하느라 standalone 결과물 미활용
조치:
- runner stage 재작성:
- .next 전체 → .next/standalone (server.js + 실제 사용 node_modules)
- .next/static 별도 COPY (standalone 가 자동 포함 안 함)
- public 별도 COPY (standalone 가 자동 포함 안 함)
- node_modules 통째 COPY 제거 (standalone 가 알아서 포함)
- package.json COPY 제거 (server.js 직접 실행)
- CMD: npm start → node server.js
검증:
- frontend 에 dynamic require/import 0건 (정적 import 만) → standalone 의존성 추적 정확
- prisma 가 package.json 에 있으나 코드 import 0건 → 자연 제외, 추가 설정 불필요
예상 효과:
- 빌드 시간 21m 34s → 약 9분 (12분 단축, 57% 감소)
- 이미지 크기 약 1GB → 약 300MB (70% 감소)
- pull 시간 단축
- runtime memory footprint 감소
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main 의 최근 8연속 build 실패 (run 113~120) 원인이 docker build 단계의 OOM Killed.
진단:
- wace 호스트 32GB / available 24GB 충분, 시스템 OOM 기록 없음
- act_runner systemd MemoryMax=infinity, config container.options=null (제한 없음)
- 그러나 Next.js build V8 heap spike (5-8GB+) 가 다른 30개 동시 가동 서비스 (k3s/mailu/nextcloud/mattermost 등) 와 충돌
- Committed_AS 21.6 GB / Limit 24.8 GB 한계 — page touch 시 oom-killer 가 build process kill
- 결과: 28분 빌드 후 Killed → 8연속 main 배포 실패
조치:
- builder stage 에 NODE_OPTIONS=--max-old-space-size=4096 명시 → V8 heap 4GB 로 cap
- build process 가 알아서 절제 → OOM killer 트리거 안 됨
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Docker Desktop on Windows 의 bind mount 가 host inotify 이벤트를
컨테이너로 전파하지 못해 Turbopack file watcher 가 host 편집을 감지 못 함.
webpack 은 WATCHPACK_POLLING=true 폴백을 지원하므로 Windows 에서만
Turbopack 을 끄고 webpack 으로 폴백 → 자동 HMR 복원.
- frontend/package.json: dev:docker:nopack 스크립트 추가 (next dev, no turbopack)
- docker/dev/docker-compose.windows.yml: Windows 전용 frontend command override
- scripts/start/invyone-start-docker-all.bat: windows.yml 자동 merge
Mac/Linux 진입점은 영향 없음 (start.bat 만 windows override 활성).
첫 컴파일은 약간 느려지지만 (~10-30%) 수정→반영 시간이 80s → 1~3s 로 단축.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 음성 인식 (scada-demo/js/voice.js) — 한국어 발화 → 키워드 매핑 → INVYONE_UI.select()
· 사이드바 마이크 버튼 + transcript 라벨, 매칭 시 청록 펄스
· Chrome/Edge HTTPS 환경 (운영 siflex.invyone.com OK)
- 경고시스템/다중경고 버튼을 음성 인식과 동일 톤
· 🚨 emoji → SVG 삼각형 아이콘, voice-btn 패턴 (다크 솔리드 + 컬러 액센트)
· 정적 (반짝 펄스 애니메이션 제거)
- client.ts stash pop conflict 정리 (DEV_TENANT_HOST + 도메인 정리 통합)
- ui.js 다중 경고 시연 wiring + scada 작업 노트 2건
- 기타 syncthing 보류분 batch (대시보드/레이아웃/로그인 layout 정리)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- backend-spring.Dockerfile: CMD에 sh ./gradlew 명시 호출 — 호스트가 Windows일 때 바인드마운트가 빌드 시점 chmod +x를 덮어쓰면서 ./gradlew가 실행 비트 없이 매핑되는 문제 해결. Linux/Mac 환경에도 동일하게 동작.
- .gitattributes 신규: gradlew와 *.sh 를 eol=lf 로 고정해 Windows core.autocrlf=true 환경에서 CRLF 변환으로 컨테이너 내 sh 파싱이 깨지는 문제 재발 방지.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
빌드 컨텍스트 변경에도 운영 frontend chunk 에 신규 라우트가 들어가지
않는 증상 발견. Kaniko/Docker layer cache 가 npm run build 단계를
잘못된 시점에 hit 하는 것으로 의심. GIT_SHA build-arg 를 npm run build
직전에 주입해 매 commit 마다 그 layer 부터 강제 invalidate.
또 진단 step 에 deploy 이미지 tag 표시 추가 — 새 image 로 갱신
됐는지 즉시 확인 가능.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영 도메인이 실제로는 v1.invyone.com / solution.invyone.com / api.invyone.com 인데
코드/문서 곳곳에 v1.invion.com / api.invion.com 등 미존재 도메인이 박혀 있어 정리.
변경 파일 (21):
- frontend lib/api/client.ts, lib/utils/apiUrl.ts: hostname 체크 endsWith(\".invyone.com\") 일반화
- frontend lib/api/dashboard.ts, file.ts, flow.ts, FileViewerModal*2.tsx: 도메인 치환
- frontend invion-layout-v5.html: 시안 내 placeholder 도메인 정리
- backend-spring SecurityConfig.java: CORS 주석 예시 정리
- docker/deploy/docker-compose.yml, k8s/traefik-dynamic.yaml: traefik Host 라벨 정리
- scripts/prod/deploy.sh: 안내 메시지 정리
- .cursor/rules/api-client-usage.mdc, project-conventions.mdc: AI 가이드 정리
- docs/* 4개: 아키텍처/플로우 문서 도메인 정리
- notes/gbpark/* 3개: 과거 메모 정리
신규:
- docs/DOMAIN_MAPPING.md: 운영/개발/폐기 도메인 영구 기록.
AI 에이전트와 신규 개발자가 헷갈리지 않도록 단일 진실 출처.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- application.yml, k8s configmap, docker-compose 4종: SPRING_DATASOURCE_URL path
- provisioning 코드: {prefix}_vexplor → {prefix}_invyone 테넌트 DB 네이밍 규칙
- 프론트 마법사: Step1Basic, Step4Run 미리보기 라벨
- CompanyAccordionRow: 기본 DB 이름 포맷
- 마이그레이션/멀티테넌시 문서 동기화
- Traefik 와일드카드 설정 산출물 보관 (notes/)
비밀번호(vexplor0909!!) 및 역사 기록 문서(INVYONE_CONCEPT,
DDD1542, test-output, dashboard-runtime-fixes) 는 의도적으로 미변경.
User confirmed test_dev is the correct database for invyone (the
old TEST-VEX project), matching what the previous mac compose was
using. Same host (211.115.91.141:11134), same credentials, just a
different database name.
Verified end-to-end: real login (POST /api/auth/login from the
browser path) returns 200 with a valid JWT, meaning the full chain
browser → next dev rewrites → backend-spring → HikariCP → test_dev
works and the user table lookup + password check both pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
NEXT_PUBLIC_API_URL was hardcoded to http://localhost:8083/api which
gets baked into webpack bundles at build time. NEXT_PUBLIC_* vars
run in the browser, so "localhost" resolves to the *user's own PC*,
not the office host running the container — connect refused for
anyone hitting the site over Tailscale or LAN.
Use a relative URL (/api) and let next dev's rewrites proxy to
SERVER_API_URL (invyone-backend-spring:8081 inside invyone-net).
This way the request always lands on whatever host the browser is
already talking to (localhost / 100.126.230.80 / public domain),
and the Next dev server forwards it to the backend container.
Verified: POST /api/auth/login from browser path returns the spring
controller's 400 response, confirming the full
browser → frontend → backend chain works.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
invyone (= old TEST-VEX) is React + Java only; backend-node belongs
to a different project (PMS) and was bundled by mistake. Remove the
backend-node service from docker-compose.invyone.yml, drop the
backend-node.Dockerfile, and clean up the now-unused frontend env
vars that pointed at the node API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds backend-node.Dockerfile (Node 20-alpine + nodemon) and a single
docker-compose.invyone.yml that brings up all three services on
invyone-net with restart unless-stopped, intended for the office
Ubuntu host. Uses vexplor_dev DB for both backends and exposes
9772 (frontend) / 8083 (spring) / 8082 (node) on the host.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pop 컴포넌트 중간 병합:
- feat(pop-card-list): PopCardList 컴포넌트 구현 + 3섹션 분리 + 포장 2단계 계산기
- feat(pop-cart): 장바구니 저장 시스템 구현 + 선택적 컬럼 저장
- feat(pop-search): 모달 뷰 개선 (아이콘 뷰, 가나다/ABC 필터 탭)
- feat(pop-button): 버튼 컴포넌트 확장
- fix(pop): 전수 점검 방어 코드 추가
장바구니 담기 -> DB 저장 전체 플로우 구현 및 검증 완료.
- useCartSync 훅 신규: DB(cart_items) <-> 로컬 상태 동기화, dirty check, 일괄 저장
- pop-button cart 프리셋: 배지 표시, 저장 트리거, 확인 모달, 3색 데이터 흐름 시각화
- pop-card-list: 담기/취소 UI, cart_save_trigger 수신 시 saveToDb 실행
- 선택적 컬럼 저장: RowDataMode(all/selected) + 연결 기반 자동 컬럼 로딩
- ComponentEditorPanel: allComponents/connections/componentId를 ConfigPanel에 전달
- connectionMeta: cart_save_trigger/cart_updated/cart_save_completed 이벤트 정의
- ConnectionEditor: 이벤트 타입 연결 구분 (데이터 vs 이벤트)
- types.ts: CartItemWithId, CartSyncStatus, CartButtonConfig 등 타입 추가
- 접근성: NumberInputModal/PackageUnitModal에 DialogTitle 추가
Made-with: Cursor
- Added a new controller for managing process work standards, including CRUD operations for work items and routing processes.
- Introduced routes for fetching items with routing, retrieving routings with processes, and managing work items.
- Integrated the new process work standard routes into the main application file for API accessibility.
- Created a migration script for exporting data related to the new process work standard feature.
- Updated frontend components to support the new process work standard functionality, enhancing the overall user experience.
- Docker Compose 설정에서 Node.js 메모리 제한을 8192MB로 증가시키고, Next.js telemetry를 비활성화하여 성능을 개선하였습니다.
- Next.js 구성에서 메모리 사용량 최적화를 위한 webpackMemoryOptimizations를 활성화하였습니다.
- ScreenModal 컴포넌트에서 overflow 속성을 조정하여 라벨이 잘리지 않도록 개선하였습니다.
- InteractiveScreenViewerDynamic 컴포넌트에서 라벨 표시 여부를 확인하는 로직을 추가하여 사용자 경험을 향상시켰습니다.
- RealtimePreviewDynamic 컴포넌트에서 라벨 표시 및 디버깅 로그를 추가하여 렌더링 과정을 추적할 수 있도록 하였습니다.
- ImprovedButtonControlConfigPanel에서 controlMode 설정을 추가하여 플로우 제어 기능을 개선하였습니다.
- V2PropertiesPanel에서 라벨 텍스트 및 표시 상태 업데이트 로직을 개선하여 일관성을 높였습니다.
- DynamicComponentRenderer에서 라벨 표시 로직을 개선하여 사용자 정의 스타일을 보다 효과적으로 적용할 수 있도록 하였습니다.
- layoutV2Converter에서 webTypeConfig를 병합하여 버튼 제어 기능과 플로우 가시성을 보존하였습니다.
- ScreenModal 컴포넌트의 모달 크기 조정을 위해 헤더 및 푸터 높이를 수정하고, 여백을 최소화하여 디자인 일치를 도모하였습니다.
- V2 컴포넌트에서 라벨 높이를 계산하여 절대 위치로 배치하도록 변경하였으며, 입력 필드 및 선택 컴포넌트의 구조를 개선하여 일관된 사용자 경험을 제공하였습니다.
- 플레이스홀더 기능을 추가하여 날짜 선택 시 사용자 편의성을 높였습니다.
- 관련 CSS 클래스를 업데이트하여 반응형 디자인을 강화하였습니다.
- 레거시 컴포넌트를 제거하고, V2 및 Unified 컴포넌트 전용 Zod 스키마와 기본값 레지스트리를 통합 관리합니다.
- V2 컴포넌트와 Unified 컴포넌트의 overrides 스키마를 정의하고, 기본값과의 병합 로직을 추가하였습니다.
- 레이아웃 조회 시 V2 테이블을 우선적으로 조회하고, 없을 경우 V1 테이블을 조회하도록 개선하였습니다.
- 관련된 테스트 계획 및 에러 처리 계획을 수립하여 안정성을 높였습니다.