Skip to content

Latest commit

ย 

History

History
380 lines (287 loc) ยท 24.5 KB

File metadata and controls

380 lines (287 loc) ยท 24.5 KB

Bluetape4k Projects

Kotlin ์–ธ์–ด๋กœ JVM ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•  ๋•Œ ์‚ฌ์šฉํ•  ๊ณต์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Blue Tape

KDoc ์ž‘์„ฑ ์ง€์นจ: doc/Kdoc_Instruction.md

์†Œ๊ฐœ

Kotlin ์–ธ์–ด๋ฅผ ๋ฐฐ์šฐ๊ณ , ์‚ฌ์šฉํ•˜๋ฉด์„œ, Backend ๊ฐœ๋ฐœ์— ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์ˆ , Coroutines ๋“ฑ ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ ๋“ค์„ ๊ฐœ๋ฐœํ•ด ์™”์Šต๋‹ˆ๋‹ค.

  1. Kotlin ์˜ ์žฅ์ ์„ ์ตœ๋Œ€ํ™” ํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”์ฒœํ•  ๋งŒํ•œ ์ฝ”๋”ฉ ์Šคํƒ€์ผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-core ์˜ assertions, required ๊ฐ™์€ ๊ธฐ๋Šฅ
    • bluetape4k-measured ์˜ ์กฐํ•ฉ ๊ฐ€๋Šฅํ•œ ๋‹จ์œ„ ํƒ€์ž…(Units)๊ณผ ์ธก์ •๊ฐ’(Measure) ์ œ๊ณต
  2. ๊ธฐ์กด Java ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฌด์ง€์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์ข€ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-core ์˜ LZ4, Zstd ๋“ฑ ์••์ถ• ๊ธฐ๋Šฅ ๊ฐœ์„ 
    • bluetape4k-redis ์˜ lettuce, redisson ์šฉ Codec ์ œ๊ณต (๊ณต์‹ Codec ๋ณด๋‹ค ์„ฑ๋Šฅ์ด ์›”๋“ฑํ•จ)
  3. ํ…Œ์ŠคํŠธ๋ฅผ ์ข€ ๋” ์™„์„ฑ๋„ ์žˆ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-junit5 ๋‹ค์–‘ํ•œ ํ…Œ์ŠคํŠธ ๊ธฐ๋ฒ•์„ Junit5 ๊ธฐ๋ฐ˜์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
    • bluetape4k-testcontainers ๋‹ค์–‘ํ•œ ์„œ๋น„์Šค๋“ค์„ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  4. Kotlin Coroutines ๋“ฑ Async/Non-Blocking ๋ฐฉ์‹์˜ ๊ฐœ๋ฐœ์„ ์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-coroutines Coroutine ์„ ์‚ฌ์šฉํ•  ๋•Œ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
    • bluetape4k-feigh, bluetape4k-retrofit2 ๋“ฑ์€ HTTP ํ†ต์‹  ์‹œ async/non-blocking์„ ์œ„ํ•ด Coroutines ์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค
  5. AWS SDK ์‚ฌ์šฉ ์‹œ ์„ฑ๋Šฅ์„ ์œ„ํ•ด ๊ฐœ์„ ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-aws AWS Java SDK v2 ๊ธฐ๋ฐ˜์œผ๋กœ DynamoDB, S3, SES, SNS, SQS, KMS, CloudWatch, Kinesis, STS ๋“ฑ์„ Async/Non-Blocking ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
    • S3 TransferManager๋ฅผ ํ™œ์šฉํ•œ ๋Œ€์šฉ๋Ÿ‰ ํŒŒ์ผ ์ „์†ก ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  6. AWS Kotlin SDK ๋ฅผ ์‚ฌ์šฉ์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-aws-kotlin AWS Kotlin SDK ๊ธฐ๋ฐ˜์œผ๋กœ native suspend ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋ณธ ์ œ๊ณตํ•˜์—ฌ Coroutines ํ™˜๊ฒฝ์—์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  7. MSA์˜ ํ•„์ˆ˜์ธ Resilience4j ์— ๋Œ€ํ•œ Kotlin Coroutines ์ง€์›์„ ๊ฐ•ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

    • bluetape4k-resilience4j Resilience4j ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Kotlin Coroutines ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
    • ๋˜ํ•œ Coroutines ์šฉ Cache๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ, Coroutines ํ™˜๊ฒฝ์—์„œ๋„ API ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  8. Redis ๋ฅผ ๋Œœ์–‘ํ•œ ๋ฐฉ์‹์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

    • bluetape4k-redis๋Š” Lettuce, Redisson ์šฉ ๊ณ ์„ฑ๋Šฅ Codec ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
    • Redisson์˜ ๋‹ค์–‘ํ•œ Lock ๊ธฐ๋Šฅ์„ Coroutines ํ™˜๊ฒฝ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
    • Redis๋ฅผ ๋ถ„์‚ฐ ์บ์‹œ๋กœ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, Near Cache๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์—ฌ ๋”์šฑ ์„ฑ๋Šฅ์„ ๋†’ํž ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ์™ธ ํ˜„์—…์—์„œ ๋งˆ์ฃผ์ณค๋˜ ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์—์„œ ํ•„์š”๋กœ ํ•˜๋Š” ๊ธฐ๋Šฅ ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์•ž์œผ๋กœ๋„ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋‹ค๋ฉด Issue ์— ์ œ์•ˆ ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๊ธฐ์ˆ  ์Šคํƒ

  • Java: 21 (JVM Toolchain)
  • Kotlin: 2.3 (Language & API Version)
  • Spring Boot: 3.4.0+ / 4.0.0+
  • Kotlin Exposed: 1.0.0+
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค: H2, PostgreSQL, MySQL

