102 lines
4.9 KiB
Markdown
102 lines
4.9 KiB
Markdown
---
|
|
title: "HikariCP knob 간 제약을 Spring Boot 시작 guard 로 강제하는 패턴"
|
|
source_type: blog-topic
|
|
status: raw
|
|
related_branches: [feature-database-connection-pool-contract]
|
|
related_projects: [ca-tmpl]
|
|
tags: [blog-topic, ca-tmpl, hikaricp, spring-boot, startup-validation, connection-pool, clean-architecture]
|
|
created: 2026-06-09
|
|
status_label: ready-for-canonical
|
|
target_audience: backend-engineer
|
|
inspiration_url:
|
|
archive_url:
|
|
---
|
|
|
|
# HikariCP inter-knob constraints as a Spring Boot startup guard
|
|
|
|
## Parent
|
|
|
|
- [[raw/branch-notes/feature-database-connection-pool-contract]]
|
|
|
|
## 트리거 / Trigger
|
|
|
|
- 트리거 유형: `branch-work`
|
|
- 트리거 날짜: 2026-06-09
|
|
- 트리거 연결 노트: [[raw/branch-notes/feature-database-connection-pool-contract]]
|
|
|
|
## 글감 / Topic seed
|
|
|
|
- 한 문장 요지: HikariCP knob 간 제약을 runtime 경고에 맡기지 않고 Spring Boot startup guard로 수집해 fail-fast시키는 패턴이다.
|
|
- 예상 제목 후보:
|
|
- HikariCP 설정 오류를 startup에서 잡기
|
|
- Connection pool knob 제약을 Spring Boot guard로 고정하기
|
|
|
|
## 핵심 주장 후보 / Claim candidates
|
|
|
|
- 사실 후보:
|
|
- `validationTimeout < connectionTimeout`, `keepaliveTime < maxLifetime` 같은 inter-knob 제약이 있다.
|
|
- `SmartInitializingSingleton`과 `ApplicationContextRunner`로 startup guard를 검증할 수 있다.
|
|
- 의견/해석 후보:
|
|
- pool 설정 오류는 traffic을 받기 전 startup phase에서 실패시키는 편이 운영적으로 더 명확하다.
|
|
|
|
## Outline seed
|
|
|
|
1. HikariCP knob 간 제약과 runtime 경고/reset의 한계를 정리한다.
|
|
2. String 기반 defensive parse로 Duration drift를 안전하게 처리한다.
|
|
3. `ApplicationContextRunner`로 guard failure를 작은 테스트로 고정한다.
|
|
|
|
## 핵심 아이디어
|
|
|
|
HikariCP 에는 knob 간 순서 제약이 있다:
|
|
- `validationTimeout < connectionTimeout`
|
|
- `keepaliveTime < maxLifetime`
|
|
- `connectionTimeout >= 250 ms`
|
|
- `leakDetectionThreshold >= 2000 ms` (0 = disabled 허용)
|
|
|
|
이 제약들은 HikariCP 내부에서 경고 또는 reset 으로만 처리되고, 설정 오류가 runtime 에서만 드러나는 경우가 많다. `SmartInitializingSingleton` + `Environment.getProperty(key)` (String, not typed) 패턴으로 context refresh 완료 직전에 모든 위반을 한꺼번에 수집해 `IllegalStateException` 으로 boot fail 시키면, 잘못된 pool 설정이 prod 에 배포되는 것을 막을 수 있다.
|
|
|
|
## 흥미로운 구현 포인트
|
|
|
|
### Defensive parseMillis (CONNECTION_TIMEOUT_FORMAT_DRIFT)
|
|
|
|
`environment.getProperty("spring.datasource.hikari.connection-timeout", Long.class)` 는 env-keys.yaml default 가 `"5s"` (Duration string) 일 때 `ConversionFailedException` 을 던진다. 대신 `getProperty(key)` 로 String 을 받아 `Long.parseLong(raw.trim())` + `NumberFormatException catch → return null` 패턴으로 방어 파싱하면:
|
|
1. 숫자 ms 값은 정상 검증
|
|
2. Duration string 은 null (absent 취급) — 크래시 없이 skip
|
|
3. 명세에서 두 포맷이 공존하는 drift 환경에서 안전
|
|
|
|
### ApplicationContextRunner 기반 단위 테스트
|
|
|
|
`@SpringBootTest` 없이 `ApplicationContextRunner.withUserConfiguration(ValidatorConfig.class)` 만으로 `SmartInitializingSingleton` 의 `afterSingletonsInstantiated()` 가 호출된다. `context.hasFailed()` + `context.getStartupFailure().hasStackTraceContaining(...)` 으로 각 위반 케이스를 격리 검증.
|
|
|
|
## 글감 방향
|
|
|
|
- Spring Boot startup contract 패턴 시리즈 (`SmartInitializingSingleton` vs `ApplicationListener<ContextRefreshedEvent>` vs `@PostConstruct`)
|
|
- HikariCP 운영에서 놓치기 쉬운 knob 간 제약 총정리
|
|
- "설정 오류를 runtime 이 아닌 startup 에서 잡는다" 원칙의 구현 패턴들
|
|
|
|
## Canonical 전환 후보 / Canonical extraction candidates
|
|
|
|
- `wiki/projects/ca-tmpl/data-layer-persistence-cache-outbound.md` 후보:
|
|
- HikariCP inter-knob constraint startup guard를 data-layer/pool configuration 글감으로 연결.
|
|
- 필요한 추가 검증:
|
|
- 실제 validator class, `ApplicationContextRunner` 테스트, env duration drift 처리 범위.
|
|
|
|
## Sources / 근거 후보
|
|
|
|
- [[raw/branch-notes/feature-database-connection-pool-contract]]
|
|
|
|
## 미해결 / Unknown
|
|
|
|
- 아직 확인해야 할 사실: 현재 ca-tmpl 코드에 startup guard와 관련 테스트가 존재하는지.
|
|
- 과장하면 안 되는 부분: HikariCP 자체가 모든 오류를 방치한다고 쓰지 않고, ca-tmpl에서 선택한 fail-fast 보강으로 제한한다.
|
|
|
|
## Related / 관련
|
|
|
|
- 관련 branch: [[raw/branch-notes/feature-database-connection-pool-contract]]
|
|
|
|
## Decision / 처리 결정
|
|
|
|
- 액션: `promote-to-canonical`
|
|
- 이유: `wiki/projects/ca-tmpl/data-layer-persistence-cache-outbound.md` 에 HikariCP startup guard 글감으로 반영했다.
|
|
- 다음 단계: target canonical이 아직 `draft` 이므로 `blogify` 전 pool guard 구현·검증 여부를 branch-note/code 기준으로 확인한다.
|