# 샤딩 게이트웨이의 네 작업
  MongoShardingAdminGateway.java:33   /**
  MongoShardingAdminGateway.java:34    * Enables sharding on a collection.
  MongoShardingAdminGateway.java:35    *
  MongoShardingAdminGateway.java:36    * @throws MongoOperationRejectedException when the key was not approved or its index is missing
  MongoShardingAdminGateway.java:37    */
  MongoShardingAdminGateway.java:38   public void shardCollection(
  MongoShardingAdminGateway.java:39       String collection,
  MongoShardingAdminGateway.java:40       ShardKeyDescriptor shardKey,
  MongoShardingAdminGateway.java:41       ShardKeyReadinessReport readiness,
  MongoShardingAdminGateway.java:42       List<String> supportingIndexFields,
  MongoShardingAdminGateway.java:43       String operator,
  MongoShardingAdminGateway.java:44       String reason,
  MongoShardingAdminGateway.java:45       Supplier<Void> apply) {
  MongoShardingAdminGateway.java:46     Objects.requireNonNull(collection, "collection");
  MongoShardingAdminGateway.java:47     Objects.requireNonNull(shardKey, "shardKey");
  MongoShardingAdminGateway.java:48     Objects.requireNonNull(readiness, "readiness");
  MongoShardingAdminGateway.java:49     if (!readiness.approved()) {
  MongoShardingAdminGateway.java:50       throw MongoOperationRejectedException.of(
  MongoShardingAdminGateway.java:51           "sharding.shard-collection",
  MongoShardingAdminGateway.java:52           "the shard key for '" + collection + "' was not approved: " + readiness.reasons());
  MongoShardingAdminGateway.java:53     }
  MongoShardingAdminGateway.java:54     if (!supportingIndexFields
  MongoShardingAdminGateway.java:55         .subList(0, Math.min(shardKey.fields().size(), supportingIndexFields.size()))
  MongoShardingAdminGateway.java:56         .equals(shardKey.fields())) {
  MongoShardingAdminGateway.java:57       throw MongoOperationRejectedException.of(
  MongoShardingAdminGateway.java:58           "sharding.shard-collection",
  MongoShardingAdminGateway.java:59           "sharding '"
  MongoShardingAdminGateway.java:60               + collection
  MongoShardingAdminGateway.java:61               + "' needs a supporting index prefixed by the shard key "
  MongoShardingAdminGateway.java:62               + shardKey.fields());
  MongoShardingAdminGateway.java:63     }
  MongoShardingAdminGateway.java:64     adminGateway.execute(MongoAdminOperation.SHARD_COLLECTION, collection, operator, reason, apply);
  MongoShardingAdminGateway.java:65   }
  MongoShardingAdminGateway.java:66 
  MongoShardingAdminGateway.java:67   /** Adds a field to an existing shard key. Requires the same evidence as a reshard. */
  MongoShardingAdminGateway.java:68   public void refineShardKey(
  MongoShardingAdminGateway.java:69       String collection,
  MongoShardingAdminGateway.java:70       ReshardApproval approval,
  MongoShardingAdminGateway.java:71       String operator,
  MongoShardingAdminGateway.java:72       String reason,
  MongoShardingAdminGateway.java:73       Supplier<Void> apply) {
  MongoShardingAdminGateway.java:74     Objects.requireNonNull(approval, "approval").require();
  MongoShardingAdminGateway.java:75     adminGateway.execute(MongoAdminOperation.REFINE_SHARD_KEY, collection, operator, reason, apply);
  MongoShardingAdminGateway.java:76   }
  MongoShardingAdminGateway.java:77 
  MongoShardingAdminGateway.java:78   /** Changes a collection's shard key, rewriting the whole collection. */
  MongoShardingAdminGateway.java:79   public void reshardCollection(
  MongoShardingAdminGateway.java:80       String collection,
  MongoShardingAdminGateway.java:81       ReshardApproval approval,
  MongoShardingAdminGateway.java:82       String operator,
  MongoShardingAdminGateway.java:83       String reason,
  MongoShardingAdminGateway.java:84       Supplier<Void> apply) {
  MongoShardingAdminGateway.java:85     Objects.requireNonNull(approval, "approval").require();
  MongoShardingAdminGateway.java:86     adminGateway.execute(
  MongoShardingAdminGateway.java:87         MongoAdminOperation.RESHARD_COLLECTION, collection, operator, reason, apply);
  MongoShardingAdminGateway.java:88   }
  MongoShardingAdminGateway.java:89 
  MongoShardingAdminGateway.java:90   /** Starts or stops the balancer. */
  MongoShardingAdminGateway.java:91   public void controlBalancer(String scope, String operator, String reason, Supplier<Void> apply) {
  MongoShardingAdminGateway.java:92     adminGateway.execute(MongoAdminOperation.BALANCER_CONTROL, scope, operator, reason, apply);
  MongoShardingAdminGateway.java:93   }
  네 메서드가 부르는 것 : 4 개

