182 lines
23 KiB
Markdown
182 lines
23 KiB
Markdown
# app.redis.enabled에서 capability bean까지: Spring 조립 코드 읽기
|
|
|
|
> **Redis 코드 상세 시리즈 03/20** · [전체 지도](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-backend-policy-boundary.md) · 이전: [Redis 모듈 해부: Gradle leaf에서 app-bootstrap까지](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-module-package-boundaries.md) · 다음: [Redis 설정은 어떻게 실패하는가: 바인딩·검증·Secret·Credential 추적](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-settings-secrets-credentials.md)
|
|
|
|
## 이 글이 답하는 코드 질문
|
|
|
|
`app.redis.enabled=true`는 Redis 기능 전체를 켜는 selector가 아닙니다. 이 값은 공통 SDK runtime을 만들 권한이고, cache·rate-limit·lease·idempotency·session은 각자의 selector를 가집니다. 이 글은 Spring context refresh 동안 어떤 조건과 method가 어떤 bean을 만드는지, 그리고 현재 5개 semantic role 중 왜 4개만 production 조립되는지를 추적합니다.
|
|
|
|
## 코드 지도
|
|
|
|
| 클래스·리소스 | 입력 | 출력 | 다음 호출 |
|
|
|---|---|---|---|
|
|
| [`AutoConfiguration.imports`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:1) | classpath | `RedisSdkAutoConfiguration` 등록 | global switch 조건 |
|
|
| [`RedisSdkAutoConfiguration`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:32) | `app.redis.*`, secret source, resource loader | settings, credentials, client, owner, health beans | topology factory |
|
|
| [`RedisCapabilityConfig`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:35) | owner, settings, capability selector/settings | 4종 semantic port와 V2 executor | request-time adapter |
|
|
| [`RedisCapabilitySettings`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilitySettings.java:9) | `ca-skeleton.capabilities.*` | cache/rate-limit/lease/idempotency 세부 설정 | 각 bean factory method |
|
|
| [`RedisActivationValidator`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/RedisActivationValidator.java:11) | global switch와 5개 role selector | 정상 종료 또는 startup failure | 없음 |
|
|
| [`SecretSourceConfig`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/SecretSourceConfig.java:8) | secret source strategy, environment | `SecretSource`, 두 startup validator | Redis secret bridge |
|
|
|
|
## 객체 생성 시점: 두 composition root
|
|
|
|
SDK 쪽 auto-configuration은 [`@ConditionalOnProperty`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:53)로 `app.redis.enabled=true`를 요구합니다. 값이 `false`이거나 property가 없으면 이 클래스가 제공하는 bean은 만들어지지 않습니다.
|
|
|
|
bootstrap 쪽 [`RedisCapabilityConfig`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:54)도 같은 global condition을 사용합니다. 두 class의 책임은 다릅니다.
|
|
|
|
- `RedisSdkAutoConfiguration`: provider 공통 runtime을 만듭니다.
|
|
- `RedisCapabilityConfig`: deployment가 선택한 provider-neutral semantic port를 그 runtime 위에 만듭니다.
|
|
|
|
이 분리는 `Redis on`과 `Redis가 어떤 역할을 맡음`을 같은 뜻으로 만들지 않습니다. global switch만 켜고 role을 하나도 고르지 않으면 client와 owner는 있지만 semantic port는 없습니다. [`noRoleComposesNoPort()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:53)가 이 상태를 고정합니다.
|
|
|
|
## context refresh 호출 순서
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant E as Environment
|
|
participant S as RedisSdkAutoConfiguration
|
|
participant V as Settings validation
|
|
participant F as TopologyClientFactory
|
|
participant O as RedisRuntimeOwner
|
|
participant C as RedisCapabilityConfig
|
|
participant A as RedisActivationValidator
|
|
E->>S: app.redis.enabled 평가
|
|
S->>V: bind RedisSdkSettings 후 validate
|
|
V->>S: warnings 또는 예외
|
|
S->>S: credential reference resolve
|
|
S->>F: validated settings + credentials
|
|
F-->>S: RedisRuntimeClient
|
|
S->>O: lane limit + drain timeout
|
|
C->>C: role selector별 semantic bean 생성
|
|
A->>E: off + Redis role 모순 검사
|
|
A-->>E: 정상 또는 모든 모순을 묶은 startup failure
|
|
```
|
|
|
|
세부 순서는 bean dependency로 고정됩니다.
|
|
|
|
1. [`redisSdkSettings()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:83)가 mutable settings 객체를 만들고 `@ConfigurationProperties(prefix="app.redis")`로 binding합니다.
|
|
2. [`redisSdkSettingsValidation()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:101)이 `validate()`와 raw allowlist resource 검사를 실행합니다.
|
|
3. [`redisResolvedCredentials()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:156)는 validation bean에 의존하므로 검증 뒤 reference를 해석합니다.
|
|
4. [`redisRuntimeClient()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:226)가 topology factory를 호출합니다. client object와 event-loop resource는 이때 생기지만 lane connection은 아직 열리지 않습니다.
|
|
5. [`redisRuntimeOwner()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:273)가 여섯 lane의 ceiling과 drain timeout을 받습니다.
|
|
6. `RedisCapabilityConfig`의 조건이 맞는 factory method만 semantic bean을 만듭니다.
|
|
|
|
실제 Redis TCP connection은 request-time에 owner가 처음 `borrow()`할 때 `RedisRuntimeClient.openLane()`을 호출하며 lazy하게 열립니다. 따라서 bean graph가 성공했다는 사실만으로 endpoint 접속과 인증 성공을 증명하지 않습니다.
|
|
|
|
### context close에는 두 client shutdown 경로가 겹칩니다
|
|
|
|
생성 dependency 때문에 context 종료 시 [`redisRuntimeOwner()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:273)이 client bean보다 먼저 destroy됩니다. owner의 explicit [`close()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisRuntimeOwner.java:197)는 lane을 drain한 뒤 내부에서 runtime client를 닫습니다. 그러나 [`redisRuntimeClient()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:226)는 destroy inference를 끄지 않은 일반 `@Bean`입니다. 반환 type인 [`RedisRuntimeClient`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisRuntimeClient.java:19)는 `AutoCloseable`을 확장하고 public no-arg `close()`를 노출합니다. Spring이 다음으로 client bean의 inferred destroy를 실행하면 같은 client의 `close()`가 다시 호출될 수 있습니다.
|
|
|
|
따라서 auto-configuration 주석의 “owner before client”는 종료 순서를 설명하지만 client shutdown authority가 owner 하나뿐임을 보장하지는 않습니다. owner state가 `CLOSED`인지 확인하는 context test와 종료 후 Lettuce thread가 남지 않는 live test는 있지만, runtime client close 횟수를 세는 context-level test는 없습니다.
|
|
|
|
## SecretSource bridge가 필요한 이유
|
|
|
|
SDK는 [`RedisSecretSource`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:373)라는 작은 interface만 압니다. bean이 없으면 process environment를 직접 읽는 fallback을 씁니다.
|
|
|
|
애플리케이션은 별도의 [`SecretSource`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/SecretSource.java:1)를 composition root에서 선택합니다. [`redisSdkSecretSource()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:73)는 이를 method reference로 SDK에 연결합니다. 이 bridge가 없으면 향후 secret manager backend를 선택해도 Redis만 process environment를 직접 읽게 됩니다.
|
|
|
|
## 4/5 semantic composition
|
|
|
|
현재 `RedisCapabilityConfig`가 production bean으로 만드는 역할은 네 가지입니다.
|
|
|
|
### Cache
|
|
|
|
`ca-skeleton.capabilities.cache.bindings.default=redis`이면 [`redisDefaultCacheRegion()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:95)이 실행됩니다. method는 cache TTL을 검증하고, key HMAC secret을 해석한 뒤 `RedisCacheRegionAdapter<String, byte[]>`를 `CacheRegionPort`로 반환합니다.
|
|
|
|
정상 출력은 cache port 하나입니다. soft TTL이 hard TTL보다 크거나 hard TTL이 floor보다 작거나 command timeout/key version이 유효하지 않으면 bean creation이 실패합니다. HMAC secret reference가 없거나 secret을 찾지 못해도 startup failure입니다.
|
|
|
|
### Rate limit
|
|
|
|
`ca-skeleton.capabilities.rate-limit.provider=redis`이면 [`redisEdgeRateLimitPort()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:131)가 `RedisEdgeRateLimitAdapter`를 만듭니다.
|
|
|
|
`policiesOf()`는 policy가 하나도 없으면 실패하고, `defaultPolicyId`가 map에 없으면 실패합니다. algorithm은 `fixed-window`, `sliding-counter`, `token-bucket`만 받습니다. failure policy는 현재 `fail-closed`만 지원하며 다른 값은 [`policyOf()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:174)에서 거부합니다.
|
|
|
|
### Lease
|
|
|
|
`ca-skeleton.capabilities.lease.provider=redis`이면 [`redisDistributedLeasePort()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:227)가 `RedisDistributedLeaseAdapter`를 반환합니다. 이 port는 efficiency용 lease이며 fencing을 제공하지 않습니다. 조립 성공을 distributed lock correctness로 확대하면 안 됩니다.
|
|
|
|
### Idempotency V2
|
|
|
|
`ca-skeleton.capabilities.idempotency.provider=redis`이면 [`redisIdempotencyStore()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:255)가 owner-safe `IdempotencyStorePortV2`를 만듭니다. 이어 [`idempotencyExecutorV2()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:286)가 같은 selector 아래 provider-neutral V2 executor를 만듭니다.
|
|
|
|
### Session 공백
|
|
|
|
다섯 번째 selector `ca-skeleton.security.auth-mode=redis-session`은 activation validator와 correctness health predicate에는 들어 있습니다. 그러나 `RedisCapabilityConfig`에는 session repository를 만드는 method가 없습니다. production source에는 snapshot이 없는 요청에서 인증된 `Authentication` 객체를 최초로 만드는 form login, HTTP Basic, custom authentication filter나 login endpoint도 확인되지 않습니다. 즉 Redis session을 선택하면 global runtime 조건과 readiness 조건에는 반영되지만 `SessionRepository`와 `springSessionRepositoryFilter`로 이어지는 persistence 경로와 최초 인증 경로는 완성되지 않습니다. 이것이 4/5 composition입니다.
|
|
|
|
## selector와 global switch의 모순 처리
|
|
|
|
[`RedisActivationValidator.REDIS_SELECTING_VALUES`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/RedisActivationValidator.java:26)는 다음 다섯 selector를 압니다.
|
|
|
|
| 역할 | Redis를 선택하는 값 |
|
|
|---|---|
|
|
| default cache binding | `redis` |
|
|
| rate limit provider | `redis` |
|
|
| idempotency provider | `redis` |
|
|
| lease provider | `redis` |
|
|
| auth mode | `redis-session` |
|
|
|
|
global switch가 true이면 validator는 즉시 끝납니다. false이면 selector를 모두 검사해 모순을 정렬하고 하나의 `requiredAdapterDisabled` startup failure로 묶습니다. 첫 번째 missing bean에서 멈추는 대신 잘못된 설정을 한 번에 보여 줍니다. [`afterSingletonsInstantiated()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/RedisActivationValidator.java:41)가 이 동작을 구현합니다.
|
|
|
|
중요한 순서상의 특성이 있습니다. `RedisCapabilityConfig` 자체는 switch-off일 때 존재하지 않으므로 semantic bean을 만들지 않습니다. validator는 별도 `SecretSourceConfig`에서 unconditional bean으로 생성되어 모순을 설명합니다. [`SecretSourceConfig.redisActivationValidator()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/SecretSourceConfig.java:27)를 보면 이 연결이 보입니다.
|
|
|
|
## 정상·거절·timeout 분기
|
|
|
|
### 정상
|
|
|
|
- switch off + Redis role 없음: Redis settings도 bean도 만들지 않고 시작합니다.
|
|
- switch on + role 없음: validated runtime과 optional health contributor만 만듭니다.
|
|
- switch on + 1개 이상 role: 공통 owner 위에 선택된 semantic bean만 만듭니다.
|
|
- switch on + 4개 구현 role: cache, rate-limit, lease, idempotency V2가 동시에 한 namespace를 씁니다.
|
|
|
|
### startup 거절
|
|
|
|
- switch off + Redis role: activation validator가 설정 모순으로 거절합니다.
|
|
- switch on + invalid settings/credential/resource/topology: SDK bean dependency chain에서 거절합니다.
|
|
- rate-limit 선택 + policy 없음/unknown default/unsupported algorithm: rate-limit bean creation에서 거절합니다.
|
|
- cache 선택 + TTL/HMAC 설정 오류: cache bean creation에서 거절합니다.
|
|
|
|
### request-time timeout과 unavailable
|
|
|
|
조립 class는 command를 전송하지 않습니다. request-time timeout, ambiguous execution, typed unavailable은 semantic adapter와 command executor의 책임입니다. 다만 connection은 lazy하므로 잘못된 endpoint나 password가 context refresh 뒤 첫 borrow/command에서 드러날 수 있습니다. production startup probe가 조립되지 않은 현재 상태에서는 이 차이가 남습니다.
|
|
|
|
## 테스트가 고정하는 계약
|
|
|
|
[`RedisSdkAutoConfigurationTest`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfigurationTest.java:49)는 absent/off switch에서 settings조차 없고 malformed Redis property도 무시되는 것을 고정합니다. on 상태에서는 settings binding, credential role별 resolution, topology mode, owner lifecycle, raw/admin fail-fast를 확인합니다. [`theRuntimeOwnerFollowsTheContext()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfigurationTest.java:418)는 종료 뒤 owner state만 확인하므로 client의 exactly-once close를 고정하지 않습니다.
|
|
|
|
[`RedisCapabilityCompositionTest`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:21)는 server 없이 bean graph만 검사합니다.
|
|
|
|
- [`cacheBindingComposesTheCacheRegion()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:67): cache만 선택하면 다른 port가 생기지 않습니다.
|
|
- [`rateLimitProviderComposesThePort()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:81): web bridge가 요구하는 rate-limit port가 생깁니다.
|
|
- [`aRateLimiterWithoutPoliciesIsRefused()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:93): 빈 policy 설정은 startup failure입니다.
|
|
- [`allRolesComposeTogether()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:138): 구현된 네 port가 동시에 생깁니다.
|
|
- [`theSwitchOffComposesNothing()`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:157): role property가 있어도 configuration은 아무 bean도 만들지 않습니다.
|
|
|
|
[`RedisActivationValidatorTest`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/runtime/RedisActivationValidatorTest.java:26)는 다섯 role 각각과 다중 모순 보고를 고정합니다.
|
|
|
|
real-server 행동은 [`LiveRedisCompositionTest`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/LiveRedisCompositionTest.java:21)에 있지만 기본 test에서 제외되는 opt-in topology lane입니다. 이번 작성에서는 실행하지 않았습니다.
|
|
|
|
## 현재 구현 공백과 잘못 읽기 쉬운 지점
|
|
|
|
- `app.redis.enabled=true`는 semantic capability가 존재한다는 뜻이 아닙니다. selector와 bean을 따로 확인해야 합니다.
|
|
- session selector는 validator와 readiness에는 포함되지만 session repository production bean과 인증된 `Authentication` 객체를 최초로 만드는 production mechanism은 없습니다. 두 공백을 모두 해결하고 end-to-end 인증·session persistence를 검증해야 합니다.
|
|
- aggregate `RedisOperations`와 `ReactiveRedisOperations` facade, command guard/executor/translator의 production DI도 확인되지 않습니다. semantic adapter는 `RedisRuntimeOwner`와 직접 조립됩니다.
|
|
- `RedisStartupProbe`/`RedisCapabilityProbe`는 production bean과 server-fact collector가 없습니다. context refresh 성공은 endpoint reachability나 server capability 확인이 아닙니다.
|
|
- owner destroy가 runtime client를 닫은 뒤 client bean의 inferred destroy가 같은 `close()`를 다시 부를 수 있습니다. lifecycle authority와 exactly-once 보장이 production bean graph와 context test에서 명확하지 않습니다.
|
|
- capability settings의 validation은 한 곳에서 일괄 실행되지 않습니다. 예를 들어 cache validation은 cache bean factory가 호출될 때 실행되고, rate-limit은 `policiesOf()`에서 검증됩니다.
|
|
- idempotency는 V2 store와 executor가 조립되지만 기존 V1 inbound bridge가 자동으로 V2를 쓰는지는 별도 문제입니다.
|
|
|
|
## 다음에 열어볼 source와 관련 글
|
|
|
|
1. [`RedisSdkAutoConfiguration`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/config/RedisSdkAutoConfiguration.java:53)
|
|
2. [`RedisCapabilityConfig`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/redis/RedisCapabilityConfig.java:54)
|
|
3. [`RedisActivationValidator`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/RedisActivationValidator.java:24)
|
|
4. [`RedisCapabilityCompositionTest`](/home/donghyeon/workspace/desktop-server-git/clean-architecture-backend-template/src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/redis/RedisCapabilityCompositionTest.java:33)
|
|
|
|
이어지는 시리즈 주제는 설정·Secret·Credential, topology factory, connection lane lifecycle, health/readiness, semantic capability별 request 흐름입니다.
|
|
|
|
## 시리즈에서 이어 읽기
|
|
|
|
- 이전 글: [Redis 모듈 해부: Gradle leaf에서 app-bootstrap까지](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-module-package-boundaries.md)
|
|
- 다음 글: [Redis 설정은 어떻게 실패하는가: 바인딩·검증·Secret·Credential 추적](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-settings-secrets-credentials.md)
|
|
- 전체 흐름: [Redis를 범용 클라이언트가 아니라 정책 경계로 다루기](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-backend-policy-boundary.md)
|
|
- 운영 흐름: [Redis를 켠다는 말의 운영적 의미: 단일 활성화 스위치에서 Sentinel 쓰기 손실 검증까지](/home/donghyeon/workspace/ai-tool/document-haness/.run/redis/redis-platform-sre-operations.md)
|