Phase 0: wbx-spring-core 라이브러리 전환 - java-library 플러그인, WbxAutoConfiguration, Admin 조건부 활성화 - 루트 settings.gradle + build.gradle (멀티모듈) Phase 1: wtm-api 모듈 생성 - 23개 JPA Entity, 14개 Controller, 79개 API 엔드포인트 - Flyway V100~V107 MySQL 마이그레이션 - TimesheetRuleEngine, TimesheetApprovalHandler, P6WbsParser Phase 2: wtm-frontend (Vue 3 + PrimeVue 4) - 10개 도메인 모듈, 17개 View, 5개 서브컴포넌트 - 반응형 레이아웃 (AppLayout, AppSidebar, AppTopbar) - BaseCrudTable, BaseFormDialog, BasePageHeader 표준 컴포넌트 - JWT 인터셉터, 역할 기반 메뉴 필터링 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
25 KiB
12. WTM 프로젝트 구성 계획
작성일: 2026-03-25 목적: wbx-spring-core를 라이브러리로 전환하고, wtm-api 모듈을 생성하기 위한 구체적 작업 계획
1. 현황 분석
wbx-spring-core 현재 구조
| 항목 | 현재 상태 | 문제점 |
|---|---|---|
| Gradle 플러그인 | org.springframework.boot (fat JAR) |
라이브러리로 사용 불가 |
| 진입점 | WbxSpringCoreApplication.java (@SpringBootApplication) |
라이브러리에 main() 불필요 |
| application.yml | 하드코딩된 DB/Redis/서버 설정 | 소비 모듈이 자체 설정 불가 |
| DB 드라이버 | MySQL/PG/Oracle/MSSQL 4개 모두 포함 | 소비 모듈이 필요한 것만 선택해야 함 |
| Admin UI | Thymeleaf 세션 기반 (12개 템플릿) | 모든 소비 모듈에 전이 의존성 |
| Enable 어노테이션 | main 클래스에 @EnableJpaAuditing 등 집중 |
라이브러리 전환 시 분리 필요 |
wbx-spring-core 제공 기능 (10개 모듈)
| 패키지 | 기능 | 주요 클래스 | WTM 사용 여부 |
|---|---|---|---|
auth/ |
JWT, SSO, MFA, 비밀번호 정책, 리프레시 토큰 | JwtProvider, JwtFilter, AuthController |
O |
rbac/ |
역할-모듈-액션 권한, dept_scope | PermissionEvaluator (bean "wbx") |
O |
approval/ |
통합 결재 엔진 (Handler Registry) | ApprovalHandler interface, UnifiedApprovalController |
O |
notification/ |
SSE 실시간 알림 | SseNotificationService |
O |
compat/ |
WBX 호환 (detail 에러, skip/limit) | WbxErrorHandler, WbxPaginationConfig |
O |
file/ |
파일 스토리지 (Local/Azure/AWS/GCP) | FileStorageService interface |
O |
datasource/ |
멀티 데이터소스 라우팅 | MultiDataSourceConfig, @DataSource |
O |
config/ |
시큐리티, CORS, OpenAPI, 중앙 설정 | SecurityAutoConfig, WbxSpringProperties |
O |
common/ |
베이스 엔티티, 유틸, 예외 | BaseEntity, SecurityUtils, BusinessException |
O |
audit/ |
감사 로그 | AuditLogService |
O |
admin/ |
관리 콘솔 UI (Thymeleaf) | AdminController, 12개 HTML |
조건부 |
2. 목표 구조: 멀티프로젝트 플랫폼
설계 원칙
- wbx-spring-core: 모든 프로젝트가 공유하는 프레임워크 (1개)
- {project}-api: 고객/프로젝트별 백엔드 애플리케이션 (N개)
- {project}-frontend: 고객/프로젝트별 프론트엔드 (N개, Gradle 외부)
- 새 프로젝트 추가 = 모듈 2개 추가 (settings.gradle에 include만 추가)
전체 구조
WBX-Spring/
├── settings.gradle # rootProject.name = 'wbx-spring'
│ # include 'wbx-spring-core'
│ # include 'wtm-api' ← 한화오션 WTM
│ # include 'xxx-api' ← 향후 프로젝트 B
│ # include 'yyy-api' ← 향후 프로젝트 C
├── build.gradle # 공통: Java 21, Lombok, Spring BOM
│
├── wbx-spring-core/ # 🔧 공유 프레임워크 라이브러리
│ ├── build.gradle # java-library (Boot 플러그인 없음)
│ ├── src/main/java/kr/co/accura/wbx/spring/
│ │ ├── auth/ # JWT, SSO, MFA, 비밀번호 정책
│ │ ├── rbac/ # RBAC 권한 (PermissionEvaluator)
│ │ ├── approval/ # 통합 결재 엔진 (Handler Registry)
│ │ ├── notification/ # SSE 실시간 알림
│ │ ├── compat/ # WBX 호환 (detail 에러, skip/limit)
│ │ ├── file/ # 파일 스토리지 (Local/Azure/AWS/GCP)
│ │ ├── datasource/ # 멀티 데이터소스 라우팅
│ │ ├── config/ # 시큐리티, CORS, OpenAPI, 중앙 설정
│ │ ├── common/ # BaseEntity, SecurityUtils, 예외
│ │ ├── audit/ # 감사 로그
│ │ └── admin/ # 관리 콘솔 (조건부: wbx.spring.admin-ui.enabled)
│ └── src/main/resources/
│ ├── META-INF/spring/
│ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ └── templates/admin/ # Thymeleaf (admin-ui.enabled=true 시만)
│
├── wtm-api/ # 🏗️ 한화오션 WTM 백엔드
│ ├── build.gradle # spring-boot + project(':wbx-spring-core')
│ ├── src/main/java/kr/co/accura/wtm/
│ │ ├── WtmApplication.java # @SpringBootApplication
│ │ ├── domain/
│ │ │ ├── user/ # HR 확장 필드 (discipline, location 등)
│ │ │ ├── project/ # 프로젝트, 인력 배정
│ │ │ ├── wbs/ # WBS, Canonical WBS, P6 파서
│ │ │ ├── teal/ # TEAL 버전, Activity
│ │ │ ├── timesheet/ # 시수 3종, 규칙 엔진
│ │ │ ├── approval/handler/ # TimesheetApprovalHandler
│ │ │ ├── report/ # QueryDSL 동적 리포트
│ │ │ ├── config/ # OverheadType, WorkRule
│ │ │ └── audit/ # SaAccessLog
│ │ ├── api/ # REST Controller 13개 (79 API)
│ │ ├── integration/ # SAP BTP, P6, Cognite
│ │ └── config/ # WTM 전용 설정
│ └── src/main/resources/
│ ├── application.yml # WTM 전용 설정
│ ├── application-mysql.yml # 개발 (MySQL)
│ ├── application-mssql.yml # 운영 (Azure SQL)
│ └── db/migration/
│ ├── common/ # ANSI SQL (seed data)
│ ├── mysql/ # 개발용 DDL
│ └── mssql/ # 운영용 DDL
│
├── wtm-frontend/ # 🎨 한화오션 WTM 프론트엔드
│ ├── package.json # Vue 3 + PrimeVue 4 + Vite
│ └── src/
│ ├── app/ # 셸 (router, plugins)
│ ├── core/ # 공유 인프라
│ ├── modules/ # 도메인 모듈 10개
│ └── assets/ # 스타일, 이미지
│
├── {향후}-api/ # 🆕 프로젝트 B 백엔드 (동일 패턴)
│ ├── build.gradle # project(':wbx-spring-core')
│ └── src/main/java/kr/co/accura/{project}/
│ ├── {Project}Application.java
│ ├── domain/ # 프로젝트 B 전용 도메인
│ ├── api/ # 프로젝트 B 전용 API
│ └── config/
│
└── {향후}-frontend/ # 🆕 프로젝트 B 프론트엔드 (동일 패턴)
└── src/
├── app/
├── core/ # 복사 후 커스터마이징 또는 공유 npm 패키지
└── modules/
프로젝트 간 관계도
┌─────────────────────┐
│ wbx-spring-core │ ← 공유 프레임워크
│ (java-library) │
│ 인증/권한/결재/알림 │
└──────┬──────┬───────┘
│ │
┌────────────┘ └────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ wtm-api │ │ {향후}-api │
│ (spring-boot) │ │ (spring-boot) │
│ 한화오션 WTM │ │ 고객 B 프로젝트 │
└────────┬────────┘ └────────┬────────┘
│ │
┌────────┴────────┐ ┌────────┴────────┐
│ wtm-frontend │ │ {향후}-frontend │
│ (Vue+PrimeVue) │ │ (Vue+PrimeVue) │
└─────────────────┘ └─────────────────┘
새 프로젝트 추가 절차 (3단계)
Step 1. settings.gradle에 모듈 추가
include '{project}-api'
Step 2. {project}-api/build.gradle 생성
plugins {
id 'org.springframework.boot' version '3.5.0'
}
dependencies {
implementation project(':wbx-spring-core')
// 프로젝트 전용 의존성 추가
}
Step 3. Application 클래스 + application.yml 생성
@SpringBootApplication(scanBasePackages = {
"kr.co.accura.wbx.spring",
"kr.co.accura.{project}"
})
@EntityScan(basePackages = {
"kr.co.accura.wbx.spring",
"kr.co.accura.{project}"
})
@EnableJpaRepositories(basePackages = {
"kr.co.accura.wbx.spring",
"kr.co.accura.{project}"
})
public class {Project}Application {
public static void main(String[] args) {
SpringApplication.run({Project}Application.class, args);
}
}
각 프로젝트는 독립 실행 가능 — 자체 DB, 자체 포트, 자체 JWT 설정. wbx-spring-core의 기능(인증/권한/결재/알림)은
wbx.spring.*속성으로 ON/OFF.
프로젝트별 커스터마이징 포인트
| 항목 | 설정 위치 | 예시 |
|---|---|---|
| API prefix | wbx.spring.api-prefix |
/api/wtm, /api/ems, /api/qms |
| JWT secret | wbx.spring.jwt.secret |
프로젝트별 독립 키 |
| DB | spring.datasource.* |
프로젝트별 독립 DB |
| 결재 핸들러 | @Component implements ApprovalHandler |
Bean 등록만으로 자동 연동 |
| SSO (Azure) | spring.security.oauth2.client.* |
고객별 Entra ID 테넌트 |
| 파일 스토리지 | wbx.spring.file.storage-type |
local, azure, aws, gcp |
| Admin UI | wbx.spring.admin-ui.enabled |
true / false |
| CORS | wbx.spring.cors.allowed-origins |
프로젝트별 프론트 URL |
---
## 3. 전환 작업 상세
### Phase 0: wbx-spring-core 라이브러리 전환 (선행 작업)
#### 3.1 루트 프로젝트 생성
| 작업 | 파일 | 설명 |
|------|------|------|
| `settings.gradle` 이동 | `WBX-Spring/settings.gradle` | 프로젝트 모듈 등록 |
| 루트 `build.gradle` 생성 | `WBX-Spring/build.gradle` | 공통 설정 (Java 21, repositories, Lombok) |
```groovy
// WBX-Spring/settings.gradle
rootProject.name = 'wbx-spring'
// 공유 프레임워크
include 'wbx-spring-core'
// === 고객 프로젝트 (추가 시 여기에 include) ===
include 'wtm-api' // 한화오션 WTM (시수관리)
// include 'xxx-api' // 향후 프로젝트 B
// include 'yyy-api' // 향후 프로젝트 C
// WBX-Spring/build.gradle (루트)
plugins {
id 'java'
id 'io.spring.dependency-management' version '1.1.7'
}
subprojects {
group = 'kr.co.accura'
version = '1.0.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:3.5.0"
}
}
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
}
3.2 wbx-spring-core build.gradle 변경
핵심 변경: org.springframework.boot 플러그인 제거 → java-library 적용
// wbx-spring-core/build.gradle
plugins {
id 'java-library'
}
dependencies {
// Spring Boot Starters (api로 노출 — 소비 모듈이 사용)
api 'org.springframework.boot:spring-boot-starter-web'
api 'org.springframework.boot:spring-boot-starter-data-jpa'
api 'org.springframework.boot:spring-boot-starter-security'
api 'org.springframework.boot:spring-boot-starter-validation'
api 'org.springframework.boot:spring-boot-starter-data-redis'
api 'org.springframework.boot:spring-boot-starter-cache'
api 'org.springframework.boot:spring-boot-starter-actuator'
api 'org.springframework.boot:spring-boot-starter-oauth2-client'
api 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
// JWT
api 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
// OpenAPI
api 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6'
// Admin Console (조건부)
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// Flyway (소비 모듈이 DBMS별 추가)
api 'org.flywaydb:flyway-core'
// DB 드라이버 — compileOnly (소비 모듈이 runtimeOnly로 선택)
compileOnly 'com.mysql:mysql-connector-j'
compileOnly 'org.postgresql:postgresql'
compileOnly 'com.oracle.database.jdbc:ojdbc11:23.6.0.24.10'
compileOnly 'com.microsoft.sqlserver:mssql-jdbc:12.8.1.jre11'
// Micrometer
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
// Test
testRuntimeOnly 'com.h2database:h2'
}
3.3 Auto-Configuration 전환
| 작업 | 설명 |
|---|---|
WbxSpringCoreApplication.java 삭제 |
main() 제거, 라이브러리에 불필요 |
WbxAutoConfiguration.java 생성 |
@Configuration + @EnableJpaAuditing + @EnableAsync + @EnableScheduling + @EnableCaching |
AutoConfiguration.imports 생성 |
Spring Boot 3.x 자동 설정 등록 |
application.yml 정리 |
하드코딩된 설정 제거, 기본값만 WbxSpringProperties에서 관리 |
HealthController 이동 |
범용으로 유지 (actuator가 대체 가능) |
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
kr.co.accura.wbx.spring.config.WbxAutoConfiguration
3.4 Admin UI 조건부 활성화
// wbx-spring-core
@Configuration
@ConditionalOnProperty(name = "wbx.spring.admin-ui.enabled", havingValue = "true", matchIfMissing = true)
public class AdminAutoConfiguration {
// AdminController, AdminLoginController, AdminUserDetailsService 등록
// SecurityAutoConfig의 adminFilterChain도 여기로 이동
}
Phase 1: wtm-api 모듈 생성
3.5 wtm-api build.gradle
// wtm-api/build.gradle
plugins {
id 'org.springframework.boot' version '3.5.0'
}
dependencies {
// wbx-spring 프레임워크
implementation project(':wbx-spring-core')
// WTM 전용
implementation 'org.apache.poi:poi-ooxml:5.3.0' // P6 WBS, Excel 업로드/다운로드
// QueryDSL (리포트 동적 쿼리)
implementation 'com.querydsl:querydsl-jpa:5.1.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.1.0:jakarta'
// MapStruct (DTO 매핑)
implementation 'org.mapstruct:mapstruct:1.6.3'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.6.3'
// Flyway — Azure SQL
implementation 'org.flywaydb:flyway-sqlserver'
// DB Driver — 개발: MySQL, 운영: MSSQL (Azure SQL)
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.microsoft.sqlserver:mssql-jdbc:12.8.1.jre11'
// Test
testRuntimeOnly 'com.h2database:h2'
}
3.6 WtmApplication.java
@SpringBootApplication(scanBasePackages = {
"kr.co.accura.wbx.spring",
"kr.co.accura.wtm"
})
@EntityScan(basePackages = {
"kr.co.accura.wbx.spring",
"kr.co.accura.wtm"
})
@EnableJpaRepositories(basePackages = {
"kr.co.accura.wbx.spring",
"kr.co.accura.wtm"
})
public class WtmApplication {
public static void main(String[] args) {
SpringApplication.run(WtmApplication.class, args);
}
}
Auto-Configuration 방식 적용 시
scanBasePackages제거 가능
3.7 wtm-api application.yml
spring:
application:
name: wtm-api
datasource:
url: jdbc:mysql://${DB_HOST:ws.ubuilder.co.kr}:${DB_PORT:3306}/${DB_NAME:wtm_db}
username: ${DB_USER:jsh}
password: ${DB_PASS:jsh@}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: validate # Flyway로 스키마 관리
open-in-view: false
flyway:
enabled: true
locations: classpath:db/migration
data:
redis:
host: ${REDIS_HOST:localhost}
port: 6379
server:
port: 8080
wbx:
spring:
api-prefix: /api/wtm
jwt:
secret: ${JWT_SECRET:dev-secret-key-minimum-256-bits}
expiration: 28800
admin-ui:
enabled: false # WTM은 자체 Admin 불필요
cors:
allowed-origins: ${CORS_ORIGINS:http://localhost:5173}
notification:
sse-enabled: true
wtm:
work-rules:
default-min-daily-hours: 8
default-max-weekly-hours: 52
4. WTM 도메인 모듈별 구현 범위
신규 JPA Entity (23개)
DB 스키마 상세:
02-database-schema.md(Single Source of Truth) Flyway 마이그레이션:02-database-schema.md의 V1~V7 참조 (본 문서에서 복제하지 않음)
| 도메인 | Entity | 테이블 | Phase |
|---|---|---|---|
| user | User |
users |
PH1-1 |
| user | Role |
roles |
PH1-1 |
| user | UserRole |
user_roles |
PH1-1 |
| user | OrgHierarchy |
org_hierarchy |
PH1-1 |
| user | HrUpload |
hr_uploads |
PH1-1 |
| project | Project |
projects |
PH1-1 |
| project | ProjectAssignment |
project_assignments |
PH1-1 |
| project | ProjectTypeConfig |
project_type_config |
PH1-1 |
| wbs | WbsVersion |
wbs_versions |
PH1-1 |
| wbs | WbsNode |
wbs_nodes |
PH1-1 |
| wbs | CanonicalWbs |
canonical_wbs |
PH1-1 |
| wbs | WbsDisciplineAssignment |
wbs_discipline_assignments |
PH1-1 |
| teal | TealVersion |
teal_versions |
PH1-1 |
| teal | TealEntry |
teal_entries |
PH1-1 |
| timesheet | Timesheet |
timesheets |
PH1-1 |
| timesheet | TimesheetEntry |
timesheet_entries |
PH1-1 |
| timesheet | TimesheetUpload |
timesheet_uploads |
PH1-1 |
| approval | TtApproval |
approvals |
PH1-1 |
| approval | TtApprovalLine |
approval_lines |
PH1-1 |
| approval | TtApprovalComment |
approval_comments |
PH1-1 |
| config | OverheadType |
overhead_types |
PH1-1 |
| config | WorkRule |
work_rules |
PH1-1 |
| audit | SaAccessLog |
sa_access_logs |
PH1-2 |
User Entity 전략 확정: WTM은
02-database-schema.md에 정의된users테이블을 직접 사용. wbx-spring-core의WbxUser와 별도로, WTM 전용User엔티티가 HR 확장 필드(discipline, location, employment_type 등)를 포함한users테이블에 매핑됨. 인증은 wbx-spring-core의WbxUser(wbx_users)가 담당하며,users.email = wbx_users.email로 연동.
신규 REST Controller (13개, 79 API)
| Controller | API 수 | Phase |
|---|---|---|
AuthController (WTM 전용 라우팅) |
8 | PH1-1 |
UserController |
8 | PH1-1 ~ PH1-2 |
ProjectController |
7 | PH1-1 |
WbsController |
7 | PH1-1 ~ PH1-2 |
TealController |
4 | PH1-1 |
TimesheetController |
8 | PH1-1 |
ApprovalController |
8 | PH1-1 ~ PH1-2 |
ReportController |
9 | PH1-1 ~ PH2 |
HomeController (대시보드/알림) |
2 | PH1-1 |
OverheadTypeController (SA) |
3 | PH1-1 |
WorkRuleController (SA) |
2 | PH1-1 |
ResourceAssignController |
5 | PH1-1 |
HrIntegrationController |
2 | PH1-2 |
wbx-spring-core 활용 포인트
// RBAC 권한 체크
@PreAuthorize("@wbx.check('TIMESHEET', 'VIEW')")
// 데이터 필터링 범위
DeptScope scope = evaluator.getScope("TIMESHEET", "VIEW");
// 결재 핸들러 등록 (Bean 등록만으로 자동 연동)
@Component
public class TimesheetApprovalHandler implements ApprovalHandler { ... }
// SSE 실시간 알림
sseNotificationService.sendToUser(approverId, notification);
// 에러 응답 (자동 적용)
throw new BusinessException("주간 합계 54시간 — 최대 52h 초과");
// → {"detail": "주간 합계 54시간 — 최대 52h 초과"}
5. User Entity 전략
선택지
| 방안 | 장점 | 단점 |
|---|---|---|
| A: WbxUser 확장 (WTM 필드를 wbx_users에 추가) | 테이블 하나, 간단 | core 엔티티 오염 |
| B: WtmUser 별도 (wtm.users + wbx.wbx_users 동기화) | 도메인 분리 깔끔 | 두 테이블 동기화 필요 |
| C: WtmUserProfile (wbx_users FK → wtm_user_profiles) | core 불변, 확장 자유 | JOIN 필요 |
권장: 방안 C — WtmUserProfile 확장 테이블
CREATE TABLE wtm_user_profiles (
id BIGINT IDENTITY PRIMARY KEY,
wbx_user_id BIGINT NOT NULL UNIQUE REFERENCES wbx_users(id),
employee_id VARCHAR(50) UNIQUE,
discipline VARCHAR(100),
location VARCHAR(50),
employment_type VARCHAR(20) DEFAULT 'INTERNAL',
business_unit VARCHAR(100),
division VARCHAR(100),
department VARCHAR(100),
part VARCHAR(100),
created_at DATETIME2 DEFAULT GETDATE()
);
이유: wbx-spring-core의 WbxUser 엔티티를 수정하지 않고, WTM 전용 HR 필드를 별도 테이블로 관리. wbx_user_id FK로 연결.
6. 작업 순서 (Implementation Order)
Phase 0 — wbx-spring-core 라이브러리 전환 (1~2일)
├── 0-1. 루트 settings.gradle, build.gradle 생성
├── 0-2. wbx-spring-core build.gradle → java-library 전환
├── 0-3. WbxSpringCoreApplication 삭제, WbxAutoConfiguration 생성
├── 0-4. application.yml → 기본값만 남기고 정리
├── 0-5. Admin UI 조건부 활성화 (@ConditionalOnProperty)
├── 0-6. Enable 어노테이션 분리 → 개별 @Configuration
└── 0-7. 빌드 검증 (./gradlew :wbx-spring-core:build)
Phase 1 — wtm-api 스캐폴딩 (1일)
├── 1-1. wtm-api 디렉토리 + build.gradle 생성
├── 1-2. WtmApplication.java 생성
├── 1-3. application.yml (개발 환경)
├── 1-4. Flyway V1~V7 마이그레이션 SQL 생성
├── 1-5. 빌드 + 부팅 검증 (./gradlew :wtm-api:bootRun)
└── 1-6. wbx-spring-core 연동 검증 (JWT, RBAC, 결재 등)
Phase 2 — WTM 도메인 구현 (W3~W8, 계획서 10-schedule 참조)
├── 2-1. domain/user + domain/project (W3~W4)
├── 2-2. domain/wbs + domain/teal + P6 파서 (W4~W5)
├── 2-3. domain/timesheet + 규칙 엔진 (W5~W7)
├── 2-4. domain/approval/handler (W6~W7)
├── 2-5. domain/report + Excel Export (W7~W8)
└── 2-6. integration/sap (PH1-2)
7. 주의사항
어노테이션 프로세서 순서
Lombok + MapStruct + QueryDSL을 함께 사용 시:
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.6.3'
annotationProcessor 'com.querydsl:querydsl-apt:5.1.0:jakarta'
DB 이중 구조 — Flyway 듀얼 마이그레이션
- 개발: MySQL (ws.ubuilder.co.kr) —
wtm_db스키마 - 운영: Azure SQL (MSSQL) — Flyway 마이그레이션
DDL 구문 차이(IDENTITY vs AUTO_INCREMENT, DATETIME2 vs DATETIME, GETDATE() vs NOW())를
프로필별 마이그레이션 경로로 해결:
# application-mysql.yml (개발)
spring:
flyway:
locations: classpath:db/migration/common,classpath:db/migration/mysql
# application-mssql.yml (운영)
spring:
flyway:
locations: classpath:db/migration/common,classpath:db/migration/mssql
src/main/resources/db/migration/
├── common/ # ANSI SQL 호환 (seed data, VIEW 등)
│ └── V10__seed_roles.sql
├── mysql/ # MySQL 전용 DDL
│ ├── V1__init_users.sql # AUTO_INCREMENT, DATETIME, NOW()
│ ├── V2__init_projects.sql
│ └── ...
└── mssql/ # Azure SQL 전용 DDL
├── V1__init_users.sql # IDENTITY, DATETIME2, GETDATE()
├── V2__init_projects.sql
└── ...
02-database-schema.md의 DDL은 MSSQL 기준. MySQL 버전은 구현 시 변환 생성.
wbx-spring-core의 WbxUser와 WTM User
- wbx-spring-core의
wbx_users테이블: 인증/권한 용도 (JWT, SSO, MFA) - WTM의
users테이블: HR 확장 필드 포함 (discipline, location, employment_type 등) - 연동:
users.email = wbx_users.email기준으로 매칭 - WTM
User엔티티는users테이블에 직접 매핑 (별도 확장 테이블 불필요)