๋ชจ๋“ˆ ๊ตฌ์กฐ

Bluetape4k๋Š” ๊ธฐ๋Šฅ๋ณ„๋กœ ๋ถ„๋ฆฌ๋œ ๋ฉ€ํ‹ฐ ๋ชจ๋“ˆ Gradle ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.

Core ๋ชจ๋“ˆ (bluetape4k/)

  • core: ํ•ต์‹ฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ (assertions, required, ์ปฌ๋ ‰์…˜(BoundedStack, RingBuffer, PaginatedList, Permutation), Wildcard ํŒจํ„ด ๋งค์นญ, XXHasher ๋“ฑ)
  • coroutines: Kotlin Coroutines ํ™•์žฅ (DeferredValue, Flow extensions, AsyncFlow)
  • logging: ๋กœ๊น… ๊ด€๋ จ ๊ธฐ๋Šฅ
  • bom: Bill of Materials (์˜์กด์„ฑ ๊ด€๋ฆฌ)

I/O ๋ชจ๋“ˆ (io/)

  • io: ํŒŒ์ผ I/O, ์••์ถ•(LZ4, Zstd, Snappy, Zip), ์ง๋ ฌํ™”(Kryo, Fory), ZIP ๋นŒ๋”/์œ ํ‹ธ๋ฆฌํ‹ฐ, Okio ํ†ตํ•ฉ (Tink ๊ธฐ๋ฐ˜ ์•”ํ˜ธํ™” Sink/Source ํฌํ•จ)
  • okio: Okio ๊ธฐ๋ฐ˜ I/O ํ™•์žฅ โ€” Buffer/Sink/Source ์œ ํ‹ธ๋ฆฌํ‹ฐ, Base64, Channel, Cipher, Compress, Coroutines, Jasypt/Tink ์•”ํ˜ธํ™” Sink/Source
  • **jackson2/jackson3 **: Jackson 2.x/3.x ํ†ตํ•ฉ โ€” ๋ฐ”์ด๋„ˆ๋ฆฌ(CBOR, Ion, Smile) ๋ฐ ํ…์ŠคํŠธ(CSV, YAML, TOML) ํฌ๋งท ํฌํ•จ (๊ตฌ jackson-binary/text, jackson3-binary/text ํ†ตํ•ฉ๋จ)
  • json: JSON ์ฒ˜๋ฆฌ
  • csv: CSV ์ฒ˜๋ฆฌ
  • feign: Feign HTTP ํด๋ผ์ด์–ธํŠธ (Coroutines ์ง€์›)
  • retrofit2: Retrofit2 HTTP ํด๋ผ์ด์–ธํŠธ (Coroutines ์ง€์›)
  • protobuf: Protobuf ์œ ํ‹ธ๋ฆฌํ‹ฐ (Timestamp/Duration/Money ๋ณ€ํ™˜, ProtobufSerializer)
  • grpc: gRPC ์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ์ถ”์ƒํ™” (bluetape4k-protobuf ํฌํ•จ)
  • crypto: ์•”ํ˜ธํ™” ๊ธฐ๋Šฅ (Jasypt ๊ธฐ๋ฐ˜ PBE, BouncyCastle) โ€” Deprecated (bluetape4k-tink๋กœ ๋Œ€์ฒด)
  • tink: Google Tink ๊ธฐ๋ฐ˜ ํ˜„๋Œ€์  ์•”ํ˜ธํ™” โ€” AEAD, Deterministic AEAD, MAC, Digest, ํ†ตํ•ฉ Encryptor (TinkEncryptor), Okio TinkEncryptSink/TinkDecryptSource
  • http: HTTP ์œ ํ‹ธ๋ฆฌํ‹ฐ
  • netty: Netty ํ†ตํ•ฉ
  • avro: Apache Avro
  • fastjson2: FastJSON2
  • vertx: Vert.x ๋‹จ์ผ ํ†ตํ•ฉ ๋ชจ๋“ˆ โ€” ํ•ต์‹ฌ ๊ธฐ๋Šฅ, SQL ํด๋ผ์ด์–ธํŠธ, Resilience4j ํ†ตํ•ฉ ํฌํ•จ (๊ตฌ vertx/core, vertx/sqlclient, vertx/resilience4j ํ†ตํ•ฉ๋จ)

AWS ๋ชจ๋“ˆ (aws/)

