{"id":24440061,"url":"https://github.com/yuseogi0218/pos-system","last_synced_at":"2026-04-11T09:04:34.853Z","repository":{"id":268995675,"uuid":"906091157","full_name":"yuseogi0218/POS-system","owner":"yuseogi0218","description":"POS(Point of Sale) System Project","archived":false,"fork":false,"pushed_at":"2025-01-22T05:58:07.000Z","size":626,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-14T01:12:36.505Z","etag":null,"topics":["docker","docker-compose","grafana","java","mysql","prometheus","prometheus-pushgateway","redis","spring","spring-batch"],"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/yuseogi0218.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}},"created_at":"2024-12-20T06:30:09.000Z","updated_at":"2025-01-22T05:58:11.000Z","dependencies_parsed_at":"2024-12-20T08:17:43.334Z","dependency_job_id":"6e247fe4-5b7e-410a-af80-410df2c66426","html_url":"https://github.com/yuseogi0218/POS-system","commit_stats":null,"previous_names":["yuseogi0218/pos-system"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuseogi0218%2FPOS-system","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuseogi0218%2FPOS-system/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuseogi0218%2FPOS-system/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuseogi0218%2FPOS-system/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yuseogi0218","download_url":"https://codeload.github.com/yuseogi0218/POS-system/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243505959,"owners_count":20301618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["docker","docker-compose","grafana","java","mysql","prometheus","prometheus-pushgateway","redis","spring","spring-batch"],"created_at":"2025-01-20T20:27:59.608Z","updated_at":"2025-12-28T10:07:08.626Z","avatar_url":"https://github.com/yuseogi0218.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# POS 정산 시스템 \n### 프로젝트 기획 문서 🗂 → [링크](https://yuseogi0218.notion.site/POS-17e5a0fb7695816fa036d16d9dc9f609)\n\u003cimg width=\"711\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1bb8ade1-0c61-473b-9ce9-91119aaa6044\" /\u003e\n\n### 음식점을 대상으로 한 POS(Point Of Sale) 시스템 및 정산 시스템\n- 상점 주인과 고객을 위한 상품 주문 및 거래 완료(가상 결제) 기능 제공 \n- 상점 주인을 위한 상품 판매 통계 및 거래 정산을 위한 **배치 프로그램 및 확장성을 고려한 설계 적용**\n---\n\n**👨‍💻1인 프로젝트**\n\n**프로젝트 수행 기간** : 2024.12.18 ~ 2025.01.18\n\n### 사용 기술 스택\n**Backend**\n\n![Java](https://img.shields.io/badge/-Java-333333?style=flat\u0026logo=Java)\n![springboot](https://img.shields.io/badge/-springboot-333333?style=flat\u0026logo=springboot)\n![springdatajpa](https://img.shields.io/badge/-springdataJPA-333333?style=flat\u0026logo=spring)\n![springcloud](https://img.shields.io/badge/-springcloud-333333?style=flat\u0026logo=iCloud\u0026logoColor=6DB33F)\n![springbatch](https://img.shields.io/badge/-springbatch-333333?style=flat\u0026logo=Buffer\u0026logoColor=6DB33F)\n![springsecurity](https://img.shields.io/badge/-springsecurity-333333?style=flat\u0026logo=springsecurity)\n![JWT](https://img.shields.io/badge/-JWT-333333?style=flat\u0026logo=jsonwebtokens)\n![MySQL](https://img.shields.io/badge/-MySQL-333333?style=flat\u0026logo=mysql)\n![Redis](https://img.shields.io/badge/-Redis-333333?style=flat\u0026logo=Redis)\n![Kafka](https://img.shields.io/badge/-Kafka-333333?style=flat\u0026logo=apachekafka)\n\n**DevOps \u0026 Testing**\n\n![Git](https://img.shields.io/badge/-Git-333333?style=flat\u0026logo=git)\n![GitHub](https://img.shields.io/badge/-GitHub-333333?style=flat\u0026logo=github)\n![Docker](https://img.shields.io/badge/-Docker-333333?style=flat\u0026logo=docker)\n![Pushgateway](https://img.shields.io/badge/-Pushgateway-333333?style=flat\u0026logo=prometheus\u0026logoColor=2480E6)\n![Prometheus](https://img.shields.io/badge/-Prometheus-333333?style=flat\u0026logo=prometheus)\n![Grafana](https://img.shields.io/badge/-Grafana-333333?style=flat\u0026logo=grafana)\n![Postman](https://img.shields.io/badge/-Postman-333333?style=flat\u0026logo=postman)\n![AWS-EC2](https://img.shields.io/badge/-AmazonEC2-333333?style=flat\u0026logo=AmazonEC2)\n![AWS-RDS](https://img.shields.io/badge/-AmazonRDS-333333?style=flat\u0026logo=AmazonRDS)\n![JUnit](https://img.shields.io/badge/-JUnit5-333333?style=flat\u0026logo=JUnit5)\n\n---\n\n## Micro Service Architecture \u0026 ERD ⚙️\n\u003e 이미지 클릭 시, 확대하여 자세히 보실 수 있습니다.\n\n|Micro Service Architecture|ERD|\n|---|---|\n|![Micro Service Architecture](https://github.com/user-attachments/assets/d9b71c0c-35da-4237-8d3a-8a0a02e557f7)|![ERD](https://github.com/user-attachments/assets/db3acfb8-2c9c-432f-81a1-5614ab57b4d2)|\n\n---\n\n## 주요 비즈니스 기능 📦\n- User Domain\n  - 상점 주인 소셜(카카오) 회원가입 및 로그인 / 로그아웃\n- Store Domain\n  - 상점 주인에 의한 판매 상품 관리(CRUD)\n  - 상품 판매 통계 및 정산 데이터 조회\n- Trade Domain\n  - 주문용 태블릿 기기에 의한 상품 주문\n  - 현재 진행중인 거래의 주문 내역 조회\n  - 상점 주인에 의한 현재 진행중인 거래의 주문 내역에 대한 일괄 (현금/카드) 결제\n- Batch Server\n  - 1일, 1주(월요일 ~ 일요일), 1달 단위의 상품 판매 통계 데이터 생성\n  - 1일, 1달(상점별 정산일)의 정산 데이터 생성\n\n---\n\n## 기술적 경험 💻\n- **MSA 기반**으로 각 서비스의 확장성 제공 및 독립적인 운영 지원 \n- **Eureka** 서비스 디스커버리와 **API Gateway** 를 활용한 동적 서비스 등록 및 라우팅 구현\n- **JWT 인증** 필터를 API Gateway 에 적용하여 통합 인증 기능 구현\n- **OpenFeign** 을 통한 내・외부 모듈 통신 구현\n- **Choreography Saga 패턴** 적용을 통한 분산 환경에서의 트랜잭션 제어 (With Kafka)\n- **Prometheus With Pushgateway \u0026 Grafana** 를 통한 애플리케이션 및 배치 프로그램 모니터링 구성\n- **Docker Compose** 로 컨테이너 기반의 통합 개발/배포 환경 구성\n- **JUnit**을 활용한 통합 및 단위 테스트 코드 작성 - 비즈니스 코드 98% Line Coverage 달성\n\n---\n## Spring Batch 를 활용한 배치 프로그램 및 서비스 확장을 고려한 설계 적용\u003cbr\u003e→ 🔗 [자세히 보기](https://yuseogi0218.notion.site/Batch-Server-17e5a0fb7695815dba38f77c84460b1f)\n- 대용량 데이터 처리에 적합한 Chunk 기반 설계 적용\n- JdbcPagingItemReader 와 JdbcBatchItemWriter 를 활용한 배치 프로그램 구성\n\n\u003e **프로젝트 테스트 실행 환경**\n\u003e - 서버 자원 - AWS EC2 → t2.micro 인스턴스 (Free-Tier), 가상 CPU 1 core, 메모리 1GiB\n\u003e - 데이터베이스 자원 - AWS RDS → db.t4g.micro 인스턴스 (Free-Tier), 가상 CPU 2 core, 메모리 1GiB\n\u003e \n\u003e *보통 vCPU(가상 CPU) 는 물리 CPU 사양의 절반 정도의 성능을 가진다.*\n\n### Ver 1. GROUP BY + SUM 쿼리를 활용한 데이터 조회 시, 집계 수행\n\u003e 예를 들어 50만개의 상품에 대한 판매 데이터 1,000만개가 있다고 하자. 이때 집계 결과로 50만개의 상품 판매 통계 데이터가 생성되게 된다.\n\n![Architecture](https://github.com/user-attachments/assets/5eb9c3fd-7e20-44e0-9930-fba6973f36be)\n\n\n- 테스트 수행 결과 (3회 평균 시간)\n  \u003cbr\u003e\u003cbr\u003e\n  |Job|Input data 개수|Output data 개수|소요 시간|\n  |---|---|---|---|\n  |상품 판매 통계 데이터 생성\u003cbr\u003e(1달 기준)|2,791,000 건|1,000 건|33.761초|\n  |정산 데이터 생성\u003cbr\u003e(월정산)|930,100 건|100 건|4.907초|\n\n\n### GROUP BY + SUM 쿼리를 통한 집계 수행 시, 한계점\n- 데이터를 가져오는 시점부터 집계가 완료되어 처리 및 저장이 간단하다는 장점이 있음\n  \u003cbr\u003e\u003cbr\u003e\n- 하지만 집계 연산이 쿼리에 의존적이기 때문에 쿼리의 실행 계획이 복잡해지고, 이는 데이터베이스의 성능 저하로 이어질 수 있음\n  - 특히, 데이터베이스로부터 집계 데이터를 조회해오는 ItemReader는 배치 작업 전체 성능의 90% 이상을 좌우함\n- 또한 서비스의 도메인(데이터베이스 스키마) 증가 및 데이터 누적으로 인해 서비스의 규모가 커지면,\u003cbr\u003e집계 쿼리 작성 및 유지보수에 더 많은 리소스가 필요함 \n\n\n### Ver 2. 서비스 규모 증가 및 확장성을 고려한 배치 프로그램 설계 적용 → 🔗 [자세히 보기](https://yuseogi0218.notion.site/ItemReader-Group-by-Redis-Aggregation-17e5a0fb76958132bac6c59f1bbd1cfe)\n![New Architecture](https://github.com/user-attachments/assets/e75c6491-e747-4258-aadf-9a7c8d9e30d4)\n- Database에서 GROUP BY + SUM 쿼리를 통해서 수행하던 집계 역할을, Redis 가 대신 수행하는 설계\n  - 쿼리 작성 및 유지보수에 대한 리소스 절약과 쿼리 실행 계획의 단순화를 통해 대규모 데이터 처리 시, 성능 향상 기대\n  - Redis 의 O(1) 의 시간복잡도를 보장하는 hash 함수와 다수의 연산을 묶어서 Redis 에게 요청하는 Redis Pipeline 을 통한 성능 저하 방지\n\u003cbr\u003e\u003cbr\u003e\n- 테스트 수행 결과 (3회 평균 시간)\n  \u003cbr\u003e\u003cbr\u003e\n  |Job|Input data 개수|Output data 개수|소요 시간|\n  |---|---|---|---|\n  |상품 판매 통계 데이터 생성\u003cbr\u003e(1달 기준)|2,791,000 건|1,000 건|4분 17.106초|\n  |정산 데이터 생성\u003cbr\u003e(월정산)|930,100 건|100 건|43.984초|\n- 정산 데이터 생성 (월정산) 작업의 경우 기존 18분 4.17초에 수행되었지만, 내장 함수 제거와 인덱스 추가등의 쿼리 튜닝을 통해 43.984초로 단축 → **(95.94% 성능 개선)**\n\n### ⭐️ 프로젝트 Insight 💫\nVer 1 : GROUP BY + SUM 쿼리를 활용한 집계 수행, Ver 2 : Redis 를 활용한 집계 수행\n- 데이터가 작고 쿼리가 단순한 서비스의 초기 단계일 경우에는, Ver 1이 더 적합함\n  - 하지만 Ver 1 의 GROUP BY + SUM과 같은 쿼리는 연산이 데이터베이스에 의존적이며 성능 저하 및 난해한 쿼리 튜닝의 원인이 될 수 있음\n\u003cbr\u003e\u003cbr\u003e\n- 서비스의 도메인(데이터베이스 스키마) 증가 및 데이터 누적으로 인해 서비스의 규모가 커지면, Ver 2가 더 적합한 방법\n  - 데이터량이 증가하고 쿼리가 복잡해질수록 Ver 2가 시간 및 리소스 절약 측면에서 유리함\n  - 또한, 쿼리가 단순해져서 코드 작성 및 유지보수도 더욱 간결해질 수 있음\n\u003cbr\u003e\u003cbr\u003e\n- 결론적으로, 집계 연산을 어디에서 수행할지는 유지보수성과 성능의 균형이 중요한 요소\n  \u003cbr\u003e성능 기준점을 충족하는 범위 내에서, 서비스 특성과 확장성을 고려하여 유지보수에 적합한 설계를 선택하는 것이 최선의 선택\n\n---\n\n## 프로젝트 문서화 진행 🗒️ → [링크](https://yuseogi0218.notion.site/pos-settlement-system)\n- 프로젝트 진행 시, 내용 정리 및 진행사항 트래킹을 위해 문서화 작업 수행\n- 항해99 취업 리부트 코스 6기 - 우수 프로젝트 기록 선정\n  \u003cbr\u003e\u003cbr\u003e\n- **기능 명세서 📋** → [링크](https://yuseogi0218.notion.site/17e5a0fb769581f099eef1587bab2d7b)\n  - 서비스의 비즈니스 기능에 대한 상세 내용을 정리한 문서\n- **API 명세서 🛰️**️ → [링크](https://yuseogi0218.notion.site/API-17e5a0fb76958142b2c2f62329f4eb8d)\n  - 서비스의 비즈니스 기능에 대한 API 명세를 정리한 문서\n- **Error Code 🚫** → [링크](https://yuseogi0218.notion.site/Error-Code-17e5a0fb769581abbf2afbe4da2bf628)\n  - API 호출 시, 발생할 수 있는 예외 코드를 정리한 문서\n- **기술적 의사 결정️ ⚒️** → [링크](https://yuseogi0218.notion.site/17e5a0fb769581f39c33c981122bc2e0)\n  - 프로젝트 진행 시, 요구 사항을 구현하기 위한 기술 선택의 이유 및 근거를 정리한 문서\n\n---\n\n## 프로젝트 실행 방법 ⌨️\n1. Github Repository Clone\n2. Kakao 개발자 센터 App 등록 및 설정 For OAuth Login \n3. [.env](/.env) 파일 수정 - 환경 변수 설정 \n4. docker compose file 실행\n    ```shell\n    docker compose -f docker-compose.infrastructure.yml -p pos up -d\n    docker compose -f docker-compose.application.yml -p pos up -d\n    docker compose -f docker-compose.monitoring.yml -p pos up -d\n    ```\n5. database 접속 및 schema.sql 의 DDL 실행\n    - service-db (:3307)\n      - [user-domain](user-service/src/main/resources/database/schema.sql), [store-domain](store-service/src/main/resources/database/schema.sql), [trade-domain](trade-service/src/main/resources/database/schema.sql), [batch-server](batch-server/src/main/resources/database/schema.sql)\n    - meta-db (:3308)\n      - [batch-server](batch-server/src/main/resources/database/meta-schema.sql)\n---\n\n**프로젝트 참고**\n\u003e - [[우아한 형제들] 정산 시스템 팀을 소개합니다.](https://techblog.woowahan.com/2701/)\n\u003e - [[TossPayments] API 문서 - 정산](https://docs.tosspayments.com/reference#%EC%A0%95%EC%82%B0)\n\u003e - [[if kakao 2022] Batch Performance를 고려한 최선의 Aggregation](https://tech.kakaopay.com/post/ifkakao2022-batch-performance-aggregation/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuseogi0218%2Fpos-system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyuseogi0218%2Fpos-system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuseogi0218%2Fpos-system/lists"}