# 그 다섯 인자 오버로드가 하는 일
  MongoAdminGateway.java:40     this.guard = Objects.requireNonNull(guard, "guard");
  MongoAdminGateway.java:41     this.authorization = Objects.requireNonNull(authorization, "authorization");
  MongoAdminGateway.java:42     this.auditSink = Objects.requireNonNull(auditSink, "auditSink");
  MongoAdminGateway.java:43     this.clock = Objects.requireNonNull(clock, "clock");
  MongoAdminGateway.java:44     guard.validate();
  MongoAdminGateway.java:45   }
  MongoAdminGateway.java:46 
  MongoAdminGateway.java:47   /**
  MongoAdminGateway.java:48    * Runs one administrative operation.
  MongoAdminGateway.java:49    *
  MongoAdminGateway.java:50    * @param operation what is being done
  MongoAdminGateway.java:51    * @param target the collection, index or database it is being done to
  MongoAdminGateway.java:52    * @param operator who is running it
  MongoAdminGateway.java:53    * @param reason why
  MongoAdminGateway.java:54    * @param body the work
  MongoAdminGateway.java:55    * @throws MongoOperationRejectedException when the operation is not authorized
  MongoAdminGateway.java:56    */
  MongoAdminGateway.java:57   public <T> T execute(
  MongoAdminGateway.java:58       MongoAdminOperation operation,
  MongoAdminGateway.java:59       String target,
  MongoAdminGateway.java:60       String operator,
  MongoAdminGateway.java:61       String reason,
  MongoAdminGateway.java:62       Supplier<T> body) {
  MongoAdminGateway.java:63     return execute(
  MongoAdminGateway.java:64         MongoAdminCommand.routine(
  MongoAdminGateway.java:65             operation, target, operator, reason, clock.instant().plus(COMMAND_VALIDITY)),
  MongoAdminGateway.java:66         null,
  MongoAdminGateway.java:67         body);
  MongoAdminGateway.java:68   }