๊ฐ ์„œ๋น„์Šค๋งˆ๋‹ค 3๋‹จ๊ณ„ API ํŒจํ„ด ์ œ๊ณต: sync โ†’ async (CompletableFuture) โ†’ coroutines (suspend)

  • bluetape4k-aws: AWS Java SDK v2 ๊ธฐ๋ฐ˜ ๋‹จ์ผ ํ†ตํ•ฉ ๋ชจ๋“ˆ โ€” DynamoDB, S3(TransferManager), SES, SNS, SQS, KMS, CloudWatch/Logs, Kinesis, STS ํฌํ•จ. ๊ฐ ์„œ๋น„์Šค์˜ coroutines ํ™•์žฅ (XxxAsyncClientCoroutinesExtensions.kt) ์ œ๊ณต
  • bluetape4k-aws-kotlin: AWS Kotlin SDK ๊ธฐ๋ฐ˜ ๋‹จ์ผ ํ†ตํ•ฉ ๋ชจ๋“ˆ โ€” native suspend ํ•จ์ˆ˜ ๊ธฐ๋ณธ ์ œ๊ณต (.await() ๋ณ€ํ™˜ ๋ถˆํ•„์š”). DynamoDB, S3, SES/SESv2, SNS, SQS, KMS, CloudWatch/Logs, Kinesis, STS ํฌํ•จ. DSL ์ง€์› (metricDatum {}, inputLogEvent {}, stsClientOf {} ๋“ฑ)

๋ฐ์ดํ„ฐ ๋ชจ๋“ˆ (data/)

Exposed ๋ชจ๋“ˆ (๊ธฐ๋Šฅ๋ณ„ ๋ถ„๋ฆฌ)

  • exposed: umbrella ๋ชจ๋“ˆ โ€” exposed-core + exposed-dao + exposed-jdbc ๋ฌถ์Œ (ํ•˜์œ„ ํ˜ธํ™˜)
  • exposed-core: JDBC ์—†์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•ต์‹ฌ ๊ธฐ๋Šฅ โ€” ์••์ถ•/์•”ํ˜ธํ™”/์ง๋ ฌํ™” ์ปฌ๋Ÿผ ํƒ€์ž…, ID ์ƒ์„ฑ ํ™•์žฅ, HasIdentifier, ExposedPage
  • exposed-dao: DAO ์—”ํ‹ฐํ‹ฐ ํ™•์žฅ โ€” EntityExtensions, StringEntity, ์ปค์Šคํ…€ IdTable (KsuidTable, SnowflakeIdTable, SoftDeletedIdTable ๋“ฑ)
  • exposed-jdbc: JDBC ์ „์šฉ โ€” ExposedRepository, SoftDeletedRepository, SuspendedQuery, VirtualThreadTransaction
  • exposed-r2dbc: Exposed + R2DBC (reactive, ExposedR2dbcRepository)
  • exposed-jdbc-redisson: Exposed JDBC + Redisson (๋ถ„์‚ฐ ๋ฝ)
  • exposed-r2dbc-redisson: Exposed R2DBC + Redisson (๋ถ„์‚ฐ ๋ฝ)
  • exposed-jackson2/jackson3: Exposed JSON ์ปฌ๋Ÿผ ์ง€์› (Jackson 2.x/3.x)
  • exposed-fastjson2: Exposed FastJSON2 JSON ์ปฌ๋Ÿผ ์ง€์›
  • exposed-jasypt: Exposed Jasypt ์•”ํ˜ธํ™” ์ปฌ๋Ÿผ
  • exposed-tink: Exposed ์•”ํ˜ธํ™” ์ปฌ๋Ÿผ (Google Tink AEAD/Deterministic AEAD)
  • exposed-measured: Exposed ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„ ์ธก์ • (Micrometer ํ†ตํ•ฉ)
  • exposed-jdbc-tests: JDBC ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ๊ณตํ†ต ์ธํ”„๋ผ
  • exposed-r2dbc-tests: R2DBC ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ๊ณตํ†ต ์ธํ”„๋ผ

