Spring Boot 4 워크숍의 Jackson 3 전환

Spring Boot 4로 예제를 전환할 때는 Spring Framework 7, 스타터 이름, 테스트 패키지 변경을 먼저 확인하게 됩니다. 그러나 실제 정리 과정에서는 JSON 호환성 경계에서도 문제가 반복되었습니다.
Spring Boot 4의 기본 JSON 구성은 Jackson 3입니다. Spring Boot 문서도 Jackson 3을 기본이자 선호 라이브러리로
설명하고, Jackson 2 지원은 마이그레이션을 위한 임시 경로로 둡니다. 따라서 Spring Boot 4 워크숍 모듈이
bluetape4k-jackson2나 Jackson 2 매퍼 패키지를 계속 사용하면 Boot 4 예제 안에 서로 다른 JSON 기준선이
공존하게 됩니다.
예제는 사용자가 실제 프로젝트의 출발점으로 재사용하는 실행 가능한 문서입니다. 오래된 클래스패스를 남겨두면
독자는 예제의 핵심 기능보다 NoSuchMethodError나 설정 충돌을 먼저 해결해야 합니다.
문제는 버전 숫자가 아니라 호환성 기준선이다
섹션 제목: “문제는 버전 숫자가 아니라 호환성 기준선이다”bluetape4k-workshop에서는 Spring Kafka 요청-응답 예제와 Spring Data Elasticsearch 예제에 남아 있던
bluetape4k-jackson2 의존성을 정리했습니다. 핵심은 단순히 라이브러리 버전을 올리는 것이 아니라, 다음 세
경계를 같은 기준에 맞추는 것입니다.
정리 방향은 단순했습니다.
| 확인할 것 | Spring Boot 4 예제에서 기대하는 상태 |
|---|---|
| bluetape4k JSON 지원 모듈 | bluetape4k-jackson3 |
| Jackson 패키지 | tools.jackson.* |
| Jackson BOM | tools.jackson:jackson-bom |
| Spring Boot 기준 | Spring Boot 4 BOM과 스타터 |
| 예외 | 아직 Jackson 2 API만 노출하는 상위 라이브러리 또는 애너테이션 패키지 |
여기서 중요한 점은 “Jackson2를 싹 지운다”가 아닙니다. Spring Boot 4 예제가 어떤 호환성 기준선을 보여주는지 분명히 하는 것입니다. 예제가 Boot 4라면 기본 JSON 구성도 Jackson 3이어야 합니다.
bluetape4k-workshop 루트 빌드는 Spring Boot 4 BOM과 Jackson 3 BOM을 함께 관리합니다.
dependencyManagement { imports { mavenBom(rootLibs.spring.boot4.dependencies.get().toString()) mavenBom(rootLibs.jackson3.bom.get().toString()) }}버전 카탈로그에도 Jackson 2와 Jackson 3 별칭이 나란히 있습니다.
# Jackson 2jackson-bom = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "jackson" }jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind" }
# Jackson 3jackson3-bom = { module = "tools.jackson:jackson-bom", version.ref = "jackson3" }jackson3-databind = { module = "tools.jackson.core:jackson-databind" }jackson3-module-kotlin = { module = "tools.jackson.module:jackson-module-kotlin" }두 계열이 카탈로그에 함께 있다고 해서 모듈이 임의로 선택해도 된다는 뜻은 아닙니다. 예제가 기준으로 삼는 Spring Boot 버전과 상위 라이브러리의 지원 범위가 선택을 결정합니다.

