# 매니페스트 쪽 TTL
  MongoIndexManifest.java:28     String partialFilterExpression,
  MongoIndexManifest.java:29     String collationProfile,
  MongoIndexManifest.java:30     Duration expireAfter,
  MongoIndexManifest.java:31     String wildcardProjection,
  MongoIndexManifest.java:32     boolean shardKeySupport,
  MongoIndexManifest.java:50     }
  MongoIndexManifest.java:51     if (keys.isEmpty()) {
  MongoIndexManifest.java:52       throw new IllegalArgumentException("index '" + name + "' declares no keys");
  MongoIndexManifest.java:53     }
  MongoIndexManifest.java:54     if (expireAfter != null && expireAfter.isNegative()) {
  MongoIndexManifest.java:55       throw new IllegalArgumentException("index '" + name + "' declares a negative TTL");
  MongoIndexManifest.java:56     }
  MongoIndexManifest.java:57     if (metadataOwnership == MongoMetadataOwnership.APPLICATION && expectedUsage.isEmpty()) {
  MongoIndexManifest.java:58       throw new IllegalArgumentException(
  MongoIndexManifest.java:66   /** Starts an index declaration. */
  MongoIndexManifest.java:67   public static Builder named(String name) {
  MongoIndexManifest.java:68     return new Builder(name);
  MongoIndexManifest.java:69   }
  MongoIndexManifest.java:70 
  MongoIndexManifest.java:71   /** The TTL, when this is a TTL index. */
  MongoIndexManifest.java:72   public Optional<Duration> ttl() {
  MongoIndexManifest.java:73     return Optional.ofNullable(expireAfter);
  MongoIndexManifest.java:74   }
  MongoIndexManifest.java:75 
  MongoIndexManifest.java:76   /** True when this index is a TTL index. */
  MongoIndexManifest.java:77   public boolean isTtlIndex() {
  MongoIndexManifest.java:78     return expireAfter != null;
  MongoIndexManifest.java:79   }
  MongoIndexManifest.java:80 
  MongoIndexManifest.java:186     }
  MongoIndexManifest.java:187 
  MongoIndexManifest.java:188     /** Declares this a TTL index with the given retention. */
  MongoIndexManifest.java:189     public Builder expireAfter(Duration retention) {
  MongoIndexManifest.java:190       this.expireAfter = Objects.requireNonNull(retention, "retention");
  MongoIndexManifest.java:191       return this;
  MongoIndexManifest.java:192     }
  MongoIndexManifest.java:193 
  MongoIndexManifest.java:194     /** Declares a wildcard projection, as canonical extended JSON. */
  expireAfter 라는 이름이 그 파일에 나오는 줄 : 8 개
  그중 값을 거절하는 줄 : 1 개

# 규칙을 가진 쪽
  MongoTtlPolicyValidator.java:7 /**
  MongoTtlPolicyValidator.java:8  * Rejects the two ways a TTL index is misused (design §21.1, D-13).
  MongoTtlPolicyValidator.java:9  *
  MongoTtlPolicyValidator.java:10  * <p>The first is treating it as a scheduler: the TTL monitor's sweep interval is unspecified and
  MongoTtlPolicyValidator.java:11  * load-dependent, so "delete this at 09:00" is not something it promises. The second is relying on
  MongoTtlPolicyValidator.java:12  * it for access control: a document that still exists is still readable, so if expiry must hide
  MongoTtlPolicyValidator.java:13  * data the read has to say so.
  MongoTtlPolicyValidator.java:14  */
  MongoTtlPolicyValidator.java:15 public final class MongoTtlPolicyValidator {
  MongoTtlPolicyValidator.java:16 
  MongoTtlPolicyValidator.java:17   /**
  MongoTtlPolicyValidator.java:18    * A TTL reduction below this threshold would expire a large population in one sweep, turning a
  MongoTtlPolicyValidator.java:19    * configuration change into an unplanned bulk delete.
  MongoTtlPolicyValidator.java:20    */
  MongoTtlPolicyValidator.java:21   public static final Duration MINIMUM_SAFE_RETENTION = Duration.ofMinutes(1);
  MongoTtlPolicyValidator.java:22 
  MongoTtlPolicyValidator.java:23   /**
  MongoTtlPolicyValidator.java:24    * Validates one TTL policy.
  MongoTtlPolicyValidator.java:25    *
  MongoTtlPolicyValidator.java:26    * @throws MongoOperationRejectedException when the policy claims a guarantee TTL does not provide
  MongoTtlPolicyValidator.java:27    */
  MongoTtlPolicyValidator.java:28   public void validate(MongoTtlPolicy policy) {
  MongoTtlPolicyValidator.java:29     Objects.requireNonNull(policy, "policy");
  MongoTtlPolicyValidator.java:30     if (policy.claimsExactExpiry()) {
  MongoTtlPolicyValidator.java:31       throw MongoOperationRejectedException.of(
  MongoTtlPolicyValidator.java:32           "ttl.policy",
  MongoTtlPolicyValidator.java:33           "the TTL policy on '"
  MongoTtlPolicyValidator.java:34               + policy.field()
  MongoTtlPolicyValidator.java:35               + "' claims an exact business transition; MongoDB's TTL monitor sweeps on an "
  MongoTtlPolicyValidator.java:36               + "unspecified interval, so an exact transition needs its own scheduler and the TTL "
  MongoTtlPolicyValidator.java:37               + "index stays physical cleanup");
  MongoTtlPolicyValidator.java:38     }
  MongoTtlPolicyValidator.java:39     if (!policy.queryChecksLogicalExpiry()) {
  MongoTtlPolicyValidator.java:40       throw MongoOperationRejectedException.of(
  MongoTtlPolicyValidator.java:41           "ttl.policy",
  MongoTtlPolicyValidator.java:42           "the TTL policy on '"
  MongoTtlPolicyValidator.java:43               + policy.field()
  MongoTtlPolicyValidator.java:44               + "' does not declare a query-time expiry check; an expired document remains readable "
  MongoTtlPolicyValidator.java:45               + "until the monitor deletes it, so reads must filter on "
  MongoTtlPolicyValidator.java:46               + policy.field()
  MongoTtlPolicyValidator.java:47               + " > applicationNow");
  MongoTtlPolicyValidator.java:48     }
  MongoTtlPolicyValidator.java:49     if (!policy.retention().isZero() && policy.retention().compareTo(MINIMUM_SAFE_RETENTION) < 0) {
  MongoTtlPolicyValidator.java:50       throw MongoOperationRejectedException.of(
  MongoTtlPolicyValidator.java:51           "ttl.policy",
  MongoTtlPolicyValidator.java:52           "a TTL retention of "
  MongoTtlPolicyValidator.java:53               + policy.retention()
  MongoTtlPolicyValidator.java:54               + " is below the safe minimum of "
  MongoTtlPolicyValidator.java:55               + MINIMUM_SAFE_RETENTION
  MongoTtlPolicyValidator.java:56               + "; it would expire the existing population in a single sweep");
  MongoTtlPolicyValidator.java:57     }
  MongoTtlPolicyValidator.java:58   }
  MongoTtlPolicyValidator.java:59 
  MongoTtlPolicyValidator.java:60   /**
  MongoTtlPolicyValidator.java:61    * Validates a TTL index descriptor, including the BSON type of its expiry field.
  MongoTtlPolicyValidator.java:62    *
  MongoTtlPolicyValidator.java:63    * @throws MongoOperationRejectedException when the field type cannot be expired
  MongoTtlPolicyValidator.java:64    */
  MongoTtlPolicyValidator.java:65   public void validate(MongoTtlIndexDescriptor descriptor) {
  MongoTtlPolicyValidator.java:66     Objects.requireNonNull(descriptor, "descriptor");
  MongoTtlPolicyValidator.java:67     validate(descriptor.policy());
  MongoTtlPolicyValidator.java:68     if (!descriptor.expiryFieldTypeIsSupported()) {
  MongoTtlPolicyValidator.java:69       throw MongoOperationRejectedException.of(
  MongoTtlPolicyValidator.java:70           "ttl.policy",
  MongoTtlPolicyValidator.java:71           "TTL index '"
  MongoTtlPolicyValidator.java:72               + descriptor.indexName()
  MongoTtlPolicyValidator.java:73               + "' expires on a field stored as "
  MongoTtlPolicyValidator.java:74               + descriptor.expiryFieldBsonType()
  MongoTtlPolicyValidator.java:75               + "; MongoDB only expires BSON date fields and ignores the rest silently");
  MongoTtlPolicyValidator.java:76     }
  MongoTtlPolicyValidator.java:77   }
  MongoTtlPolicyValidator.java:78 
  MongoTtlPolicyValidator.java:79   /**
  MongoTtlPolicyValidator.java:80    * Validates the read-side predicate that gives expiry its actual guarantee.
  MongoTtlPolicyValidator.java:81    *
  MongoTtlPolicyValidator.java:82    * @throws MongoOperationRejectedException when reads do not filter on logical expiry
  MongoTtlPolicyValidator.java:83    */
  MongoTtlPolicyValidator.java:84   public void validate(MongoExpirationAccessPolicy accessPolicy) {
  MongoTtlPolicyValidator.java:85     Objects.requireNonNull(accessPolicy, "accessPolicy");
  MongoTtlPolicyValidator.java:86     if (!accessPolicy.applied()) {
  MongoTtlPolicyValidator.java:87       throw MongoOperationRejectedException.of(
  MongoTtlPolicyValidator.java:88           "ttl.access",
  MongoTtlPolicyValidator.java:89           "reads of this collection do not apply '"
  MongoTtlPolicyValidator.java:90               + accessPolicy.describePredicate()
  MongoTtlPolicyValidator.java:91               + "', so an expired document stays visible until the TTL monitor happens to delete it");
  MongoTtlPolicyValidator.java:92     }
  MongoTtlPolicyValidator.java:93   }
  MongoTtlPolicyValidator.java:94 }

# 그 정책 타입이 요구하는 것
  MongoTtlPolicy.java:1 package dev.caskeleton.adapter.outbound.mongo.schema.ttl;
  MongoTtlPolicy.java:2 
  MongoTtlPolicy.java:3 import java.time.Duration;
  MongoTtlPolicy.java:4 import java.util.Objects;
  MongoTtlPolicy.java:5 
  MongoTtlPolicy.java:6 /**
  MongoTtlPolicy.java:7  * What a TTL index is being used for (design §21.1, D-13).
  MongoTtlPolicy.java:8  *
  MongoTtlPolicy.java:9  * <p>MongoDB's TTL monitor runs roughly once a minute and deletes in batches, so an expired
  MongoTtlPolicy.java:10  * document stays readable for an unspecified interval after its expiry — longer under load, longer
  MongoTtlPolicy.java:11  * still on a busy secondary. That is fine for reclaiming space and wrong for anything that must
  MongoTtlPolicy.java:12  * stop being visible at a particular moment.
  MongoTtlPolicy.java:13  *
  MongoTtlPolicy.java:14  * <p>Both booleans are therefore part of the declaration. {@code physicalCleanupOnly} says the TTL
  MongoTtlPolicy.java:15  * is only reclaiming space; {@code queryChecksLogicalExpiry} says the application filters on {@code
  MongoTtlPolicy.java:16  * expiresAt > now} so visibility does not depend on the monitor's timing.
  MongoTtlPolicy.java:17  */
  MongoTtlPolicy.java:18 public record MongoTtlPolicy(
  MongoTtlPolicy.java:19     String field,
  MongoTtlPolicy.java:20     Duration retention,
  MongoTtlPolicy.java:21     boolean physicalCleanupOnly,
  MongoTtlPolicy.java:22     boolean queryChecksLogicalExpiry) {
  MongoTtlPolicy.java:23 
  MongoTtlPolicy.java:24   public MongoTtlPolicy {
  MongoTtlPolicy.java:25     Objects.requireNonNull(field, "field");
  MongoTtlPolicy.java:26     Objects.requireNonNull(retention, "retention");
  MongoTtlPolicy.java:27     if (field.isBlank()) {
  MongoTtlPolicy.java:28       throw new IllegalArgumentException("a TTL policy needs an expiry field");
  MongoTtlPolicy.java:29     }
  MongoTtlPolicy.java:30     if (retention.isNegative()) {
  MongoTtlPolicy.java:31       throw new IllegalArgumentException("a TTL retention must not be negative");
  MongoTtlPolicy.java:32     }
  MongoTtlPolicy.java:33   }
  MongoTtlPolicy.java:34 
  MongoTtlPolicy.java:35   /** The supported shape: physical cleanup, with the application filtering on logical expiry. */
  MongoTtlPolicy.java:36   public static MongoTtlPolicy physicalCleanup(String field, Duration retention) {
  MongoTtlPolicy.java:37     return new MongoTtlPolicy(field, retention, true, true);
  MongoTtlPolicy.java:38   }
  MongoTtlPolicy.java:39 
  MongoTtlPolicy.java:40   /**

# 두 표현 사이에 참조가 있는가
  schema/ttl 밖 main 에서 그 네 타입을 언급하는 줄 : 0 개
  [대조] schema/ttl 안에서는 : 22 개
  MongoIndexManifest 가 그 네 타입을 언급하는 줄 : 0 개
  isTtlIndex() 나 ttl() 을 부르는 줄 : 0 개
  [대조] 그 두 이름이 나오는 줄 (선언 포함) : 2 개

# 두 표현을 조립하는 main 코드가 있는가
  MongoIndexManifest 를 만드는 main 줄 : 1 개
    MongoIndexManifest.java:226  return new MongoIndexManifest(
  [대조] 시험에서 만드는 줄 : 7 개
  MongoTtlPolicyValidator 를 만드는 main 줄 : 0 개
  [대조] 시험에서 검증기를 만드는 줄 : 1 개
