{"id":49326911,"url":"https://github.com/devnogi/open-api-batch-server","last_synced_at":"2026-04-26T20:32:42.472Z","repository":{"id":297919103,"uuid":"959504425","full_name":"devnogi/open-api-batch-server","owner":"devnogi","description":"데브노기 OPEN API Batch 마이크로서비스","archived":false,"fork":false,"pushed_at":"2026-03-05T14:50:46.000Z","size":1754,"stargazers_count":1,"open_issues_count":3,"forks_count":1,"subscribers_count":0,"default_branch":"dev","last_synced_at":"2026-03-05T16:19:36.084Z","etag":null,"topics":["mabinogi","mysql","openapi","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devnogi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2025-04-02T22:28:09.000Z","updated_at":"2026-03-05T14:56:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"73d63416-5631-4c05-858b-a760c2539a26","html_url":"https://github.com/devnogi/open-api-batch-server","commit_stats":null,"previous_names":["devnogi/open-api-batch-server"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/devnogi/open-api-batch-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devnogi%2Fopen-api-batch-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devnogi%2Fopen-api-batch-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devnogi%2Fopen-api-batch-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devnogi%2Fopen-api-batch-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devnogi","download_url":"https://codeload.github.com/devnogi/open-api-batch-server/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devnogi%2Fopen-api-batch-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32312365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T19:15:34.056Z","status":"ssl_error","status_checked_at":"2026-04-26T19:15:15.467Z","response_time":129,"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":["mabinogi","mysql","openapi","spring-boot"],"created_at":"2026-04-26T20:32:41.728Z","updated_at":"2026-04-26T20:32:42.467Z","avatar_url":"https://github.com/devnogi.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 마비노기 경매장 거래 내역 조회 및 통계 서비스\n\n[![codecov](https://codecov.io/gh/devnogi/open-api-batch-server/branch/dev/graph/badge.svg)](https://codecov.io/gh/devnogi/open-api-batch-server)\n[![License](https://img.shields.io/github/license/devnogi/open-api-batch-server)](LICENSE)\n[![Last Commit](https://img.shields.io/github/last-commit/devnogi/open-api-batch-server)](https://github.com/devnogi/open-api-batch-server)\n\n마비노기 경매장 거래 내역을 수집하고 분석하여 사용자에게 시세 정보를 제공하는 마이크로서비스입니다.\n\n\u003cbr\u003e\n\n## 주요 기능\n\n### 경매장 거래 내역 수집\n- 매 1시간마다 마비노기 경매장 거래 내역을 Nexon Open API를 통해 수집\n- 약 70개의 아이템 카테고리에 대한 커서 기반 페이지네이션으로 데이터 수집\n- 카테고리별 요청 간 딜레이 설정으로 API Rate Limit 준수\n\n### 실시간 경매장 데이터 수집\n- 10분 간격으로 현재 판매 중인 아이템 정보 수집\n- 만료된 아이템 자동 삭제\n- 거래 내역과 분리된 별도 테이블로 관리\n\n### 뿔피리 데이터 수집\n- 5분마다 거대한 외침의 뿔피리 내역 수집\n- 4개 서버 지원 (류트, 만돌린, 하프, 울프)\n- 지수 백오프 기반 재시도 로직 구현\n- **Elasticsearch 연동**: 한글 전문 검색 지원 (Ngram Parser)\n\n### 통계 분석\n- **일간 통계**: 경매 데이터 수집 완료 시 자동 트리거 (이벤트 기반)\n- **주간 통계**: 매주 월요일 04:00에 집계\n- **전일 통계**: 매일 00:10에 전일 통계 확정\n\n### 데이터 조회\n- 아이템별 최저가, 최고가, 평균가, 거래량 등 시세 조회\n- 서버별/전체 뿔피리 내역 조회\n- 아이템 옵션 필터링 (무기 공격력, 방어구 방어력, 세공 옵션 등)\n\n\u003cbr\u003e\n\n## 기술 스택\n\n| 분류 | 기술 |\n|------|------|\n| **Backend** | Java 21, Spring Boot 3.5.0, Spring Data JPA, QueryDSL |\n| **HTTP Client** | Spring WebFlux (WebClient) |\n| **Database** | MySQL 8, Flyway |\n| **Search Engine** | Elasticsearch (한글 전문 검색) |\n| **Security** | Spring Security, JWT |\n| **Test** | JUnit5, Mockito, AssertJ, Testcontainers |\n| **Code Quality** | Spotless (Google Java Format AOSP), Jacoco |\n| **Documentation** | Swagger (Springdoc OpenAPI), Spring REST Docs |\n| **DevOps** | Docker Compose, GitHub Actions |\n| **Deployment** | Oracle Cloud |\n\n\u003cbr\u003e\n\n## 프로젝트 구조\n\n```\nsrc/main/java/until/the/eternity/\n├── auctionhistory/          # 경매장 거래 내역 수집 및 검색\n├── auctionrealtime/         # 실시간 경매장 데이터 수집 (10분 간격)\n├── auctionitem/             # 경매장 아이템 엔티티\n├── auctionitemoption/       # 아이템 옵션 정보 (세공 옵션 포함)\n├── hornBugle/               # 뿔피리 내역 수집 및 검색 (Elasticsearch 연동)\n├── statistics/              # 일간/주간 통계 집계\n├── iteminfo/                # 아이템 메타데이터\n├── itemoptioninfo/          # 아이템 옵션 정보\n├── metalwareinfo/           # 금속류 아이템 정보\n├── auctionsearchoption/     # 검색 옵션 메타데이터\n├── common/                  # 공통 유틸리티, 예외, 필터\n└── config/                  # 설정 (Security, QueryDSL, Web, OpenAPI)\n```\n\n### 아키텍처 (Clean Architecture)\n```\ninterfaces/       # Controller, DTO, External API Client\n  └── rest/       # REST API 엔드포인트\n  └── external/   # 외부 API 연동 (Nexon Open API)\napplication/      # Service, Scheduler, Event\ndomain/           # Entity, Repository Port, Mapper\ninfrastructure/   # Repository 구현체, JPA\n```\n\n\u003cbr\u003e\n\n## API 엔드포인트\n\n### 경매장 거래 내역\n| Endpoint | Method | 설명 |\n|----------|--------|------|\n| `/auction-history/search` | GET | 경매 내역 검색 (필터 및 페이징) |\n| `/auction-history/{id}` | GET | 단일 거래 내역 조회 |\n| `/auction-history/batch` | POST | 배치 수동 실행 |\n\n### 실시간 경매장\n| Endpoint | Method | 설명 |\n|----------|--------|------|\n| `/auction-realtime/search` | GET | 현재 판매 중인 아이템 검색 |\n| `/auction-realtime/{id}` | GET | 단일 아이템 조회 |\n\n### 뿔피리\n| Endpoint | Method | 설명 |\n|----------|--------|------|\n| `/horn-bugle` | GET | 뿔피리 내역 검색 (서버별/전체) |\n| `/horn-bugle/batch` | POST | 뿔피리 배치 수동 실행 |\n\n### 통계\n| Endpoint | Method | 설명 |\n|----------|--------|------|\n| `/statistics/daily/items` | GET | 일간 아이템 통계 |\n| `/statistics/daily/subcategories` | GET | 일간 서브카테고리 통계 |\n| `/statistics/daily/top-categories` | GET | 일간 상위카테고리 통계 |\n| `/statistics/weekly/items` | GET | 주간 아이템 통계 |\n| `/statistics/weekly/subcategories` | GET | 주간 서브카테고리 통계 |\n| `/statistics/weekly/top-categories` | GET | 주간 상위카테고리 통계 |\n\n### 메타데이터\n| Endpoint | Method | 설명 |\n|----------|--------|------|\n| `/api/item-infos` | GET | 아이템 메타데이터 |\n| `/api/v1/item-option-infos` | GET | 아이템 옵션 정보 |\n| `/api/auction-search-options` | GET | 검색 옵션 메타데이터 |\n\n### 시스템\n| Endpoint | Method | 설명 |\n|----------|--------|------|\n| `/actuator/health` | GET | 헬스체크 |\n| `/swagger-ui/index.html` | - | API 문서 |\n\n\u003cbr\u003e\n\n## 스케줄러\n\n| 스케줄러 | Cron 표현식 | 설명 |\n|----------|-------------|------|\n| 경매 내역 수집 | `0 0 * * * *` | 매 시 정각 |\n| 실시간 경매장 수집 | `0 0/10 * * * *` | 10분마다 |\n| 뿔피리 수집 | `0 */5 * * * *` | 5분마다 |\n| 전일 통계 확정 | `0 10 0 * * *` | 매일 00:10 |\n| 주간 통계 집계 | `5 0 4 * * MON` | 매주 월요일 04:00 |\n\n\u003cbr\u003e\n\n## 환경 변수\n\n### 필수 환경 변수\n```bash\n# 서버\nSERVER_PORT=8080\n\n# 데이터베이스\nDB_IP=localhost\nDB_PORT=3306\nDB_SCHEMA=devnogi\nDB_USER=username\nDB_PASSWORD=password\n\n# JWT\nJWT_SECRET_KEY=your-secret-key\nJWT_ACCESS_TOKEN_VALIDITY=3600000\nJWT_REFRESH_TOKEN_VALIDITY=86400000\n\n# Nexon Open API\nNEXON_OPEN_API_KEY=your-api-key\n\n# Elasticsearch\nELASTICSEARCH_URIS=http://localhost:9200\nELASTICSEARCH_USERNAME=\nELASTICSEARCH_PASSWORD=\n```\n\n### 선택 환경 변수\n```bash\n# 경매 내역 배치\nAUCTION_HISTORY_CRON=0 0 * * * *\nAUCTION_HISTORY_DELAY_MS=1000\n\n# 실시간 경매장 배치\nAUCTION_REALTIME_CRON=0 0/10 * * * *\nAUCTION_REALTIME_DELAY_MS=500\n\n# 뿔피리 배치\nHORN_BUGLE_CRON=0 */5 * * * *\nHORN_BUGLE_MAX_RETRIES=3\nHORN_BUGLE_RETRY_DELAY_MS=2000\n\n# Elasticsearch 기능\nELASTICSEARCH_ENABLED=true\nELASTICSEARCH_INDEX_ENABLED=true\n\n# 통계\nSTATISTICS_PREVIOUS_DAY_CRON=0 10 0 * * *\nSTATISTICS_WEEKLY_CRON=5 0 4 * * MON\n```\n\n\u003cbr\u003e\n\n## 로컬 개발 환경 (Docker)\n\n### 1. 환경 설정\n\n```bash\n# .env.local.sample을 복사하여 .env.local 생성\ncp .env.local.sample .env.local\n\n# .env.local 파일 수정\n# - NEXON_OPEN_API_KEY: Nexon Open API 키\n# - DB_PASSWORD: 로컬 MySQL 비밀번호\n```\n\n### 2. Docker로 실행\n\n```bash\n# 빌드 및 실행\ndocker-compose -f docker-compose-local.yml --env-file .env.local up --build\n\n# 백그라운드 실행\ndocker-compose -f docker-compose-local.yml --env-file .env.local up -d --build\n\n# 로그 확인\ndocker-compose -f docker-compose-local.yml logs -f spring-app\n\n# 중지\ndocker-compose -f docker-compose-local.yml down\n```\n\n### 3. 환경별 Docker Compose 파일\n\n| 환경 | 파일 | 설명 |\n|------|------|------|\n| 로컬 개발 | `docker-compose-local.yml` | 로컬 빌드, MySQL, Elasticsearch 포함 |\n| 개발 서버 | `docker-compose-dev.yml` | 개발 환경 배포, Autoheal 컨테이너 포함 |\n| 운영 서버 | `docker-compose-prod.yml` | 운영 환경 배포, 높은 리소스 할당 |\n\n\u003cbr\u003e\n\n## 빌드 및 테스트\n\n```bash\n# 빌드\n./gradlew clean build\n\n# 테스트\n./gradlew test\n\n# 코드 포맷팅\n./gradlew spotlessApply\n\n# 테스트 커버리지 리포트\n./gradlew jacocoTestReport\n\n# REST Docs 생성\n./gradlew asciidoctor\n\n# 로컬 실행\n./gradlew bootRun\n```\n\n\u003cbr\u003e\n\n## 데이터베이스 스키마\n\nFlyway를 통한 마이그레이션 관리 (17개 버전)\n\n### 주요 테이블\n| 테이블 | 설명 |\n|--------|------|\n| `auction_history` | 경매장 거래 내역 |\n| `auction_realtime_item` | 현재 판매 중인 아이템 |\n| `auction_history_item_option` | 거래 아이템 옵션 (세공 포함) |\n| `auction_realtime_item_option` | 실시간 아이템 옵션 |\n| `horn_bugle_world_history` | 뿔피리 내역 (FULLTEXT 인덱스) |\n| `item_daily_statistics` | 일간 아이템 통계 |\n| `item_weekly_statistics` | 주간 아이템 통계 |\n| `subcategory_daily_statistics` | 일간 서브카테고리 통계 |\n| `subcategory_weekly_statistics` | 주간 서브카테고리 통계 |\n| `top_category_daily_statistics` | 일간 상위카테고리 통계 |\n| `top_category_weekly_statistics` | 주간 상위카테고리 통계 |\n| `item_info` | 아이템 메타데이터 |\n| `item_option_value_info` | 아이템 옵션 정보 |\n| `metalware_info` | 금속류 정보 |\n\n\u003cbr\u003e\n\n## API 응답 형식\n\n```json\n{\n  \"success\": true,\n  \"code\": \"string\",\n  \"message\": \"string\",\n  \"data\": {},\n  \"timestamp\": \"2025-01-01T12:00:00Z\"\n}\n```\n\n\u003cbr\u003e\n\n## 개발자 문서\n\n- **실행 방법**: [Notion - How to run](https://periwinkle-bridge-1c6.notion.site/How-to-run-2385c107dcf380f993d8e733d664caf9)\n- **API 명세서**: [Notion - API 명세서](https://periwinkle-bridge-1c6.notion.site/API-2195c107dcf380f2a465f9840b5d5dbf)\n- **Git branch 전략**: Git-flow ([관련 블로그](https://velog.io/@kw2577/Git-branch-%EC%A0%84%EB%9E%B5))\n\n\u003cbr\u003e\n\n## 지원 아이템 카테고리\n\n약 70개의 마비노기 아이템 카테고리 지원:\n- **전투 장비**: 한손/양손 무기, 검, 도끼, 둔기, 랜스 등\n- **원거리 장비**: 활, 석궁, 총, 수리검, 아틀라틀\n- **마법 장비**: 실린더, 스태프, 완드, 마법서, 오브\n- **방어구**: 중갑/경갑/천옷, 장갑, 신발, 모자, 방패, 로브\n- **악세서리**: 얼굴 장식, 날개, 꼬리, 일반 악세서리\n- **특수 장비**: 악기, 라이프 도구, 마리오네트, 에코스톤, 유물\n- **소모품**: 물약, 음식, 허브, 던전 통행증, 보석, 염료\n- **강화 재료**: 인챈트 스크롤, 마법 가루, 설계도, 악마 스크롤\n- **서적**: 책, 페이지, 마비노벨\n- **구조물**: 의자, 팜 아일랜드 아이템\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevnogi%2Fopen-api-batch-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevnogi%2Fopen-api-batch-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevnogi%2Fopen-api-batch-server/lists"}