๊ธฐํƒ€ ๋ฐ์ดํ„ฐ ๋ชจ๋“ˆ

  • exposed-postgresql: PostgreSQL ์ „์šฉ Exposed ํ™•์žฅ โ€” PostGIS ๊ณต๊ฐ„ ๋ฐ์ดํ„ฐ(POINT/POLYGON), pgvector ๋ฒกํ„ฐ ๊ฒ€์ƒ‰(VECTOR(n)), TSTZRANGE ์‹œ๊ฐ„ ๋ฒ”์œ„ ์ปฌ๋Ÿผ ํƒ€์ž…; H2 fallback ์ง€์›
  • exposed-mysql8: MySQL 8.0 ์ „์šฉ Exposed ํ™•์žฅ โ€” GIS ๊ณต๊ฐ„ ๋ฐ์ดํ„ฐ(8์ข…), JTS ๊ธฐ๋ฐ˜ Geometry ์ปฌ๋Ÿผ, ST_Contains/ST_Distance ๋“ฑ ๊ณต๊ฐ„ ํ•จ์ˆ˜; MySQL Internal Format WKB ๋ณ€ํ™˜
  • exposed-duckdb: DuckDB JDBC ํ†ตํ•ฉ โ€” DuckDBDialect(PostgreSQL ์ƒ์†), DuckDBDatabase ํŒฉํ† ๋ฆฌ(์ธ๋ฉ”๋ชจ๋ฆฌ/ํŒŒ์ผ/์ฝ๊ธฐ์ „์šฉ), suspendTransaction, queryFlow
  • exposed-bigquery: Google BigQuery REST API ํ†ตํ•ฉ โ€” H2(PostgreSQL ๋ชจ๋“œ)๋กœ SQL ์ƒ์„ฑ ํ›„ BigQuery REST ์‹คํ–‰, BigQueryContext(SELECT/INSERT/UPDATE/DELETE/DDL), BigQueryResultRow(Column ์ฐธ์กฐ ํƒ€์ž… ์•ˆ์ „ ์ ‘๊ทผ), suspend/Flow API
  • exposed-jdbc-lettuce: Exposed JDBC + Lettuce Redis ์บ์‹œ โ€” Read-through/Write-through/Write-behind, AbstractJdbcLettuceRepository, ์ฝ”๋ฃจํ‹ด ๋„ค์ดํ‹ฐ๋ธŒ AbstractSuspendedJdbcLettuceRepository
  • exposed-r2dbc-lettuce: Exposed R2DBC + Lettuce Redis ์บ์‹œ โ€” ์ฝ”๋ฃจํ‹ด ๋„ค์ดํ‹ฐ๋ธŒ Read-through/Write-through/Write-behind, AbstractR2dbcLettuceRepository
  • hibernate/hibernate-reactive: Hibernate ORM ํ†ตํ•ฉ
  • hibernate-cache-lettuce: Hibernate 2nd Level Cache + Lettuce NearCache (Caffeine L1 + Redis L2) โ€” LettuceNearCacheRegionFactory, LettuceNearCacheStorageAccess, region๋ณ„ TTL ์˜ค๋ฒ„๋ผ์ด๋“œ, 15๊ฐ€์ง€ ์ฝ”๋ฑ ์ง€์›
  • mongodb: MongoDB Kotlin Coroutine Driver ํ™•์žฅ โ€” mongoClient {} DSL, findFirst, exists, upsert, findAsFlow, documentOf {}, Aggregation Pipeline DSL
  • r2dbc: R2DBC ์ง€์›
  • cassandra: Cassandra ๋“œ๋ผ์ด๋ฒ„
  • jdbc: JDBC ์œ ํ‹ธ๋ฆฌํ‹ฐ

์ธํ”„๋ผ ๋ชจ๋“ˆ (infra/)

  • redis: Lettuce/Redisson umbrella ๋ชจ๋“ˆ (ํ•˜์œ„ ํ˜ธํ™˜)
    • lettuce: Lettuce ํด๋ผ์ด์–ธํŠธ, ๊ณ ์„ฑ๋Šฅ Codec (Jdk/Kryo/Fory ร— GZip/LZ4/Snappy/Zstd), RedisFuture โ†’ Coroutines ์–ด๋Œ‘ํ„ฐ, ๋ถ„์‚ฐ Primitive (Lock, Semaphore, AtomicLong, Leader Election), MapLoader/MapWriter/LettuceLoadedMap (Read-through/Write-through/Write-behind), BloomFilter/CuckooFilter (Lua ์Šคํฌ๋ฆฝํŠธ ๊ธฐ๋ฐ˜, RedisBloom ๋ถˆํ•„์š”), HyperLogLog (PFADD/PFCOUNT/PFMERGE)
    • redisson: Redisson ํด๋ผ์ด์–ธํŠธ, Codec, Memorizer, NearCache ( RLocalCachedMap), Leader Election (Coroutines ์ง€์›)
  • kafka: Kafka ํด๋ผ์ด์–ธํŠธ
  • resilience4j: Resilience4j + Coroutines, Coroutines Cache
  • bucket4j: Rate limiting
  • micrometer: ๋ฉ”ํŠธ๋ฆญ
  • opentelemetry: ๋ถ„์‚ฐ ์ถ”์ 

์บ์‹œ ๋ชจ๋“ˆ (infra/cache-*)

ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฐฉ์‹์œผ๋กœ ๋ฐฑ์—”๋“œ๋ฅผ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ์บ์‹œ ์ถ”์ƒํ™” ๋ ˆ์ด์–ด์ž…๋‹ˆ๋‹ค.

  • cache: umbrella ๋ชจ๋“ˆ (cache-core + hazelcast + redisson + lettuce)
  • cache-core: JCache ์ถ”์ƒํ™” + Caffeine/Cache2k/Ehcache ๋กœ์ปฌ ์บ์‹œ (๊ตฌ cache-local ๋ณ‘ํ•ฉ) โ€” AsyncCache, SuspendCache, NearCache, SuspendNearCache, Memorizer ๊ตฌํ˜„์ฒด, testFixtures 6์ข… ์ถ”์ƒ ํ…Œ์ŠคํŠธ
  • cache-hazelcast: Hazelcast ๋ถ„์‚ฐ ์บ์‹œ + Caffeine 2-Tier Near Cache (๊ตฌ cache-hazelcast-near ๋ณ‘ํ•ฉ)
  • cache-redisson: Redisson ๋ถ„์‚ฐ ์บ์‹œ + Caffeine 2-Tier Near Cache (๊ตฌ cache-redisson-near ๋ณ‘ํ•ฉ)
  • cache-lettuce: Lettuce(Redis) ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ ์บ์‹œ โ€” LettuceNearCacheConfig, RESP3 CLIENT TRACKING ๊ธฐ๋ฐ˜ ์ž๋™ invalidation

