{"id":44003369,"url":"https://github.com/closeup1202/curve","last_synced_at":"2026-02-20T06:00:54.782Z","repository":{"id":336189173,"uuid":"1127778084","full_name":"closeup1202/curve","owner":"closeup1202","description":"Declarative Event Publishing Library for Spring Boot - Kafka, PII Protection, DLQ, Outbox Pattern","archived":false,"fork":false,"pushed_at":"2026-02-19T05:02:05.000Z","size":3944,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-19T07:10:57.822Z","etag":null,"topics":["event-driven","event-driven-architecture","event-management","java","kafka","microservices","outbox-pattern","pii-detection","spring","spring-boot"],"latest_commit_sha":null,"homepage":"https://closeup1202.github.io/curve/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/closeup1202.png","metadata":{"files":{"readme":"README.ko.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-04T15:22:58.000Z","updated_at":"2026-02-19T05:01:17.000Z","dependencies_parsed_at":"2026-02-03T20:00:24.066Z","dependency_job_id":null,"html_url":"https://github.com/closeup1202/curve","commit_stats":null,"previous_names":["closeup1202/curve"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/closeup1202/curve","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/closeup1202%2Fcurve","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/closeup1202%2Fcurve/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/closeup1202%2Fcurve/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/closeup1202%2Fcurve/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/closeup1202","download_url":"https://codeload.github.com/closeup1202/curve/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/closeup1202%2Fcurve/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29642902,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T05:21:04.652Z","status":"ssl_error","status_checked_at":"2026-02-20T05:21:04.238Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["event-driven","event-driven-architecture","event-management","java","kafka","microservices","outbox-pattern","pii-detection","spring","spring-boot"],"created_at":"2026-02-07T13:05:43.273Z","updated_at":"2026-02-20T06:00:54.776Z","avatar_url":"https://github.com/closeup1202.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Curve\n\n**Spring Boot 마이크로서비스를 위한 선언적 이벤트 발행 라이브러리**\n\n[![Java](https://img.shields.io/badge/Java-17-orange.svg)](https://openjdk.java.net/)\n[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.5.9-brightgreen.svg)](https://spring.io/projects/spring-boot)\n[![Kafka](https://img.shields.io/badge/Apache%20Kafka-3.0+-red.svg)](https://kafka.apache.org/)\n[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![CI](https://github.com/closeup1202/curve/actions/workflows/ci.yml/badge.svg)](https://github.com/closeup1202/curve/actions)\n[![codecov](https://codecov.io/gh/closeup1202/curve/branch/main/graph/badge.svg)](https://codecov.io/gh/closeup1202/curve)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=closeup1202_curve\u0026metric=alert_status)](https://sonarcloud.io/project/overview?id=closeup1202_curve)\n\n[English](README.md) | [한국어](README.ko.md)\n\n\u003c/div\u003e\n\n---\n\n## Project Stats\n\n![GitHub stars](https://img.shields.io/github/stars/closeup1202/curve?style=social)\n![Maven Central](https://img.shields.io/maven-central/v/io.github.closeup1202/curve)\n![GitHub last commit](https://img.shields.io/github/last-commit/closeup1202/curve)\n\n---\n\n## Quick Start\n\n```java\n// 어노테이션 하나만 추가하면 끝!\n@PublishEvent(eventType = \"USER_CREATED\")\npublic User createUser(CreateUserRequest request) {\n    return userRepository.save(new User(request));\n}\n```\n\n**→ Kafka 자동 발행 + PII 마스킹 + 실패 시 DLQ + 메트릭 수집** ✨\n\n\u003c!-- 데모 GIF 추가: ![Demo](docs/demo.gif) --\u003e\n\n---\n\n## Why Curve?\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n### Before (기존 방식)\n```java\n// 50줄 이상의 보일러플레이트 코드\n@Service\npublic class UserService {\n\n    @Autowired\n    private KafkaTemplate\u003cString, Object\u003e kafka;\n\n    @Autowired\n    private ObjectMapper objectMapper;\n\n    public User createUser(UserRequest request) {\n        User user = userRepository.save(\n            new User(request)\n        );\n\n        try {\n            // 수동으로 이벤트 생성\n            EventEnvelope event = EventEnvelope.builder()\n                .eventId(UUID.randomUUID().toString())\n                .eventType(\"USER_CREATED\")\n                .occurredAt(Instant.now())\n                .publishedAt(Instant.now())\n                .metadata(/* ... */)\n                .payload(/* ... */)\n                .build();\n\n            // 수동으로 PII 마스킹\n            String json = maskPii(\n                objectMapper.writeValueAsString(event)\n            );\n\n            // 수동으로 Kafka 전송 및 재시도\n            kafka.send(\"user-events\", json)\n                .get(30, TimeUnit.SECONDS);\n\n        } catch (Exception e) {\n            // 수동으로 에러 처리\n            log.error(\"Failed to publish event\", e);\n            sendToDlq(event);\n        }\n\n        return user;\n    }\n}\n```\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\n### After (Curve)\n```java\n// 어노테이션 하나만!\n@Service\npublic class UserService {\n\n    @PublishEvent(eventType = \"USER_CREATED\")\n    public User createUser(UserRequest request) {\n        return userRepository.save(\n            new User(request)\n        );\n    }\n}\n```\n\n**코드 90% 감소**\n\n모든 것이 자동으로 처리됩니다:\n- ✅ 이벤트 ID 생성\n- ✅ 메타데이터 추출\n- ✅ PII 마스킹\n- ✅ Kafka 발행\n- ✅ 재시도 \u0026 DLQ\n- ✅ 메트릭 수집\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n---\n\n## Key Features\n\n### 선언적 이벤트 발행\nKafka 보일러플레이트 코드 불필요 - `@PublishEvent` 어노테이션만 추가. SpEL을 통한 유연한 페이로드 추출 지원.\n\n### 표준화된 이벤트 구조\n모든 이벤트가 메타데이터(source, actor, trace, tags)를 포함한 통일된 스키마 사용\n\n### 3단계 장애 복구\n**Main Topic → DLQ → 로컬 파일 백업**\nKafka가 24시간 장애여도 이벤트 손실 제로\n\n### 자동 PII 보호\n`@PiiField` 어노테이션으로 민감 데이터 자동 마스킹/암호화. **AWS KMS** 및 **HashiCorp Vault** 키 관리 지원.\n\n### 고성능\n- **동기 모드**: ~500 TPS\n- **비동기 모드**: ~10,000+ TPS (MDC 컨텍스트 전파 포함)\n- **Transactional Outbox**: 원자성 및 일관성 보장\n\n### Hexagonal Architecture\n최대 유연성을 위한 프레임워크 독립적 코어\n\n### 내장 관찰성\n- Spring Actuator Health Indicator\n- 커스텀 메트릭 엔드포인트 (`/actuator/curve-metrics`)\n- 상세한 이벤트 추적\n- **비동기 컨텍스트 전파**: 비동기 스레드에서도 MDC(Trace ID)가 유지됩니다.\n\n### 테스트 용이성\n- Kafka 없이 단위/통합 테스트를 할 수 있는 `MockEventProducer` 제공.\n\n---\n\n## Quick Start\n\n### 1. 의존성 추가\n\n**Gradle (build.gradle)**\n```gradle\ndependencies {\n    implementation 'io.github.closeup1202:curve:0.1.2'\n}\n```\n\n**Maven (pom.xml)**\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.closeup1202\u003c/groupId\u003e\n    \u003cartifactId\u003ecurve\u003c/artifactId\u003e\n    \u003cversion\u003e0.1.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### 2. 설정\n\n**application.yml**\n```yaml\nspring:\n  kafka:\n    bootstrap-servers: localhost:9092\n\ncurve:\n  enabled: true\n  kafka:\n    topic: event.audit.v1\n    dlq-topic: event.audit.dlq.v1\n```\n\n### 3. 사용\n\n```java\nimport io.github.closeup1202.curve.spring.audit.annotation.PublishEvent;\nimport io.github.closeup1202.curve.core.type.EventSeverity;\n\n@Service\npublic class OrderService {\n\n    @PublishEvent(\n        eventType = \"ORDER_CREATED\",\n        severity = EventSeverity.INFO\n    )\n    public Order createOrder(OrderRequest request) {\n        // 비즈니스 로직\n        return orderRepository.save(new Order(request));\n    }\n}\n```\n\n### 4. 로컬 Kafka 실행\n\n```bash\ndocker-compose up -d\n```\n\n### 5. 확인\n\n- **Kafka UI**: http://localhost:8080\n- **Health Check**: http://localhost:8081/actuator/health/curve\n- **메트릭**: http://localhost:8081/actuator/curve-metrics\n\n---\n\n## Comparison\n\n| 기능 | Spring Events | Spring Cloud Stream | Curve |\n|---------|--------------|---------------------|-------|\n| Kafka 연동 | ❌ | ✅ | ✅ |\n| 선언적 사용 | ✅ | △ | ✅ |\n| 표준화된 스키마 | ❌ | ❌ | ✅ |\n| PII 보호 | ❌ | ❌ | ✅ |\n| KMS 통합 | ❌ | ❌ | ✅ |\n| DLQ 지원 | ❌ | ✅ | ✅ |\n| 로컬 파일 백업 | ❌ | ❌ | ✅ |\n| Health Check | ❌ | ❌ | ✅ |\n| 커스텀 메트릭 | ❌ | ❌ | ✅ |\n| Snowflake ID | ❌ | ❌ | ✅ |\n| Transactional Outbox | ❌ | ❌ | ✅ |\n| **보일러플레이트** | **중간** | **많음** | **최소** |\n\n---\n\n## Architecture\n\n### Hexagonal Architecture (Ports \u0026 Adapters)\n\n```mermaid\ngraph TB\n    A[Domain Layer Core] --\u003e B[Spring Adapter]\n    A --\u003e C[Kafka Adapter]\n    B --\u003e D[AOP / Context]\n    C --\u003e E[Producer / DLQ]\n\n    style A fill:#4051b5\n    style B fill:#00897b\n    style C fill:#00897b\n```\n\n### System Context\n\n```mermaid\ngraph LR\n   User[User Service] --\u003e|\"@PublishEvent\"| Curve[Curve Library]\n    \n    subgraph Curve Library\n        Context[Context Extractor]\n        PII[PII Masking]\n        Outbox[Outbox Saver]\n        Producer[Kafka Producer]\n    end\n\n    Curve --\u003e|Sync/Async| Kafka[Kafka Topic]\n    Curve --\u003e|Transaction| DB[(Database)]\n    \n    DB --\u003e|Polling| Producer\n    Producer --\u003e|Retry/DLQ| Kafka\n```\n\n\n### Module Structure\n\n```\ncurve/\n├── core/                          # 순수 도메인 모델 (프레임워크 독립)\n│   ├── envelope/                  # EventEnvelope, EventMetadata\n│   ├── port/                      # EventProducer, IdGenerator (인터페이스)\n│   ├── context/                   # ContextProvider (인터페이스)\n│   ├── validation/                # EventValidator\n│   └── exception/                 # 도메인 예외\n│\n├── spring/                        # Spring Framework 어댑터\n│   ├── aop/                       # @PublishEvent Aspect\n│   ├── context/                   # Spring 기반 Context Provider 구현\n│   ├── factory/                   # EventEnvelopeFactory\n│   ├── infrastructure/            # SnowflakeIdGenerator, UtcClockProvider\n│   ├── publisher/                 # AbstractEventPublisher\n│   └── test/                      # 테스트 유틸리티 (MockEventProducer)\n│\n├── kafka/                         # Kafka 어댑터\n│   ├── producer/                  # KafkaEventProducer\n│   └── dlq/                       # FailedEventRecord\n│\n├── kms/                           # KMS 어댑터\n│   ├── provider/                  # AwsKmsProvider, VaultKeyProvider\n│   └── autoconfigure/             # KMS 자동 설정\n│\n└── spring-boot-autoconfigure/     # Spring Boot 자동 설정\n    ├── CurveAutoConfiguration     # 메인 설정\n    ├── CurveProperties            # 설정 속성\n    └── health/                    # Health indicator \u0026 메트릭\n```\n\n### Core Design Principles\n\n1. **의존성 역전 원칙 (DIP)**\n   - Core 모듈은 프레임워크 의존성 제로\n   - Port 인터페이스를 통해 외부 의존성 격리\n\n2. **단일 책임 원칙 (SRP)**\n   - 각 ContextProvider는 하나의 책임만 처리\n   - EventValidator는 검증만, EventProducer는 발행만\n\n3. **개방-폐쇄 원칙 (OCP)**\n   - EventProducer 인터페이스로 Kafka 외 다른 브로커 사용 가능\n   - ContextProvider 구현체 교체 가능\n\n---\n\n## Use Cases\n\n### 1. 감사 로깅\n```java\n@PublishEvent(eventType = \"USER_LOGIN\", severity = INFO)\npublic User login(String username, String password) {\n    return authService.authenticate(username, password);\n}\n```\n\n### 2. 이벤트 기반 아키텍처\n```java\n@PublishEvent(eventType = \"ORDER_COMPLETED\")\npublic Order completeOrder(Long orderId) {\n    Order order = orderRepository.findById(orderId);\n    order.setStatus(OrderStatus.COMPLETED);\n    return orderRepository.save(order);\n}\n```\n\n### 3. 데이터 파이프라인\n```java\n@PublishEvent(eventType = \"CUSTOMER_REGISTERED\")\npublic Customer registerCustomer(CustomerRequest request) {\n    // 이벤트가 자동으로 데이터 레이크/웨어하우스로 전달\n    return customerRepository.save(new Customer(request));\n}\n```\n\n---\n\n## Security Features\n\n### Automatic PII Protection\n\n```java\npublic class UserEventPayload implements DomainEventPayload {\n\n    @PiiField(type = PiiType.EMAIL, strategy = PiiStrategy.MASK)\n    private String email;  // \"user@example.com\" → \"user@***.com\"\n\n    @PiiField(type = PiiType.PHONE, strategy = PiiStrategy.ENCRYPT)\n    private String phone;  // AES-256-GCM 암호화\n\n    @PiiField(type = PiiType.NAME, strategy = PiiStrategy.HASH)\n    private String name;   // HMAC-SHA256 해싱\n}\n```\n\n**지원되는 전략:**\n- **MASK**: 패턴 기반 마스킹 (예: `j***@gm***.com`)\n- **ENCRYPT**: AES-256-GCM 암호화 (복원 가능, Base64 인코딩된 32바이트 키 필요)\n- **HASH**: HMAC-SHA256 해싱 (복원 불가, salt 권장)\n\n**KMS 지원:**\n- **AWS KMS**: Envelope 암호화 및 DEK 캐싱 지원\n- **HashiCorp Vault**: 중앙 집중식 키 관리 지원\n\n**설정:**\n```yaml\ncurve:\n  pii:\n    enabled: true\n    kms:\n      enabled: true\n      type: aws  # 또는 vault\n      aws:\n        region: us-east-1\n        default-key-arn: arn:aws:kms:us-east-1:123456789012:key/uuid\n```\n\n---\n\n## Observability\n\n### Health Check\n\n```bash\ncurl http://localhost:8081/actuator/health/curve\n```\n\n**응답:**\n```json\n{\n  \"status\": \"UP\",\n  \"details\": {\n    \"kafkaProducerInitialized\": true,\n    \"clusterId\": \"lkc-abc123\",\n    \"nodeCount\": 3,\n    \"topic\": \"event.audit.v1\",\n    \"dlqTopic\": \"event.audit.dlq.v1\"\n  }\n}\n```\n\n### Custom Metrics Endpoint\n\n```bash\ncurl http://localhost:8081/actuator/curve-metrics\n```\n\n**응답:**\n```json\n{\n  \"summary\": {\n    \"totalEventsPublished\": 1523,\n    \"successfulEvents\": 1520,\n    \"failedEvents\": 3,\n    \"successRate\": \"99.80%\",\n    \"totalDlqEvents\": 3,\n    \"totalKafkaErrors\": 0\n  },\n  \"events\": {\n    \"published\": [...],\n    \"publishDuration\": [...]\n  },\n  \"dlq\": {...},\n  \"kafka\": {...}\n}\n```\n\n---\n\n## Configuration\n\n### Full Configuration Example\n\n```yaml\ncurve:\n  enabled: true\n\n  id-generator:\n    worker-id: 1  # 0-1023, 인스턴스마다 고유\n    auto-generate: false\n\n  async:\n    enabled: false  # 전용 비동기 실행기 활성화\n    core-pool-size: 2\n    max-pool-size: 10\n    queue-capacity: 500\n\n  kafka:\n    topic: event.audit.v1\n    dlq-topic: event.audit.dlq.v1\n    retries: 3\n    retry-backoff-ms: 1000\n    request-timeout-ms: 30000\n    sync-timeout-seconds: 30\n    async-mode: false  # 높은 처리량을 위해 true\n    async-timeout-ms: 5000\n\n  retry:\n    enabled: true\n    max-attempts: 3\n    initial-interval: 1000\n    multiplier: 2.0\n    max-interval: 10000\n\n  security:\n    use-forwarded-headers: false  # 프록시 뒤에서는 true\n\n  pii:\n    enabled: true\n    crypto:\n      default-key: ${PII_ENCRYPTION_KEY}  # Base64 인코딩된 32바이트 AES-256 키\n      salt: ${PII_HASH_SALT}\n    kms:\n      enabled: false  # KMS 사용 시 true로 설정\n      type: aws  # aws 또는 vault\n\n  outbox:\n    enabled: true\n    publisher-enabled: true  # CDC 기반 발행 시 false\n    poll-interval-ms: 1000\n    batch-size: 100\n    max-retries: 3\n    send-timeout-seconds: 10\n    dynamic-batching-enabled: true\n    circuit-breaker-enabled: true\n    cleanup-enabled: true\n    retention-days: 7\n    cleanup-cron: \"0 0 2 * * *\"\n\n  serde:\n    type: JSON  # JSON, AVRO, PROTOBUF\n    # schema-registry-url: http://localhost:8081  # AVRO 사용 시 필수\n```\n\n### Avro Serialization (Optional)\n\nAvro 직렬화(`serde.type: AVRO`)를 사용하려면 다음 의존성을 추가하세요:\n\n**build.gradle:**\n```groovy\nrepositories {\n    mavenCentral()\n    maven { url 'https://packages.confluent.io/maven/' }\n}\n\ndependencies {\n    implementation 'org.apache.avro:avro:1.11.4'\n    implementation 'io.confluent:kafka-avro-serializer:7.5.0'\n}\n```\n\n\u003e **참고**: JSON 직렬화는 추가 의존성 없이 바로 사용 가능합니다.\n\n### Environment-Specific Profiles\n\n**개발:**\n```yaml\nspring:\n  config:\n    activate:\n      on-profile: dev\n\ncurve:\n  kafka:\n    async-mode: true  # 빠른 반복\n    topic: event.audit.dev.v1\n```\n\n**프로덕션:**\n```yaml\nspring:\n  config:\n    activate:\n      on-profile: prod\n\ncurve:\n  id-generator:\n    worker-id: ${POD_ORDINAL}  # Kubernetes StatefulSet\n  kafka:\n    async-mode: false  # 안정성 우선\n    retries: 5\n```\n\n자세한 내용은 [설정 가이드](docs/CONFIGURATION.md)를 참고하세요.\n\n---\n\n## Advanced Features\n\n### 1. Snowflake ID Generator\n\n충돌 없는 분산 고유 ID 생성.\n\n**구조:**\n```\n| 42비트: 타임스탬프 | 10비트: Worker ID | 12비트: Sequence |\n```\n\n**용량:**\n- 최대 **1,024 워커**\n- **밀리초당 4,096개 ID** (워커당)\n- **시간 정렬 가능**\n\n### 2. Transactional Outbox Pattern\n\nDB 트랜잭션과 이벤트 발행의 원자성을 보장합니다.\n\n- **지수 백오프(Exponential Backoff)**: 실패한 이벤트를 1초, 2초, 4초... 간격으로 재시도하여 DB 부하를 줄입니다.\n- **SKIP LOCKED**: 다중 인스턴스 환경에서 중복 처리를 방지하기 위해 비관적 락을 사용합니다.\n\n```java\n@Transactional\n@PublishEvent(\n    eventType = \"ORDER_CREATED\",\n    outbox = true,\n    aggregateType = \"Order\",\n    aggregateId = \"#result.orderId\"\n)\npublic Order createOrder(OrderRequest req) {\n    return orderRepo.save(new Order(req));\n}\n```\n\n### 3. Flexible Payload Extraction (SpEL)\n\nSpEL을 사용하여 이벤트 페이로드로 사용할 데이터를 유연하게 추출합니다.\n\n```java\n@PublishEvent(\n    eventType = \"USER_UPDATED\",\n    payload = \"#args[0].toEventDto()\"\n)\npublic User updateUser(UserUpdateRequest request) {\n    // ...\n}\n```\n\n### 4. Custom Event Producer\n\nKafka가 아닌 다른 브로커를 위해 `EventProducer` 인터페이스 구현:\n\n```java\n@Component\npublic class RabbitMqEventProducer extends AbstractEventPublisher {\n\n    private final RabbitTemplate rabbitTemplate;\n\n    @Override\n    protected \u003cT extends DomainEventPayload\u003e void send(EventEnvelope\u003cT\u003e envelope) {\n        String json = objectMapper.writeValueAsString(envelope);\n        rabbitTemplate.convertAndSend(exchange, routingKey, json);\n    }\n}\n```\n\n### 5. DLQ Recovery\n\n```bash\n# 백업 파일 목록\n./scripts/dlq-recovery.sh --list\n\n# 모든 파일 복구\n./scripts/dlq-recovery.sh --topic event.audit.v1 --broker localhost:9094\n\n# 특정 파일 복구\n./scripts/dlq-recovery.sh --file 1234567890.json --topic event.audit.v1\n```\n\n---\n\n## Roadmap\n\n### v0.1.0 (2026년 2분기)\n- [ ] 성능 벤치마크 \u0026 최적화 가이드\n- [ ] GraphQL 구독 지원\n- [ ] AWS EventBridge 어댑터\n- [ ] Grafana 대시보드 템플릿\n- [ ] 추가 PII 타입 프리셋 (주민등록번호, 신용카드 등)\n\n### v1.0.0 (2026년 3분기)\n- [ ] 프로덕션 준비 릴리스\n- [ ] Spring Cloud Stream 바인더\n- [ ] Avro 스키마 진화 지원\n- [ ] gRPC 이벤트 스트리밍\n- [ ] 멀티 클라우드 KMS 지원 (GCP, Azure)\n\n**아이디어가 있으신가요?** [GitHub Discussions](https://github.com/closeup1202/curve/discussions)에서 기능에 투표하거나 새로운 기능을 제안해주세요 💡\n\n---\n\n## Documentation\n\n| 문서 | 설명 |\n|------|------|\n| [설정 가이드](docs/CONFIGURATION.md) | 상세 설정 옵션 |\n| [운영 가이드](docs/OPERATIONS.md) | 프로덕션 운영 및 모범 사례 |\n| [문제 해결](docs/TROUBLESHOOTING.md) | 일반적인 문제 및 해결 방법 |\n| [모니터링 가이드](docs/MONITORING.md) | 메트릭, 대시보드, 알림 설정 |\n| [마이그레이션 가이드](docs/MIGRATION.md) | 버전 업그레이드 지침 |\n| [변경 이력](docs/CHANGELOG.md) | 버전 히스토리 및 변경 사항 |\n| [예시 설정](application.example.yml) | 설정 예시 |\n| [샘플 애플리케이션](sample/) | 완전한 작동 예시\n\n---\n\n## Community \u0026 Support\n\nCurve 커뮤니티에 참여하세요:\n\n- 💬 **[GitHub Discussions](https://github.com/closeup1202/curve/discussions)** - 질문하기, 아이디어 공유, 도움 받기\n- 🐛 **[Issues](https://github.com/closeup1202/curve/issues)** - 버그 신고, 기능 요청\n- 🤝 **[Contributing](docs/community/contributing.md)** - 기여 가이드라인\n\n**프로덕션에서 Curve를 사용하고 계신가요?** 여러분의 이야기를 들려주세요! [Discussions](https://github.com/closeup1202/curve/discussions)에서 공유하시면 여기에 소개해드립니다 🌟\n\n---\n\n## Contributing\n\n기여를 환영합니다! Pull Request를 자유롭게 제출해주세요.\n\n가이드라인은 [CONTRIBUTING.md](docs/community/contributing.md)를 참고하세요.\n\n---\n\n## License\n\n이 프로젝트는 MIT 라이선스로 배포됩니다 - 자세한 내용은 [LICENSE](LICENSE) 파일을 참고하세요.\n\n---\n\n## Acknowledgments\n\n- **Spring Cloud Stream**과 **Spring Kafka**에서 영감을 받았습니다\n- **Spring Boot**와 **Apache Kafka**로 구축되었습니다\n- **Alistair Cockburn**의 Hexagonal Architecture 패턴 적용\n\n---\n\n## Contact\n\n- **이슈**: [GitHub Issues](https://github.com/closeup1202/curve/issues)\n- **이메일**: closeup1202@gmail.com\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n[⬆ Back to top](#curve)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloseup1202%2Fcurve","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloseup1202%2Fcurve","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloseup1202%2Fcurve/lists"}