boolean 필드 초기값 DDL DEFAULT 미반영 — 설계 검토 안건
현상
@Column(nullable = false)
private boolean isActive = true;
-- 기대
`active` TINYINT(1) NOT NULL DEFAULT '1'
-- 실제
`active` TINYINT(1) NOT NULL DEFAULT '0'
= false 또는 초기값 미지정 케이스는 DEFAULT '0'이 정확히 생성됨.
= true 케이스만 DEFAULT '0'으로 잘못 생성됨.
근본 원인
1. 타입 매퍼 하드코딩
MySqlJavaTypeMapper에서 boolean/Boolean 타입의 defaultValue가 "0"으로 정적 정의됨.
entry("java.lang.Boolean", new MysqlJavaType(..., "0")),
entry("boolean", new MysqlJavaType(..., "0")),
2. Processor가 DEFAULT를 세팅하지 않음
ColumnBuilderFactory가 ColumnModel.defaultValue를 채우지 않으므로 항상 null.
MySqlDialect.getColumnDefinitionSql() 우선순위:
1순위: ColumnModel.defaultValue → null (processor에서 미설정)
2순위: UUID 생성 전략
3순위: JavaTypeMapper.defaultValue → 항상 "0" ← 여기서 결정됨
3. APT API 제약 — 핵심
VariableElement.getConstantValue()는 컴파일 타임 상수 변수(static final 필드)에서만 값을 반환함.
// static final → getConstantValue() = true (읽기 가능)
private static final boolean ENABLED = true;
// 일반 인스턴스 필드 → getConstantValue() = null (읽기 불가)
private boolean isActive = true;
JPA 엔티티에서 사용하는 인스턴스 필드의 초기화자는 바이트코드에만 존재하며, APT의 언어 모델(javax.lang.model) 레벨에서는 접근 수단이 없음.
영향 범위
- JPA 경유 INSERT: Hibernate가 Java 필드값을 명시적으로 바인딩하므로 런타임 무영향
- DB 직접 INSERT / seed 스크립트: DEFAULT 의존 시
false로 저장됨 → 비즈니스 로직 불일치
- 스키마 가독성: 필드 초기값이
true임에도 스키마상 DEFAULT '0'으로 표현됨
해결 방향 검토
방향 A — @DefaultValue Jinx 전용 어노테이션 추가
@Column(nullable = false)
@DefaultValue("1")
private boolean isActive = true;
Processor에서 @DefaultValue를 읽어 ColumnModel.defaultValue에 세팅.
장점
- APT 제약 우회 가능
- 명시적이고 의도가 명확함
- boolean 외 다른 타입(String, int 등)에도 동일하게 활용 가능
단점
- Jinx 전용 어노테이션 → JPA 표준 밖의 침습적 변경
- Java 필드 초기값과
@DefaultValue가 달라질 경우 혼란 가능
- 기존 코드에 어노테이션 추가 작업 필요 (9개 필드 → 실제 운영 코드에선 더 많을 수 있음)
방향 B — 타입 매퍼의 boolean "0" 제거
MySqlJavaTypeMapper에서 boolean의 defaultValue = "0" 제거.
boolean 컬럼에 DEFAULT 절 자체를 생성하지 않음.
-- 변경 전
`active` TINYINT(1) NOT NULL DEFAULT '0'
-- 변경 후
`active` TINYINT(1) NOT NULL
장점
- 코드 변경 최소
- "잘못된 DEFAULT '0'" 문제 즉시 해소
- JPA 표준 범위 내 동작 (JPA는 DDL DEFAULT를 정의하지 않음)
단점
= false로 초기화된 필드도 DEFAULT 절이 사라짐
- DB 직접 INSERT 시 NOT NULL 컬럼에 값을 명시해야 함
(단, 이는 현행 DEFAULT '0'보다 오히려 명확한 동작)
- 기존 마이그레이션 파일과의 diff가 발생함 (운영 중인 경우)
방향 C — @Column(columnDefinition) workaround 문서화 (현행 유지)
변경 없이 명시적 DDL 지정 방법을 안내.
@Column(nullable = false, columnDefinition = "TINYINT(1) NOT NULL DEFAULT 1")
private boolean isActive = true;
장점
단점
- 사용자가 직접 DDL 문자열을 작성해야 함 (타입명, 방언 의존)
- 근본 원인(잘못된 DEFAULT '0') 미해결 → 버그가 아니라 설계로 인정하는 것
방향 D — A + B 병행 (중장기)
- 즉시: 타입 매퍼에서 boolean
"0" 제거 (방향 B)
- 추후:
@DefaultValue 어노테이션 추가 (방향 A)
B로 "잘못된 DEFAULT '0'" 문제를 선제 해소한 뒤,
필요한 경우 @DefaultValue로 명시적 제어를 제공.
정리
| 질문 |
내용 |
| JPA DDL에서 boolean DEFAULT는 필수인가? |
JPA 스펙 미정의. 선택사항. |
DEFAULT '0'이 없으면 문제가 되는가? |
NOT NULL 컬럼이면 INSERT 시 값 명시 필요. JPA 경유엔 무관. |
= true 필드의 실제 사용 빈도는? |
도메인 검증 결과 9개. 운영 코드에서는 더 많을 가능성. |
| 어노테이션 추가(A) vs 타입 매퍼 정리(B) 우선? |
B가 더 빠르고 부작용 적음. A는 별도 기능 범위. |
제안
단기: 방향 B 채택
타입 매퍼에서 boolean DEFAULT 하드코딩 제거.
"잘못된 DEFAULT '0'" 출력을 즉시 해소하고, 스키마를 JPA 표준에 가깝게 유지.
중장기: 방향 A를 별도 이슈로 트래킹
@DefaultValue 어노테이션은 boolean 한정이 아닌 범용 기능이므로,
별도 스펙 설계 후 독립 구현.
boolean 필드 초기값 DDL DEFAULT 미반영 — 설계 검토 안건
현상
= false또는 초기값 미지정 케이스는DEFAULT '0'이 정확히 생성됨.= true케이스만DEFAULT '0'으로 잘못 생성됨.근본 원인
1. 타입 매퍼 하드코딩
MySqlJavaTypeMapper에서 boolean/Boolean 타입의defaultValue가"0"으로 정적 정의됨.2. Processor가 DEFAULT를 세팅하지 않음
ColumnBuilderFactory가ColumnModel.defaultValue를 채우지 않으므로 항상null.MySqlDialect.getColumnDefinitionSql()우선순위:3. APT API 제약 — 핵심
VariableElement.getConstantValue()는 컴파일 타임 상수 변수(static final필드)에서만 값을 반환함.JPA 엔티티에서 사용하는 인스턴스 필드의 초기화자는 바이트코드에만 존재하며, APT의 언어 모델(
javax.lang.model) 레벨에서는 접근 수단이 없음.영향 범위
false로 저장됨 → 비즈니스 로직 불일치true임에도 스키마상DEFAULT '0'으로 표현됨해결 방향 검토
방향 A —
@DefaultValueJinx 전용 어노테이션 추가Processor에서
@DefaultValue를 읽어ColumnModel.defaultValue에 세팅.장점
단점
@DefaultValue가 달라질 경우 혼란 가능방향 B — 타입 매퍼의 boolean
"0"제거MySqlJavaTypeMapper에서 boolean의defaultValue = "0"제거.boolean 컬럼에 DEFAULT 절 자체를 생성하지 않음.
장점
단점
= false로 초기화된 필드도 DEFAULT 절이 사라짐(단, 이는 현행
DEFAULT '0'보다 오히려 명확한 동작)방향 C —
@Column(columnDefinition)workaround 문서화 (현행 유지)변경 없이 명시적 DDL 지정 방법을 안내.
장점
단점
방향 D — A + B 병행 (중장기)
"0"제거 (방향 B)@DefaultValue어노테이션 추가 (방향 A)B로 "잘못된 DEFAULT '0'" 문제를 선제 해소한 뒤,
필요한 경우
@DefaultValue로 명시적 제어를 제공.정리
DEFAULT '0'이 없으면 문제가 되는가?= true필드의 실제 사용 빈도는?제안
단기: 방향 B 채택
타입 매퍼에서 boolean DEFAULT 하드코딩 제거.
"잘못된 DEFAULT '0'" 출력을 즉시 해소하고, 스키마를 JPA 표준에 가깝게 유지.
중장기: 방향 A를 별도 이슈로 트래킹
@DefaultValue어노테이션은 boolean 한정이 아닌 범용 기능이므로,별도 스펙 설계 후 독립 구현.