# 프로파일이 선언하는 세 상한
 * @param maxDepth deepest accepted nesting
 * @param maxArrayElements most elements accepted in one array
 * @param maxStringBytes longest accepted string
    boolean rejectScalarCoercion,
    int maxDepth,
    int maxArrayElements,
    int maxStringBytes) {
  public static WebJsonProfile strict() {
    return new WebJsonProfile(true, true, true, true, true, 64, 100_000, 1_048_576);
  }

  maxArrayElements() 를 부르는 자리 : (0)

# 같은 이름의 필드가 예산 타입에도 있다
22: * @param maxArrayElements most elements accepted in one JSON array
33:    int maxArrayElements,
51:  private static final int ABSOLUTE_ARRAY_ELEMENTS_MAX = 100_000;
59:    requirePositive(maxArrayElements, "maxArrayElements");
85:    requireAtMost(maxArrayElements, ABSOLUTE_ARRAY_ELEMENTS_MAX, "maxArrayElements");
110:            ABSOLUTE_ARRAY_ELEMENTS_MAX,
123:        && maxArrayElements <= other.maxArrayElements
  프로덕션이 등록하는 값과 그 필드 순서 :
 * @param maxExecutionTime longest this operation may run before its deadline expires
 * @param maxResponseBytes largest response this operation may produce
 */
public record WebRequestBudget(
    int maxUriBytes,
    int maxHeaderBytes,
    int maxQueryParameters,
    long maxBodyBytes,
    int maxJsonDepth,
    int maxArrayElements,
    int maxMultipartParts,
  public static WebRequestBudget standard() {
    return new WebRequestBudget(
        2048, 8192, 64, 256L * 1024, 32, 1_000, 16, Duration.ofSeconds(10), 4L * 1024 * 1024);
  }
  절대 상한을 쓰는 술어를 프로덕션에서 부르는 자리 : test · WebRequestBudgetTest.java:43     assertThat(WebRequestBudget.standard().withinPlatformMaximum()).isTrue(); test · WebRequestBudgetTest.java:58             () -> catalog.registerOverride(new WebBudgetProfileName("orders.bulk"), base, tighter)) test · WebRequestBudgetTest.java:66                 catalog.registerOverride( 
  그 예산 목록은 프로덕션 자동설정이 만들고, 등록하는 예산은 하나다 :
  WebMvcPlatformAutoConfiguration.java:67     WebBudgetCatalog catalog = new WebBudgetCatalog();
  WebMvcPlatformAutoConfiguration.java:68     catalog.register(WebBudgetProfileName.standard(), WebRequestBudget.standard());
  WebFluxPlatformAutoConfiguration.java:85     WebBudgetCatalog catalog = new WebBudgetCatalog();
  WebFluxPlatformAutoConfiguration.java:86     catalog.register(WebBudgetProfileName.standard(), WebRequestBudget.standard());
  WebRequestBudget 의 공개 팩토리 : 1

# 그 예산을 강제하는 필터가 실제로 읽는 필드
  budget.maxBodyBytes()
  budget.maxHeaderBytes()
  budget.maxQueryParameters()
  budget.maxResponseBytes()
  budget.maxUriBytes()
  반응형 필터가 자기 파일에서 읽는 필드 :
  budget.maxBodyBytes()
  budget.maxHeaderBytes()
  budget.maxQueryParameters()
  budget.maxUriBytes()
  나머지 둘은 이 감싼 교환에 넘겨 잰다 :
64:        .filter(new BoundedServerWebExchange(exchange, budget))
  budget.maxBodyBytes()
  budget.maxResponseBytes()
  두 필터를 등록하는 자리 :
  webfluxContractTest · ReactiveBudgetFixtureApplication.java
  testkit · BudgetFixtureApplication.java

# 유계 팩토리가 파서에 거는 것과 그 이유
/**
 * Builds the reader whose limits are enforced before a document is materialised.
 *
 * <p>The constraints go on the {@code JsonFactory} rather than being checked after parsing, and
 * that placement is the whole point. A depth limit applied to a parsed tree has already paid for
 * the tree; a nesting bomb is cheap to send and expensive to hold, so the only limit that helps is
 * one the streaming parser refuses to exceed.
    JsonFactoryBuilder builder =
        JsonFactory.builder()
            .streamReadConstraints(
                StreamReadConstraints.builder()
                    .maxNestingDepth(profile.maxDepth())
                    .maxStringLength(profile.maxStringBytes())
                    .build());
    if (profile.rejectDuplicateKeys()) {
      builder.enable(StreamReadFeature.STRICT_DUPLICATE_DETECTION);
    }
    return builder.build();

# 파서가 실제로 제공하는 상한 전부
  jackson-core-3.1.5.jar
  maxNestingDepth(int)
  maxDocumentLength(long)
  maxTokenCount(long)
  maxNumberLength(int)
  maxStringLength(int)
  maxNameLength(int)
  유계 팩토리를 부르는 자리와 그것을 부르는 자동설정 :
  WebMvcPlatformAutoConfiguration.java:135     return WebObjectMapperFactory.jsonMapper(
  WebFluxPlatformAutoConfiguration.java:129     return WebObjectMapperFactory.jsonMapper(WebJsonProfile.strict());
  WebObjectMapperFactory.java:59         JsonMapper.builder(BoundedJsonFactory.create(profile))
  그중 이 저장소가 이미 쓰는 것 :
  JacksonMessageCodec.java:213                     .maxDocumentLength(maxBytes)
  StrictWebSocketJsonCodec.java:64                             .maxDocumentLength(budget.maxMessageBytes())
  WebSocketCborCodec.java:76                             .maxDocumentLength(binary.maxMessageBytes())
  WebCborMapperFactory.java:55                     .maxDocumentLength(budget.maxBodyBytes())
  WebXmlMapperFactory.java:74                     .maxDocumentLength(budget.maxBodyBytes())
  LocalJsonSchemaRegistry.java:623                     .maxDocumentLength(limits.maximumEnvelopeBytes())
  같은 어댑터의 두 자리가 받는 예산 타입과 그 출하값 :
  WebCborMapperFactory.java:41   public static ObjectMapper create(CodecBudget budget) {
  WebXmlMapperFactory.java:39   public static ObjectMapper create(CodecBudget budget) {
  WebXmlMapperFactory.java:56   public static ObjectMapper create(CodecBudget budget, XMLInputFactory input) {
21:    int maxBodyBytes,
43:  public static CodecBudget conventional(WebRepresentation representation) {
  여섯 자리를 실제로 만드는 곳 :
  main · JacksonMessageCodec.java:66  public static JacksonMessageCodec of(Map<MessageContractKey, Class<?>> registry) {
  main · JacksonMessageCodec.java:77  public static JacksonMessageCodec of(Map<MessageContractKey, Class<?>> registry, int maxBytes) {
  main · MessagingCoreAutoConfiguration.java:364        dev.caskeleton.messaging.schema.json.JacksonMessageCodec.of(
  test · BinaryCodecRoundTripTest.java:118                new WebSocketCborCodec(
  test · BinaryCodecRoundTripTest.java:64    return new WebSocketCborCodec(
  test · JsonContractRegistryTest.java:108        JacksonMessageCodec.of(Map.of(new MessageContractKey(text, V1), String.class), exact);
  test · JsonContractRegistryTest.java:37      JacksonMessageCodec.of(
  test · JsonContractRegistryTest.java:87        JacksonMessageCodec.of(Map.of(new MessageContractKey(largeList, V1), List.class), 1_024);
  test · JsonSchemaIntegrationEventEncoderTest.java:229        new LocalJsonSchemaRegistry(
  test · JsonSchemaIntegrationEventEncoderTest.java:242    return new LocalJsonSchemaRegistry.SchemaSource(path, bytes, sha256(bytes));
  test · LocalJsonSchemaRegistryTest.java:119                new LocalJsonSchemaRegistry(
  test · LocalJsonSchemaRegistryTest.java:122                        new LocalJsonSchemaRegistry.SchemaSource(
  test · LocalJsonSchemaRegistryTest.java:134        new LocalJsonSchemaRegistry.SchemaSource(
  test · LocalJsonSchemaRegistryTest.java:136    assertThatThrownBy(() -> new LocalJsonSchemaRegistry(duplicate, LIMITS))
  test · LocalJsonSchemaRegistryTest.java:346    return new LocalJsonSchemaRegistry(
  test · LocalJsonSchemaRegistryTest.java:355    return new LocalJsonSchemaRegistry(
  test · LocalJsonSchemaRegistryTest.java:356        Map.of(path, new LocalJsonSchemaRegistry.SchemaSource(path, bytes, sha256(bytes))), LIMITS);
  test · LocalJsonSchemaRegistryTest.java:367    return new LocalJsonSchemaRegistry.SchemaSource(path, bytes, sha256(bytes));
  test · MessagingEvidenceManifestSchemaValidator.java:48        new LocalJsonSchemaRegistry(
  test · MessagingEvidenceManifestSchemaValidator.java:51                new LocalJsonSchemaRegistry.SchemaSource(
  test · WebCodecMapperTest.java:109                WebXmlMapperFactory.create(
  test · WebCodecMapperTest.java:163    ObjectMapper mapper = WebCborMapperFactory.create(shallow);
  test · WebCodecMapperTest.java:38    return WebCborMapperFactory.create(CodecBudget.conventional(WebRepresentation.CBOR));
  test · WebCodecMapperTest.java:42    return WebXmlMapperFactory.create(CodecBudget.conventional(WebRepresentation.XML));
  test · WebCodecMapperTest.java:86            () -> WebCborMapperFactory.create(CodecBudget.conventional(WebRepresentation.XML)))
  test · WebSocketJsonWireManifestTest.java:49      new StrictWebSocketJsonCodec(
  그 백엔드 잠금 항목이 실린 구성 :
  tools.jackson.dataformat:jackson-dataformat-cbor:3.1.5=compileClasspath,jettyCompatTestCompileClasspath,jettyCompatTestRuntimeClasspath,nginxProxyTestCompileClasspath,nginxProxyTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath,testkitCompileClasspath,testkitRuntimeClasspath
  tools.jackson.dataformat:jackson-dataformat-xml:3.1.5=compileClasspath,jettyCompatTestCompileClasspath,jettyCompatTestRuntimeClasspath,nginxProxyTestCompileClasspath,nginxProxyTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath,testkitCompileClasspath,testkitRuntimeClasspath

# 표본 애플리케이션은 컬렉션 본문에 크기 제약을 건다
206-  public record BatchCreateRequest(
207-      @Valid
208:          @Size(max = MAX_BATCH_SIZE, message = "batch may not exceed " + MAX_BATCH_SIZE + " items")
