25 KiB
25 KiB
title, source_type, status, related_branches, related_projects, tags, created, status_label
| title | source_type | status | related_branches | related_projects | tags | created | status_label | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| error / spring-boot-four-jackson-three-migration-2026-06-30 | error-note | raw |
|
|
2026-06-30 | resolved |
error: spring-boot-four-jackson-three-migration-2026-06-30
Layer:
raw/errors/— Spring Boot 4 / Jackson 3 / Testcontainers 2 / Spring Integration 7 migration 중 발생한 실패 묶음의 트러블슈팅 기록.
Parent / 부모
- raw/project-notes/ca-skeleton-operational-contract
- 작업 식별자:
chore-spring-boot-four-migration(별도 branch-note 없음)
증상 / Symptom
- 에러 메시지 (원문 그대로):
Property 'server.error.include-stacktrace' is Deprecated: Use 'spring.web.error.include-stacktrace' instead.vscode-spring-boot(YAML_DEPRECATED_ERROR) - 에러 메시지 (원문 그대로):
server.error.include-stacktrace -> spring.web.error.include-stacktrace Default: never Deprecated! When to include the "trace" attribute. - 에러 메시지 (원문 그대로):
MethodName must match pattern '^[a-z][a-zA-Z0-9]*$' - 에러 메시지 (원문 그대로):
ConstantName must match pattern NeedBraces StaticVariableName - 에러 메시지 (원문 그대로):
The method asText() from the type JsonNode is deprecatedJava(67108967) String tools.jackson.databind.JsonNode.asText() Deprecated. Use asString() instead. Source: jackson-databind-3.0.2.jar - 에러 메시지 (원문 그대로):
Execution failed for task ':adapter-web:spotlessJavaCheck'. The following files had format violations: Run './gradlew spotlessApply' to fix all violations. - 에러 메시지 (원문 그대로):
Execution failed for task ':app-bootstrap:compileTestJava'. bad class file: /home/donghyeon/workspace/ca-tmpl/src/app-bootstrap/build/classes/java/test/dev/caskeleton/bootstrap/integration/outbox/OutboxContainerTestSupport.class unable to access file: java.nio.file.NoSuchFileException Please remove or make sure it appears in the correct subdirectory of the classpath. - 에러 메시지 (원문 그대로):
H S SECUJDES: Unsafe Jackson deserialization configuration used in dev.caskeleton.bootstrap.architecture.violations.boundary.DefaultTypingFixture.unsafe() SpotBugs ended with exit code 1 - 에러 메시지 (원문 그대로):
java.lang.Error: Failed Approval Approved: .../EnvelopeContractTest.successEnvelopeShape.approved.txt Received: .../EnvelopeContractTest.successEnvelopeShape.received.txt - 경고 메시지 (원문 그대로):
Assigning String value 'high' to property of enum type 'com.github.spotbugs.snom.Confidence'. This behavior has been deprecated. This will fail with an error in Gradle 10. - 경고 메시지 (원문 그대로):
Invocation of Task.project at execution time has been deprecated. This will fail with an error in Gradle 10. - 경고 메시지 (요약):
MissingJavadocMethodCheck 310 MissingJavadocTypeCheck 34 - CI 실패 메시지 후보 (workflow 원문):
A governed contract baseline changed but the PR lacks the 'intent:breaking-change-approved' label. - 서버 시작 실패 메시지 (원문 발췌):
Caused by: org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation Migration checksum mismatch for migration version 4 -> Applied to database : 1718831886 -> Resolved locally : -37693890 Either revert the changes to the migration, or run repair to update the schema history. - 서버 시작 실패 메시지 (local
bootRun):Failed to bind properties under 'spring.profiles.active' to java.util.Set<java.lang.String> Value: "${SPRING_PROFILES_ACTIVE}" Profile '${SPRING_PROFILES_ACTIVE}' must contain a letter, digit or allowed char - 서버 시작 실패 메시지 (local
bootRun):Could not initialize Logback logging from classpath:logback-spring.xml Could not resolve placeholder 'APP_NAME' in value "${APP_NAME}" - 서버 시작 실패 메시지 (사용자 신규 로그):
org.flywaydb.core.api.FlywayException: Found more than one migration with version 4 Offenders: -> .../adapter-persistence-postgresql-0.0.1+3a300d89ec30.jar!/db/migration/postgresql/V4__int_lock.sql -> .../adapter-persistence-postgresql/build/resources/main/db/migration/postgresql/V4__int_lock.sql - 발생 컨텍스트: Spring Boot 4 dependency set에서 Gradle compile/test/check 및 VSCode Spring Boot YAML validation 실행.
- 발생 시점: 2026-06-30
- 발생 환경: local
- 재현 가능 여부:
always
재현 절차 / Reproduction
- Spring Boot 4 / Spring Framework 7 / Jackson 3 dependency set으로 프로젝트를 refresh한다.
src/app-bootstrap/src/test/resources/application-test.yml또는 application yml에서 deprecatedserver.error.include-stacktracekey를 유지한다.- VSCode Spring Boot YAML validation 또는 Gradle test/check를 실행한다.
- 기대 결과: 설정 key, compile surface, tests가 현 dependency set과 일치한다.
- 실제 결과: deprecated YAML warning/error, moved package compile errors, Jackson runtime test failures, JDBC lock schema/API mismatch, Checkstyle method naming failures가 발생한다.
조사 단계 / Investigation log
- 2026-06-30 —
rg -n "server\\.error\\.include"실행 → repository config에 deprecated key가 남아 있음을 확인. - 2026-06-30 — Spring Boot 4.0.0 jar metadata에서 replacement 확인 →
spring.web.error.include-stacktrace와spring.web.error.include-message로 이동. - 2026-06-30 — focused adapter-web/app-bootstrap/sample tests 실행 → Jackson 3
tools.jackson.*API와 local JsonNullable module 필요 확인. - 2026-06-30 — Spring Integration 7 source/API 확인 →
JdbcLockRegistryTTL constructor와DistributedLock.tryLock(wait, ttl)path 필요 확인. - 2026-06-30 —
./gradlew test --continue실행 → 전체 test suite 통과 확인. - 2026-06-30 —
./gradlew check실행 → architecture/env checks는 통과했으나 Checkstyle/Spotless 단계에서 test method naming 위반으로 실패 확인. - 2026-07-01 —
rg -n "\\.asText\\(" src실행 → adapter-web auth 테스트 2개 파일에서 Jackson 3 deprecated call 확인. - 2026-07-01 — adapter-web auth focused tests 실행 →
asString()전환 후 테스트 통과 확인. - 2026-07-01 —
./gradlew check --continue실행 → blocking failures가adapter-web,app-bootstrap,sample-portfolioSpotless format drift였음을 확인. - 2026-07-01 —
./gradlew spotlessApply실행 → formatter-owned import order / google-java-format drift 정리. - 2026-07-01 —
./gradlew check재실행 →app-bootstrap:compileTestJava가 staleOutboxContainerTestSupport.class경로를 참조하며 실패. - 2026-07-01 —
./gradlew :app-bootstrap:cleanTest :app-bootstrap:compileTestJava실행 → stale test output 제거 후 재컴파일 성공. - 2026-07-01 — Checkstyle XML report를 집계 →
MethodName,ConstantName,NeedBraces,StaticVariableNameerror entries가 test source에 남아 있음을 확인. - 2026-07-01 — test method/constant bulk rename 및 one-line
ifbrace cleanup 실행 →./gradlew checkstyleTest checkstyleSampleOffTest --continue후 XML parsertotal_errors=0확인. - 2026-07-01 — ApprovalTests failed path 확인 →
PackageSettings.UseApprovalSubdirectoryexact field convention을 lowerCamelCase로 바꾸면 approved snapshot directory lookup이 깨짐을 확인. - 2026-07-01 — SpotBugs
SECUJDESoutput 확인 → architecture negative fixture가 의도적으로 unsafe Jackson call을 포함해 false-positive처럼 출력됨을 확인. - 2026-07-01 — ApprovalTests snapshot filename을 lowerCamelCase method name과 맞추고, exact field/negative fixture만 targeted suppression/filter 적용.
- 2026-07-01 —
./gradlew build --warning-mode all실행 → Gradle 10 deprecation 후보가 SpotBugs enum coercion과 task action project lookup 2건임을 확인. - 2026-07-01 — Checkstyle XML report 집계 → 남은 warning이
MissingJavadocMethodCheck310건,MissingJavadocTypeCheck34건뿐임을 확인. - 2026-07-01 — SpotBugs
reportLevel을 enum value로 넘기고verifyCleanArchitectureDependencieslookup을rootProject.project(...)로 변경. - 2026-07-01 — default Checkstyle에서 Javadoc warning-tier modules를 제거 → Checkstyle XML warning/error total 0 확인.
- 2026-07-01 — CI quality-gates workflow 검토 → PR 전용 breaking-change-approval gate가
.approved.txtfilename-only rename도 label-required로 볼 수 있음을 확인. - 2026-07-01 — old/new ApprovalTests approved snapshot SHA 비교 → 세 snapshot 모두 내용 동일, 파일명만 변경됨을 확인.
- 2026-07-01 —
.github/scripts/verify-breaking-change-approval.sh추가 →R100identical-content rename은 통과, content change는 label 없으면 실패하도록 분리. - 2026-07-01 — temp git repo에서 no-change / identical rename / content change without label / content change with label path 검증.
- 2026-07-01 —
./gradlew check,./gradlew build실행 → 둘 다 success. - 2026-07-01 — 사용자 서버 startup log 확인 → 실제 root cause는 후속
BeanCreationException이 아니라 마지막Caused by의 Flyway V4 checksum mismatch임을 확인. - 2026-07-01 —
git show b3bd7fa:.../V4__int_lock.sql확인 → 기존 V4에는EXPIRED_AFTER가 없고 최근 커밋에서 V4에 컬럼을 직접 추가했음을 확인. - 2026-07-01 —
FlywayMigrationCompatibilityContractTest추가 → old V4가 이미 적용된 PostgreSQL DB에 current V4/V5 migration set을 적용하는 시나리오를 재현. - 2026-07-01 —
V4__int_lock.sql에서EXPIRED_AFTER를 제거하고V5__int_lock_expired_after.sql을 추가 → focused migration compatibility test 통과. - 2026-07-01 — 순수
bootRun실행 → profile placeholder literal binding failure 확인. - 2026-07-01 —
spring.profiles.active에localfallback과EnvProfileMatrixContractTest회귀 테스트 추가 → focused test 통과. - 2026-07-01 — 순수
bootRun재실행 → logback early placeholder failure 확인. - 2026-07-01 —
logback-spring.xmlspringProperty source를 direct env key로 변경하고StructuredLogFieldContractTest회귀 테스트 추가 → focused test 통과. - 2026-07-01 —
.env를 process env로 명시 주입한bootRun실행 → 서버가Started CaSkeletonApplication까지 도달하고 기존 DB에 V5 migration이 적용됨을 확인. - 2026-07-01 — Gradle
bootRun이src/.env를 Java process env로 주입하도록 변경 → 순수timeout 60s ./gradlew :app-bootstrap:bootRun --no-daemon --stacktrace도Started CaSkeletonApplication까지 도달. - 2026-07-01 —
./gradlew check verifyPublicPathSnapshot --no-daemon --stacktrace재실행 → success. - 2026-07-01 — 사용자 신규 startup log 확인 → root cause가 이전 checksum mismatch가 아니라 stale
adapter-persistence-postgresqlJAR와 current resources의 Flyway migration duplicate version임을 확인. - 2026-07-01 —
find src/adapter-persistence-postgresql/build/libs -name 'adapter-persistence-postgresql-*.jar'실행 →0.0.1+3a300d89ec30.jar포함 다수의 old git-revision JAR가 남아 있음을 확인. - 2026-07-01 —
verifyNoStaleTraceableJars를 먼저 추가하고 실행 → 10개 module의 stale traceable JAR를 감지하며 실패해 검증이 실제 문제를 잡는 것을 확인. - 2026-07-01 —
cleanStaleTraceableJars,verifyNoStaleTraceableJars,Jar/BootJar실행 전 stale archive cleanup을 추가하고check에 연결. - 2026-07-01 —
./gradlew verifyNoStaleTraceableJars --no-daemon --stacktrace재실행 → stale archive 105개 삭제 후 success. - 2026-07-01 —
find src -path '*/build/libs/*.jar'실행 → 각 module에 current git-revision archive만 남은 것을 확인. - 2026-07-01 —
timeout 45s ./gradlew :app-bootstrap:bootRun --no-daemon --stacktrace실행 → Flyway duplicate 오류 없이Started CaSkeletonApplication까지 도달. - 2026-07-01 —
./gradlew check verifyPublicPathSnapshot --no-daemon --stacktrace재실행 → new stale-jar gate 포함 success.
근본 원인 / Root cause
- 직접 원인: Spring Boot 4 / Spring Framework 7 / Jackson 3 / Testcontainers 2 / Spring Integration 7에서 package, module, configuration key, serializer API, lock schema/API가 변경되었는데 기존 코드와 설정이 Boot 3/Jackson 2 계열 surface에 남아 있었다.
- 근본 원인: patch upgrade와 달리 major upgrade는 compiler output뿐 아니라 runtime auto-configuration metadata, test-slice module split, third-party module compatibility까지 함께 바뀐다.
- 추가 원인: warning-only static-analysis task라도 rule severity가
error면 Gradle 출력에 error처럼 보이는 로그가 남는다. 이 경우 ignoreFailures 정책은 exit code만 완화하고 리포트의 severity를 바꾸지 않는다. - 추가 원인: Gradle warning은 default mode에서 요약만 보이고 실제 제거 지점은
--warning-mode all에서만 드러난다. Checkstyle Javadoc warning은 meaningful documentation 없이 대량 주석을 강제하는 baseline이라 기본 build signal로 적합하지 않았다. - 추가 원인: CI breaking-change approval gate가 content diff가 아니라 path glob 중심으로 governed snapshot 변경을 판단해, 동일 내용 rename도 breaking change로 오탐할 수 있었다.
- 추가 원인: 적용된 Flyway versioned migration인
V4__int_lock.sql에 Spring Integration 7용EXPIRED_AFTER컬럼을 직접 추가해 기존 DB의flyway_schema_historychecksum과 소스 checksum이 달라졌다. - 추가 원인: Boot 4 early profile/logging initialization은
spring-dotenv가.env를 Spring Environment에 넣기 전에 실행될 수 있어, required placeholder가 literal 또는 unresolved 상태로 실패했다. - 추가 원인: Gradle
bootRun은 working directory만src로 바꿨고,.env값을 Java process environment로 직접 주입하지는 않았다. - 추가 원인: traceable artifact 이름에 git revision이 포함되는데
build/libs에 old revision JAR가 누적되었다. IDE/runtime classpath가 stale JAR와 currentbuild/resources/main을 함께 잡으면 Flyway가 동일 versioned migration을 두 번 발견한다. - 트리거 조건: Boot 4 dependency set refresh 후 Gradle compile/test/check 및 IDE YAML validation 실행.
Sources / 근거 (해결 근거가 된 자료, 최소 1개+ 권장)
- raw/official-docs/spring-boot-test-slices-webmvctest-datajpatest-official — Boot test slice/Jackson component scan semantics 확인.
- raw/official-docs/lock-spring-integration-lock-registry — LockRegistry/JdbcLockRegistry와 TTL 만료 위험 확인.
- raw/official-docs/config-spring-boot-externalized-configuration — Spring Boot 설정 검증 관점 확인.
- raw/official-docs/tracing-spring-boot-3-actuator-tracing-reference — Micrometer tracing/OpenTelemetry starter 선택지 확인.
- local Spring Boot 4.0.0 configuration metadata —
server.error.include-*replacement 확인.
해결 / Resolution
- 적용한 조치:
- Boot 4 moved package imports와 split module dependencies를 갱신했다.
- Jackson 3
tools.jackson.*API로 production/test code를 전환했다. - Jackson 2 기반 nullable module 대신 local Jackson 3
JsonNullableserializer/deserializer module을 구성했다. - Testcontainers PostgreSQL package를 Testcontainers 2 module namespace로 갱신했다.
- Spring Integration 7 JDBC lock schema에
EXPIRED_AFTER를 추가하고 TTL-aware lock API를 사용했다. server.error.include-stacktrace/message를spring.web.error.include-stacktrace/message로 이전하고 env registry를 갱신했다.- Jackson 3.0.2에서 deprecated 된
JsonNode.asText()테스트 assertion을asString()으로 변경했다. spotlessApply로 formatter-owned drift를 정리했다.:app-bootstrap:cleanTest :app-bootstrap:compileTestJava로 stale test compile output을 재생성했다.- test method
snake_case를 lowerCamelCase로, static constant를UPPER_SNAKE_CASE로 정리했다. - Checkstyle
NeedBraces위반이 남은 single-lineif에 braces를 추가했다. - ApprovalTests approved snapshot 파일명을 새 lowerCamelCase method name과 맞췄다.
- ApprovalTests reflection convention인
UseApprovalSubdirectory만 file-scoped Checkstyle exception으로 문서화했다. - architecture negative fixture의
SECUJDES는DefaultTypingFixture.javasource에 한정해 SpotBugs exclude했다. - SpotBugs Gradle
reportLevel은 문자열 coercion 대신com.github.spotbugs.snom.Confidence.valueOf('HIGH')를 사용했다. verifyCleanArchitectureDependenciestask action 내부 project lookup은rootProject.project(...)로 변경했다.- Checkstyle default ruleset에서
MissingJavadocType,MissingJavadocMethod,NonEmptyAtclauseDescriptionwarning-tier modules를 제거했다. - breaking-change approval workflow inline shell을
.github/scripts/verify-breaking-change-approval.sh로 분리하고,git diff --name-status --find-renames=100%기반으로 identical-content rename을 통과시켰다. - 이미 적용된
V4__int_lock.sql을 원래 checksum으로 되돌리고V5__int_lock_expired_after.sql전진 migration으로EXPIRED_AFTER를 추가했다. - 기존 V4가 적용된 DB도 repair 없이 V5로 올라가는 Testcontainers 회귀 테스트를 추가했다.
spring.profiles.active에localfallback을 추가하고 early profile binding 계약 테스트를 추가했다.logback-spring.xml의 early properties를application.yml경유가 아니라 direct env key + default로 읽게 바꿨다.- Gradle
bootRun이src/.env를 Java process env로 주입하되 이미 export된 env를 덮어쓰지 않게 했다. cleanStaleTraceableJars와verifyNoStaleTraceableJars를 추가해 old git-revision JAR를 삭제하고 남아 있으면 검증 실패하도록 했다.verifyNoStaleTraceableJars를 기본check에 연결했다.- 모든
Jar/BootJar계열 archive task 실행 전에 같은 archive base/classifier의 old git-revision JAR를 삭제하게 했다.
- 검증 방법:
./gradlew test --continuesuccess../gradlew verifyCleanArchitectureDependencies verifyEnvKeys verifyPublicPathSnapshotsuccess../gradlew checkstyleTest checkstyleSampleOffTest --continuesuccess and Checkstyle XMLtotal_errors=0../gradlew checkstyleMain checkstyleTest checkstyleSampleOffTest --continuesuccess and Checkstyle XML total warning/error0../gradlew :app-bootstrap:spotbugsTest :app-bootstrap:spotbugsSampleOffTestsuccess withoutSECUJDESoutput../gradlew build --warning-mode allsuccess without Gradle deprecation output../gradlew check verifyPublicPathSnapshot --no-daemon --stacktracesuccess../gradlew :app-bootstrap:sampleOffTest verifyCleanArchitectureDependencies --no-daemon --stacktracesuccess.bash .github/scripts/verify-gate-matrix.sh && bash .github/scripts/verify-supply-chain-contract.sh && bash .github/scripts/test-supply-chain-scripts.shsuccess.- temp git repo script test success for breaking-change approval paths.
./gradlew checksuccess../gradlew buildsuccess../gradlew :app-bootstrap:test --tests dev.caskeleton.bootstrap.integration.FlywayMigrationCompatibilityContractTest --no-daemon --stacktracesuccess../gradlew :app-bootstrap:test --tests dev.caskeleton.bootstrap.contract.EnvProfileMatrixContractTest --no-daemon --stacktracesuccess../gradlew :app-bootstrap:test --tests dev.caskeleton.bootstrap.contract.StructuredLogFieldContractTest --no-daemon --stacktracesuccess.timeout 60s ./gradlew :app-bootstrap:bootRun --no-daemon --stacktrace→ process는 timeout 124로 종료했지만 로그에서Started CaSkeletonApplication및 ReadinessACCEPTING_TRAFFIC확인../gradlew check verifyPublicPathSnapshot --no-daemon --stacktracesuccess../gradlew verifyNoStaleTraceableJars --no-daemon --stacktrace→ stale traceable JAR 삭제 후 success.find src -path '*/build/libs/*.jar'→ old git-revision JAR 제거 확인.timeout 45s ./gradlew :app-bootstrap:bootRun --no-daemon --stacktrace→ process는 timeout 124로 종료했지만 로그에서 Flyway validate/migrate와Started CaSkeletonApplication확인../gradlew check verifyPublicPathSnapshot --no-daemon --stacktracesuccess,verifyNoStaleTraceableJars포함.rg -n "server\\.error\\.include|spring\\.jackson\\.generator|SPRING_JACKSON_GEN_WRITE_BIGDECIMAL_AS_PLAIN" .로 deprecated/removed keys 제거 확인.rg -n "\\.asText\\(" srcno matches../gradlew :adapter-web:test --tests 'dev.caskeleton.adapter.web.auth.EnvelopeAccessDeniedHandlerTest' --tests 'dev.caskeleton.adapter.web.auth.EnvelopeAuthenticationEntryPointTest'success.
- 잔여 위험 / 후속 작업:
- 기본 빌드의 Javadoc warning은 제거했지만, public API documentation 자체가 완료된 것은 아니다.
- tracing fallback은 local test contract를 유지하기 위한 최소 bean 구성이다. 운영 exporter 구성은 별도 작업으로 분리해야 한다.
- 대규모 test method rename으로 외부 IDE run configuration이나 문서가 old snake_case method name을 직접 참조하면 갱신이 필요하다.
- remote Gitea CI 로그는 로컬에
gh가 없고 GitHub remote가 아니어서 직접 조회하지 못했다. remote runner 재실행으로 최종 확인 필요. - 누군가 잘못된 V4 내용으로
flyway repair를 이미 실행한 DB는 이번 V4 원복 후 반대 방향 checksum mismatch가 날 수 있다. 해당 경우에는 DB별 schema history 확인 후 별도 repair/backout 절차가 필요하다. .envparser는 단순KEY=value형식만 처리한다. quoted value, escaped newline,export KEY=value가 필요하면 확장해야 한다.- IDE run configuration이 삭제된 old JAR absolute path를 직접 고정하고 있다면 IDE classpath refresh가 필요하다. Gradle
check와 archive task는 stale JAR를 다시 만들지 않도록 막지만 IDE 설정 자체의 old path 참조까지 수정하지는 않는다.
회고 / Lessons
- 빨리 감지하는 신호:
- Boot major upgrade 후
YAML_DEPRECATED_ERROR,tools.jackson/com.fasterxml혼재,JsonNode.asText()deprecation,NoSuchMethod/schema mismatch, Testcontainers package missing이 함께 보이면 단순 import fix가 아니라 migration surface 전체를 점검해야 한다.
- Boot major upgrade 후
- 예방 체크리스트 항목 후보:
- Boot metadata replacement grep.
- Jackson 2 module compatibility audit.
- Testcontainers module namespace audit.
- Spring Integration schema/API diff audit.
test --continue와check를 분리해 test pass와 style gate failure를 별도 보고.- Spotless failure가 보이면 수동 import/order patch보다
spotlessApply로 formatter-owned 영역을 정규화. bad class file+NoSuchFileException조합은 stale Gradle test output 가능성이 크므로 해당 source set clean 후 재컴파일.- ApprovalTests
PackageSettings처럼 reflection convention을 쓰는 도구 설정은 일반 naming cleanup 전에 exact symbol contract인지 먼저 확인한다. - warning-only 정적분석 task라도 developer-facing error log를 줄이려면 XML severity entry를 0으로 만드는 별도 검증이 필요하다.
- Gradle deprecation은
--warning-mode all을 정기적으로 돌려 실제 Gradle 10 failure 후보를 조기에 제거한다. - Javadoc은 대량 기계 주석으로 해결하지 말고, 공개 API 문서화 정책과 범위를 별도 작업으로 잡는 편이 낫다.
- Contract snapshot 게이트는 파일 경로 변경과 내용 변경을 분리해야 한다. ApprovalTests method rename은 filename drift를 만들지만 wire contract drift를 뜻하지 않는다.
- Flyway versioned migration은 한 번 적용되면 코드 리뷰에서도 immutable artifact로 취급해야 한다. schema drift는 새 version migration으로만 전진시킨다.
- Boot major upgrade 후 local
bootRun검증은 compiler/test와 별개로 필요하다. profile/logging은 application context보다 먼저 실패할 수 있다. .env를 working directory에 두는 것과 process env에 주입하는 것은 다르다. early initialization 경로는 process env 또는 inline default가 더 안전하다.- git revision을 archive name에 포함하는 build에서는
build/libs누적 산출물도 runtime 위험이 될 수 있다. IDE classpath가 Gradle classpath와 다르게 움직일 수 있으므로 stale artifact cleanup과 검증을 빌드에 포함해야 한다.
- wiki로 끌어올릴 가치가 있는 일반화된 교훈:
- Major framework migration은 "compile surface", "runtime metadata", "test slice auto-config", "third-party module compatibility", "registry/env contract"를 별도 축으로 검증한다.
- Static-analysis noise cleanup은 "진짜 코드 스타일 위반", "도구 convention", "negative fixture"를 분리해야 한다.
Related / 관련
- 관련 작업 식별자:
chore-spring-boot-four-migration(별도 branch-note 없음) - 선행 patch upgrade 작업 식별자:
chore-spring-boot-patch-upgrade(별도 branch-note 없음)