Skip to content
 
 

Latest commit

 

History

38 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🥔 POTATO

POTATO는 자취생이 직접 요리한 식사를 인증하고, 보상으로 받은 경험치와 재화 스푼으로 캐릭터를 성장시키는 식생활 습관 형성 서비스입니다.

🧭 시스템 작동 방식

  1. 사용자가 직접 요리한 식사를 인증합니다.
  2. 인증 결과에 따라 경험치와 서비스 재화인 스푼을 지급합니다.
  3. 사용자는 스푼으로 상점 아이템을 구매합니다.
  4. 구매한 아이템을 인벤토리에서 장착해 캐릭터를 성장시킵니다.
요리 인증 → 경험치·스푼 지급 → 아이템 구매 → 인벤토리 저장 → 캐릭터 장착

📦 저장소

  • Backend: Spring Boot 기반 API 서버
  • Frontend: React와 Vite 기반 웹 클라이언트

📁 폴더 구조

POTATO-119/
├── Backend/
│   ├── src/main/java/com/example/potato/
│   │   ├── controller/      # HTTP 요청 및 응답 처리
│   │   ├── service/         # 구매, 인벤토리 등 비즈니스 규칙
│   │   ├── repository/      # 데이터베이스 접근
│   │   ├── entity/          # 사용자, 아이템, 인벤토리 모델
│   │   ├── dto/             # API 요청·응답 데이터
│   │   └── config/          # CORS 및 애플리케이션 설정
│   ├── src/main/resources/  # DB 및 Spring Boot 설정
│   └── src/test/            # 백엔드 테스트
└── Frontend/
    ├── src/pages/           # 로그인, 회원가입, 홈 화면
    ├── src/features/        # 인증 등 도메인별 기능
    ├── src/components/      # 공통 및 화면 구성 컴포넌트
    ├── src/lib/             # Axios API 클라이언트
    ├── src/router/          # 화면 경로 설정
    ├── src/store/           # 클라이언트 상태 관리
    └── src/assets/          # 이미지와 정적 리소스

🛠 기술 스택

  • Backend: Java 21, Spring Boot 4, Spring Data JPA, Gradle
  • Database: MySQL
  • Frontend: React 18, TypeScript, Vite

🚀 로컬 실행 가이드

1. 저장소 클론

git clone https://github.com/POTATO-119/potato-back.git potato-backend
git clone https://github.com/POTATO-119/potato-front.git potato-frontend

2. 실행 환경 준비

  • Java 21
  • MySQL 8.x
  • Node.js 20 이상
  • npm

3. 데이터베이스 및 환경 변수 설정

MySQL에서 데이터베이스를 생성합니다.

CREATE DATABASE potato CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

백엔드 실행 터미널에 데이터베이스 접속 정보를 설정합니다. Spring Boot 환경 변수가 저장소의 기본 설정보다 우선 적용됩니다.

export SPRING_DATASOURCE_URL="jdbc:mysql://localhost:3306/potato?serverTimezone=Asia/Seoul&characterEncoding=UTF-8"
export SPRING_DATASOURCE_USERNAME="root"
export SPRING_DATASOURCE_PASSWORD="your-mysql-password"

프론트엔드에서는 예제 파일을 복사한 뒤 로컬 API 주소를 설정합니다.

cd potato-frontend
cp .env.example .env.local

.env.local의 값을 다음과 같이 변경합니다.

VITE_API_BASE_URL=http://localhost:8080
VITE_API_TIMEOUT=5000
VITE_APP_NAME=POTATO
VITE_APP_ENV=development

4. 백엔드 실행

cd potato-backend
bash ./gradlew bootRun

서버가 실행되면 다음 주소에서 API 문서를 확인할 수 있습니다.

5. 프론트엔드 의존성 설치 및 실행

새 터미널에서 다음 명령을 실행합니다.

cd potato-frontend
npm install
npm run dev

6. 실행 확인

  • 백엔드 Swagger UI가 열리는지 확인합니다.
  • 프론트엔드 로그인 화면이 표시되는지 확인합니다.
  • 회원가입 또는 로그인 요청이 http://localhost:8080으로 전달되는지 브라우저 개발자 도구에서 확인합니다.
  • 상점 조회 → 아이템 구매 → 인벤토리 조회 → 아이템 장착 순서로 데이터가 연결되는지 확인합니다.

🔐 동시성 제어 및 구매 데이터 정합성 (Concurrency Control)

재화 차감과 아이템 지급이 일어나는 상점 커머스 도메인의 특성상, 대량의 동시 요청 상황에서도 데이터 무결성과 트랜잭션 원자성(Atomicity)을 완벽히 보장하도록 설계되었습니다.

1. 동시성 제어 아키텍처 (Redisson RLock + Pessimistic Lock)

  • 트랜잭션 외부 Redis 락 대기: Redisson RLock을 사용자 단위로 적용하여 동일 사용자의 중복 요청을 애플리케이션 입구에서 직렬화합니다. 락 획득 대기를 @Transactional 외부에서 수행함으로써 동시 요청 시 DB 커넥션 Pool(HikariCP)의 불필요한 점유를 최소화했습니다.
  • DB 레벨 2차 방어: 트랜잭션 내부에서 JPA Pessimistic Write Lock(user_id, item_id) DB 유니크 제약 조건을 조합하여 Race Condition 및 중복 지급을 차단합니다.

2. JMeter 동시성 실측 테스트 검증

동일 사용자의 100 VUser 동시 결제 요청 상황을 재현하고, 락 적용 후의 데이터 정합성을 검증했습니다.

항목 실측 결과 비고
정상 결제 (200 OK) 1건 최초 요청자 정상 재화 차감 및 아이템 지급
차단 요청 (400 Bad Request) 99건 잔액 부족 및 중복 구매에 따른 정당한 비즈니스 예외 처리
서버 오류 (500 Server Error) 0건 Deadlock 및 타임아웃 없이 전량 안전하게 상쇄
최종 데이터 정합성 100% 잔액 정확 차감, 인벤토리 1건 생성, Redis 락 잔존 0건
  • 구매 실패 시 재화만 차감되거나 아이템만 지급되는 부분 반영(Partial Commit)을 방지합니다.
  • 카테고리별 장착 아이템 자동 해제 및 소유권 검증 로직을 단일 트랜잭션 내에서 처리합니다.

🔗 주요 API

  • POST /api/users/join: 회원가입
  • POST /api/users/login: 로그인
  • GET /api/items: 전체·카테고리별 아이템 조회
  • POST /api/items/purchase: 아이템 구매 및 재화 차감
  • GET /api/items/inventory/{userId}: 사용자 인벤토리 조회
  • POST /api/items/inventory/equip: 아이템 장착 및 기존 아이템 자동 해제

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages