Skip to content

devers2/s2-util

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

105 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

S2Util: Unified Dynamic Validator ๐Ÿš€

Java CI

Write Once, Validate Anywhere.
(Java & JavaScript) ํ•œ ๋ฒˆ์˜ ์ž‘์„ฑ์œผ๋กœ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋ชจ๋‘๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ฐ€์žฅ ์Šค๋งˆํŠธํ•œ ๋ฐฉ๋ฒ•.


Overview (๊ฐœ์š”)

[English]

S2Util is a high-performance Java utility library featuring a Unified Dynamic Validator that seamlessly synchronizes validation logic between Server (Java) and Client (JavaScript). Designed for production-ready environments, it leverages advanced technologies like Method Handles and intelligent caching to ensure maximum efficiency and type safety.

[ํ•œ๊ตญ์–ด]

S2Util์€ ์„œ๋ฒ„(Java)์™€ ํด๋ผ์ด์–ธํŠธ(JavaScript) ๊ฐ„์˜ ๊ฒ€์ฆ ๋กœ์ง์„ ์™„๋ฒฝํ•˜๊ฒŒ ๋™๊ธฐํ™”ํ•˜๋Š” ํ†ตํ•ฉ ๋™์  ๊ฒ€์ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜๊ธ‰(Production-ready) ์„ฑ๋Šฅ๊ณผ ์•ˆ์ •์„ฑ์„ ๋ชฉํ‘œ๋กœ ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ, Method Handle ๋ฐ ์ง€๋Šฅํ˜• ์บ์‹ฑ๊ณผ ๊ฐ™์€ ์ฒจ๋‹จ ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•˜์—ฌ ์ตœ์ ์˜ ์‹คํ–‰ ์†๋„์™€ ์ •์  ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


๐Ÿš€ Quick Start (๋น ๋ฅธ ์‹œ์ž‘ ๊ฐ€์ด๋“œ)

1. Installation (์„ค์น˜)

Add the following dependencies to your build.gradle (using Maven Central).

dependencies {
    implementation 'io.github.devers2:s2-util:1.1.6'
}

// [Optional] S2Validator Static Analysis Plugin
// โœจ Prevent runtime errors caused by typos or field name mismatches.
// When using Generics (e.g., S2Validator.<UserCommand>builder()), this plugin performs
// static analysis during the build to verify that all referenced field names
// actually exist in the specified DTO class.
// It triggers a build error if a non-existent field is detected.
// (์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ(์˜ˆ: S2Validator.<UserCommand>builder()), ๋นŒ๋“œ ์‹œ์ ์— ์ •์  ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
// ๋ช…์‹œ๋œ DTO์— ์‹ค์ œ ํ•„๋“œ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์—ฌ, ์˜คํƒ€ ๋“ฑ์œผ๋กœ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ•„๋“œ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด
// ๋นŒ๋“œ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๋ฅผ ์™„๋ฒฝํžˆ ์˜ˆ๋ฐฉํ•ฉ๋‹ˆ๋‹ค.)
plugins {
    id 'io.github.devers2.validator' version '1.1.1'
}

2. Usage (์‚ฌ์šฉ๋ฒ•)

Unified validation for server and client.

[Controller]

Note: This example assumes Spring Framework integration. If Spring is not available, you can use S2Validator and S2ValidatorFactory directly, but BindingResult integration will not be available.
(์ฐธ๊ณ : ์ด ์˜ˆ์ œ๋Š” Spring Framework ํ†ตํ•ฉ์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. Spring์ด ์—†๋Š” ํ™˜๊ฒฝ์—์„œ๋„ S2Validator ๋ฐ S2ValidatorFactory๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, BindingResult ์—ฐ๋™์€ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.)