Spring Boot 3 ๋ชจ๋“ˆ (spring-boot3/)

  • bluetape4k-spring-boot3 ( spring-boot3/core): Spring Boot 3 ๊ธฐ๋ฐ˜ ๊ณตํ†ต ๊ธฐ๋Šฅ ํ†ตํ•ฉ ๋ชจ๋“ˆ โ€” Spring core ์œ ํ‹ธ๋ฆฌํ‹ฐ, WebFlux + Coroutines, Retrofit2 ํ†ตํ•ฉ, ํ…Œ์ŠคํŠธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํฌํ•จ (๊ตฌ spring/core, spring/webflux, spring/retrofit2, spring/tests ํ†ตํ•ฉ๋จ)
  • data-redis: Spring Data Redis ๊ณ ์„ฑ๋Šฅ ์ง๋ ฌํ™” โ€” RedisBinarySerializer, RedisCompressSerializer, redisSerializationContext {} DSL
  • cassandra: Spring Data Cassandra
  • mongodb: Spring Data MongoDB Reactive โ€” ReactiveMongoOperations ์ฝ”๋ฃจํ‹ด ํ™•์žฅ, Criteria/Query/Update infix DSL
  • r2dbc: Spring Data R2DBC
  • exposed-jdbc (bluetape4k-spring-boot3-exposed-jdbc): Exposed DAO ์—”ํ‹ฐํ‹ฐ ๊ธฐ๋ฐ˜ Spring Data JDBC Repository โ€” PartTree ์ฟผ๋ฆฌ, QBE, Page/Sort ์ง€์›
  • exposed-r2dbc (bluetape4k-spring-boot3-exposed-r2dbc): Exposed R2DBC DSL ๊ธฐ๋ฐ˜ ์ฝ”๋ฃจํ‹ด Spring Data Repository โ€” suspend CRUD, Flow ์ง€์›
  • exposed-jdbc-demo (bluetape4k-spring-boot3-exposed-jdbc-demo): Exposed DAO + Spring Data JDBC + Spring MVC ํ†ตํ•ฉ ๋ฐ๋ชจ
  • exposed-r2dbc-demo (bluetape4k-spring-boot3-exposed-r2dbc-demo): Exposed R2DBC + suspend Repository + Spring WebFlux ํ†ตํ•ฉ ๋ฐ๋ชจ
  • hibernate-lettuce (bluetape4k-spring-boot3-hibernate-lettuce): Hibernate 2nd Level Cache + Lettuce NearCache Spring Boot Auto-Configuration โ€” Properties ๋ฐ”์ธ๋”ฉ, Micrometer Metrics, Actuator Endpoint
  • hibernate-lettuce-demo (bluetape4k-spring-boot3-hibernate-lettuce-demo): Hibernate Lettuce NearCache + Spring MVC ํ†ตํ•ฉ ๋ฐ๋ชจ

Spring Data JPA๋Š” data/hibernate ๋ชจ๋“ˆ๋กœ ์ด๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

Spring Boot 4 ๋ชจ๋“ˆ (spring-boot4/)

Spring Boot 4.x ์ „์šฉ ๋ชจ๋“ˆ. Spring Boot 3 ๋ชจ๋“ˆ๊ณผ ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

BOM ์ ์šฉ ์ฃผ์˜: dependencyManagement { imports } ๋Œ€์‹  implementation(platform(...)) ๋ฐฉ์‹์œผ๋กœ ์ ์šฉํ•ด์•ผ KGP 2.3.x์™€ ์ถฉ๋Œ ์—†์ด ๋นŒ๋“œ๋ฉ๋‹ˆ๋‹ค.

  • core (bluetape4k-spring-boot4-core): Spring Boot 4 ๊ธฐ๋ฐ˜ ๊ณตํ†ต ๊ธฐ๋Šฅ โ€” WebFlux + Coroutines, RestClient DSL (suspendGet, suspendPost ๋“ฑ), Jackson 2 ์ปค์Šคํ„ฐ๋งˆ์ด์ €, Retrofit2 ํ†ตํ•ฉ, WebTestClient ํ…Œ์ŠคํŠธ ์œ ํ‹ธ๋ฆฌํ‹ฐ
  • data-redis: Spring Data Redis ๊ณ ์„ฑ๋Šฅ ์ง๋ ฌํ™” โ€” RedisBinarySerializer, RedisCompressSerializer, redisSerializationContext {} DSL
  • cassandra: Spring Data Cassandra ์ฝ”๋ฃจํ‹ด ํ™•์žฅ
  • mongodb: Spring Data MongoDB Reactive ์ฝ”๋ฃจํ‹ด ํ™•์žฅ, Criteria/Query/Update infix DSL
  • r2dbc: Spring Data R2DBC ์ฝ”๋ฃจํ‹ด ํ™•์žฅ
  • cassandra-demo: Cassandra ์‚ฌ์šฉ ์˜ˆ์ œ
  • exposed-jdbc (bluetape4k-spring-boot4-exposed-jdbc): Exposed DAO ์—”ํ‹ฐํ‹ฐ ๊ธฐ๋ฐ˜ Spring Data JDBC Repository โ€” PartTree ์ฟผ๋ฆฌ, QBE, Page/Sort ์ง€์› (Spring Boot 4 BOM)
  • exposed-r2dbc (bluetape4k-spring-boot4-exposed-r2dbc): Exposed R2DBC DSL ๊ธฐ๋ฐ˜ ์ฝ”๋ฃจํ‹ด Spring Data Repository โ€” suspend CRUD, Flow ์ง€์› (Spring Boot 4 BOM)
  • exposed-jdbc-demo (bluetape4k-spring-boot4-exposed-jdbc-demo): Exposed DAO + Spring Data JDBC + Spring MVC ํ†ตํ•ฉ ๋ฐ๋ชจ (Spring Boot 4 BOM)
  • exposed-r2dbc-demo (bluetape4k-spring-boot4-exposed-r2dbc-demo): Exposed R2DBC + suspend Repository + Spring WebFlux ํ†ตํ•ฉ ๋ฐ๋ชจ (Spring Boot 4 BOM)
  • hibernate-lettuce (bluetape4k-spring-boot4-hibernate-lettuce): Hibernate 2nd Level Cache + Lettuce NearCache Spring Boot Auto-Configuration (Spring Boot 4 BOM)
  • hibernate-lettuce-demo (bluetape4k-spring-boot4-hibernate-lettuce-demo): Hibernate Lettuce NearCache + Spring MVC ํ†ตํ•ฉ ๋ฐ๋ชจ (Spring Boot 4 BOM)

์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ชจ๋“ˆ (utils/)

  • bluetape4k-geo ( utils/geo): ์ง€๋ฆฌ ์ •๋ณด ์ฒ˜๋ฆฌ ๋‹จ์ผ ํ†ตํ•ฉ ๋ชจ๋“ˆ โ€” geocode(Bing/Google), geohash, geoip2(MaxMind) ํฌํ•จ (๊ตฌ utils/geocode, utils/geohash, utils/geoip2 ํ†ตํ•ฉ๋จ)
  • idgenerators: ID ์ƒ์„ฑ๊ธฐ โ€” Uuid(V1~V7 ํ†ต์ผ API), ULID, Ksuid(Seconds/Millis), Snowflakers ํ†ต์ผ ํŒฉํ† ๋ฆฌ, Flake, Hashids ๋“ฑ ๋‹ค์–‘ํ•œ ID ์ƒ์„ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ œ๊ณต
  • images: ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
  • javatimes: ๋‚ ์งœ/์‹œ๊ฐ„ ์œ ํ‹ธ๋ฆฌํ‹ฐ
  • jwt: JWT ์ฒ˜๋ฆฌ
  • leader: Leader ์„ ์ถœ
  • math: ์ˆ˜ํ•™ ์œ ํ‹ธ๋ฆฌํ‹ฐ
  • measured: ์กฐํ•ฉ ๊ฐ€๋Šฅํ•œ ๋‹จ์œ„ ํƒ€์ž…(Units)๊ณผ ์ธก์ •๊ฐ’(Measure) ๊ธฐ๋ฐ˜์œผ๋กœ, ๋ณตํ•ฉ ๋‹จ์œ„(m/s, kg*m/s^2)๋ฅผ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ํ‘œํ˜„
  • money: Money API
  • mutiny: Mutiny reactive ํ†ตํ•ฉ
  • units: ๋‹จ์œ„ ํ‘œํ˜„ value class โ€” Deprecated (bluetape4k-measured์˜ ๊ธฐ๋Šฅ์œผ๋กœ ํ†ตํ•ฉ)

ํ…Œ์ŠคํŠธ ๋ชจ๋“ˆ (testing/)

  • junit5: JUnit 5 ํ™•์žฅ ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ
  • testcontainers: Testcontainers ์ง€์› (Redis, Kafka, DB ๋“ฑ)

Virtual Thread ๋ชจ๋“ˆ (virtualthread/)

  • virtualthread: Java 21/25 Virtual Thread ์ง€์›
    • api: Virtual Thread API ๋ฐ ServiceLoader ๊ธฐ๋ฐ˜ ๋Ÿฐํƒ€์ž„ ์„ ํƒ
    • jdk21: Java 21 Virtual Thread ๊ตฌํ˜„์ฒด
    • jdk25: Java 25 Virtual Thread ๊ตฌํ˜„์ฒด

๊ธฐํƒ€ ๋ชจ๋“ˆ

  • timefold: Timefold Solver + Exposed ํ†ตํ•ฉ

์˜ˆ์ œ ๋ชจ๋“ˆ (examples/)

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ์ œ ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค. ๋ฐฐํฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ๊ธฐ๋œ ๋ชจ๋“ˆ (x-obsoleted/)

๋” ์ด์ƒ ์œ ์ง€๋ณด์ˆ˜๋˜์ง€ ์•Š๋Š” ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค. ๋นŒ๋“œ์—์„œ ์ œ์™ธ๋˜์—ˆ์œผ๋ฉฐ ์‚ญ์ œ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

  • vertx-coroutines: Vert.x + Coroutines โ€” bluetape4k-vertx๋กœ ํ†ตํ•ฉ๋จ
  • vertx-sqlclient: Vert.x SQL Client โ€” bluetape4k-vertx๋กœ ํ†ตํ•ฉ๋จ
  • vertx-webclient: Vert.x Web Client โ€” bluetape4k-vertx๋กœ ํ†ตํ•ฉ๋จ
  • mapstruct: MapStruct ํ†ตํ•ฉ โ€” ๋ฏธ์‚ฌ์šฉ์œผ๋กœ ํ๊ธฐ
  • bloomfilter: Bloom Filter โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • captcha: CAPTCHA ์ƒ์„ฑ โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • logback-kafka: Logback Kafka Appender โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • nats: NATS ๋ฉ”์‹œ์ง• โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • javers: JaVers ๊ฐ์‚ฌ ๋กœ๊ทธ โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • tokenizer: ํ•œ๊ตญ์–ด/์ผ๋ณธ์–ด ํ˜•ํƒœ์†Œ ๋ถ„์„๊ธฐ โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • ahocorasick: ๋ฌธ์ž์—ด ๊ฒ€์ƒ‰ (Aho-Corasick) โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • lingua: ์–ธ์–ด ๊ฐ์ง€ โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • naivebayes: Naive Bayes ๋ถ„๋ฅ˜๊ธฐ โ€” ์‚ฌ์šฉ ๋นˆ๋„ ๋‚ฎ์•„ ํ๊ธฐ
  • mutiny-examples: Mutiny ์‚ฌ์šฉ ์˜ˆ์ œ โ€” ํ๊ธฐ

๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ

ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ

# ์ „์ฒด ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ
./gradlew clean build

# ํŠน์ • ๋ชจ๋“ˆ๋งŒ ๋นŒ๋“œ
./gradlew :bluetape4k-coroutines:build

# ํ…Œ์ŠคํŠธ ์ œ์™ธํ•˜๊ณ  ๋นŒ๋“œ
./gradlew build -x test

ํ…Œ์ŠคํŠธ ์‹คํ–‰

# ์ „์ฒด ํ…Œ์ŠคํŠธ ์‹คํ–‰
./gradlew test

# ํŠน์ • ๋ชจ๋“ˆ ํ…Œ์ŠคํŠธ
./gradlew :bluetape4k-io:test

# ํŠน์ • ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ์‹คํ–‰
./gradlew test --tests "io.bluetape4k.io.CompressorTest"

# ์ƒ์„ธ ๋กœ๊ทธ์™€ ํ•จ๊ป˜ ํ…Œ์ŠคํŠธ
./gradlew test --info

์ฝ”๋“œ ํ’ˆ์งˆ ๊ฒ€์‚ฌ

# Detekt ์ •์  ๋ถ„์„ ์‹คํ–‰
./gradlew detekt

๋ฐฐํฌ ๋ฐฉ๋ฒ•

๋ฒ„์ „ ํ™•์ธ์€ gradle.properties ํŒŒ์ผ์—์„œ ํ™•์ธ

projectGroup=io.github.bluetape4k
baseVersion=1.5.0
snapshotVersion=-SNAPSHOT

Maven Central SNAPSHOT ๋ฐฐํฌ

./gradlew publishAggregationToCentralSnapshots --no-daemon --no-configuration-cache

Maven Central SNAPSHOT ๋ฐฐํฌ

# ๊ธฐ๋ณธ ๋ณ‘๋ ฌ๋„(centralSnapshotsParallelism=8)๋กœ SNAPSHOT ๋ฐฐํฌ
./gradlew publishAggregationToCentralSnapshots

