128 lines
5.0 KiB
Markdown
128 lines
5.0 KiB
Markdown
---
|
|
title: Spring Boot 3 @ConfigurationProperties record 에 보조 생성자를 추가하면 바인딩이 깨지는 이유
|
|
source_type: blog-topic
|
|
status: raw
|
|
created: 2026-06-12
|
|
related_branches: [feature-domain-event-outbox-contract]
|
|
related_projects: [ca-tmpl]
|
|
tags: [blog-topic, ca-tmpl, spring-boot, configuration-properties, record, constructor-binding, java21]
|
|
status_label: ready-for-canonical
|
|
target_audience: backend-engineer
|
|
inspiration_url:
|
|
archive_url:
|
|
---
|
|
|
|
# Spring Boot 3 `@ConfigurationProperties` record 에 보조 생성자를 추가하면 바인딩이 깨지는 이유
|
|
|
|
## Parent
|
|
|
|
[[raw/branch-notes/feature-domain-event-outbox-contract]]
|
|
|
|
---
|
|
|
|
## 글감 씨앗
|
|
|
|
`OutboundHttpSettings` record 에 기존 호출부 호환을 위한 보조 6-arg 생성자를 추가했을 때, `ApplicationContextRunner` 로 바인딩을 테스트하자 `No default constructor found` 로 실패한 경험. 해결책은 `@ConstructorBinding` 을 canonical compact constructor 에 추가하는 것이었다.
|
|
|
|
---
|
|
|
|
## 블로그 글 아이디어
|
|
|
|
### 제목 후보
|
|
|
|
- "Spring Boot 3 `@ConfigurationProperties` 레코드에 보조 생성자를 추가하면 생기는 일"
|
|
- "왜 Java record 에 생성자를 하나 더 추가했더니 Spring Boot 설정 바인딩이 깨졌나"
|
|
|
|
### 핵심 메시지
|
|
|
|
Spring Boot 3.x 는 record 에 생성자가 **딱 하나**일 때만 자동으로 constructor binding 경로를 선택한다. 생성자가 둘 이상이면 일반 JavaBean 경로(no-arg constructor 탐색)로 fallback 하기 때문에, 보조 생성자를 추가하는 순간 기존에 잘 돌던 바인딩이 깨진다.
|
|
|
|
### 커버할 내용
|
|
|
|
1. Spring Boot `@ConfigurationProperties` 에서 record 바인딩이 동작하는 원리 (single-constructor auto-detect)
|
|
2. 보조 생성자 추가 시 발생하는 예외 메시지와 스택 트레이스 분석
|
|
3. 해결책: `@ConstructorBinding` (from `org.springframework.boot.context.properties.bind`) 을 canonical compact constructor 에 명시
|
|
4. Spring Boot 2.x vs 3.x import 경로 차이 (`@ConstructorBinding` deprecated 위치 변경)
|
|
5. 실전 패턴: 기존 호출부 호환을 유지하면서 record 필드를 확장하는 방법 (보조 생성자 + `@ConstructorBinding`)
|
|
|
|
### 코드 예시
|
|
|
|
```java
|
|
@ConfigurationProperties(prefix = "app.outbound.http")
|
|
public record MySettings(
|
|
Duration connectTimeout,
|
|
Retry retry) {
|
|
|
|
@ConstructorBinding // 다중 생성자 record 필수!
|
|
public MySettings { /* validation */ }
|
|
|
|
/** 보조 생성자: 기존 호출부 호환 */
|
|
public MySettings(Duration connectTimeout) {
|
|
this(connectTimeout, null);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 독자 대상
|
|
|
|
Java 21 + Spring Boot 3.x 를 사용하며 `@ConfigurationProperties` 를 record 로 작성하는 개발자.
|
|
|
|
---
|
|
|
|
## Claims To Verify
|
|
|
|
- Spring Boot 3.4 릴리즈 노트에 이 동작의 공식 문서 여부 확인 필요.
|
|
- `@ConstructorBinding` import 경로 변경 이력 (2.x → 3.x) 공식 마이그레이션 가이드 인용 필요.
|
|
|
|
## 트리거 / Trigger
|
|
|
|
- 트리거 유형: `troubleshooting`
|
|
- 트리거 날짜: 2026-06-12
|
|
- 트리거 연결 노트: [[raw/branch-notes/feature-domain-event-outbox-contract]]
|
|
|
|
## 글감 / Topic seed
|
|
|
|
- 한 문장 요지: Spring Boot 3 record `@ConfigurationProperties`에 보조 생성자를 추가하면 constructor binding auto-detect가 깨질 수 있어 canonical constructor에 `@ConstructorBinding`을 명시해야 한다.
|
|
- 예상 제목 후보:
|
|
- Spring Boot 3 record configuration binding이 깨지는 이유
|
|
- 보조 생성자와 `@ConstructorBinding`의 함정
|
|
|
|
## 핵심 주장 후보 / Claim candidates
|
|
|
|
- 사실 후보:
|
|
- multi-constructor record는 single-constructor auto-detect 경로를 벗어날 수 있다.
|
|
- 의견/해석 후보:
|
|
- backward-compatible constructor를 추가할 때 binding entrypoint를 명시하는 테스트가 필요하다.
|
|
|
|
## Outline seed
|
|
|
|
1. record binding auto-detect와 multi-constructor fallback을 설명한다.
|
|
2. `ApplicationContextRunner` failure로 원인을 좁힌다.
|
|
3. `@ConstructorBinding` import 경로와 canonical constructor 명시 패턴을 정리한다.
|
|
|
|
## Canonical 전환 후보 / Canonical extraction candidates
|
|
|
|
- `wiki/projects/ca-tmpl/config-and-adapter-templates.md` 후보:
|
|
- configuration properties record binding troubleshooting 글감.
|
|
- 필요한 추가 검증:
|
|
- 공식 문서/마이그레이션 가이드 source 보강.
|
|
|
|
## Sources / 근거 후보
|
|
|
|
- [[raw/branch-notes/feature-domain-event-outbox-contract]]
|
|
|
|
## 미해결 / Unknown
|
|
|
|
- 아직 확인해야 할 사실: Spring Boot 3.x 공식 문서의 정확한 constructor binding 문구.
|
|
- 과장하면 안 되는 부분: 모든 record multi-constructor가 동일하게 실패한다고 단정하지 않는다.
|
|
|
|
## Decision / 처리 결정
|
|
|
|
- 액션: `promote-to-canonical`
|
|
- 이유: `wiki/projects/ca-tmpl/config-and-adapter-templates.md` 에 Spring Boot 3 record configuration binding 글감으로 반영한다.
|
|
- 다음 단계: blogify 전 official doc 근거를 보강한다.
|
|
|
|
## Related / 관련
|
|
|
|
- 관련 branch: [[raw/branch-notes/feature-domain-event-outbox-contract]]
|