private S2Validator<UserCommand> profileValidator() {
    return S2Validator.<UserCommand>builder()
            // If no rule is specified, S2RuleType.REQUIRED is applied by default
            // (Rule์ด ์—†์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ REQUIRED ์ ์šฉ)
            // "Name" is the label used in error messages (์—๋Ÿฌ ๋ฉ”์‹œ์ง€์— ์‚ฌ์šฉ๋  ๋ผ๋ฒจ)
            .field("name", "Name")
            .field("password", "Password")
            // When specifying explicit rules, REQUIRED must be added manually if needed
            // (์ง์ ‘ Rule ์ง€์ • ์‹œ ํ•„์ˆ˜ ์ฒดํฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด REQUIRED ๋ณ„๋„ ์ง€์ •)
            .field("passwordCheck", "Confirm Password")
                .rule(S2RuleType.REQUIRED)
                // Verifies value equals "password" field (password ํ•„๋“œ์™€ ๋™์ผํ•œ ๊ฐ’์ธ์ง€ ๊ฒ€์ฆ)
                .rule(S2RuleType.EQUALS_FIELD, "password")
                    // Set English error message (์˜๋ฌธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์„ค์ •)
                    .en("Password check does not match.")
                    .message(Locale.ENGLISH, "Password check does not match.")
                    // Set Korean error message (ํ•œ๊ธ€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์„ค์ •)
                    .ko("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
                    // Set Hindi error message (ํžŒ๋””์–ด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์„ค์ •)
                    .message(Locale.forLanguageTag("hi"), "เคชเคพเคธเคตเคฐเฅเคก เคฎเฅ‡เคฒ เคจเคนเฅ€เค‚ เค–เคพเคคเฅ‡.")
            .field("userType", "User Type")
            .field("paymentMethod", "Payment Method")
            .field("cardNumber", "Card Number")
                // โœจ Conditional validation: cardNumber if (USER + CREDIT_CARD) OR (SELLER)
                // (์ผ๋ฐ˜ํšŒ์›์˜ ์นด๋“œ๊ฒฐ์ œ ๊ฑด ๋˜๋Š” ํŒ๋งค์ž์ผ ๊ฒฝ์šฐ ์นด๋“œ๋ฒˆํ˜ธ ๊ฒ€์ฆ)
                .when("userType", "USER").and("paymentMethod", "CREDIT_CARD")
                .when("userType", "SELLER")
            .build();
}

@GetMapping("/sign-up")
public String signUpPage(@ModelAttribute("command") UserCommand command, Model model) {
    // Convert validator to JSON and pass to client for validation
    // (ํด๋ผ์ด์–ธํŠธ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ์œ„ํ•ด JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ „๋‹ฌ)
    model.addAttribute("rules", S2BindValidator.context("sign-up", this::profileValidator).getRulesJson());
    return "sign-up";
}

@PostMapping("/sign-up")
public String signUp(@ModelAttribute("command") UserCommand command, BindingResult result, Model model) {
    // Perform server-side validation using the same validator configuration
    // (์„ค์ •๋œ ๊ฒ€์ฆ๊ธฐ๋กœ ์„œ๋ฒ„ ์ธก์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ๊ฒ€์ฆ ์ˆ˜ํ–‰)
    S2BindValidator.context("sign-up", this::profileValidator).validate(command, result);

    if (result.hasErrors()) {
        return signUpPage(command, model);
    }
    userService.createUser(command);
    return "redirect:/sign-in";
}

[HTML / Client]

<!-- Inject the validation rules JSON string passed from the controller -->
<!-- ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ „๋‹ฌ๋ฐ›์€ ๊ฒ€์ฆ ๊ทœ์น™(JSON ๋ฌธ์ž์—ด)์„ ํผ์˜ data ์†์„ฑ์— ์ฃผ์ž… -->
<form id="myForm" th:data-s2-rules="${rules}">...</form>

<script type="module">
  // s2.validator.js is served automatically from the JAR's META-INF/resources.
  // (s2.validator.js๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด๋ถ€(META-INF/resources)์— ํฌํ•จ๋˜์–ด ์žˆ์–ด ๋ณ„๋„ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.)
  import '/s2-util/js/s2.validator.js';
  // Just importing the script automatically performs validation using the browser's native UI during submit, matching the server-side rules.
  // (์ž„ํฌํŠธ๋งŒ ํ•˜๋ฉด ํผ ์ „์†ก ์‹œ ๋ธŒ๋ผ์šฐ์ € ๋„ค์ดํ‹ฐ๋ธŒ UI๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์™€ ๋™์ผํ•œ ๊ฒ€์ฆ์ด ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.)
</script>

๐Ÿ“ฆ Core Modules (ํ•ต์‹ฌ ๋ชจ๋“ˆ)

1. s2-core - Foundation Library

s2-core/README.md

[English]

The foundational library providing high-performance core utility classes. Features include:

  • High-Performance Reflection: Method Handle-based reflection with JIT optimization
  • Intelligent Caching: Built-in optimized lightweight cache (concurrent-safe, zero-dependency) with optional Caffeine support for extreme high-concurrency environments
  • Java Version-Adaptive Thread Factory: Virtual Thread support (Java 21+) with platform thread fallback
  • Optimized Data Access: getValue() and setValue() with dot notation and bracket indexing support
  • Comprehensive Utilities: String manipulation, date/time handling, type conversion, and more

[ํ•œ๊ตญ์–ด]

๊ณ ์„ฑ๋Šฅ ํ•ต์‹ฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ฃผ์š” ๊ธฐ๋Šฅ:

  • ๊ณ ์„ฑ๋Šฅ ๋ฆฌํ”Œ๋ ‰์…˜: Method Handle ๊ธฐ๋ฐ˜ ๋ฆฌํ”Œ๋ ‰์…˜ (JIT ์ตœ์ ํ™”)
  • ์ง€๋Šฅํ˜• ์บ์‹ฑ: ์™ธ๋ถ€ ์˜์กด์„ฑ ์—†๋Š” ์ž์ฒด ๊ณ ์„ฑ๋Šฅ ๋™์‹œ์„ฑ ๊ฒฝ๋Ÿ‰ ์บ์‹œ ์ œ๊ณต (๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ ํ™˜๊ฒฝ์„ ์œ„ํ•œ ์„ ํƒ์  Caffeine ์ง€์›)
  • ์ž๋ฐ” ๋ฒ„์ „ ์ ์‘ํ˜• ์Šค๋ ˆ๋“œ ํŒฉํ† ๋ฆฌ: ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ์ง€์› (Java 21+) ๋ฐ ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ ํด๋ฐฑ
  • ์ตœ์ ํ™”๋œ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ: ์  ํ‘œ๊ธฐ๋ฒ• ๋ฐ ๋Œ€๊ด„ํ˜ธ ์ธ๋ฑ์‹ฑ ์ง€์›
  • ์ข…ํ•ฉ ์œ ํ‹ธ๋ฆฌํ‹ฐ: ๋ฌธ์ž์—ด ์กฐ์ž‘, ๋‚ ์งœ/์‹œ๊ฐ„ ์ฒ˜๋ฆฌ, ํƒ€์ž… ๋ณ€ํ™˜ ๋“ฑ

2. s2-validator - Unified Validation Library

s2-validator/README.md

[English]

A unified cross-platform validation Library supporting both server and client with single configuration. Features include:

  • Fluent API: Natural, chainable validation rules with sequential method application
  • 30+ Built-in Rule Types: REQUIRED, LENGTH, REGEX, EMAIL, MPHONE_NO, DATE, and more
  • Korea-specific Rules: MPHONE_NO, TEL_NO, ZIP, BIZRNO, NWINO, JUMIN, PASSWORD_ANSWR
  • Advanced Nested Object Support: Dot notation (user.address.street) and bracket indexing (items[0])
  • Comprehensive i18n: Message localization with ko(), en(), custom locales, and S2ResourceBundle
  • Custom & Conditional Validation: CustomRule interface and when()/and() conditional logic
  • Spring Integration (Optional): S2BindValidator with BindingResult for standard Spring error handling

[ํ•œ๊ตญ์–ด]

๋‹จ์ผ ์„ค์ •์œผ๋กœ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋ชจ๋‘๋ฅผ ์ง€์›ํ•˜๋Š” ํ†ตํ•ฉ ๊ฒ€์ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ฃผ์š” ๊ธฐ๋Šฅ:

  • ์œ ์—ฐํ•œ API: ์ž์—ฐ์Šค๋Ÿฌ์šด ์ฒด์ด๋‹ ๊ฒ€์ฆ ๊ทœ์น™
  • 30๊ฐ€์ง€ ์ด์ƒ ๋‚ด์žฅ ๊ทœ์น™: REQUIRED, LENGTH, REGEX, EMAIL, MPHONE_NO, DATE ๋“ฑ
  • ํ•œ๊ตญ ์ „์šฉ ๊ทœ์น™: MPHONE_NO, TEL_NO, ZIP, BIZRNO, NWINO, JUMIN, PASSWORD_ANSWR
  • ๊ณ ๊ธ‰ ์ค‘์ฒฉ ๊ฐ์ฒด ์ง€์›: ์  ํ‘œ๊ธฐ๋ฒ• ๋ฐ ๋Œ€๊ด„ํ˜ธ ์ธ๋ฑ์‹ฑ
  • ํฌ๊ด„์  i18n: ๋กœ์ปฌ๋ผ์ด์ œ์ด์…˜ ๋ฐ S2ResourceBundle ํ†ตํ•ฉ
  • ์ปค์Šคํ…€ ๋ฐ ์กฐ๊ฑด๋ถ€ ๊ฒ€์ฆ: CustomRule ์ธํ„ฐํŽ˜์ด์Šค์™€ when()/and() ์กฐ๊ฑด ๋กœ์ง
  • Spring ํ†ตํ•ฉ (์„ ํƒ์‚ฌํ•ญ): BindingResult๋ฅผ ํ†ตํ•œ ํ‘œ์ค€ Spring ์—๋Ÿฌ ์ฒ˜๋ฆฌ

3. s2-validator-plugin - Gradle Build Plugin

s2-validator-plugin/README.md

[English]

A Gradle build plugin for static source code analysis to validate S2Validator field names at compile-time. Features include:

  • Static Analysis: JavaParser AST parsing for accurate code analysis
  • Compile-Time Validation: Detects typos and non-existent fields before runtime
  • Multi-Project Support: Scans all subprojects and modules
  • Zero Configuration: Automatically integrates with standard Gradle build tasks
  • Smart Validation: Skips validation for generic wildcards and incomplete type information
  • Detailed Error Reporting: Color-coded messages with file paths and line numbers

[ํ•œ๊ตญ์–ด]

S2Validator ํ•„๋“œ๋ช…์„ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ •์  ๋ถ„์„์œผ๋กœ ๊ฒ€์ฆํ•˜๋Š” Gradle ๋นŒ๋“œ ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค. ์ฃผ์š” ๊ธฐ๋Šฅ:

  • ์ •์  ๋ถ„์„: JavaParser AST ํŒŒ์‹ฑ์œผ๋กœ ์ •ํ™•ํ•œ ์ฝ”๋“œ ๋ถ„์„
  • ์ปดํŒŒ์ผ ํƒ€์ž„ ๊ฒ€์ฆ: ๋Ÿฐํƒ€์ž„ ์ด์ „์— ์˜คํƒ€์™€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ•„๋“œ ๊ฐ์ง€
  • ๋‹ค์ค‘ ํ”„๋กœ์ ํŠธ ์ง€์›: ๋ชจ๋“  ์„œ๋ธŒํ”„๋กœ์ ํŠธ ๋ฐ ๋ชจ๋“ˆ ์Šค์บ”
  • ์„ค์ • ๋ถˆํ•„์š”: ํ‘œ์ค€ Gradle ๋นŒ๋“œ ํƒœ์Šคํฌ ์ž๋™ ํ†ตํ•ฉ
  • ์Šค๋งˆํŠธ ๊ฒ€์ฆ: ์ œ๋„ค๋ฆญ ์™€์ผ๋“œ์นด๋“œ ๋ฐ ๋ถˆ์™„์ „ํ•œ ํƒ€์ž… ์ •๋ณด๋Š” ๊ฒ€์ฆ ์Šคํ‚ต
  • ์ƒ์„ธ ์—๋Ÿฌ ๋ณด๊ณ : ์ƒ‰์ƒ ์ฝ”๋”ฉ๋œ ๋ฉ”์‹œ์ง€์™€ ํŒŒ์ผ ๊ฒฝ๋กœ/์ค„ ๋ฒˆํ˜ธ

โš™๏ธ Requirements (์š”๊ตฌ์‚ฌํ•ญ)

[English]

This project is built with JDK 21, but it can be used reliably in all environments running Java 17 or higher.

[ํ•œ๊ตญ์–ด]

๋ณธ ํ”„๋กœ์ ํŠธ๋Š” JDK 21 ํ™˜๊ฒฝ์—์„œ ๋นŒ๋“œ๋˜์—ˆ์œผ๋‚˜, Java 17 ์ด์ƒ์˜ ๋ชจ๋“  ํ™˜๊ฒฝ์—์„œ ์•ˆ์ •์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ“œ License & Copyright

[English]

This library is provided under the Apache License 2.0. You are free to use, modify, and distribute this software, provided that you comply with the obligations of the license (such as copyright notice and source code disclosure requirements). For detailed terms and conditions, please refer to the LICENSE file.

Third-party Notice: This project uses external libraries. For detailed third-party license notices, please refer to the licenses/NOTICE file.

[ํ•œ๊ตญ์–ด]

๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” Apache License 2.0 ํ•˜์— ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ๋ผ์ด์„ ์Šค์˜ ์˜๋ฌด ์‚ฌํ•ญ(์ €์ž‘๊ถŒ ๊ณ ์ง€, ์†Œ์Šค ์ฝ”๋“œ ๊ณต๊ฐœ ๋ฒ”์œ„ ๋“ฑ)์„ ์ค€์ˆ˜ํ•˜๋Š” ์กฐ๊ฑด ํ•˜์— ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉ, ์ˆ˜์ • ๋ฐ ์žฌ๋ฐฐํฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ธํ•œ ์กฐ๊ฑด์€ LICENSE ํŒŒ์ผ์„ ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.

  • ์ €์ž‘๊ถŒ 2020 - 2026 devers2 (์ด์Šน์ˆ˜, ๋Œ€ํ•œ๋ฏผ๊ตญ ๋Œ€์ „)
  • ๋ฌธ์˜: eseungsu.dev@gmail.com

์ œ3์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ณ ์ง€: ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ธํ•œ ์ œ3์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ณ ์ง€์‚ฌํ•ญ์€ licenses/NOTICE ํŒŒ์ผ์„ ์ฐธ์กฐํ•ด ์ฃผ์„ธ์š”.



To use certain functionalities (e.g., S2BindValidator), the end-user project must explicitly add the following dependencies to be available at runtime. Failure to include these dependencies will result in a java.lang.NoClassDefFoundError at runtime.

[For Gradle Users]

dependencies {
    // Essential runtime dependencies for optional functionalities
    implementation 'com.github.ben-manes.caffeine:caffeine:3.2.3'
    implementation 'org.springframework:spring-context:6.2.15'
    implementation 'jakarta.persistence:jakarta.persistence-api:3.2.0'
}

About

Unified Dynamic Validator for Java & JS: Write Once, Validate Anywhere ๐Ÿš€

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors