init: 클린 기반 auth 서버 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:30:18 +09:00
parent 471db0203d
commit 8a1ac1e769
3642 changed files with 275893 additions and 1 deletions
@@ -0,0 +1,180 @@
# @ConfigurationProperties 사용 기준
## 목적
외부 설정은 산발적인 문자열 주입이 아니라, **의미 있는 설정 객체**로 묶어 관리한다.
설정은 business object가 아니라 **configuration contract** 로 취급한다.
## 공식 의미
- `@ConfigurationProperties`는 externalized configuration을 타입 안전하게 바인딩하기 위한 애노테이션이다.
- 클래스 또는 `@Configuration` 안의 `@Bean` 메서드에 붙일 수 있다.
- 바인딩은 setter 또는 생성자 인자를 통해 수행될 수 있다.
- `@EnableConfigurationProperties` 또는 `@ConfigurationPropertiesScan`으로 등록할 수 있다.
- `@ConfigurationProperties``@Value`보다 relaxed binding, metadata 지원에 유리하다.
- `@ConfigurationProperties`는 SpEL을 평가하지 않는다.
- `@ConfigurationPropertiesScan``@Component`가 붙은 클래스를 스캔 대상으로 잡지 않는다.
- `@Validated`로 properties validation을 수행할 수 있다.
- `Optional``@ConfigurationProperties`에서 권장되지 않는다.
## 기본 규칙
### 1. 의미 있는 설정 그룹은 `@ConfigurationProperties` 우선
다음은 `@ConfigurationProperties`를 우선 검토한다.
- 같은 prefix 아래 여러 설정값이 함께 움직임
- 계층형/nested 설정이 있음
- 설정 검증이 중요함
- 여러 bean이 같은 설정 집합을 참조함
- 운영 문서와 IDE metadata 지원이 중요함
예:
- Vault 설정
- OAuth client 설정
- JWT 설정
- scheduler/retry 설정
- feature toggle 묶음
### 2. 단발성 한두 값만 필요하면 `@Value`를 제한적으로 허용
다음은 `@Value`를 허용할 수 있다.
- 단일 상수성 설정값
- 로컬 config class 안에서만 쓰는 매우 작은 값
- SpEL이 실제로 필요한 경우
단, 애플리케이션 자체 설정 키 집합이라면 `@ConfigurationProperties`를 우선한다.
### 3. properties class는 설정 계약만 표현
`@ConfigurationProperties` 클래스의 책임은:
- 설정값 구조 표현
- 타입 안전 바인딩
- 검증
- 합리적 기본값 표현
다음은 넣지 않는다.
- business logic
- 외부 API 호출
- repository/service 호출
- 큰 계산 로직
- runtime mutable state
### 4. prefix는 명확하고 안정적으로 설계
prefix는 기능/도메인 경계를 드러내야 한다.
좋은 방향:
- `auth.jwt`
- `auth.oauth.google`
- `vault.transit`
- `app.retry`
지양:
- `config`
- `common`
- `misc`
- 의미가 너무 넓은 prefix
### 5. 등록 방식은 스캔과 명시 등록을 구분
기본 선택:
- 애플리케이션 내부 일반 설정 타입 -> `@ConfigurationPropertiesScan`
- 조건부 등록/auto-configuration/명시적 wiring 필요 -> `@EnableConfigurationProperties` 또는 `@Bean` + `@ConfigurationProperties`
### 6. `@Component`와 `@ConfigurationProperties`를 습관적으로 같이 쓰지 않는다
properties class는 설정 바인딩 타입이지 일반 component가 아니다.
기본:
- scanning 대상 properties -> `@ConfigurationPropertiesScan`
- 명시 등록이 필요하면 `@EnableConfigurationProperties`
`@Component`를 붙여 일반 bean처럼 다루는 패턴은 지양한다.
### 7. 가능한 한 immutable 구조를 선호
설정은 보통 startup 후 바뀌지 않는 계약이다.
기본 방향:
- 생성자 기반 바인딩 또는 immutable한 구조 선호
- 변경 가능한 setter-only bag object를 기본값으로 삼지 않음
- 필수 설정은 생성 시점에 확정되게 설계
### 8. `Optional` 필드 금지
Spring Boot 공식 문서상 `Optional``@ConfigurationProperties`에서 권장되지 않는다.
기본:
- nullable field
- 기본값
- nested object
- 명시적 default object
중 하나로 표현한다.
### 9. validation은 startup에서 최대한 실패하게
설정이 잘못되면 런타임 깊은 지점에서 터지지 않게, 바인딩 시점 검증을 우선한다.
기본:
- `@Validated`
- Bean Validation annotation (`@NotNull`, `@Min`, `@Pattern` 등)
- nested properties는 필요 시 `@Valid`
### 10. 기본값 정책을 숨기지 않는다
기본값은 다음 중 하나로 명시한다.
- 필드 기본값
- 생성자 기본값
- 명시적 nested default object
- 문서화된 운영 기본값
“값이 없으면 나중에 어딘가에서 처리”를 금지한다.
### 11. Environment 직접 조회보다 properties bean 주입 우선
application/service/infrastructure 코드에서 `Environment#getProperty(...)`를 흩뿌리지 않는다.
기본:
- 관련 설정은 properties 객체로 묶고
- 필요한 bean에 주입한다
예외:
- truly dynamic property lookup
- framework/bootstrap 초기화 특수 상황
### 12. 설정 객체는 소유 모듈 가까이에 둔다
properties class는 그것을 사용하는 기능/모듈 옆에 둔다.
예:
- `vault` 설정은 vault adapter/config 근처
- `jwt` 설정은 jwt/token 모듈 근처
`CommonProperties`, `AppProperties`처럼 전역 잡동사니 설정 객체는 지양한다.
### 13. third-party bean 바인딩도 가능하지만, 범위를 제한
외부 라이브러리 객체를 `@Bean` 메서드 + `@ConfigurationProperties`로 바인딩할 수 있다.
단, 그 경우도:
- 명확한 prefix
- 명확한 config class
- 외부 라이브러리 설정 범위 제한
을 지킨다.
### 14. 설정 계약과 business meaning을 혼동하지 않는다
예:
- `token-expiration-seconds`는 설정 계약
- `TokenTtl`은 도메인 의미일 수 있다
필요하면 properties -> domain config/value object 변환 단계를 둔다.
설정 타입을 그대로 domain everywhere에 흘려보내지 않는다.
### 15. 문서와 metadata를 함께 고려
`@ConfigurationProperties`의 장점 중 하나는 metadata/IDE 지원이다.
애플리케이션이 제공하는 설정 키는:
- prefix 일관성
- 이름 일관성
- 설명/문서화
를 함께 고려한다.
## 프로젝트 기준 요약
- 의미 있는 설정 집합은 `@ConfigurationProperties` 우선
- 한두 개 단발성 값만 `@Value` 제한 허용
- properties class는 설정 계약만 표현
- `@Component`와 습관적 결합 금지
- immutable 구조 선호
- `Optional` 필드 금지
- validation은 startup에서 최대한 실패하게
- `Environment` 직접 조회보다 properties bean 주입 우선
- 설정 객체는 owning module 가까이에 둔다