# 다섯 검사
  public static String requireIdentifier(String value) {
    if (value == null || !IDENTIFIER.matcher(value).matches()) {
      throw new IllegalArgumentException(
          "identifier must be 1..128 characters of [A-Za-z0-9._~-] and must not contain a"
              + " key separator");
    }
    String lowerCase = value.toLowerCase(Locale.ROOT);
    if (value.indexOf('@') >= 0) {
      throw new IllegalArgumentException("identifier must not contain a mail address");
    }
    if (JSON_WEB_TOKEN.matcher(value).matches()) {
      throw new IllegalArgumentException("identifier must not contain a JSON web token");
    }
    if (INTERNATIONAL_PHONE.matcher(value).matches()) {
      throw new IllegalArgumentException("identifier must not contain a phone number");
    }
    if (lowerCase.startsWith("bearer") || lowerCase.startsWith("eyj")) {
      throw new IllegalArgumentException("identifier must not contain authentication material");
    }
    return value;
  }

# 검사가 쓰는 패턴 넷
  private static final Pattern IDENTIFIER = Pattern.compile("^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$");

  private static final Pattern JSON_WEB_TOKEN =
      Pattern.compile("^[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}$");

  private static final Pattern INTERNATIONAL_PHONE = Pattern.compile("^\\+\\d[\\d.~-]{7,}$");

# 이 메서드에 값을 넣는 test 가 무엇을 단언하는가
  @Test
  void rejectsEmailInIdentifier() {
    assertThatThrownBy(() -> new RedisKeyName("user", "person@example.com"))
        .isInstanceOf(IllegalArgumentException.class);
  }

  @Test
  void rejectsAuthenticationMaterialInIdentifier() {
    for (String forbidden :
        List.of(
            "eyJhbGciOiJIUzI1NiJ9",
            "bearer-abcdefabcdef",
            "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.c2lnbmF0dXJlLXZhbHVl")) {
      assertThatThrownBy(() -> new RedisKeyName("session", forbidden))
          .as("identifier '%s'", forbidden)
          .isInstanceOf(IllegalArgumentException.class);
    }
  }

  @Test
  void rejectsInternationalPhoneNumbersInIdentifier() {
    assertThatThrownBy(() -> new RedisKeyName("contact", "+821012345678"))
        .isInstanceOf(IllegalArgumentException.class);
  }

  @Test
  void rejectsSeparatorInjectionInEveryKeyPart() {
    assertThatThrownBy(() -> new RedisKeyName("user", "1:2"))
        .isInstanceOf(IllegalArgumentException.class);
    assertThatThrownBy(() -> new RedisSlotTag("{nested}"))
        .isInstanceOf(IllegalArgumentException.class);
    assertThatThrownBy(() -> new RedisNamespace("prod", "order:service", "shared"))
        .isInstanceOf(IllegalArgumentException.class);
  }
  @Test
  void rejectsAnIdentifierAboveTheTokenLimit() {
    String oversized = "a".repeat(129);
    assertThatThrownBy(() -> new RedisKeyName("user", oversized))
        .isInstanceOf(IllegalArgumentException.class);
  }

# 저장소 전체에서 네 메시지가 나오는 곳 (파일 형식 제한 없음)
    sdk/api/key/RedisKeyRules.java:67:      throw new IllegalArgumentException("identifier must not contain a mail address");
    sdk/api/key/RedisKeyRules.java:70:      throw new IllegalArgumentException("identifier must not contain a JSON web token");
    sdk/api/key/RedisKeyRules.java:73:      throw new IllegalArgumentException("identifier must not contain a phone number");
    sdk/api/key/RedisKeyRules.java:76:      throw new IllegalArgumentException("identifier must not contain authentication material");