# ๋ณ‘๋ ฌ๋„๋ฅผ ๋‚ฎ์ถฐ ์„œ๋ฒ„ ๋ถ€๋‹ด์„ ์ค„์ด๊ณ  ์‹ถ์„ ๋•Œ
./gradlew -PcentralSnapshotsParallelism=4 publishAggregationToCentralSnapshots
  • ๋ฃจํŠธ ์ง‘๊ณ„ task๋Š” publishAggregationToCentralSnapshots ์ž…๋‹ˆ๋‹ค.
  • SNAPSHOT ๋ฐฐํฌ๋Š” release ์™€ ๋‹ฌ๋ฆฌ ZIP 1ํšŒ ์—…๋กœ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ file-by-file ์—…๋กœ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ๋ชจ๋“ˆ ์ˆ˜๊ฐ€ ๋งŽ์„์ˆ˜๋ก PUT ์š”์ฒญ์ด ๋งŽ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค.
  • ์—…๋กœ๋“œ ๋Œ€์ƒ์€ workshop/**, examples/**, -demo ๋ชจ๋“ˆ์„ ์ œ์™ธํ•œ publishable modules ์ž…๋‹ˆ๋‹ค.
  • Snapshot ์ €์žฅ์†Œ๋Š” https://central.sonatype.com/repository/maven-snapshots/ ์ž…๋‹ˆ๋‹ค.
  • ๋ณ‘๋ ฌ๋„๋Š” centralSnapshotsParallelism property ๋กœ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ 8 ์ž…๋‹ˆ๋‹ค.

Maven Central RELEASE ๋ฐฐํฌ

# snapshotVersion์„ ์ œ๊ฑฐํ•˜๊ณ  RELEASE ๋ฐฐํฌ
./gradlew publishAggregationToCentralPortal -PsnapshotVersion= --no-daemon --no-configuration-cache
  • ๋ฃจํŠธ ์ง‘๊ณ„ task๋Š” publishAggregationToCentralPortal ์ž…๋‹ˆ๋‹ค.
  • RELEASE ๋ฐฐํฌ๋Š” NMCP aggregation ZIP ์„ ๋งŒ๋“ค์–ด Central Portal Publisher API ๋กœ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  • SNAPSHOT๊ณผ ๋‹ฌ๋ฆฌ artifact ํŒŒ์ผ๋“ค์„ ๊ฐœ๋ณ„ PUT ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์š”์ฒญ ์ˆ˜๊ฐ€ ํ›จ์”ฌ ์ ์Šต๋‹ˆ๋‹ค.
  • ์—…๋กœ๋“œ ๋Œ€์ƒ์€ workshop/**, examples/**, -demo ๋ชจ๋“ˆ์„ ์ œ์™ธํ•œ publishable modules ์ž…๋‹ˆ๋‹ค.
  • ๋™์ผ RELEASE ๋ฒ„์ „์€ ์žฌ๋ฐฐํฌํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์‹คํŒจ ์‹œ baseVersion์„ ์˜ฌ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•„์ˆ˜ ์„ค์ • (~/.gradle/gradle.properties)

# Sonatype Central Portal ๊ณ„์ •
central.user=your-central-portal-username
central.password=your-central-portal-password

# ๊ถŒ์žฅ: In-memory PGP signing
signingUseGpgCmd=false
signingKeyId=YOUR_KEY_ID
signingKey=-----BEGIN PGP PRIVATE KEY BLOCK-----\n...\n-----END PGP PRIVATE KEY BLOCK-----
signingPassword=YOUR_KEY_PASSPHRASE

# Maven Central Snapshots ์—…๋กœ๋“œ ๋ณ‘๋ ฌ๋„ (๊ธฐ๋ณธ๊ฐ’: 8)
centralSnapshotsParallelism=8

์ฐธ๊ณ 

  • ๊ธฐ์กด publishAggregationToCentralPortalSnapshots ๋Š” deprecated alias ์ด๋ฉฐ, publishAggregationToCentralSnapshots ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
  • publishAllPublicationsToCentralPortalSnapshots / publishAllPublicationsToCentralSnapshots ๊ฐ™์€ ๊ฐœ๋ณ„ task ์ง์ ‘ ์‹คํ–‰ ๋Œ€์‹  ๋ฃจํŠธ ์ง‘๊ณ„ task ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
  • SNAPSHOT์ด ๋А๋ฆฌ๊ฑฐ๋‚˜ ์š”์ฒญ์ด ๊ณผ๋„ํ•ด ๋ณด์ด๋ฉด centralSnapshotsParallelism ๊ฐ’์„ 4, 8, 12 ์ •๋„ ๋ฒ”์œ„์—์„œ ์กฐ์ ˆํ•ด ๋ณด์„ธ์š”.
  • RELEASE๋Š” aggregation ZIP ์—…๋กœ๋“œ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ SNAPSHOT๊ณผ ๋™์ž‘ ๋ฐฉ์‹์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

ํ† ํฐ ์ ˆ์•ฝํ˜• ์š”์•ฝ ๋ช…๋ น

AI ์—์ด์ „ํŠธ๋‚˜ ๊ธด ํ„ฐ๋ฏธ๋„ ์„ธ์…˜์—์„œ ์›์‹œ git/Gradle ์ถœ๋ ฅ์„ ๋ฐ”๋กœ ์—ด๊ธฐ ์ „์—, ์•„๋ž˜ ์š”์•ฝ ๋ช…๋ น์„ ๋จผ์ € ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

# ์ €์žฅ์†Œ ์ƒํƒœ ์š”์•ฝ
./bin/repo-status

# ํŒŒ์ผ๋ณ„ diff ๋ณ€๊ฒฝ๋Ÿ‰ ์š”์•ฝ
./bin/repo-diff

# Gradle ํ…Œ์ŠคํŠธ/๋นŒ๋“œ ๋กœ๊ทธ ์š”์•ฝ
./bin/repo-test-summary -- ./gradlew :05-exposed-dml:01-dml:test

๊ธฐ๋ณธ ํ๋ฆ„์€ "์š”์•ฝ ๋จผ์ €, ํ•„์š”ํ•œ ํŒŒ์ผ์ด๋‚˜ ํƒœ์Šคํฌ๋งŒ ์›๋ณธ ์ถœ๋ ฅ ํ™•์ธ"์ž…๋‹ˆ๋‹ค.