{"id":50678882,"url":"https://github.com/sjh9714/new-portfolio","last_synced_at":"2026-06-08T17:04:00.866Z","repository":{"id":359381436,"uuid":"1245535400","full_name":"sjh9714/new-portfolio","owner":"sjh9714","description":"Java/Spring 백엔드 포트폴리오 - 동시성, 이벤트 정합성, 실시간 메시징, 과금/정산 사례를 수치와 테스트로 정리한 사이트","archived":false,"fork":false,"pushed_at":"2026-05-21T20:15:29.000Z","size":368,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T00:49:54.673Z","etag":null,"topics":["backend","event-driven","idempotency","java","k6","kafka","nextjs","outbox-pattern","portfolio","postgresql","rabbitmq","redis","spring-boot","testcontainers","websocket"],"latest_commit_sha":null,"homepage":"https://new-portfolio-smoky-one-41.vercel.app","language":"TypeScript","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/sjh9714.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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-21T10:06:03.000Z","updated_at":"2026-05-21T20:15:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sjh9714/new-portfolio","commit_stats":null,"previous_names":["sjh9714/new-portfolio"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sjh9714/new-portfolio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjh9714%2Fnew-portfolio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjh9714%2Fnew-portfolio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjh9714%2Fnew-portfolio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjh9714%2Fnew-portfolio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sjh9714","download_url":"https://codeload.github.com/sjh9714/new-portfolio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjh9714%2Fnew-portfolio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34071688,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["backend","event-driven","idempotency","java","k6","kafka","nextjs","outbox-pattern","portfolio","postgresql","rabbitmq","redis","spring-boot","testcontainers","websocket"],"created_at":"2026-06-08T17:03:58.962Z","updated_at":"2026-06-08T17:04:00.860Z","avatar_url":"https://github.com/sjh9714.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 성진혁 Java/Spring 백엔드 포트폴리오\n\n고동시성 예약, 이벤트 정합성, 실시간 메시징, 멀티테넌트 과금 흐름을\n문제-설계-검증 근거로 읽히게 만든 한국 백엔드 개발자 포트폴리오입니다.\n\n- Live: [new-portfolio-smoky-one-41.vercel.app](https://new-portfolio-smoky-one-41.vercel.app)\n- Resume PDF: [resume-sung-jinhyuk-backend.pdf](public/resume-sung-jinhyuk-backend.pdf)\n- GitHub: [github.com/sjh9714](https://github.com/sjh9714)\n- Email: [jinhyuk9714@gmail.com](mailto:jinhyuk9714@gmail.com)\n- Redis 글: [Redis를 캐시로만 쓰지 않기 위해 구현한 대기열, 분산 락, Presence, 정합성 복구][redis-blog]\n\n## 30초 요약\n\n- 이 사이트가 증명하는 것:\n  Java/Spring 백엔드의 동시성, 이벤트 정합성, 실시간 메시징, 과금/정산 문제 해결입니다.\n- 가장 강한 근거:\n  동일 좌석 100 concurrent requests에서 success 1, fail 99, overselling 0을 기록했습니다.\n- 아직 주장하지 않는 것:\n  공개 운영 트래픽, production benchmark, compliance 수준의 보증은 주장하지 않습니다.\n\n## 대표 사례\n\n### [Concert Booking](https://new-portfolio-smoky-one-41.vercel.app/case-studies/concert-booking)\n\n- 문제: 동일 좌석 경합, 대기열 우회, 결제/만료 race, Kafka publish 실패\n- 설계: 좌석 락 전략, Queue token, Idempotency-Key, Outbox/DLT, Redis reconciliation\n- 근거: 동일 좌석 100 concurrent requests -\u003e success 1, fail 99, overselling 0\n- 검증: 예약/결제/만료 정합성 Testcontainers 시나리오 검증\n\n### [Realtime Chat](https://new-portfolio-smoky-one-41.vercel.app/case-studies/realtime-chat)\n\n- 문제: WebSocket 구독 권한, 순서, presence, reconnect 복구\n- 설계: STOMP 구독 인가, roomId key ordering, Redis presence, reconnect sync\n- 근거: 채팅방 조회 API 937 -\u003e 1,598 RPS, p95 212.85ms -\u003e 149.22ms\n- 경계: production/mixed delivery benchmark는 추가 측정 예정\n\n### [AI Usage Billing Gateway](https://new-portfolio-smoky-one-41.vercel.app/case-studies/ai-usage-billing-gateway)\n\n- 문제: organization 단위 사용량 수집, API key 보안, usage/webhook 중복 처리\n- 설계: tenant isolation, prefix/hash API key, idempotency, quota reservation, ledger\n- 근거: usage duplicate/conflict, webhook duplicate/conflict, ledger invariant 시나리오 검증\n- 측정: 2026-05-23 local full mixed repeat3\n\n## 기술 스택\n\n- Next.js App Router\n- TypeScript\n- Tailwind CSS\n- MDX case-study content\n- shadcn/ui primitives\n- lucide-react\n- Vitest content guard tests\n\n## 전체 아키텍처\n\n![new-portfolio 콘텐츠 아키텍처](public/architecture/overall/new-portfolio.svg)\n\nSVG 구조도는 `public/architecture/overall`과 `public/architecture/cases`에 둡니다.\n전체 구조도는 프로젝트 목록에서 맥락을 보여주고, 문제 구간 구조도는 각 사례 상세에서\n문제-설계-검증 근거를 읽는 순서를 보조합니다. PNG/JPG/WebP 스크린샷이나 근거 없는 운영\nclaim은 추가하지 않습니다.\n\n문제 구간 구조도는 raw SVG를 직접 수정하지 않고\n`src/architecture/specs/*.ts`의 nodes/edges 데이터에서 생성합니다.\n\n```bash\nnpm run generate:architecture\nnpm run check:architecture\n```\n\n전체 아키텍처 SVG(`public/architecture/overall/*.svg`)는 프로젝트 전체 맥락을 보여주는\n수동 문서 자산으로 유지하고, 문제 구간 SVG(`public/architecture/cases/*.svg`)는\ngenerator output으로 관리합니다. 작성 규칙은\n[`docs/ARCHITECTURE_SVG_RULES.md`](docs/ARCHITECTURE_SVG_RULES.md)에 정리했습니다.\n\n이 다이어그램은 구현된 핵심 흐름과 검증 대상 경계를 설명하기 위한 단순화된 구조도이며,\n운영 배포 토폴로지나 production SLO를 주장하지 않습니다.\n\n## GitHub 메타데이터\n\n- 실제 GitHub About topics:\n  `backend`, `portfolio`, `java`, `spring-boot`, `kafka`, `redis`, `rabbitmq`,\n  `postgresql`, `testcontainers`, `k6`, `event-driven`, `idempotency`,\n  `outbox-pattern`, `websocket`, `nextjs`\n\n## 검증 명령\n\n```bash\nnpm run ci\n```\n\n`npm run ci`는 아래 순서로 실행됩니다.\n\n```bash\nnpm run format:check\nnpm run typecheck\nnpm test\nnpm run lint\nnpm run build\n```\n\n## 콘텐츠 원칙\n\n프로젝트 근거는 `src/content/projects.ts`와 `src/content/case-studies/*.mdx`에 커밋된 내용만 사용합니다.\n\n- 수치가 있는 결과만 `측정 완료`로 표시합니다.\n- 반복 가능한 통합 테스트나 시나리오는 `시나리오 검증`으로 표시합니다.\n- 공개 운영 데이터나 추가 측정이 필요한 항목은 `추가 측정 예정`으로 표시합니다.\n- 운영 트래픽, production benchmark, compliance 같은 근거 없는 주장은 하지 않습니다.\n- README와 사이트 문구는 문제-설계-결과-근거 순서로 작성합니다.\n\n[redis-blog]: https://new-portfolio-smoky-one-41.vercel.app/blog/redis-queue-lock-presence-reconciliation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsjh9714%2Fnew-portfolio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsjh9714%2Fnew-portfolio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsjh9714%2Fnew-portfolio/lists"}