의존성은 이렇게 바꿨다
섹션 제목: “의존성은 이렇게 바꿨다”messaging/kafka-reply는 요청-응답 흐름을 보여주는 Spring Kafka 예제입니다. Spring Boot 4 기준에서는
Jackson 3 의존성을 명시합니다.
dependencies { api(libs.bluetape4k.jackson3) api(libs.jackson3.databind) api(libs.jackson3.module.kotlin) api(libs.jackson3.module.blackbird)
implementation(libs.bluetape4k.kafka4) implementation(libs.bluetape4k.coroutines) implementation(libs.spring.boot.starter.webflux.lib)}이 변경은 “새 기능을 하나 더 붙인 작업”이 아닙니다. 예제가 설명하는 실행 환경을 맞춘 작업입니다. Spring Boot 4,
Spring Kafka 4, Jackson 3, bluetape4k-jackson3가 서로 맞는 버전 조합이 되도록 정리했습니다.
spring-data/elasticsearch도 Spring Boot 4 예제 기준에 맞춰 bluetape4k-jackson3를 사용합니다.
dependencies { implementation(libs.spring.boot.starter.data.elasticsearch.lib) implementation(libs.spring.boot.starter.webflux.lib)
implementation(libs.bluetape4k.jackson3) implementation(libs.bluetape4k.coroutines)}의존성을 맞춘 뒤에는 임포트와 매퍼 빈을 확인해야 합니다.
임포트는 패키지 이름으로 기준선을 확인한다
섹션 제목: “임포트는 패키지 이름으로 기준선을 확인한다”Jackson 3는 의존성 그룹과 패키지가 달라졌습니다. Spring Boot 4 마이그레이션 가이드도
com.fasterxml.jackson에서 tools.jackson으로 옮겨야 한다고 설명합니다. 예제 코드에서는 이런 모양이 됩니다.
import io.bluetape4k.jackson3.Jacksonimport tools.jackson.databind.json.JsonMapper
@Configuration(proxyBeanMethods = false)class JacksonConfig {
@Bean fun jsonMapper(): JsonMapper = Jackson.defaultJsonMapper
}bluetape4k-jackson3의 Jackson.defaultJsonMapper는 Kotlin 모듈, Java Time 모듈, Blackbird를 미리
등록한 매퍼입니다. 예제마다 같은 모듈 등록 코드를 반복하지 않아도 됩니다.
추가 설정이 필요하면 rebuild()로 이어갑니다.
protected val defaultMapper: JsonMapper by lazy { Jackson.defaultJsonMapper .rebuild() .apply { configure(SerializationFeature.INDENT_OUTPUT, true) } .build()}이 패턴은 공통 설정을 보존하면서 예제에 필요한 차이만 추가합니다. 독자는 Jackson 모듈을 처음부터 다시 구성하지 않고도 로컬 설정을 어디에 추가해야 하는지 확인할 수 있습니다.
com.fasterxml.jackson.annotation은 예외다
섹션 제목: “com.fasterxml.jackson.annotation은 예외다”rg "com.fasterxml.jackson" 검색 결과를 일괄 치환해서는 안 됩니다.
Jackson 3 마이그레이션에서 패키지가 tools.jackson으로 옮겨졌지만, 애너테이션 패키지는 호환성을 위해
com.fasterxml.jackson.annotation에 남습니다. 따라서 워크숍 소스에도 다음 임포트가 정상적으로 남아 있습니다.
import com.fasterxml.jackson.annotation.JsonView그래서 점검 규칙은 이렇게 잡아야 합니다.
| 검색 결과 | 처리 |
|---|---|
com.fasterxml.jackson.databind.* | Jackson 3 모듈에서는 대체로 tools.jackson.databind.*로 이동 |
com.fasterxml.jackson.module.* | Jackson 3 모듈에서는 tools.jackson.module.*로 이동 |
com.fasterxml.jackson.annotation.* | 그대로 유지할 수 있는 애너테이션 패키지인지 확인 |
bluetape4k-jackson2 | Spring Boot 4 예제라면 bluetape4k-jackson3로 전환 검토 |
마이그레이션에서는 문자열을 일괄 치환하기보다 검색 결과를 패키지 역할에 따라 분류해야 합니다.
설정 파일도 같이 확인해야 한다
섹션 제목: “설정 파일도 같이 확인해야 한다”의존성과 임포트만 바꿨다고 끝나지 않습니다. Spring Boot 4와 Jackson 3 조합에서는 spring.jackson.* 설정도
확인해야 합니다.
bluetape4k-workshop의 Exposed 예제 재작성 과정에서는 다음 설정이 애플리케이션 컨텍스트 로딩을
실패하게 했습니다.
spring: jackson: serialization: write-dates-as-timestamps: false해당 예제에서는 열거형 변환이 write-dates-as-timestamps를 Jackson 3의
WRITE_DATES_AS_TIMESTAMPS로 처리하지 못했습니다. 이 사례의 해결책은 spring.jackson 섹션을 제거하고,
필요한 매퍼 설정을 코드에서 구성하는 것이었습니다. 이는 모든 spring.jackson.* 속성이 Jackson 3에서
무효라는 뜻은 아닙니다. 사용 중인 속성이 Spring Boot 4와 Jackson 3 조합에서 실제로 바인딩되는지 각각
검증해야 합니다.
spring.jackson.use-jackson2-defaults=true는 Jackson 2를 활성화하는 설정이 아닙니다. Jackson 3 매퍼의
기본값을 Spring Boot 3과 Jackson 2의 동작에 가깝게 맞추는 마이그레이션 보조 설정입니다. Jackson 2를
계속 사용해야 한다면 별도의 spring-boot-jackson2 호환 모듈과 spring.jackson2.* 설정 경계를 검토해야
합니다. 신규 예제에서는 이런 호환 경로를 기본값으로 숨기지 않고, 필요한 경우에만 이유와 제거 조건을 함께
기록하는 편이 안전합니다.
그래도 못 바꾸는 경우는 있다
섹션 제목: “그래도 못 바꾸는 경우는 있다”모든 모듈을 한 번에 Jackson 3로 옮길 수는 없습니다. 상위 라이브러리가 아직 Jackson 2 API만 노출하면 강행할 수 없습니다.
실제 마이그레이션에서도 Quarkus Jackson 확장 모듈은 소스가 Jackson 2 API를 노출하고 있어 유지했습니다.
spring-data/elasticsearch 계열도 Elasticsearch 클라이언트와 Spring Boot 4 Jackson 3
조합에서 충돌하는 테스트는 비활성화되어 있습니다.
이 경우에는 전환을 완료했다고 간주하지 말고 현재 상태를 문서에 남겨야 합니다.
@Disabled("Elasticsearch Client 가 Jackson2 를 사용합니다. Spring Boot 4 는 Jackson 3를 사용해서 충돌이 발생합니다.")독자에게 필요한 정보는 전환 범위와 남아 있는 제약입니다. 비활성화된 테스트는 완료 증거가 아니라, 상위 라이브러리의 지원을 기다리는 호환성 부채로 관리해야 합니다.
마이그레이션 점검표
섹션 제목: “마이그레이션 점검표”Spring Boot 4 워크숍 모듈을 만들거나 정리할 때는 아래 순서로 확인하면 됩니다.
| 단계 | 확인할 것 | 예시 |
|---|---|---|
| 1 | 모듈 기준 | Spring Boot 4 모듈인지 먼저 확인 |
| 2 | bluetape4k JSON 지원 모듈 | bluetape4k-jackson2 대신 bluetape4k-jackson3 |
| 3 | Jackson 의존성 | jackson3-databind, jackson3-module-kotlin |
| 4 | 임포트 | tools.jackson.databind.*, tools.jackson.module.* |
| 5 | 애너테이션 예외 | com.fasterxml.jackson.annotation.*는 일괄 삭제하지 않기 |
| 6 | 매퍼 빈 | JsonMapper와 Jackson.defaultJsonMapper 우선 검토 |
| 7 | 설정 파일 | spring.jackson.* 속성이 Jackson 3에서도 유효한지 확인 |
| 8 | 상위 라이브러리 예외 | Jackson 2만 지원하는 클라이언트와 확장 모듈의 상태 기록 |
| 9 | 검증 | 관련 모듈의 testClasses 또는 test 실행 |
관련 모듈의 컴파일·테스트 구성은 다음 명령으로 함께 확인했습니다.
./gradlew :messaging-kafka-reply:testClasses :spring-data-elasticsearch:testClasses검증 과정에서는 버전 카탈로그의 중복 별칭이 Gradle 구성 단계를 먼저 실패하게 한 사례도 있었습니다. 테스트
작업을 선택하기 전에 빌드가 중단된다면 모듈 코드뿐 아니라 libs.versions.toml의 별칭 충돌과 BOM 구성을
먼저 확인해야 합니다.
예제는 의존성 조합까지 보여주는 문서다
섹션 제목: “예제는 의존성 조합까지 보여주는 문서다”Spring Boot 4 워크숍 예제에서 Jackson 3로 옮긴 이유는 단순히 새 버전을 사용하기 위해서가 아닙니다. 예제는 사용자에게 “이 조합으로 시작하면 된다”는 기준선을 제공해야 합니다.
Spring Boot 4 예제가 Jackson 2 지원 모듈을 함께 사용하면 독자는 예제가 설명하려는 기능과 피해야 할 클래스패스 혼합을 동시에 접하게 됩니다.
Spring Boot 4, Jackson 3, bluetape4k-jackson3, tools.jackson.*, JsonMapper. 이 다섯 가지가 맞아야
독자는 예제의 핵심 흐름에 집중할 수 있습니다. 중요한 것은 오류를 숨기는 것이 아니라, 의존성·코드 API·설정과
검증이 처음부터 같은 기준선을 가리키도록 만드는 것입니다.
댓글
GitHub 계정으로 의견을 남기거나 reaction을 남길 수 있습니다.