# 실행 경로가 승인을 요구하는 자리
  MongoAdminGateway.java:69 
  MongoAdminGateway.java:70   /**
  MongoAdminGateway.java:71    * Runs one administrative command under the audit state machine.
  MongoAdminGateway.java:72    *
  MongoAdminGateway.java:73    * <p>Three things changed from the single-record version. The intent is recorded before the
  MongoAdminGateway.java:74    * command runs and claims nothing; a terminal record follows, saying what actually happened; and
  MongoAdminGateway.java:75    * an audit sink that fails stops the command, because an unauditable administrative operation is
  MongoAdminGateway.java:76    * one nobody can reconstruct afterwards — which for a drop or a reshard is the whole point of
  MongoAdminGateway.java:77    * having the plane at all.
  MongoAdminGateway.java:78    *
  MongoAdminGateway.java:79    * @param approval required for a high-risk operation and bound to this exact command
  MongoAdminGateway.java:80    * @throws MongoOperationRejectedException when authorization, approval, expiry or the audit sink
  MongoAdminGateway.java:81    *     refuses
  MongoAdminGateway.java:82    */
  MongoAdminGateway.java:83   public <T> T execute(MongoAdminCommand command, MongoAdminApproval approval, Supplier<T> body) {
  MongoAdminGateway.java:84     Objects.requireNonNull(command, "command");
  MongoAdminGateway.java:85     Objects.requireNonNull(body, "body");
  MongoAdminGateway.java:86     Instant now = clock.instant();
  MongoAdminGateway.java:87     authorization.require(command.operation());
  MongoAdminGateway.java:88     if (command.expiredAt(now)) {
  MongoAdminGateway.java:89       throw MongoOperationRejectedException.of(
  MongoAdminGateway.java:90           "admin.command",
  MongoAdminGateway.java:91           "this admin command expired before it ran; a stale command may describe a cluster that no"
  MongoAdminGateway.java:92               + " longer looks like the one it was written for");
  MongoAdminGateway.java:93     }
  MongoAdminGateway.java:94     if (command.operation().highRisk()) {
  MongoAdminGateway.java:95       if (approval == null) {
  MongoAdminGateway.java:96         throw MongoOperationRejectedException.of(
  MongoAdminGateway.java:97             "admin.approval",
  MongoAdminGateway.java:98             "admin operation "
  MongoAdminGateway.java:99                 + command.operation()
  MongoAdminGateway.java:100                 + " destroys data or rewrites a collection; it runs under an approval bound to this"
  MongoAdminGateway.java:101                 + " exact command or not at all");
  MongoAdminGateway.java:102       }
  MongoAdminGateway.java:103       approval.require(command, now);
  MongoAdminGateway.java:104       // Single use. Without this, one approval for one reshard authorizes every later reshard of
  MongoAdminGateway.java:105       // the same shape, including the one nobody discussed.
  MongoAdminGateway.java:106       if (!consumed.add(command.commandDigest())) {
  MongoAdminGateway.java:107         throw MongoOperationRejectedException.of(
  MongoAdminGateway.java:108             "admin.approval",
  MongoAdminGateway.java:109             "this approval has already been used; a second execution needs a second decision");
  MongoAdminGateway.java:110       }
  MongoAdminGateway.java:111     }

# 다섯 인자 오버로드로 넘어가는 연산들의 위험 등급
  MongoAdminOperation.java:3 /**
  MongoAdminOperation.java:4  * The administrative operations the D4 plane can perform (design §5, §22).
  MongoAdminOperation.java:5  *
  MongoAdminOperation.java:6  * <p>A closed enum, and every constant is something no application runtime should be able to reach.
  MongoAdminOperation.java:7  * Grouping them here makes the boundary a list somebody can review rather than an emergent property
  MongoAdminOperation.java:8  * of which methods happen to exist.
  MongoAdminOperation.java:9  */
  MongoAdminOperation.java:10 public enum MongoAdminOperation {
  MongoAdminOperation.java:13  CREATE_COLLECTION(false),
  MongoAdminOperation.java:16  COLL_MOD(false),
  MongoAdminOperation.java:37  SHARD_COLLECTION(true),
  MongoAdminOperation.java:40  REFINE_SHARD_KEY(true),
  MongoAdminOperation.java:43  RESHARD_COLLECTION(true),
  MongoAdminOperation.java:46  BALANCER_CONTROL(false),
  MongoAdminOperation.java:49  MANAGE_ENCRYPTION_KEY(true),
  그 일곱 가운데 highRisk(true) 인 것 : 4 개
  [대조] 열거형 전체에서 highRisk(true) 인 것 : 8 개
  [대조] 열거형 상수 전체 : 15 개

# 세 인자 오버로드를 부르는 자리가 있는가
  승인을 실제로 넘기는 main 호출 : 0 개
  execute 를 부르는 main 자리 전부 :
    MongoQueryableEncryptionCollectionManager.java:41  adminGateway.execute(
    MongoQueryableEncryptionCollectionManager.java:63  adminGateway.execute(
    MongoQueryableEncryptionCollectionManager.java:70  adminGateway.execute(MongoAdminOperation.COLL_MOD, collection, operator, reason, apply);
    MongoShardingAdminGateway.java:64  adminGateway.execute(MongoAdminOperation.SHARD_COLLECTION, collection, operator, reason, apply);
    MongoShardingAdminGateway.java:75  adminGateway.execute(MongoAdminOperation.REFINE_SHARD_KEY, collection, operator, reason, apply);
    MongoShardingAdminGateway.java:86  adminGateway.execute(
    MongoShardingAdminGateway.java:92  adminGateway.execute(MongoAdminOperation.BALANCER_CONTROL, scope, operator, reason, apply);
  [대조] 시험에서 세 인자 execute 를 부르는 줄 : 10 개
  MongoAdminApproval 을 만드는 main 줄 : 0 개
  그 이름이 main 에 나오는 자리 전부 :
    MongoAdminApproval.java:19  public record MongoAdminApproval(String commandDigest, String approver, Instant expiresAt) {
    MongoAdminApproval.java:21  public MongoAdminApproval {
    MongoAdminApproval.java:31  public static MongoAdminApproval of(
    MongoAdminApproval.java:33  return new MongoAdminApproval(
    MongoAdminGateway.java:83  public <T> T execute(MongoAdminCommand command, MongoAdminApproval approval, Supplier<T> body) {
  [대조] 시험에서 그것을 만드는 줄 : 4 개

# main 에 등장하는 연산 상수와 그 위험 등급
    BALANCER_CONTROL         highRisk=false · main 등장 1 줄
    COLL_MOD                 highRisk=false · main 등장 1 줄
    CREATE_COLLECTION        highRisk=false · main 등장 1 줄
    MANAGE_ENCRYPTION_KEY    highRisk=true  · main 등장 1 줄
    REFINE_SHARD_KEY         highRisk=true  · main 등장 1 줄
    RESHARD_COLLECTION       highRisk=true  · main 등장 1 줄
    SHARD_COLLECTION         highRisk=true  · main 등장 1 줄
  고위험인데 다섯 인자 오버로드로 넘어가는 자리 :
  MongoShardingAdminGateway.java:64     adminGateway.execute(MongoAdminOperation.SHARD_COLLECTION, collection, operator, reason, apply);
  MongoShardingAdminGateway.java:75     adminGateway.execute(MongoAdminOperation.REFINE_SHARD_KEY, collection, operator, reason, apply);
  MongoShardingAdminGateway.java:86     adminGateway.execute(
  MongoShardingAdminGateway.java:87         MongoAdminOperation.RESHARD_COLLECTION, collection, operator, reason, apply);
  MongoQueryableEncryptionCollectionManager.java:34   /** Creates the encrypted collection and its metadata collections. */
  MongoQueryableEncryptionCollectionManager.java:35   public void createEncryptedCollection(
  MongoQueryableEncryptionCollectionManager.java:36       MongoQueryableEncryptionProfile profile,
  MongoQueryableEncryptionCollectionManager.java:37       String operator,
  MongoQueryableEncryptionCollectionManager.java:38       String reason,
  MongoQueryableEncryptionCollectionManager.java:39       Supplier<Void> apply) {
  MongoQueryableEncryptionCollectionManager.java:40     Objects.requireNonNull(profile, "profile");
  MongoQueryableEncryptionCollectionManager.java:41     adminGateway.execute(
  MongoQueryableEncryptionCollectionManager.java:42         MongoAdminOperation.CREATE_COLLECTION, profile.collection(), operator, reason, apply);
  MongoQueryableEncryptionCollectionManager.java:43   }
  MongoQueryableEncryptionCollectionManager.java:61   /** Rotates a data key. Requires its own runbook and evidence. */
  MongoQueryableEncryptionCollectionManager.java:62   public void rotateDataKey(String keyAlias, String operator, String reason, Supplier<Void> apply) {
  MongoQueryableEncryptionCollectionManager.java:63     adminGateway.execute(
  MongoQueryableEncryptionCollectionManager.java:64         MongoAdminOperation.MANAGE_ENCRYPTION_KEY, keyAlias, operator, reason, apply);
  MongoQueryableEncryptionCollectionManager.java:65   }

# 두 승인 타입을 잇는 코드가 있는가
  ReshardApproval 이 main 에 나오는 줄 : 4 개
    MongoShardingAdminGateway.java:70  ReshardApproval approval,
    MongoShardingAdminGateway.java:81  ReshardApproval approval,
    ReshardApproval.java:15  public record ReshardApproval(
    ReshardApproval.java:22  public ReshardApproval {
